Movatterモバイル変換


[0]ホーム

URL:


[RFC Home] [TEXT|PDF|HTML] [Tracker] [IPR] [Info page]

INFORMATIONAL
Internet Engineering Task Force (IETF)                          B. KadukRequest for Comments: 7546                                           MITCategory: Informational                                         May 2015ISSN: 2070-1721Structure of the Generic Security Service (GSS) Negotiation LoopAbstract   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; seeSection 2 of RFC 5741.   Information about the current status of this document, any errata,   and how to provide feedback on it may be obtained athttp://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 toBCP 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 2015Table of Contents1. Introduction ....................................................22. Application Protocol Requirements ...............................33. Loop Structure ..................................................43.1. Anonymous Initiators .......................................53.2. GSS_Init_sec_context .......................................53.3. Sending from Initiator to Acceptor .........................63.4. Acceptor Sanity Checking ...................................63.5. GSS_Accept_sec_context .....................................73.6. Sending from Acceptor to Initiator .........................83.7. Initiator Input Validation .................................93.8. Continue the Loop ..........................................94. After Security Context Negotiation ..............................94.1. Authorization Checks ......................................104.2. Using Partially Complete Security Contexts ................104.3. Additional Context Tokens .................................115. Sample Code ....................................................125.1. GSS Application Sample Code ...............................136. Security Considerations ........................................197. References .....................................................207.1. Normative References ......................................207.2. Informative References ....................................20   Acknowledgements ..................................................21   Author's Address ..................................................211.  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 aKaduk                         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 20153.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.   SeeSection 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 20153.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.  SeeSection 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 toSection 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, seeSection 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 flagKaduk                         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   Sections2.2.6 and1.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 20154.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 20155.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 voidrelease_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 intsend_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 intreceive_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 voiddo_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 byRFC 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 intcheck_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 2015static voiddo_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 byRFC 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);}intmain(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 Sections2.2.6 and1.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.  References7.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.eduKaduk                         Informational                    [Page 21]

[8]ページ先頭

©2009-2025 Movatter.jp