diff options
Diffstat (limited to 'doc/rfc/rfc7546.txt')
-rw-r--r-- | doc/rfc/rfc7546.txt | 1179 |
1 files changed, 1179 insertions, 0 deletions
diff --git a/doc/rfc/rfc7546.txt b/doc/rfc/rfc7546.txt new file mode 100644 index 0000000..74b38a9 --- /dev/null +++ b/doc/rfc/rfc7546.txt @@ -0,0 +1,1179 @@ + + + + + + +Internet Engineering Task Force (IETF) B. Kaduk +Request for Comments: 7546 MIT +Category: Informational May 2015 +ISSN: 2070-1721 + + + Structure of the Generic Security Service (GSS) Negotiation Loop + +Abstract + + This document specifies the generic structure of the negotiation loop + to establish a Generic Security Service (GSS) security context + between initiator and acceptor. The control flow of the loop is + indicated for both parties, including error conditions, and + indications are given for where application-specific behavior must be + specified. + +Status of This Memo + + This document is not an Internet Standards Track specification; it is + published for informational purposes. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Not all documents + approved by the IESG are a candidate for any level of Internet + Standard; see Section 2 of RFC 5741. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + http://www.rfc-editor.org/info/rfc7546. + +Copyright Notice + + Copyright (c) 2015 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + + + + +Kaduk Informational [Page 1] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +Table of Contents + + 1. Introduction ....................................................2 + 2. Application Protocol Requirements ...............................3 + 3. Loop Structure ..................................................4 + 3.1. Anonymous Initiators .......................................5 + 3.2. GSS_Init_sec_context .......................................5 + 3.3. Sending from Initiator to Acceptor .........................6 + 3.4. Acceptor Sanity Checking ...................................6 + 3.5. GSS_Accept_sec_context .....................................7 + 3.6. Sending from Acceptor to Initiator .........................8 + 3.7. Initiator Input Validation .................................9 + 3.8. Continue the Loop ..........................................9 + 4. After Security Context Negotiation ..............................9 + 4.1. Authorization Checks ......................................10 + 4.2. Using Partially Complete Security Contexts ................10 + 4.3. Additional Context Tokens .................................11 + 5. Sample Code ....................................................12 + 5.1. GSS Application Sample Code ...............................13 + 6. Security Considerations ........................................19 + 7. References .....................................................20 + 7.1. Normative References ......................................20 + 7.2. Informative References ....................................20 + Acknowledgements ..................................................21 + Author's Address ..................................................21 + +1. Introduction + + "Generic Security Service Application Program Interface Version 2, + Update 1" [RFC2743] provides a generic interface for security + services in the form of an abstraction layer over the underlying + security mechanisms that an application may use. A GSS initiator and + acceptor exchange messages, called "tokens", until a security context + is established. Such a security context allows for each party to + authenticate the other, the passing of confidential and/or integrity- + protected messages between the initiator and acceptor, the generation + of identical pseudorandom bit strings by both participants [RFC4401], + and more. + + During context establishment, security context tokens are exchanged + synchronously, one at a time; the initiator sends the first context + token. The number of tokens that must be exchanged between the + initiator and acceptor in order to establish the security context is + dependent on the underlying mechanism as well as the desired + properties of the security context and is, in general, not known to + the application. Accordingly, the application's control flow must + include a loop within which GSS security context tokens are + exchanged; the loop terminates upon successful establishment of a + + + +Kaduk Informational [Page 2] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + security context or an error condition. The GSS-API, together with + its security mechanisms, specifies the format and encoding of the + context tokens themselves, but the application protocol must specify + the necessary framing for the application to determine what octet + strings constitute GSS security context tokens and pass them into the + GSS-API implementation as appropriate. + + The GSS-API C-bindings [RFC2744] provide some example code for such a + negotiation loop, but this code does not specify the application's + behavior on unexpected or error conditions. As such, individual + application protocol specifications have had to specify the structure + of their GSS negotiation loops, including error handling, on a per- + protocol basis (see [RFC4462], [RFC3645], [RFC5801], [RFC4752], and + [RFC2203]). This represents a substantial duplication of effort, and + the various specifications go into different levels of detail and + describe different possible error conditions. Therefore, it is + preferable to have the structure of the GSS negotiation loop, + including error conditions and token passing, described in a single + specification that can then be referred to from other documents in + lieu of repeating the structure of the loop each time. This document + fills that role. + + The necessary requirements for correctly performing a GSS negotiation + loop are essentially all included in [RFC2743], but they are + scattered in many different places. This document brings all the + requirements together into one place for the convenience of + implementors, even though the normative requirements remain in + [RFC2743]. In a few places, this document notes additional behavior + that is useful for applications but is not mandated by [RFC2743]. + +2. Application Protocol Requirements + + Part of the purpose of this document is to guide the development of + new application protocols using the GSS-API, as well as the + development of new application software using such protocols. The + following list consists of features that are necessary or useful in + such an application protocol: + + o Protocols require a way to frame and identify security context + negotiation tokens during the GSS negotiation loop. + + o Error tokens should generally also get special framing, as the + recipient may have no other way to distinguish unexpected error + context tokens from per-message tokens. + + + + + + + +Kaduk Informational [Page 3] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + o Protocols may benefit from a generic means of indicating an error, + possibly accompanied by a descriptive string, to be used if error + tokens are not available or not usable due to constraints of the + application protocol. + + o A protocol may use the negotiated GSS security context for per- + message operations; in such cases, the protocol will need a way to + frame and identify those per-message tokens and the nature of + their contents. For example, a protocol message may be + accompanied by the output of GSS_GetMIC() over that message; the + protocol must identify the location and size of that Message + Identity Code (MIC) token and indicate that it is a MIC token and + to what cleartext it corresponds. + + o Applications are responsible for authorization of the + authenticated peer principal names that are supplied by the GSS- + API. Such names are mechanism specific and may come from a + different portion of a federated identity scheme. Application + protocols may need to supply additional information to support the + authorization of access to a given resource, such as the Secure + Shell version 2 (SSHv2) "username" parameter. + +3. Loop Structure + + The loop is begun by the appropriately named initiator, which calls + GSS_Init_sec_context() with an empty (zero-length) input_token and a + fixed set of input flags containing the desired attributes for the + security context. The initiator should not change any of the input + parameters to GSS_Init_sec_context() between calls to it during the + loop, with the exception of the input_token parameter, which will + contain a message from the acceptor after the initial call, and the + input_context_handle, which must be the result returned in the + output_context_handle of the previous call to GSS_Init_sec_context() + (GSS_C_NO_CONTEXT for the first call). (In the C bindings, there is + only a single read/modify context_handle argument, so the same + variable should be passed for each call in the loop.) RFC 2743 only + requires that the claimant_cred_handle argument remain constant over + all calls in the loop, but the other non-excepted arguments should + also remain fixed for reliable operation. + + The following subsections will describe the various steps of the + loop, without special consideration to whether a call to + GSS_Init_sec_context() or GSS_Accept_sec_context() is the first such + call in the loop. + + + + + + + +Kaduk Informational [Page 4] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +3.1. Anonymous Initiators + + If the initiator is requesting anonymity by setting the anon_req_flag + input to GSS_Init_sec_context(), then on non-error returns from + GSS_Init_sec_context() (that is, when the major status is + GSS_S_COMPLETE or GSS_S_CONTINUE_NEEDED) the initiator must verify + that the output value of anon_state from GSS_Init_sec_context() is + true before sending the security context token to the acceptor. + Failing to perform this check could cause the initiator to lose + anonymity. + +3.2. GSS_Init_sec_context + + The initiator calls GSS_Init_sec_context() using the + input_context_handle for the current security context being + established and its fixed set of input parameters and the input_token + received from the acceptor (if this is not the first iteration of the + loop). The presence or absence of a nonempty output_token and the + value of the major status code are the indicators for how to proceed: + + o If the major status code is GSS_S_COMPLETE and the output_token is + empty, then the context negotiation is fully complete and ready + for use by the initiator with no further actions. + + o If the major status code is GSS_S_COMPLETE and the output_token is + nonempty, then the initiator's portion of the security context + negotiation is complete but the acceptor's is not. The initiator + must send the output_token to the acceptor so that the acceptor + can establish its half of the security context. + + o If the major status code is GSS_S_CONTINUE_NEEDED and the + output_token is nonempty, the context negotiation is incomplete. + The initiator must send the output_token to the acceptor and await + another input_token from the acceptor. + + o If the major status code is GSS_S_CONTINUE_NEEDED and the + output_token is empty, the mechanism has produced an output that + is not compliant with [RFC2743]. However, there are some known + implementations of certain mechanisms such as NT LAN Manager + Security Support Provider [NTLMSSP] that do produce empty context + negotiation tokens. For maximum interoperability, applications + should be prepared to accept such tokens and should transmit them + to the acceptor if they are generated. + + + + + + + + +Kaduk Informational [Page 5] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + o If the major status code is any other value, the context + negotiation has failed. If the output_token is nonempty, it is an + error token and the initiator should send it to the acceptor. If + the output_token is empty, then the initiator should indicate the + failure to the acceptor if an appropriate application-protocol + channel to do so is available. + +3.3. Sending from Initiator to Acceptor + + The establishment of a GSS security context between initiator and + acceptor requires some communication channel by which to exchange the + context negotiation tokens. The nature of this channel is not + specified by the GSS specification -- it could be a dedicated TCP + channel, a UDP-based Remote Procedure Call (RPC) protocol, or any + other sort of channel. In many cases, the channel will be + multiplexed with non-GSS application data; the application protocol + must always provide some means by which the GSS context tokens can be + identified (e.g., length and start location) and passed through to + the mechanism accordingly. The application protocol may also include + a facility for indicating errors from one party to the other, which + can be used to convey errors resulting from GSS-API calls when + appropriate (such as when no error token was generated by the GSS-API + implementation). Note that GSS major and minor status codes are + specified by language bindings, not the abstract API; sending a major + status code and optionally the display form of the two error codes + may be the best that can be done in this case. + + However, even the presence of a communication channel does not + necessarily indicate that it is appropriate for the initiator to + indicate such errors. For example, if the acceptor is a stateless or + near-stateless UDP server, there is probably no need for the + initiator to explicitly indicate its failure to the acceptor. + Conditions such as this can be treated in individual application + protocol specifications. + + If a regular security context output_token is produced by the call to + GSS_Init_sec_context(), the initiator must transmit this token to the + acceptor over the application's communication channel. If the call + to GSS_Init_sec_context() returns an error token as output_token, it + is recommended that the initiator transmit this token to the acceptor + over the application's communication channel. + +3.4. Acceptor Sanity Checking + + The acceptor's half of the negotiation loop is triggered by the + receipt of a context token from the initiator. Before calling + GSS_Accept_sec_context(), the acceptor may find it useful to perform + some sanity checks on the state of the negotiation loop. + + + +Kaduk Informational [Page 6] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + If the acceptor receives a context token but was not expecting such a + token (for example, if the acceptor's previous call to + GSS_Accept_sec_context() returned GSS_S_COMPLETE), this is probably + an error condition indicating that the initiator's state is invalid. + See Section 4.3 for some exceptional cases. It is likely appropriate + for the acceptor to report this error condition to the initiator via + the application's communication channel. + + If the acceptor is expecting a context token (e.g., if the previous + call to GSS_Accept_sec_context() returned GSS_S_CONTINUE_NEEDED) but + does not receive such a token within a reasonable amount of time + after transmitting the previous output_token to the initiator, the + acceptor should assume that the initiator's state is invalid + (timeout) and fail the GSS negotiation. Again, it is likely + appropriate for the acceptor to report this error condition to the + initiator via the application's communication channel. + +3.5. GSS_Accept_sec_context + + The GSS acceptor responds to the actions of an initiator; as such, + there should always be a nonempty input_token to calls to + GSS_Accept_sec_context(). The input_context_handle parameter will + always be given as the output_context_handle from the previous call + to GSS_Accept_sec_context() in a given negotiation loop, or + GSS_C_NO_CONTEXT on the first call, but the acceptor_cred_handle and + chan_bindings arguments should remain fixed over the course of a + given GSS negotiation loop. [RFC2743] only requires that the + acceptor_cred_handle remain fixed throughout the loop, but the + chan_bindings argument should also remain fixed for reliable + operation. + + The GSS acceptor calls GSS_Accept_sec_context(), using the + input_context_handle for the current security context being + established and the input_token received from the initiator. The + presence or absence of a nonempty output_token and the value of the + major status code are the indicators for how to proceed: + + o If the major status code is GSS_S_COMPLETE and the output_token is + empty, then the context negotiation is fully complete and ready + for use by the acceptor with no further actions. + + o If the major status code is GSS_S_COMPLETE and the output_token is + nonempty, then the acceptor's portion of the security context + negotiation is complete but the initiator's is not. The acceptor + must send the output_token to the initiator so that the initiator + can establish its half of the security context. + + + + + +Kaduk Informational [Page 7] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + o If the major status code is GSS_S_CONTINUE_NEEDED and the + output_token is nonempty, the context negotiation is incomplete. + The acceptor must send the output_token to the initiator and await + another input_token from the initiator. + + o If the major status code is GSS_S_CONTINUE_NEEDED and the + output_token is empty, the mechanism has produced an output that + is not compliant with [RFC2743]. However, there are some known + implementations of certain mechanisms such as NTLMSSP [NTLMSSP] + that do produce empty context negotiation tokens. For maximum + interoperability, applications should be prepared to accept such + tokens and should transmit them to the initiator if they are + generated. + + o If the major status code is any other value, the context + negotiation has failed. If the output_token is nonempty, it is an + error token and the acceptor should send it to the initiator. If + the output_token is empty, then the acceptor should indicate the + failure to the initiator if an appropriate application-protocol + channel to do so is available. + +3.6. Sending from Acceptor to Initiator + + The mechanism for sending the context token from acceptor to + initiator will depend on the nature of the communication channel + between the two parties. For a synchronous bidirectional channel, it + can be just another piece of data sent over the link, but for a + stateless UDP RPC acceptor, the token will probably end up being sent + as an RPC output parameter. Application protocol specifications will + need to specify the nature of this behavior. + + If the application protocol has the initiator driving the + application's control flow, it is particularly helpful for the + acceptor to indicate a failure to the initiator, as mentioned in some + of the above cases conditional on "an appropriate application- + protocol channel to do so". + + If a regular security context output_token is produced by the call to + GSS_Accept_sec_context(), the acceptor must transmit this token to + the initiator over the application's communication channel. If the + call to GSS_Accept_sec_context() returns an error token as + output_token, it is recommended that the acceptor transmit this token + to the initiator over the application's communication channel. + + + + + + + + +Kaduk Informational [Page 8] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +3.7. Initiator Input Validation + + The initiator's half of the negotiation loop is triggered (after the + first call) by receipt of a context token from the acceptor. Before + calling GSS_Init_sec_context(), the initiator may find it useful to + perform some sanity checks on the state of the negotiation loop. + + If the initiator receives a context token but was not expecting such + a token (for example, if the initiator's previous call to + GSS_Init_sec_context() returned GSS_S_COMPLETE), this is probably an + error condition indicating that the acceptor's state is invalid. See + Section 4.3 for some exceptional cases. It may be appropriate for + the initiator to report this error condition to the acceptor via the + application's communication channel. + + If the initiator is expecting a context token (that is, the previous + call to GSS_Init_sec_context() returned GSS_S_CONTINUE_NEEDED) but + does not receive such a token within a reasonable amount of time + after transmitting the previous output_token to the acceptor, the + initiator should assume that the acceptor's state is invalid and fail + the GSS negotiation. Again, it may be appropriate for the initiator + to report this error condition to the acceptor via the application's + communication channel. + +3.8. Continue the Loop + + If the loop is in neither a success nor a failure condition, then the + loop must continue. Control flow returns to Section 3.2. + +4. After Security Context Negotiation + + Once a party has completed its half of the security context and + fulfilled its obligations to the other party, the context is + complete, but it is not necessarily ready and appropriate for use. + In particular, the security context flags may not be appropriate for + the given application's use. In some cases, the context may be ready + for use before the negotiation is complete, see Section 4.2. + + The initiator specifies, as part of its fixed set of inputs to + GSS_Init_sec_context(), values for all defined request flag booleans, + among them: deleg_req_flag, mutual_req_flag, replay_det_req_flag, + sequence_req_flag, conf_req_flag, and integ_req_flag. Upon + completion of the security context negotiation, the initiator must + verify that the values of deleg_state, mutual_state, + replay_det_state, sequence_state, conf_avail, and integ_avail (and + any additional flags added by extensions) from the last call to + GSS_Init_sec_context() correspond to the requested flags. If a flag + + + + +Kaduk Informational [Page 9] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + was requested but is not available and that feature is necessary for + the application protocol, the initiator must destroy the security + context and not use the security context for application traffic. + + Application protocol specifications citing this document should + indicate which context flags are required for their application + protocol. + + The acceptor receives as output the following booleans: deleg_state, + mutual_state, replay_det_state, sequence_state, anon_state, + trans_state, conf_avail, and integ_avail, and any additional flags + added by extensions to the GSS-API. The acceptor must verify that + any flags necessary for the application protocol are set. If a + necessary flag is not set, the acceptor must destroy the security + context and not use the security context for application traffic. + +4.1. Authorization Checks + + The acceptor receives as one of the outputs of + GSS_Accept_sec_context() the name of the initiator that has + authenticated during the security context negotiation. Applications + need to implement authorization checks on this received name + ('client_name' in the sample code) before providing access to + restricted resources. In particular, security context negotiation + can be successful when the client is anonymous or is from a different + identity realm than the acceptor, depending on the details of the + mechanism used by the GSS-API to establish the security context. + Acceptor applications can check which target name was used by the + initiator, but the details are out of scope for this document. See + Sections 2.2.6 and 1.1.5 of [RFC2743]. Additional information can be + available in GSS-API Naming Extensions [RFC6680]. + +4.2. Using Partially Complete Security Contexts + + For mechanism/flag combinations that require multiple token + exchanges, the GSS-API specification [RFC2743] provides a + prot_ready_state output value from GSS_Init_sec_context() and + GSS_Accept_sec_context(), which indicates when per-message operations + are available. However, many mechanism implementations do not + provide this functionality and the analysis of the security + consequences of its use is rather complicated, so it is not expected + to be useful in most application protocols. + + In particular, mutual authentication, replay protection, and other + services (if requested) are services that will be active when + GSS_S_COMPLETE is returned but that are not necessarily active before + the security context is fully established. + + + + +Kaduk Informational [Page 10] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +4.3. Additional Context Tokens + + Under some conditions, a context token will be received by a party to + a security context negotiation after that party has completed the + negotiation (i.e., after GSS_Init_sec_context() or + GSS_Accept_sec_context() has returned GSS_S_COMPLETE). Such tokens + must be passed to GSS_Process_context_token() for processing. It may + not always be necessary for a mechanism implementation to generate an + error token on the initiator side or for an initiator application to + transmit that token to the acceptor; such decisions are out of scope + for this document. Both peers should always be prepared to process + such tokens and application protocols should provide means by which + they can be transmitted. + + Such tokens can be security context deletion tokens, emitted when the + remote party called GSS_Delete_sec_context() with a non-null + output_context_token parameter, or error tokens, emitted when the + remote party experiences an error processing the last token in a + security context negotiation exchange. Errors experienced when + processing tokens earlier in the negotiation would be transmitted as + normal security context tokens and processed by + GSS_Init_sec_context() or GSS_Accept_sec_context(), as appropriate. + With the GSS-API version 2, it is not recommended to use security + context deletion tokens, so error tokens are expected to be the most + common form of additional context token for new application + protocols. + + GSS_Process_context_token() may indicate an error in its major_status + field if an error is encountered locally during token processing or + to indicate that an error was encountered on the peer and conveyed in + an error token. See [Err4151] of [RFC2743]. Regardless of the + major_status output of GSS_Process_context_token(), + GSS_Inquire_context() should be used after processing the extra + token, to query the status of the security context and whether it can + supply the features necessary for the application protocol. + + At present, all tokens that should be handled by + GSS_Process_context_token() will lead to the security context being + effectively unusable. Future extensions to the GSS-API may allow for + applications to continue to function after a call to + GSS_Process_context_token(), and it is expected that the outputs of + GSS_Inquire_context() will indicate whether it is safe to do so. + However, since there are no such extensions at present (error tokens + and deletion tokens both result in the security context being + essentially unusable), there is no guidance to give to applications + regarding this possibility at this time. + + + + + +Kaduk Informational [Page 11] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + Even if GSS_Process_context_token() processes an error or deletion + token that renders the context essentially unusable, the resources + associated with the context must eventually be freed with a call to + GSS_Delete_sec_context(), just as would be needed if + GSS_Init_sec_context() or GSS_Accept_sec_context() had returned an + error while processing an input context token and the + input_context_handle was not GSS_C_NO_CONTEXT. RFC 2743 has some + text that is slightly ambiguous in this regard, but the best practice + is to always call GSS_Delete_sec_context(). + +5. Sample Code + + This section gives sample code for the GSS negotiation loop, both for + a regular application and for an application where the initiator + wishes to remain anonymous. Since the code for the two cases is very + similar, the anonymous-specific additions are wrapped in a + conditional check; that check and the conditional code may be ignored + if anonymous processing is not needed. + + Since the communication channel between the initiator and acceptor is + a matter for individual application protocols, it is inherently + unspecified at the GSS-API level, which can lead to examples that are + less satisfying than may be desired. For example, the sample code in + [RFC2744] uses an unspecified send_token_to_peer() routine. Fully + correct and general code to frame and transmit tokens requires a + substantial amount of error checking and would detract from the core + purpose of this document, so we only present the function signature + for one example of what such functions might be and leave some + comments in the otherwise empty function bodies. + + This sample code is written in C, using the GSS-API C-bindings + [RFC2744]. It uses the macro GSS_ERROR() to help unpack the various + sorts of information that can be stored in the major status field; + supplementary information does not necessarily indicate an error. + Applications written in other languages will need to exercise care + that checks against the major status value are written correctly. + + This sample code should be compilable as a standalone program, linked + against a GSS-API library. In addition to supplying implementations + for the token transmission/receipt routines, in order for the program + to successfully run when linked against most GSS-API libraries, the + initiator will need to specify an explicit target name for the + acceptor, which must match the credentials available to the acceptor. + A skeleton for how this may be done is provided, using a dummy name. + + This sample code assumes use of v2 of the GSS-API. Applications + wishing to remain compatible with v1 of the GSS-API may need to + perform additional checks in some locations. + + + +Kaduk Informational [Page 12] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +5.1. GSS Application Sample Code + +#include <unistd.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gssapi/gssapi.h> + +/* + * This helper is used only on buffers that we allocate ourselves (e.g., + * from receive_token()). Buffers allocated by GSS routines must use + * gss_release_buffer(). + */ +static void +release_buffer(gss_buffer_t buf) +{ + free(buf->value); + buf->value = NULL; + buf->length = 0; +} + +/* + * Helper to send a token on the specified file descriptor. + * + * If errors are encountered, this routine must not directly cause + * termination of the process because compliant GSS applications + * must release resources allocated by the GSS library before + * exiting. + * + * Returns 0 on success, nonzero on failure. + */ +static int +send_token(int fd, gss_buffer_t token) +{ + /* + * Supply token framing and transmission code here. + * + * It is advisable for the application protocol to specify the + * length of the token being transmitted unless the underlying + * transit does so implicitly. + * + * In addition to checking for error returns from whichever + * syscall(s) are used to send data, applications should have + * a loop to handle EINTR returns. + */ + return 1; +} + + + +Kaduk Informational [Page 13] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +/* + * Helper to receive a token on the specified file descriptor. + * + * If errors are encountered, this routine must not directly cause + * termination of the process because compliant GSS applications + * must release resources allocated by the GSS library before + * exiting. + * + * Returns 0 on success, nonzero on failure. + */ +static int +receive_token(int fd, gss_buffer_t token) +{ + /* + * Supply token framing and transmission code here. + * + * In addition to checking for error returns from whichever + * syscall(s) are used to receive data, applications should have + * a loop to handle EINTR returns. + * + * This routine is assumed to allocate memory for the local copy + * of the received token, which must be freed with release_buffer(). + */ + return 1; +} + +static void +do_initiator(int readfd, int writefd, int anon) +{ + int initiator_established = 0, ret; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + OM_uint32 major, minor, req_flags, ret_flags; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER; + gss_name_t target_name = GSS_C_NO_NAME; + + /* Applications should set target_name to a real value. */ + name_buf.value = "<service>@<hostname.domain>"; + name_buf.length = strlen(name_buf.value); + major = gss_import_name(&minor, &name_buf, + GSS_C_NT_HOSTBASED_SERVICE, &target_name); + if (GSS_ERROR(major)) { + warnx(1, "Could not import name\n"); + goto cleanup; + } + + + + + +Kaduk Informational [Page 14] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + /* Mutual authentication will require a token from acceptor to + * initiator and thus a second call to gss_init_sec_context(). */ + req_flags = GSS_C_MUTUAL_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG; + if (anon) + req_flags |= GSS_C_ANON_FLAG; + + while (!initiator_established) { + /* The initiator_cred_handle, mech_type, time_req, + * input_chan_bindings, actual_mech_type, and time_rec + * parameters are not needed in many cases. We pass + * GSS_C_NO_CREDENTIAL, GSS_C_NO_OID, 0, NULL, NULL, and NULL + * for them, respectively. */ + major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctx, + target_name, GSS_C_NO_OID, + req_flags, 0, NULL, &input_token, + NULL, &output_token, &ret_flags, + NULL); + /* This was allocated by receive_token() and is no longer + * needed. Free it now to avoid leaks if the loop continues. */ + release_buffer(&input_token); + if (anon) { + /* Initiators that wish to remain anonymous must check + * whether their request has been honored before sending + * each token. */ + if (!(ret_flags & GSS_C_ANON_FLAG)) { + warnx("Anonymous requested but not available\n"); + goto cleanup; + } + } + /* Always send a token if we are expecting another input token + * (GSS_S_CONTINUE_NEEDED is set) or if it is nonempty. */ + if ((major & GSS_S_CONTINUE_NEEDED) || + output_token.length > 0) { + ret = send_token(writefd, &output_token); + if (ret != 0) + goto cleanup; + } + /* Check for errors after sending the token so that we will send + * error tokens. */ + if (GSS_ERROR(major)) { + warnx("gss_init_sec_context() error major 0x%x\n", major); + goto cleanup; + } + /* Free the output token's storage; we don't need it anymore. + * gss_release_buffer() is safe to call on the output buffer + * from gss_int_sec_context(), even if there is no storage + * associated with that buffer. */ + (void)gss_release_buffer(&minor, &output_token); + + + +Kaduk Informational [Page 15] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + if (major & GSS_S_CONTINUE_NEEDED) { + ret = receive_token(readfd, &input_token); + if (ret != 0) + goto cleanup; + } else if (major == GSS_S_COMPLETE) { + initiator_established = 1; + } else { + /* This situation is forbidden by RFC 2743. Bail out. */ + warnx("major not complete or continue but not error\n"); + goto cleanup; + } + } /* while (!initiator_established) */ + if ((ret_flags & req_flags) != req_flags) { + warnx("Negotiated context does not support requested flags\n"); + goto cleanup; + } + printf("Initiator's context negotiation successful\n"); +cleanup: + /* We are required to release storage for nonzero-length output + * tokens. gss_release_buffer() zeros the length, so we + * will not attempt to release the same buffer twice. */ + if (output_token.length > 0) + (void)gss_release_buffer(&minor, &output_token); + /* Do not request a context deletion token; pass NULL. */ + (void)gss_delete_sec_context(&minor, &ctx, NULL); + (void)gss_release_name(&minor, &target_name); +} + +/* + * Perform authorization checks on the initiator's GSS name object. + * + * Returns 0 on success (the initiator is authorized) and nonzero + * when the initiator is not authorized. + */ +static int +check_authz(gss_name_t client_name) +{ + /* + * Supply authorization checking code here. + * + * Options include bitwise comparison of the exported name against + * a local database and introspection against name attributes. + */ + return 0; +} + + + + + + +Kaduk Informational [Page 16] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + +static void +do_acceptor(int readfd, int writefd) +{ + int acceptor_established = 0, ret; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + OM_uint32 major, minor, ret_flags; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_name_t client_name; + + major = GSS_S_CONTINUE_NEEDED; + + while (!acceptor_established) { + if (major & GSS_S_CONTINUE_NEEDED) { + ret = receive_token(readfd, &input_token); + if (ret != 0) + goto cleanup; + } else if (major == GSS_S_COMPLETE) { + acceptor_established = 1; + break; + } else { + /* This situation is forbidden by RFC 2743. Bail out. */ + warnx("major not complete or continue but not error\n"); + goto cleanup; + } + /* We can use the default behavior or do not need the returned + * information for the parameters acceptor_cred_handle, + * input_chan_bindings, mech_type, time_rec, and + * delegated_cred_handle, and pass the values + * GSS_C_NO_CREDENTIAL, NULL, NULL, NULL, and NULL, + * respectively. In some cases the src_name will not be + * needed, but most likely it will be needed for some + * authorization or logging functionality. */ + major = gss_accept_sec_context(&minor, &ctx, + GSS_C_NO_CREDENTIAL, + &input_token, NULL, + &client_name, NULL, + &output_token, &ret_flags, NULL, + NULL); + /* This was allocated by receive_token() and is no longer + * needed. Free it now to avoid leaks if the loop continues. */ + release_buffer(&input_token); + /* Always send a token if we are expecting another input token + * (GSS_S_CONTINUE_NEEDED is set) or if it is nonempty. */ + if ((major & GSS_S_CONTINUE_NEEDED) || + output_token.length > 0) { + ret = send_token(writefd, &output_token); + if (ret != 0) + + + +Kaduk Informational [Page 17] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + goto cleanup; + } + /* Check for errors after sending the token so that we will send + * error tokens. */ + if (GSS_ERROR(major)) { + warnx("gss_accept_sec_context() error major 0x%x\n", major); + goto cleanup; + } + /* Free the output token's storage; we don't need it anymore. + * gss_release_buffer() is safe to call on the output buffer + * from gss_accept_sec_context(), even if there is no storage + * associated with that buffer. */ + (void)gss_release_buffer(&minor, &output_token); + } /* while (!acceptor_established) */ + if (!(ret_flags & GSS_C_INTEG_FLAG)) { + warnx("Negotiated context does not support integrity\n"); + goto cleanup; + } + printf("Acceptor's context negotiation successful\n"); + ret = check_authz(client_name); + if (ret != 0) + printf("Client is not authorized; rejecting access\n"); +cleanup: + release_buffer(&input_token); + /* We are required to release storage for nonzero-length output + * tokens. gss_release_buffer() zeros the length, so we + * will not attempt to release the same buffer twice. */ + if (output_token.length > 0) + (void)gss_release_buffer(&minor, &output_token); + /* Do not request a context deletion token, pass NULL. */ + (void)gss_delete_sec_context(&minor, &ctx, NULL); + (void)gss_release_name(&minor, &client_name); +} + +int +main(void) +{ + pid_t pid; + int fd1 = -1, fd2 = -1; + + /* Create file descriptors for reading/writing here. */ + pid = fork(); + if (pid == 0) + do_initiator(fd1, fd2, 0); + else if (pid > 0) + do_acceptor(fd2, fd1); + else + err(1, "fork() failed\n"); + + + +Kaduk Informational [Page 18] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + exit(0); +} + +6. Security Considerations + + This document provides a (reasonably) concise description and example + for correct construction of the GSS-API security context negotiation + loop. Since everything relating to the construction and use of a GSS + security context is security related, there are security-relevant + considerations throughout the document. It is useful to call out a + few things in this section, though. + + The GSS-API uses a request-and-check model for features. An + application using the GSS-API requests certain features (e.g., + confidentiality protection for messages or anonymity), but such a + request does not require the GSS implementation to provide that + feature. The application must check the returned flags to verify + whether a requested feature is present; if the feature was non- + optional for the application, the application must generate an error. + Phrased differently, the GSS-API will not generate an error if it is + unable to satisfy the features requested by the application. + + In many cases, it is convenient for GSS acceptors to accept security + contexts using multiple acceptor names (such as by using the default + credential set, as happens when GSS_C_NO_CREDENTIAL is passed to + GSS_Accept_sec_context()). This allows acceptors to use any + credentials to which they have access for accepting security + contexts, which may not be the desired behavior for a given + application. (For example, the Secure Shell daemon (sshd) may wish + to accept only using GSS_C_NT_HOSTBASED credentials of the form + host@<hostname>, and not nfs@<hostname>.) Acceptor applications can + check which target name was used by the initiator, but the details + are out of scope for this document. See Sections 2.2.6 and 1.1.5 of + [RFC2743] + + The C sample code uses the macro GSS_ERROR() to assess the return + value of gss_init_sec_context() and gss_accept_sec_context(). This + is done to indicate where checks are needed in writing code for other + languages and what the nature of those checks might be. The C code + could be made simpler by omitting that macro. In applications + expecting to receive protected octet streams, this macro should not + be used on the result of per-message operations, as it omits checking + for supplementary status values such as GSS_S_DUPLICATE_TOKEN, + GSS_S_OLD_TOKEN, etc. Use of the GSS_ERROR() macro on the results of + GSS-API per-message operations has resulted in security + vulnerabilities in existing software. + + + + + +Kaduk Informational [Page 19] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + The security considerations from RFCs 2743 and 2744 remain applicable + to consumers of this document. + +7. References + +7.1. Normative References + + [RFC2743] Linn, J., "Generic Security Service Application Program + Interface Version 2, Update 1", RFC 2743, + DOI 10.17487/RFC2743, January 2000, + <http://www.rfc-editor.org/info/rfc2743>. + + [RFC2744] Wray, J., "Generic Security Service API Version 2 : + C-bindings", RFC 2744, DOI 10.17487/RFC2744, January 2000, + <http://www.rfc-editor.org/info/rfc2744>. + +7.2. Informative References + + [Err4151] RFC Errata, Erratum ID 4151, RFC 2743. + + [NTLMSSP] Microsoft Corporation, "[MS-NLMP]: NT LAN Manager (NTLM) + Authentication Protocol", May 2014, + <https://msdn.microsoft.com/en-us/library/cc236621.aspx>. + + [RFC2203] Eisler, M., Chiu, A., and L. Ling, "RPCSEC_GSS Protocol + Specification", RFC 2203, DOI 10.17487/RFC2203, September + 1997, <http://www.rfc-editor.org/info/rfc2203>. + + [RFC3645] Kwan, S., Garg, P., Gilroy, J., Esibov, L., Westhead, J., + and R. Hall, "Generic Security Service Algorithm for + Secret Key Transaction Authentication for DNS (GSS-TSIG)", + RFC 3645, DOI 10.17487/RFC3645, October 2003, + <http://www.rfc-editor.org/info/rfc3645>. + + [RFC4401] Williams, N., "A Pseudo-Random Function (PRF) API + Extension for the Generic Security Service Application + Program Interface (GSS-API)", RFC 4401, + DOI 10.17487/RFC4401, February 2006, + <http://www.rfc-editor.org/info/rfc4401>. + + [RFC4462] Hutzelman, J., Salowey, J., Galbraith, J., and V. Welch, + "Generic Security Service Application Program Interface + (GSS-API) Authentication and Key Exchange for the Secure + Shell (SSH) Protocol", RFC 4462, DOI 10.17487/RFC4462, May + 2006, <http://www.rfc-editor.org/info/rfc4462>. + + + + + + +Kaduk Informational [Page 20] + +RFC 7546 Structure of the GSS Negotiation Loop May 2015 + + + [RFC4752] Melnikov, A., Ed., "The Kerberos V5 ("GSSAPI") Simple + Authentication and Security Layer (SASL) Mechanism", + RFC 4752, DOI 10.17487/RFC4752, November 2006, + <http://www.rfc-editor.org/info/rfc4752>. + + [RFC5801] Josefsson, S. and N. Williams, "Using Generic Security + Service Application Program Interface (GSS-API) Mechanisms + in Simple Authentication and Security Layer (SASL): The + GS2 Mechanism Family", RFC 5801, DOI 10.17487/RFC5801, + July 2010, <http://www.rfc-editor.org/info/rfc5801>. + + [RFC6680] Williams, N., Johansson, L., Hartman, S., and S. + Josefsson, "Generic Security Service Application + Programming Interface (GSS-API) Naming Extensions", + RFC 6680, DOI 10.17487/RFC6680, August 2012, + <http://www.rfc-editor.org/info/rfc6680>. + +Acknowledgements + + Thanks to Nico Williams and Jeff Hutzleman for prompting me to write + this document. + +Author's Address + + Benjamin Kaduk + MIT Kerberos Consortium + + EMail: kaduk@mit.edu + + + + + + + + + + + + + + + + + + + + + + + +Kaduk Informational [Page 21] + |