RFC 1508

Generic Security Service Application Program Interface

πŸ“… published September 1993, from ietf

Generic Security Service Application Program Interface (GSS-API) πŸŽ€

Part 1 of 10 πŸ’–

Okay bestie, the title block is giving proper standards-track energy πŸ¦‹. It's an RFC 1508 from the Network Working Group, written by J. Linn at Geer Zolot Associates, dated September 1993. It's a standards track protocol for the Internet community πŸ”₯. The header doesn't list anything it obsoletes or updates, so there's no drama there ✨.


Status of This Memo πŸ“œ

Okay so this RFC is an Internet standards track protocol for the whole Internet community, and it's literally asking for discussion and suggestions for improvements 🫢. For the official standardization state and status, go check the current edition of the "Internet Official Protocol Standards" πŸ’…. And the distribution of this memo is unlimited, so share it with everyone 🌈.


Abstract πŸ¦‹

Okay this is the core of it, and it's so iconic πŸ‘‘. The Generic Security Service Application Program Interface (GSS-API) gives callers security services in a generic way ✨. It can run on a bunch of different underlying mechanisms and technologies, which means applications can be ported at the source level to different environments 🧚. That's main character portability πŸ’….

The spec defines GSS-API services and primitives without depending on any particular underlying mechanism or programming language environment 🌸. It's also meant to be paired with other related specs, and there are two kinds πŸŽ€:

  • Documents that define specific parameter bindings for particular language environments πŸ’œ
  • Documents that define token formats, protocols, and procedures to be implemented in order to realize GSS-API services on top of particular security mechanisms πŸ”₯

Table of Contents πŸ—‚οΈ

   1. GSS-API Characteristics and Concepts .......................    2
   1.1. GSS-API Constructs .......................................    5
   1.1.1.  Credentials ...........................................    5
   1.1.2.  Tokens ................................................    6
   1.1.3.  Security Contexts .....................................    7
   1.1.4.  Mechanism Types .......................................    8
   1.1.5.  Naming ................................................    9
   1.1.6.  Channel Bindings ......................................   10
   1.2.  GSS-API Features and Issues .............................   11
   1.2.1.  Status Reporting ......................................   11
   1.2.2.  Per-Message Security Service Availability .............   12
   1.2.3.  Per-Message Replay Detection and Sequencing ...........   13
   1.2.4.  Quality of Protection .................................   15
   2. Interface Descriptions .....................................   15
   2.1.  Credential management calls .............................   17
   2.1.1.  GSS_Acquire_cred call .................................   17
   2.1.2.  GSS_Release_cred call .................................   19
   2.1.3.  GSS_Inquire_cred call .................................   20
   2.2.  Context-level calls .....................................   21
   2.2.1.  GSS_Init_sec_context call .............................   21
   2.2.2.  GSS_Accept_sec_context call ...........................   26
   2.2.3.  GSS_Delete_sec_context call ...........................   29
   2.2.4.  GSS_Process_context_token call ........................   30
   2.2.5.  GSS_Context_time call .................................   31
   2.3.  Per-message calls .......................................   32
   2.3.1.  GSS_Sign call .........................................   32
   2.3.2.  GSS_Verify call .......................................   33
   2.3.3.  GSS_Seal call .........................................   35
   2.3.4.  GSS_Unseal call .......................................   36
   2.4.  Support calls ...........................................   37
   2.4.1.  GSS_Display_status call ...............................   37
   2.4.2.  GSS_Indicate_mechs call ...............................   38
   2.4.3.  GSS_Compare_name call .................................   38
   2.4.4.  GSS_Display_name call .................................   39
   2.4.5.  GSS_Import_name call ..................................   40
   2.4.6.  GSS_Release_name call .................................   41
   2.4.7.  GSS_Release_buffer call ...............................   41
   2.4.8.  GSS_Release_oid_set call ..............................   42
   3. Mechanism-Specific Example Scenarios .......................   42
   3.1.  Kerberos V5, single-TGT .................................   43
   3.2.  Kerberos V5, double-TGT .................................   43
   3.3.  X.509 Authentication Framework ..........................   44
   4. Related Activities .........................................   45
   5. Acknowledgments ............................................   46
   6. Security Considerations ....................................   46
   7. Author's Address ...........................................   46
   Appendix A ....................................................   47
   Appendix B ....................................................   48
   Appendix C ....................................................   49

1. GSS-API Characteristics and Concepts ✨

okay so let's talk about how GSS-API actually works πŸ’… A typical GSS-API caller is itself a communications protocol, and it calls on GSS-API to protect its communications with authentication, integrity, and/or confidentiality security services πŸ” The caller takes tokens that its local GSS-API implementation hands over and sends them to a peer on a remote system. That peer passes the tokens it receives to its own local GSS-API implementation for processing πŸ¦‹ These security services can be built over a range of underlying mechanisms based on secret-key and public-key cryptographic technologies, and people have already done it, so it's not just a theory bestie 🌈

The GSS-API splits things up into separate jobs πŸ“ First there's setting up a security context between peers and achieving peer entity authentication (This security service definition, and other definitions used in this document, corresponds to that provided in International Standard ISO 7498-2-1988(E), Security Architecture.). That's done with GSS_Init_sec_context() and GSS_Accept_sec_context() calls. Then there's per-message data origin authentication and data integrity protection, which uses GSS_Sign() and GSS_Verify() calls for messages sent after that context exists ✨ The per-message GSS_Seal() and GSS_Unseal() calls give you the same data origin authentication and data integrity that GSS_Sign() and GSS_Verify() do, and they also let the caller pick confidentiality as an option πŸ”’ On top of all that, there are extra calls that just help the GSS-API's users out πŸ’œ

Let's walk through an example so you can see the dataflow, bestie πŸ‘‘ It's a client and a server, and it's mechanism-independent, so it works no matter which underlying mechanism is doing the work. They set up a security context and send a protected message. The example assumes credential acquisition has already been completed 🧚 It also assumes the underlying authentication technology can authenticate a client to a server using elements carried within a single token, and can authenticate the server back to the client (mutual authentication) with a single returned token. This is true for the CAT mechanisms that are presently documented, but it's not necessarily true for other cryptographic technologies and their protocols, so don't assume it everywhere πŸ™ˆ

The client calls GSS_Init_sec_context() to set up a security context to the server identified by targ_name. It sets the mutual_req_flag so mutual authentication happens during context establishment πŸŽ€ That call returns an output_token to send to the server, and it reports GSS_CONTINUE_NEEDED status because the mutual authentication sequence isn't finished yet. If mutual_req_flag hadn't been set, that very first call would have returned GSS_COMPLETE status instead. Then the client sends the output_token to the server 🌸

The server passes the received token in as the input_token parameter to GSS_Accept_sec_context(). That call gives back GSS_COMPLETE status, provides the client's authenticated identity in the src_name result, and gives an output_token to send back to the client. The server sends that output_token to the client πŸ’–

The client passes the received token as the input_token parameter to a successor call to GSS_Init_sec_context(). That call processes the data in the token so the client gets mutual authentication from its side ✨ This call returns GSS_COMPLETE status, which means mutual authentication worked and context establishment is done for this example. Slay πŸŽ‰

The client makes a data message and passes it to GSS_Seal(). GSS_Seal() does data origin authentication, data integrity, and (optionally) confidentiality processing on the message, then wraps the result up into output_message and returns GSS_COMPLETE status. The client sends that output_message to the server πŸ¦‹

The server passes the received message to GSS_Unseal(). GSS_Unseal undoes the wrapping that GSS_Seal() did, decrypts the message if the optional confidentiality feature was used, and checks the data origin authentication and data integrity values. If everything checks out, it returns GSS_COMPLETE status along with the resulting output_message πŸ’…

For this example, the server knows through out-of-band means that this context won't be used for anything after one protected message goes from client to server. Given that, the server calls GSS_Delete_sec_context() to flush the context-level information. That call returns a context_token for the server to pass to the client 🌈

The client passes the returned context_token to GSS_Process_context_token(). That returns GSS_COMPLETE status after the client system deletes its own context-level information ⭐

The GSS-API design has a few basic goals it's aiming for, and they're honestly iconic πŸ‘‘

  • Mechanism independence: The GSS-API gives you an interface to cryptographically implemented strong authentication and other security services at a generic level, so it doesn't depend on any particular underlying mechanism. For example, GSS-API-provided services can be implemented with secret-key technologies (e.g., Kerberos) or public-key approaches (e.g., X.509) πŸ”‘
  • Protocol environment independence: The GSS-API doesn't care which communications protocol suite it's used with, so it works in a broad range of protocol environments 🌍 In suitable environments, an intermediate implementation "veneer" that's oriented to a particular communication protocol (e.g., Remote Procedure Call (RPC)) can sit between the applications that call that protocol and the GSS-API. That way GSS-API facilities get invoked together with that protocol's communications 🧚
  • Protocol association independence: The GSS-API's security context construct is independent of communications protocol association constructs πŸ’œ This means one GSS-API implementation can be used by a variety of invoking protocol modules on behalf of their calling applications. GSS-API services can also be invoked directly by applications, completely independent of protocol associations πŸ¦‹
  • Suitability to a range of implementation placements: GSS-API clients don't have to live inside any Trusted Computing Base (TCB) perimeter defined on a system where the GSS-API is implemented. The security services are specified in a way that works for both intra-TCB and extra-TCB callers πŸŽ€

1.1. GSS-API Constructs

This section goes over the basic building blocks of the GSS-API 🧩

1.1.1. Credentials

Credentials structures are what let peers set up security contexts with each other πŸ” A caller can say that its default credential should be used for context establishment calls, without handing over an explicit handle to it. Or, if a caller needs to pick particular credentials structures on purpose, it can reference them through GSS-API-provided credential handles ("cred_handles") πŸ’–

A single credential structure can be used for both starting outbound contexts and accepting inbound ones 🌸 Callers that only need one of those modes can say so when the credentials are acquired, which lets the underlying mechanisms optimize their processing and storage. The credential elements a particular mechanism defines may contain multiple cryptographic keys, for example so that authentication and message encryption can use different algorithms ✨

A single credential structure can hold credential information for multiple underlying mechanisms (mech_types). What's inside a credential structure depends on the set of mech_types a particular GSS-API implementation supports πŸ“ Usually one mech_type gets used for all the security contexts a given initiator sets up with a given target. The main reason to support credential sets with multiple mech_types is so initiators on systems that can handle several types can start contexts with targets on other systems that only handle a subset of those types πŸ‘‘

Keeping credentials away from the wrong people is the job of the underlying system-specific mechanisms and OS functions below the GSS-API 🚨 They have to make sure that being able to acquire and use the credentials tied to an identity is limited to the right processes on a system. Implementors should take this seriously, bestie, because being able to use a principal's credentials is the same thing as being able to successfully claim that principal's identity πŸ’€

Once a set of GSS-API credentials exists, whether those credentials can be passed to other processes or similar constructs on the system is a local matter, and the GSS-API doesn't define it πŸ¦‹ One example of a local policy would be: any credentials received from logging into a given user account, or from someone delegating rights to that account, can be accessed by, or transferred to, processes running under that account πŸ’…

Credential establishment, especially when it's done for users instead of server processes, will probably need access to passwords or other sensitive stuff πŸ™ˆ That should be protected locally and exposed for as short a time as possible. So it's often a good idea to do the preliminary credential establishment locally at user login time, then cache the results for later use 🌈 Those preliminary credentials get set aside (in a system-specific way) for later use, either:

  • to be accessed by an invocation of the GSS-API GSS_Acquire_cred() call, which returns an explicit handle to reference that credential πŸ”‘
  • as the default credentials installed on behalf of a process ✨

1.1.2. Tokens ✨

okay so tokens are the data chunks GSS-API callers pass between each other, and there are two classes πŸ’Œ. Context-level tokens get exchanged to set up and manage a security context between peers 🀝. Per-message tokens get exchanged once a context is already up, to provide protective security services for the actual data messages πŸ”. The insides of both classes are specific to whichever underlying mechanism is powering the GSS-API. Appendix B gives mechanism designers a uniform recommendation for wrapping that mechanism-specific info together with a globally-interpretable mechanism identifier πŸŽ€.

Tokens are opaque from the caller's point of view πŸ™ˆ, so no peeking inside. They get generated within the GSS-API implementation at one end system, handed to the caller so they can be sent to the peer GSS-API caller at a remote end system, and then processed by the GSS-API implementation over there πŸš€. Tokens may be output by GSS-API primitives (and are to be transferred to GSS-API peers) independent of the status indications those primitives return, so a token can show up even when the status says something else πŸ‘€. Token transfer can happen in-band, folded into the same protocol stream the callers use for their other data 🌊, or out-of-band across a logically separate channel πŸ›€οΈ.

Building GSS-API support primitives on top of a particular cryptographic technique and protocol doesn't automatically mean that GSS-API callers using that mechanism type can interoperate with peers using the same technique and protocol outside the GSS-API paradigm πŸ™ƒ. For example, the format of GSS-API tokens defined for a particular mechanism, and the techniques used to fit those tokens into callers' protocols, may not match what non-GSS-API callers of the same underlying technique do. Plot twist, but it's real 😭.


1.1.3. Security Contexts

Security contexts get established between peers, using credentials set up locally with each peer or received by peers via delegation πŸ—οΈ. Multiple contexts can exist at the same time between a pair of peers, using the same or different sets of credentials πŸ‘―. Having multiple contexts with different credentials allows graceful rollover when credentials expire πŸŒ…. Telling apart multiple contexts that share the same credentials helps applications distinguish different message streams in a security sense 🧡.

The GSS-API is independent of underlying protocols and addressing structure, and it depends on its callers to transport the GSS-API-provided data elements πŸ“¦. Because of all that, it's the caller's job to parse communicated messages, separating GSS-API-related data elements from caller-provided data 🧹. The GSS-API doesn't care whether the underlying communications service is connection-oriented or connectionless πŸ™Œ.

No correlation between a security context and a communications protocol association is dictated πŸ’…. (The optional channel binding facility, discussed in Section 1.1.6 of this document, is an intentional exception to this rule, supporting additional protection features within GSS-API supporting mechanisms πŸ”“.) This separation lets the GSS-API be used in a wide range of communications environments, and it also simplifies the calling sequences of the individual calls ✨. In many cases (depending on underlying security protocol, associated mechanism, and availability of cached information), the state information needed for context setup can be sent concurrently with initial signed user data, without interposing additional message exchanges πŸš„. Efficient, bestie!


1.1.4. Mechanism Types

To successfully establish a security context with a target peer, you need to identify an appropriate underlying mechanism type (mech_type) that both the initiator and target peers support πŸ”. A mechanism is more than just a particular cryptographic technology (or a hybrid, or a choice among alternative cryptographic technologies). It also defines the syntax and semantics of the data element exchanges that mechanism uses to support security services πŸ“œ.

It's recommended that callers initiating contexts specify the "default" mech_type value 🌟, which lets system-specific functions within or invoked by the GSS-API implementation pick the appropriate mech_type. Callers can still direct that a particular mech_type be used when necessary 🎯.

How peers identify a shared mech_type to establish a security context will vary across environments and circumstances 🌍. Examples include (but are not limited to):

  • use of a fixed mech_type, defined by configuration, within an environment
  • syntactic convention on a target-specific basis, through examination of a target's name
  • lookup of a target's name in a naming service or other database in order to identify mech_types supported by that target
  • explicit negotiation between GSS-API callers in advance of security context setup

When transferred between GSS-API peers, mech_type specifiers (per Appendix B, represented as Object Identifiers (OIDs)) serve to qualify the interpretation of associated tokens 🏷️. (The structure and encoding of Object Identifiers is defined in ISO/IEC 8824, "Specification of Abstract Syntax Notation One (ASN.1)" and in ISO/IEC 8825, "Specification of Basic Encoding Rules for Abstract Syntax Notation One (ASN.1)".) Using hierarchically structured OIDs keeps mech_type specifiers from being interpreted ambiguously 🧠.

The OID representing the DASS MechType, for example, is 1.3.12.2.1011.7.5 πŸ¦‹.


1.1.5. Naming

The GSS-API avoids prescribing naming structures πŸ™…β€β™€οΈ. It treats the names transferred across the interface to initiate and accept security contexts as opaque octet string quantities. This supports the GSS-API's goal of being implementable on top of a range of underlying security mechanisms, since different mechanisms process and authenticate names presented in different forms 🌈. Generalized services that translate among arbitrary sets of naming environments are outside the scope of the GSS-API. Using local conversion functions to translate among the naming formats supported within a given end system is anticipated instead πŸ”§.

There are two distinct classes of name representations, used with different GSS-API parameters πŸ“‡:

  • a printable form (denoted by OCTET STRING), for acceptance from and presentation to users; printable name forms are accompanied by OID tags identifying the namespace to which they correspond
  • an internal form (denoted by INTERNAL NAME), opaque to callers and defined by individual GSS-API implementations; GSS-API implementations supporting multiple namespace types are responsible for maintaining internal tags to disambiguate the interpretation of particular names

Tagging printable names lets GSS-API callers and underlying GSS-API mechanisms tell name types apart and figure out whether a name's type is one they can process 🏷️. That avoids aliasing problems that could come from misreading a name of one type as a name of another type 😬.

Besides tagging names with types, this specification defines primitives that give certain calling applications a level of naming-environment independence 🌏. To provide basic services for callers who don't need to interpret the internal syntax and semantics of names themselves, the GSS-API defines calls for name comparison (GSS_Compare_name()), human-readable display (GSS_Display_name()), input conversion (GSS_Import_name()), and internal name deallocation (GSS_Release_name()) functions. (It's anticipated that these proposed GSS-API calls will be implemented in many end systems based on system-specific name manipulation primitives already present in those end systems. Including them in the GSS-API is meant to give callers a portable way to perform specific operations, supporting authorization and audit requirements, on authenticated names πŸ“‹.)

GSS_Import_name() implementations can, where appropriate, support more than one printable syntax for a given namespace (for example, alternative printable representations for X.500 Distinguished Names), giving callers flexibility to choose among alternative representations 🎨. GSS_Display_name() implementations output a printable syntax selected as appropriate to their operational environments, and that selection is a local matter 🏠. Callers who want portability across alternative printable syntaxes should refrain from implementing comparisons based on printable name forms. Instead, they should use the GSS_Compare_name() call to determine whether or not one internal-format name matches another πŸ’œ.


1.1.6. Channel Bindings

The GSS-API supports the concept of caller-provided channel binding (chan_binding) information πŸ”—. Callers use it to bind the establishment of a security context to relevant characteristics of the underlying communications channel (for example, addresses or transformed representations of encryption keys) and of protection mechanisms applied to that channel πŸ›‘οΈ. When one peer verifies the chan_binding information the other peer provided for a context, it protects against various active attacks 🚨. The caller initiating a security context must determine the chan_binding values before making the GSS_Init_sec_context() call, and consistent values must be provided by both peers to a context 🀝. Callers should not assume that underlying mechanisms provide confidentiality protection for channel binding information πŸ™ˆ.

Using the GSS-API channel binding facility is a caller option, and GSS-API supporting mechanisms can operate in an environment where NULL channel bindings are presented 🫢. When non-NULL channel bindings are used, certain mechanisms offer enhanced security value by interpreting the content of the bindings (rather than just representing those bindings, or signatures computed on them, within tokens). Those mechanisms will therefore depend on presentation of specific data in a defined format πŸ“. To this end, agreements among mechanism implementors are defining conventional interpretations for the contents of channel binding arguments, including address specifiers (with content dependent on the communications protocol environment) for context initiators and acceptors πŸ€“. (These conventions are being incorporated into related documents.) For GSS-API callers to be portable across multiple mechanisms and to get the full security functionality each mechanism offers, it is strongly recommended that they provide channel bindings consistent with these conventions and with those of the networking environment they operate in πŸ’–.


1.2. GSS-API Features and Issues

This section describes aspects of GSS-API operations and the security services the GSS-API provides, and it comments on design issues 🧩.

1.2.1. Status Reporting πŸŽ€

okay so every GSS-API call gives you back two status return values πŸ’… The first one is major_status, which is mechanism-independent, so it doesn't care what security mechanism is underneath. It gives you a generic way to drive your normal control flow, using codes like GSS_COMPLETE, GSS_FAILURE, and GSS_CONTINUE_NEEDED ✨ Table 1 lists every defined major_status code in one spot πŸ¦‹

Table 1: GSS-API Major Status Codes

      FATAL ERROR CODES

      GSS_BAD_BINDINGS             channel binding mismatch
      GSS_BAD_MECH                 unsupported mechanism requested
      GSS_BAD_NAME                 invalid name provided
      GSS_BAD_NAMETYPE             name of unsupported type provided
      GSS_BAD_STATUS               invalid input status selector
      GSS_BAD_SIG                  token had invalid signature
      GSS_CONTEXT_EXPIRED          specified security context expired
      GSS_CREDENTIALS_EXPIRED      expired credentials detected
      GSS_DEFECTIVE_CREDENTIAL     defective credential detected
      GSS_DEFECTIVE_TOKEN          defective token detected
      GSS_FAILURE                  failure, unspecified at GSS-API
                                   level
      GSS_NO_CONTEXT               no valid security context specified
      GSS_NO_CRED                  no valid credentials provided

      INFORMATORY STATUS CODES

      GSS_COMPLETE                 normal completion
      GSS_CONTINUE_NEEDED          continuation call to routine
                                   required
      GSS_DUPLICATE_TOKEN          duplicate per-message token
                                   detected
      GSS_OLD_TOKEN                timed-out per-message token
                                   detected
      GSS_UNSEQ_TOKEN              out-of-order per-message token
                                   detected

minor_status gives more detailed info, and it can include codes that belong to the underlying security mechanism 🧚 minor_status values aren't specified in this document, so no spoilers from me πŸ™ˆ

this part is so clever tbh: GSS_CONTINUE_NEEDED and the optional message outputs come back from GSS_Init_sec_context() and GSS_Accept_sec_context() πŸ’– That way, mechanisms can use different numbers of messages in their authentication sequences without your app needing separate code paths for each one ✨ You just keep making continuation calls to GSS_Init_sec_context() and GSS_Accept_sec_context(). Mutual authentication gets folded into that same mechanism during the context initiation calls 🫢

some mech_types need to talk to third-party servers before a security context can be set up, so context establishment calls may block until those third-party chats finish ⏳ But no GSS-API calls wait on serialized interactions with GSS-API peer entities πŸ’… That means local status returns can't reflect unpredictable or asynchronous exceptions happening at remote peers πŸ’€ Passing that info along is the caller's job, outside the GSS-API πŸ‘‘


1.2.2. Per-Message Security Service Availability 🌸

when a context is established, two flags come back telling you which per-message protection security services will be available on that context πŸ¦‹

  • the integ_avail flag indicates whether per-message integrity and data origin authentication services are available
  • the conf_avail flag indicates whether per-message confidentiality services are available, and will never be returned TRUE unless the integ_avail flag is also returned TRUE

callers who want per-message security services should check these flags at context establishment time, and they must be aware that a returned FALSE value for integ_avail means that calling GSS_Sign() or GSS_Seal() on the associated context will apply no cryptographic protection to user data messages 😭πŸ”₯

The per-message protection service primitives are, like the category name says, built for operating at the granularity of protocol data units πŸŽ€ They do crypto on the data units, move the control info in tokens, and in the case of GSS_Seal(), they even wrap up the protected data unit πŸ“

So they're not really built for efficient data protection for stream-paradigm protocols (like Telnet) if cryptography has to be applied on an octet-by-octet basis πŸ™ˆ


1.2.3. Per-Message Replay Detection and Sequencing πŸ”₯

some underlying mech_types are expected to support replay detection and/or sequencing of messages transferred on their contexts 🌈 These optional protection features are separate from the replay detection and sequencing applied to the context establishment operation itself πŸ’« Whether a context has context-level replay or sequencing features is totally a function of the underlying mech_type's capabilities, and it's not something you pick as a caller option πŸ™…β€β™€οΈ

the caller initiating a context provides the flags replay_det_req_flag and sequence_req_flag to say whether they want per-message replay detection and sequencing on the context being established πŸ™Œ The GSS-API implementation at the initiator system can figure out whether these features are supported (and whether they're optionally selectable) based on mech_type, with no bilateral negotiation with the target needed πŸ’– When enabled, recipients get indicators from GSS-API processing of incoming messages saying whether those messages were detected as duplicates or out-of-sequence πŸ‘€ Detecting these doesn't stop a suspect message from reaching the recipient. What to do with it is a matter of caller policy 🫢

here's how the replay and sequencing services look to clients across the GSS-API interface:

When replay_det_state is TRUE, the possible major_status returns for well-formed and correctly signed messages are:

  1. GSS_COMPLETE means the message was inside the window (of time or sequence space) where replay events can be detected, and it wasn't a replay of a previously-processed message within that window βœ…
  2. GSS_DUPLICATE_TOKEN means the signature on the received message was correct, but the message was recognized as a duplicate of a previously-processed message πŸ‘―
  3. GSS_OLD_TOKEN means the signature on the received message was correct, but the message is too old to be checked for duplication ⏰

When sequence_state is TRUE, the possible major_status returns for well-formed and correctly signed messages are:

  1. GSS_COMPLETE means the message was inside the window (of time or sequence space) where replay events can be detected, and it wasn't a replay of a previously-processed message within that window βœ…
  2. GSS_DUPLICATE_TOKEN means the signature on the received message was correct, but the message was recognized as a duplicate of a previously-processed message πŸ‘―
  3. GSS_OLD_TOKEN means the signature on the received message was correct, but the token is too old to be checked for duplication ⏰
  4. GSS_UNSEQ_TOKEN means the signature on the received message was correct, but it's earlier in a sequenced stream than a message already processed on the context πŸŒ€
[Note: Mechanisms can be architected to provide a stricter form of sequencing service, delivering particular messages to recipients only after all predecessor messages in an ordered stream have been delivered. This type of support is incompatible with the GSS-API paradigm in which recipients receive all messages, whether in order or not, and provide them (one at a time, without intra-GSS-API message buffering) to GSS-API routines for validation. GSS-API facilities provide supportive functions, aiding clients to achieve strict message stream integrity in an efficient manner in conjunction with sequencing provisions in communications protocols, but the GSS-API does not offer this level of message stream integrity service by itself.]

the message stream integrity features (especially sequencing) can interfere with certain applications' intended communications paradigms, and support for them is likely to be resource intensive 😀 So it is highly recommended that mech_types supporting these features allow them to be activated selectively on initiator request when a context is established πŸ™ A context initiator and target get corresponding indicators (replay_det_state and sequence_state) showing whether these features are active on a given context 🎯

an example mech_type that supports per-message replay detection could (when replay_det_state is TRUE) do it like this 🧁 The underlying mechanism would insert timestamps in the data elements output by GSS_Sign() and GSS_Seal(), and it would keep a cache (qualified by originator-recipient pair) of received data elements processed by GSS_Verify() and GSS_Unseal(), maintained within a time-limited window ⏳ When this feature is active, the exception status returns (GSS_DUPLICATE_TOKEN, GSS_ OLD_TOKEN) get provided whenever GSS_Verify() or GSS_Unseal() is handed a message that's either a detected duplicate of a prior message or too old to validate against the cache of recently received messages πŸ’…


1.2.4. Quality of Protection πŸ’œ

some mech_types give their users fine-grained control over the means used to provide per-message protection 🍬 That lets callers trade off security processing overhead on the fly against the protection needs of particular messages πŸ”₯ A per-message quality-of-protection parameter (basically quality-of-service, or QOS) picks among the different QOP options that mechanism supports 🎚️ On context establishment for a multi-QOP mech_type, the context-level data provides the prerequisite data for that whole range of protection qualities 🌈

Most callers won't want explicit mechanism-specific QOP control, so it's expected they'll just request the default QOP 🫧 Definitions of non-default QOP values, and the choices among them, are mechanism-specific, and no ordered sequences of QOP values can be assumed equivalent across different mechanisms πŸ™ˆ Using non-default QOP values means callers have to know the QOP definitions of the underlying mechanism or mechanisms, which makes it a non-portable construct πŸ’€

2. Interface Descriptions ✨

okay so this section is the GSS-API's service interface, and it sorts every call into four groups πŸ’…. Credential management is about getting and dropping creds 🎫. Context-level calls set up and tear down security contexts between principals 🀝. Per-message calls protect individual messages once a context is up πŸ“¨. Support calls are the handy helpers 🧰. Table 2 is the whole squad in one glance:

      Table 2:  GSS-API Calls

      CREDENTIAL MANAGEMENT

      GSS_Acquire_cred             acquire credentials for use
      GSS_Release_cred             release credentials after use
      GSS_Inquire_cred             display information about
                                   credentials

      CONTEXT-LEVEL CALLS

      GSS_Init_sec_context         initiate outbound security context
      GSS_Accept_sec_context       accept inbound security context
      GSS_Delete_sec_context       flush context when no longer needed
      GSS_Process_context_token    process received control token on
                                   context
      GSS_Context_time             indicate validity time remaining on
                                   context

      PER-MESSAGE CALLS

      GSS_Sign                     apply signature, receive as token
                                   separate from message
      GSS_Verify                   validate signature token along with
                                   message
      GSS_Seal                     sign, optionally encrypt,
                                   encapsulate
      GSS_Unseal                   decapsulate, decrypt if needed,
                                   validate signature

      SUPPORT CALLS

      GSS_Display_status           translate status codes to printable
                                   form
      GSS_Indicate_mechs           indicate mech_types supported on
                                   local system
      GSS_Compare_name             compare two names for equality
      GSS_Display_name             translate name to printable form
      GSS_Import_name              convert printable name to
                                   normalized form
      GSS_Release_name             free storage of normalized-form
                                   name
      GSS_Release_buffer           free storage of printable name
      GSS_Release_oid_set          free storage of OID set object

2.1. Credential management calls

these calls handle the management of credentials πŸ”. Whether they might block while waiting on other network entities (like directories or authentication servers) depends partly on OS-specific, extra-GSS-API stuff, so this document doesn't pin it down πŸ™ˆ.

GSS_Acquire_cred() is defined in GSS-API for application portability, with a big focus on portable server apps πŸ–₯️. It's recognized that, for certain systems and mechanisms, creds for interactive users can be managed differently from creds for server processes. In those environments, it's the GSS-API implementation's job to tell these cases apart, and how it does that is a local matter 🏠. GSS_Release_cred() gives callers a way to tell the GSS-API they don't need a creds structure anymore πŸ‘‹. GSS_Inquire_cred() lets callers find out info about a creds structure πŸ”.

2.1.1. GSS_Acquire_cred call

Inputs:

  • desired_name INTERNAL NAME, -NULL requests locally-determined default
  • lifetime_req INTEGER,-in seconds; 0 requests default
  • desired_mechs SET OF OBJECT IDENTIFIER,-empty set requests system-selected default
  • cred_usage INTEGER-0=INITIATE-AND-ACCEPT, 1=INITIATE-ONLY, 2=ACCEPT-ONLY

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • output_cred_handle OCTET STRING,
  • actual_mechs SET OF OBJECT IDENTIFIER,
  • lifetime_rec INTEGER -in seconds, or reserved value for INDEFINITE

Return major_status codes:

  • GSS_COMPLETE means the creds were successfully established βœ…. They last for the duration in lifetime_rec, work for the usage in cred_usage, and cover the mech_types listed in actual_mechs. You can refer to them later using the handle in output_cred_handle.
  • GSS_BAD_MECH means a mech_type the GSS-API implementation doesn't support was requested, so creds couldn't be set up πŸ’€.
  • GSS_BAD_NAMETYPE means desired_name is either uninterpretable or a type the GSS-API implementation doesn't support, so no creds could be made for it πŸ™….
  • GSS_BAD_NAME means desired_name doesn't match up with its own internal type specifier info, so again, no creds 😭.
  • GSS_FAILURE means creds failed to set up for reasons not specified at the GSS-API level. This includes not being authorized to establish and use creds for the identity named in desired_name 🚫.

GSS_Acquire_cred() is how a principal grabs creds so it can initiate and/or accept security contexts (depending on cred_usage) under the identity in desired_name πŸŽ€. On success, output_cred_handle is your handle for referring back to those creds later. Honestly though, single-user client processes that only use default creds for context establishment usually don't need this call at all πŸ’.

If you pass NULL for desired_name, you're asking for creds for a default principal identity πŸͺͺ. How the GSS-API picks that identity is a local matter. Multiple pre-established creds might exist for the same identity (like from several login sessions) when you call GSS_Acquire_cred(), and how it picks one is also local. lifetime_req can help the implementation make that call in a way that best matches what you want 🎯.

lifetime_rec tells you how long the acquired creds will be valid, as an offset from now ⏳. A mechanism can return a reserved value meaning INDEFINITE if it doesn't put any limits on lifetime ♾️. You can ask for a specific validity period starting now with lifetime_req, or you can just take the default interval. (Postdated creds aren't supported in GSS-API, sorry bestie πŸ™….) Some mechanisms and implementations lock in validity periods before you ever call this, like during user login, so asking for a non-default lifetime_req can't always be honored 😬. So you have to be ready to use creds with a different lifetime than you asked for, which will be shown in lifetime_rec.

You can explicitly list the mech_types you want in the returned creds with desired_mechs, or ask for the system's default set. Going with the system-selected default is recommended for app portability 🫢. Check actual_mechs to see which mechanisms the returned creds can actually be used with.

2.1.2. GSS_Release_cred call

Input:

  • cred_handle OCTET STRING-NULL specifies default credentials

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER

Return major_status codes:

  • GSS_COMPLETE means the creds referenced by cred_handle were released, so the caller can't use them anymore πŸ‘‹. What happens to other authorized processes that share those creds is a local matter.
  • GSS_NO_CRED means nothing got released, either because cred_handle was invalid or because the caller isn't authorized to access those creds πŸ™….
  • GSS_FAILURE means the release failed for reasons not specified at the GSS-API level πŸ’”.

This call lets a caller explicitly ask for creds to be released once they're no longer needed 🧹. Heads up, though: system-specific cred management functions probably exist too. For example, they make sure shared creds get deleted when all the affected processes have ended, even if nobody explicitly released them. Since multiple callers can be authorized to access the same creds, calling GSS_Release_cred() can't be assumed to delete a particular set of creds across the whole system 🌍.

2.1.3. GSS_Inquire_cred call

Input:

  • cred_handle OCTET STRING -NULL specifies default credentials

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • cred_name INTERNAL NAME,
  • lifetime_rec INTEGER -in seconds, or reserved value for INDEFINITE
  • cred_usage INTEGER, -0=INITIATE-AND-ACCEPT, 1=INITIATE-ONLY, 2=ACCEPT-ONLY
  • mech_set SET OF OBJECT IDENTIFIER

Return major_status codes:

  • GSS_COMPLETE means the creds referenced by cred_handle are valid ✨. The output cred_name, lifetime_rec, and cred_usage values give you, in order, the creds' associated principal name, remaining lifetime, suitable usage modes, and supported mechanism types.
  • GSS_NO_CRED means no info could be returned about those creds, either because cred_handle was invalid or because the caller isn't authorized to access them πŸ™ˆ.
  • GSS_FAILURE means the operation failed for reasons not specified at the GSS-API level 😞.

GSS_Inquire_cred() is mainly for callers who use default creds instead of getting them explicitly with GSS_Acquire_cred() 🎯. It lets you check a creds structure's principal name, how much validity is left, whether it can be used to initiate and/or accept security contexts, and which mechanisms it supports. Main character energy for default-creds callers πŸ‘‘.


2.2. Context-level calls ✨

okay so this whole group is all about setting up and managing security contexts between peers πŸ’– The initiator calls GSS_Init_sec_context(), which spits out a token that the caller hands over to the target. On the target side, that token gets fed into GSS_Accept_sec_context() πŸ¦‹ Depending on the underlying mech_type and the options you picked, there might be extra token exchanges during setup. Those get handled through GSS_CONTINUE_NEEDED status returns from GSS_Init_sec_context() and GSS_Accept_sec_context() πŸ”

Either party to an established context can call GSS_Delete_sec_context() to flush the context info once it's no longer needed 🧹 GSS_Process_context_token() is for processing received tokens that carry context-level control information πŸŽ€ And GSS_Context_time() lets you check how long an established context will stay valid ⏳ it's giving organized, honestly 😭

2.2.1. GSS_Init_sec_context call πŸ’…

Inputs:

  • claimant_cred_handle OCTET STRING: NULL specifies "use default" 🌸
  • input_context_handle INTEGER: 0 specifies "none assigned yet" 🧚
  • targ_name INTERNAL NAME
  • mech_type OBJECT IDENTIFIER: a NULL parameter specifies "use default"
  • deleg_req_flag BOOLEAN
  • mutual_req_flag BOOLEAN
  • replay_det_req_flag BOOLEAN
  • sequence_req_flag BOOLEAN
  • lifetime_req INTEGER: 0 specifies default lifetime ⏰
  • chan_bindings OCTET STRING
  • input_token OCTET STRING: NULL, or a token received from the target

Outputs:

  • major_status INTEGER
  • minor_status INTEGER
  • output_context_handle INTEGER
  • mech_type OBJECT IDENTIFIER: the actual mechanism is always indicated, never NULL πŸ‘‘
  • output_token OCTET STRING: NULL, or a token to pass to the context target
  • deleg_state BOOLEAN
  • mutual_state BOOLEAN
  • replay_det_state BOOLEAN
  • sequence_state BOOLEAN
  • conf_avail BOOLEAN
  • integ_avail BOOLEAN
  • lifetime_rec INTEGER: in seconds, or a reserved value for INDEFINITE ♾️

This call might block while it waits on network interactions 🫠 That happens for those mech_types where an authentication server or some other network entity has to be consulted on behalf of the context initiator, so it can generate an output_token that's suitable for presenting to the specified target.

Return major_status codes:

  • GSS_COMPLETE means the context-level info was set up successfully, and the returned output_token gives the target enough info to do per-message processing on the newly established context πŸŽ‰
  • GSS_CONTINUE_NEEDED means the control info in the returned output_token has to be sent to the target, and a reply has to come back and get passed in as the input_token argument to a continuation call to GSS_Init_sec_context(). Only after that can per-message processing happen with this context πŸ”
  • GSS_DEFECTIVE_TOKEN means the consistency checks on the input_token failed, so no further processing based on that token 🚫
  • GSS_DEFECTIVE_CREDENTIAL means the consistency checks on the credential structure referenced by claimant_cred_handle failed, so no further processing with that credential structure πŸ™…β€β™€οΈ
  • GSS_BAD_SIG means the received input_token has an incorrect signature, so context setup can't be done πŸ’€
  • GSS_NO_CRED means no context got established. That could be because the input cred_handle was invalid, because the credentials are only valid for context acceptor use, or because the caller isn't authorized to access those credentials πŸ”
  • GSS_CREDENTIALS_EXPIRED means the credentials passed in through claimant_cred_handle are no longer valid, so context establishment can't finish βŒ›
  • GSS_BAD_BINDINGS means there's a mismatch between the caller-provided chan_bindings and the ones pulled out of the input_token. That's a security-relevant event, and it stops context establishment 🚨 (This result is only returned by GSS_Init_sec_context for contexts where mutual_state is TRUE.)
  • GSS_NO_CONTEXT means no valid context was recognized for the input context_handle provided. This major status only shows up for successor calls following GSS_CONTINUE_NEEDED returns 🧐
  • GSS_BAD_NAMETYPE means the provided targ_name has a type that's either uninterpretable or unsupported by the GSS-API implementation, so context establishment can't finish πŸ™ƒ
  • GSS_BAD_NAME means the provided targ_name is inconsistent in terms of its internally-incorporated type specifier info, so context establishment can't be done 😡
  • GSS_FAILURE means context setup couldn't be done for reasons that aren't specified at the GSS-API level, and there's no interface-defined recovery action available πŸ’”

This routine is used by a context initiator, and it usually emits one output_token (or, for a multi-step exchange, more than one) that the target can use inside the selected mech_type's protocol πŸ§ƒ Using the info in the credentials structure referenced by claimant_cred_handle, GSS_Init_sec_context() sets up the data structures it needs to establish a security context with the target targ_name πŸŽ€ The claimant_cred_handle has to point to the same valid credentials structure on the first GSS_Init_sec_context() call and on any successor calls from GSS_CONTINUE_NEEDED returns. Different protocol sequences modeled by the GSS_CONTINUE_NEEDED mechanism need access to credentials at different points in the context establishment sequence, so this matters πŸ”‘

The input_context_handle argument is 0, meaning "not yet assigned," on the first GSS_Init_sec_context() call for a given context. That call returns an output_context_handle for future references to this context πŸͺͺ When continuation attempts to GSS_Init_sec_context() are needed to finish context establishment, the handle value returned earlier (which is non-zero) gets entered into input_context_handle, and it'll be echoed back in the returned output_context_handle πŸ”„ Only on those continuation attempts (and only on them) is the input_token value used, to provide the token returned from the context's target πŸ“¨

The chan_bindings argument is how the caller provides info that binds the security context to security-related characteristics of the underlying communications channel, like addresses or cryptographic keys πŸ”— See Section 1.1.6 of this document for more discussion of how this argument gets used πŸ“–

The input_token argument holds a message received from the target, and it only matters on a GSS_Init_sec_context() call that follows an earlier return with a GSS_CONTINUE_NEEDED major_status πŸ’Œ

It's the caller's job to set up a communications path to the target, and to send any returned output_token to the target over that path. This is true no matter what major_status came back with πŸ›£οΈ The output_token can also be sent along with the first application-provided input message that gets processed by GSS_Sign() or GSS_Seal() in conjunction with a successfully established context πŸš€

The initiator can ask for various context-level functions through input flags πŸ™‹β€β™€οΈ deleg_req_flag requests delegation of access rights, mutual_req_flag requests mutual authentication, replay_det_req_flag requests that replay detection features get applied to messages transferred on the established context, and sequence_req_flag requests that sequencing be enforced. (See Section 1.2.3 for more info on replay detection and sequencing features πŸ”)

Not every optional feature will be available in every mech_type ⚠️ That's why the return state values (deleg_state, mutual_state, replay_det_state, sequence_state) tell you which features will actually be active on the context. They depend on the mech_type's processing capabilities and on the flags the initiator passed in 🎚️ Those state values are undefined unless the routine's major_status indicates COMPLETE. Not getting the exact feature set you asked for does not make context establishment fail. If the feature set isn't suitable for your use, deleting the context is your call to make 🫢 The returned mech_type tells you which mechanism got used on the context, and it will never be the value for "default" πŸ™Œ

The conf_avail return value says whether the context supports per-message confidentiality services. That tells the caller whether a request for encryption through the conf_req_flag input to GSS_Seal() can actually be honored πŸ” In the same way, integ_avail says whether per-message integrity services are available (through either GSS_Sign() or GSS_Seal()) on the established context 🧷

The lifetime_req input is the desired upper bound for the lifetime of the context being set up, and a value of 0 asks for a default lifetime ⏳ The lifetime_rec return value is how long the context will be valid, expressed as an offset from the present. Depending on mechanism capabilities, credential lifetimes, and local policy, it might not match the value you requested in lifetime_req πŸ™ˆ If no constraints on context lifetime are imposed, that can be shown by returning a reserved value that represents INDEFINITE lifetime ♾️ The values of conf_avail, integ_avail, and lifetime_rec are undefined unless the routine's major_status indicates COMPLETE 🫠

If mutual_state is TRUE, that fact gets reflected within the output_token 🀝 A call to GSS_Accept_sec_context() at the target, for a context like that, will return a token. That token gets processed by a continuation call to GSS_Init_sec_context() in order to achieve mutual authentication πŸ’œ

2.2.2. GSS_Accept_sec_context call πŸ’–

okay bestie, this is the call the receiving side makes, so it's basically the context target's big moment 🧚

Inputs:

  • acceptor_cred_handle OCTET STRING, NULL specifies "use default"
  • input_context_handle INTEGER, 0 specifies "not yet assigned"
  • chan_bindings OCTET STRING
  • input_token OCTET STRING

Outputs:

  • major_status INTEGER
  • minor_status INTEGER
  • src_name INTERNAL NAME
  • mech_type OBJECT IDENTIFIER
  • output_context_handle INTEGER
  • deleg_state BOOLEAN
  • mutual_state BOOLEAN
  • replay_det_state BOOLEAN
  • sequence_state BOOLEAN
  • conf_avail BOOLEAN
  • integ_avail BOOLEAN
  • lifetime_rec INTEGER - in seconds, or reserved value for INDEFINITE
  • delegated_cred_handle OCTET STRING
  • output_token OCTET STRING - NULL or token to pass to context initiator

This call might sit there waiting on network stuff πŸ•°οΈ for those mech_types where a directory service or some other network entity has to be checked on behalf of the context acceptor, so it can validate the input_token it got.

Return major_status codes:

  • GSS_COMPLETE means the context-level data structures got set up successfully, and per-message processing can now happen with this context βœ…
  • GSS_CONTINUE_NEEDED means the control info in the returned output_token has to go back to the initiator, and a response has to come back and be passed in as the input_token to a continuation call to GSS_Accept_sec_context(). Only then can per-message processing happen with this context πŸ”
  • GSS_DEFECTIVE_TOKEN means the consistency checks on the input_token failed, so no further processing based on that token 🚫
  • GSS_DEFECTIVE_CREDENTIAL means the consistency checks on the credential structure referenced by acceptor_cred_handle failed, so no further processing with that credential structure 🚫
  • GSS_BAD_SIG means the received input_token has an incorrect signature, so context setup can't be done πŸ™…β€β™€οΈ
  • GSS_DUPLICATE_TOKEN means the signature on the input_token was correct, but the token got recognized as a duplicate of one already processed. No new context is established πŸ‘―
  • GSS_OLD_TOKEN means the signature was correct, but the input_token is too old to be checked for duplication against previously-processed tokens. No new context is established πŸ•ΈοΈ
  • GSS_NO_CRED means no context was established, either because the input cred_handle was invalid, because the referenced credentials are only valid for context initiator use, or because the caller isn't authorized to access those credentials πŸ”’
  • GSS_CREDENTIALS_EXPIRED means the credentials given through acceptor_cred_handle are no longer valid, so context establishment can't be completed ⏰
  • GSS_BAD_BINDINGS means the caller-provided chan_bindings didn't match the ones pulled out of the input_token. That's a security-relevant event, and it stops context establishment 🚨
  • GSS_NO_CONTEXT means no valid context was recognized for the input context_handle. This status only shows up on successor calls after a GSS_CONTINUE_NEEDED return πŸ«₯
  • GSS_FAILURE means context setup couldn't be done for reasons not specified at the GSS-API level, and there's no interface-defined recovery action available πŸ’€

The GSS_Accept_sec_context() routine is used by a context target. It uses the info in the credentials structure referenced by the input acceptor_cred_handle to verify the incoming input_token. Then, once the context establishment sequence finishes successfully, it returns the authenticated src_name and the mech_type that got used. The acceptor_cred_handle has to point to the same valid credentials structure on the first call to GSS_Accept_sec_context() and on any successor calls coming from GSS_CONTINUE_NEEDED returns. Different protocol sequences modeled by the GSS_CONTINUE_NEEDED mechanism need credentials at different points in the context establishment sequence, so it's a whole thing πŸŽ€

The input_context_handle argument is 0, meaning "not yet assigned", on the first GSS_Accept_sec_context() call for a given context. That call returns an output_context_handle for future references to this context. When continuation attempts to GSS_Accept_sec_context() are needed to finish context establishment, that handle value gets entered into the input_context_handle argument 🧩

The chan_bindings argument is how the caller provides information that binds the security context to security-related characteristics (e.g., addresses, cryptographic keys) of the underlying communications channel. See Section 1.1.6 of this document for more discussion of how this argument gets used πŸ”—

The returned state results (deleg_state, mutual_state, replay_det_state, and sequence_state) reflect the same context state values that get returned to the GSS_Init_sec_context() caller at the initiator system πŸͺž

The conf_avail return value tells the caller whether the context supports per-message confidentiality services. So it lets the caller know if a request for encryption through the conf_req_flag input to GSS_Seal() can be honored πŸ”. In a similar way, integ_avail tells the caller whether per-message integrity services are available (through either GSS_Sign() or GSS_Seal()) on the established context ✨

The lifetime_rec return value shows how long the context will be valid, written as an offset from the present ⏳. The values of deleg_state, mutual_state, replay_det_state, sequence_state, conf_avail, integ_avail, and lifetime_rec are undefined unless the accompanying major_status indicates COMPLETE πŸ™ˆ

The delegated_cred_handle result only matters when deleg_state is TRUE, and it gives the target a way to reference the delegated credentials 🫢. The output_token result, when it isn't NULL, is a context-level token that goes back to the context initiator so a multi-step context establishment sequence can continue 🧢. Like we saw with GSS_Init_sec_context(), any returned token should be transferred to the context's peer (in this case, the context initiator), no matter what the accompanying returned major_status is πŸ“¬

Note: A target has to be able to tell apart a context-level input_token, which gets passed to GSS_Accept_sec_context(), from the per-message data elements passed to GSS_Verify() or GSS_Unseal(). These data elements might arrive in a single application message, and GSS_Accept_sec_context() has to be performed before per-message processing can work successfully πŸ‘€

2.2.3. GSS_Delete_sec_context call πŸ—‘οΈ

Input:

  • context_handle INTEGER

Outputs:

  • major_status INTEGER
  • minor_status INTEGER
  • output_context_token OCTET STRING

Return major_status codes:

  • GSS_COMPLETE means the context was recognized, the relevant context-specific info got flushed, and the returned output_context_token is ready to go to the context's peer 🧹
  • GSS_NO_CONTEXT means no valid context was recognized for the input context_handle provided, so no deletion happened πŸ€·β€β™€οΈ
  • GSS_FAILURE means the context is recognized, but GSS_Delete_sec_context() couldn't be performed for reasons not specified at the GSS-API level 😩

This call might block pending network interactions for mech_types where active notification has to be sent to a central server when a security context is about to be deleted 🌐

This call can be made by either peer in a security context. It flushes context-specific info and returns an output_context_token, which can be passed to the context's peer to let it know that the peer's matching context info can be flushed too πŸ’…. (Once a context is established, the peers involved are expected to keep cached credential and context-related info until the info's expiration time is reached or until a GSS_Delete_sec_context() call is made.) Attempts to do per-message processing on a deleted context will return errors 🚫


2.2.4. GSS_Process_context_token call 🧾

Inputs:

  • context_handle INTEGER,
  • input_context_token OCTET STRING

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,

Return major_status codes:

  • GSS_COMPLETE means the input_context_token got processed successfully in conjunction with the context referenced by context_handle πŸŽ‰
  • GSS_DEFECTIVE_TOKEN means the consistency checks on the received context_token failed, so no further processing with that token 🚫
  • GSS_NO_CONTEXT means no valid context was recognized for the input context_handle provided πŸ«₯
  • GSS_FAILURE means the context is recognized, but GSS_Process_context_token() couldn't be performed for reasons not specified at the GSS-API level 😭

This call processes context_tokens received from a peer once a context has been established, and it has a matching impact on the context-level state info 🧠. One use for this is processing the context_tokens generated by GSS_Delete_sec_context(). GSS_Process_context_token() won't block pending network interactions for that purpose πŸƒβ€β™€οΈ. Another use is processing tokens that signal remote-peer context establishment failures after the local GSS-API implementation has already returned GSS_COMPLETE status πŸ™ˆ


2.2.5. GSS_Context_time call ⏰

Input:

  • context_handle INTEGER,

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • lifetime_rec INTEGER - in seconds, or reserved value for INDEFINITE

Return major_status codes:

  • GSS_COMPLETE means the referenced context is valid, and it'll stay valid for the amount of time shown in lifetime_rec πŸ¦‹
  • GSS_CONTEXT_EXPIRED means data items related to the referenced context have expired πŸ’”
  • GSS_CREDENTIALS_EXPIRED means the context is recognized, but its associated credentials have expired πŸ₯€
  • GSS_NO_CONTEXT means no valid context was recognized for the input context_handle provided πŸ«₯
  • GSS_FAILURE means the requested operation failed for reasons not specified at the GSS-API level 😡

This call is used to figure out how long a currently established context will stay valid. It's giving timekeeping realness βŒ›πŸŒΈ

2.3. Per-message calls ✨

Okay bestie, this group is all about per-message protection once a security context is already set up πŸ” None of these calls block while waiting on network interactions πŸ™…β€β™€οΈ They can be invoked by a context's initiator or by its target, so either side can use them πŸ’… The four calls come in two pairs: whatever GSS_Sign() spits out is what GSS_Verify() wants, and whatever GSS_Seal() outputs is what GSS_Unseal() takes in πŸ“

GSS_Sign() and GSS_Verify() handle data origin authentication and data integrity βœ… When you run GSS_Sign() on a message, you get back a per-message token full of data items that let the underlying mechanisms provide the requested services. You send the original message and that token to the remote peer, and then GSS_Verify() checks the message against the separate token πŸ•΅οΈβ€β™€οΈ

GSS_Seal() and GSS_Unseal() do everything the sign and verify pair does, plus confidentiality if the caller asks for it πŸ”’ GSS_Seal() gives you one single data element that wraps up the user data (optionally enciphered) along with its token data items πŸŽ€ That element goes to the peer, who runs GSS_Unseal() on it. GSS_Unseal() handles the decryption (when it's needed) and checks the integrity and authentication stuff too πŸ’–

2.3.1. GSS_Sign call

Inputs:

  • context_handle INTEGER,
  • qop_req INTEGER,-0 specifies default QOP
  • message OCTET STRING

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • per_msg_token OCTET STRING

Return major_status codes:

  • GSS_COMPLETE indicates that a signature, suitable for an established security context, was successfully applied and that the message and corresponding per_msg_token are ready for transmission. πŸŽ‰
  • GSS_CONTEXT_EXPIRED indicates that context-related data items have expired, so that the requested operation cannot be performed. 😭
  • GSS_CREDENTIALS_EXPIRED indicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. πŸ₯€
  • GSS_NO_CONTEXT indicates that no valid context was recognized for the input context_handle provided. πŸ™ˆ
  • GSS_FAILURE indicates that the context is recognized, but that the requested operation could not be performed for reasons unspecified at the GSS-API level. πŸ’€

Using the security context referenced by context_handle, apply a signature to the input message (along with timestamps and/or other data included in support of mech_type-specific mechanisms) and return the result in per_msg_token. The qop_req parameter allows quality-of-protection control. The caller passes the message and the per_msg_token to the target.

The GSS_Sign() function completes before the message and per_msg_token is sent to the peer. Successful application of GSS_Sign() does not guarantee that a corresponding GSS_Verify() has been (or can necessarily be) performed successfully when the message arrives at the destination. So don't assume it's all good just because the signing worked πŸ‘€

2.3.2. GSS_Verify call

Inputs:

  • context_handle INTEGER,
  • message OCTET STRING,
  • per_msg_token OCTET STRING

Outputs:

  • qop_state INTEGER,
  • major_status INTEGER,
  • minor_status INTEGER,

Return major_status codes:

  • GSS_COMPLETE indicates that the message was successfully verified. βœ…
  • GSS_DEFECTIVE_TOKEN indicates that consistency checks performed on the received per_msg_token failed, preventing further processing from being performed with that token. 🫠
  • GSS_BAD_SIG indicates that the received per_msg_token contains an incorrect signature for the message. 🚩
  • GSS_DUPLICATE_TOKEN, GSS_OLD_TOKEN, and GSS_UNSEQ_TOKEN values appear in conjunction with the optional per-message replay detection features described in Section 1.2.3; their semantics are described in that section. πŸ”
  • GSS_CONTEXT_EXPIRED indicates that context-related data items have expired, so that the requested operation cannot be performed. 😭
  • GSS_CREDENTIALS_EXPIRED indicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. πŸ₯€
  • GSS_NO_CONTEXT indicates that no valid context was recognized for the input context_handle provided. πŸ™ˆ
  • GSS_FAILURE indicates that the context is recognized, but that the GSS_Verify() operation could not be performed for reasons unspecified at the GSS-API level. πŸ’€

Using the security context referenced by context_handle, verify that the input per_msg_token contains an appropriate signature for the input message, and apply any active replay detection or sequencing features. The quality-of-protection that was applied to the processed message comes back in the qop_state result 🧐

2.3.3. GSS_Seal call

Inputs:

  • context_handle INTEGER,
  • conf_req_flag BOOLEAN,
  • qop_req INTEGER,-0 specifies default QOP
  • input_message OCTET STRING

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • conf_state BOOLEAN,
  • output_message OCTET STRING

Return major_status codes:

  • GSS_COMPLETE indicates that the input_message was successfully processed and that the output_message is ready for transmission. πŸŽ€
  • GSS_CONTEXT_EXPIRED indicates that context-related data items have expired, so that the requested operation cannot be performed. 😭
  • GSS_CREDENTIALS_EXPIRED indicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. πŸ₯€
  • GSS_NO_CONTEXT indicates that no valid context was recognized for the input context_handle provided. πŸ™ˆ
  • GSS_FAILURE indicates that the context is recognized, but that the GSS_Seal() operation could not be performed for reasons unspecified at the GSS-API level. πŸ’€

Performs the data origin authentication and data integrity functions of GSS_Sign(). If the input conf_req_flag is TRUE, it requests that confidentiality be applied to the input_message. Confidentiality may not be supported in all mech_types or by all implementations, so the returned conf_state flag tells you whether confidentiality was actually provided for the input_message πŸ” The qop_req parameter allows quality-of-protection control.

In all cases, the GSS_Seal() call yields a single output_message data element containing (optionally enciphered) user data as well as control information. One element, all the goodies inside 🎁

2.3.4. GSS_Unseal call

Inputs:

  • context_handle INTEGER,
  • input_message OCTET STRING

Outputs:

  • conf_state BOOLEAN,
  • qop_state INTEGER,
  • major_status INTEGER,
  • minor_status INTEGER,
  • output_message OCTET STRING

Return major_status codes:

  • GSS_COMPLETE indicates that the input_message was successfully processed and that the resulting output_message is available. πŸ₯³
  • GSS_DEFECTIVE_TOKEN indicates that consistency checks performed on the per_msg_token extracted from the input_message failed, preventing further processing from being performed. 🫠
  • GSS_BAD_SIG indicates that an incorrect signature was detected for the message. 🚩
  • GSS_DUPLICATE_TOKEN, GSS_OLD_TOKEN, and GSS_UNSEQ_TOKEN values appear in conjunction with the optional per-message replay detection features described in Section 1.2.3; their semantics are described in that section. πŸ”
  • GSS_CONTEXT_EXPIRED indicates that context-related data items have expired, so that the requested operation cannot be performed. 😭
  • GSS_CREDENTIALS_EXPIRED indicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. πŸ₯€
  • GSS_NO_CONTEXT indicates that no valid context was recognized for the input context_handle provided. πŸ™ˆ
  • GSS_FAILURE indicates that the context is recognized, but that the GSS_Unseal() operation could not be performed for reasons unspecified at the GSS-API level. πŸ’€

Processes a data element generated (and optionally enciphered) by GSS_Seal(), provided as input_message. The returned conf_state value tells you whether confidentiality was applied to the input_message. If conf_state is TRUE, GSS_Unseal() deciphers the input_message. It returns the quality-of-protection that was applied to the processed message in the qop_state result. GSS_Seal() performs the data integrity and data origin authentication checking functions of GSS_Verify() on the plaintext data. The plaintext data is returned in output_message πŸ”“


2.4. Support calls 🧰

This group has the helper functions that GSS-API callers can use no matter what state their established contexts are in πŸ’β€β™€οΈ Whether they block on network interactions is unspecified.

2.4.1. GSS_Display_status call

Inputs:

  • status_value INTEGER,-GSS-API major_status or minor_status return value
  • status_type INTEGER,-1 if major_status, 2 if minor_status
  • mech_type OBJECT IDENTIFIER-mech_type to be used for minor_status translation

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • status_string_set SET OF OCTET STRING

Return major_status codes:

  • GSS_COMPLETE indicates that a valid printable status representation (possibly representing more than one status event encoded within the status_value) is available in the returned status_string_set. πŸ–¨οΈ
  • GSS_BAD_MECH indicates that translation in accordance with an unsupported mech_type was requested, so translation could not be performed. πŸ™…β€β™€οΈ
  • GSS_BAD_STATUS indicates that the input status_value was invalid, or that the input status_type carried a value other than 1 or 2, so translation could not be performed. 🀨
  • GSS_FAILURE indicates that the requested operation could not be performed for reasons unspecified at the GSS-API level. πŸ’€

This call gives callers a way to translate GSS-API-returned major and minor status codes into printable string representations πŸ“

2.4.2. GSS_Indicate_mechs call

Input:

  • (none)

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • mech_set SET OF OBJECT IDENTIFIER

Return major_status codes:

  • GSS_COMPLETE indicates that a set of available mechanisms has been returned in mech_set. 🎊
  • GSS_FAILURE indicates that the requested operation could not be performed for reasons unspecified at the GSS-API level. πŸ’€

This call lets callers figure out which mechanism types are available on the local system πŸ” It's meant for specialized callers who need to request non-default mech_type sets from GSS_Acquire_cred(), so most callers shouldn't need it at all 🫢

2.4.3. GSS_Compare_name call βš–οΈ

Inputs:

  • name1 INTERNAL NAME,
  • name2 INTERNAL NAME

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • name_equal BOOLEAN

Return major_status codes:

  • GSS_COMPLETE means name1 and name2 were comparable πŸŽ‰, and the name_equal result tells you whether they're equal or unequal.
  • GSS_BAD_NAMETYPE means one or both names had internal type specifiers the GSS-API implementation can't read, OR the two names have different types that can't be compared. Either way, the equality check couldn't finish πŸ™ƒ.
  • GSS_BAD_NAME means one or both input names were ill-formed based on their internal type specifier, so the equality check couldn't finish πŸ’€.
  • GSS_FAILURE means the operation couldn't be done for reasons the GSS-API level doesn't specify 😭.

This one lets you check whether two internal name representations are the same person or thing πŸ‘―βœ¨.

2.4.4. GSS_Display_name call πŸ–¨οΈ

Inputs:

  • name INTERNAL NAME

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • name_string OCTET STRING,
  • name_type OBJECT IDENTIFIER

Return major_status codes:

  • GSS_COMPLETE means a valid printable name representation is ready to go in name_string πŸ’–.
  • GSS_BAD_NAMETYPE means the name's type isn't something the GSS-API implementation can read, so there's no printable version it can make 😀.
  • GSS_BAD_NAME means the name's contents don't match its internal name type, so again, no printable version πŸ™ˆ.
  • GSS_FAILURE means the operation couldn't be done for reasons the GSS-API level doesn't specify 😭.

This call turns an internal name into something a human can read, along with a namespace type descriptor. The printable format is up to the local setup, so it's a local matter 🌸.

2.4.5. GSS_Import_name call πŸ“₯

Inputs:

  • input_name_string OCTET STRING,
  • input_name_type OBJECT IDENTIFIER

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER,
  • output_name INTERNAL NAME

Return major_status codes:

  • GSS_COMPLETE means a valid name representation is output in output_name βœ…, and it's described by the type value in output_name_type.
  • GSS_BAD_NAMETYPE means the input_name_type isn't supported by the GSS-API implementation, so the import couldn't happen 🚫.
  • GSS_BAD_NAME means the input_name_string is ill-formed for the input_name_type, so the import couldn't happen either πŸ’€.
  • GSS_FAILURE means the operation couldn't be done for reasons the GSS-API level doesn't specify 😭.

This is the glow-up call πŸ¦‹. You hand it a printable name, tell it which namespace to parse it with, and it converts that into an internal form that the other GSS-API routines can use. The syntax of input_name is a local matter 🧚.

2.4.6. GSS_Release_name call 🧹

Inputs:

  • name INTERNAL NAME

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER

Return major_status codes:

  • GSS_COMPLETE means the storage tied to the input name was released successfully 🫧.
  • GSS_BAD_NAME means the input name argument didn't hold a valid name πŸ™ƒ.
  • GSS_FAILURE means the operation couldn't be done for reasons the GSS-API level doesn't specify 😭.

Basically, this is your clean-up crew. It frees up the storage for an internal name representation πŸ§½πŸ’….

2.4.7. GSS_Release_buffer call πŸͺ£

Inputs:

  • buffer OCTET STRING

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER

Return major_status codes:

  • GSS_COMPLETE means the storage tied to the input buffer was released successfully 🌷.
  • GSS_FAILURE means the operation couldn't be done for reasons the GSS-API level doesn't specify 😭.

This one frees up an OCTET STRING buffer that some other GSS-API call handed you earlier πŸŽ€.

2.4.8. GSS_Release_oid_set call πŸ—‚οΈ

Inputs:

  • buffer SET OF OBJECT IDENTIFIER

Outputs:

  • major_status INTEGER,
  • minor_status INTEGER

Return major_status codes:

  • GSS_COMPLETE means the storage tied to the input object identifier set was released successfully 🎈.
  • GSS_FAILURE means the operation couldn't be done for reasons the GSS-API level doesn't specify 😭.

Last one in the support crew! This frees up an object identifier set that another GSS-API call allocated 🫢.


3. Mechanism-Specific Example Scenarios 🌈

This section is full of illustrated walkthroughs of different candidate mechanism types that can support GSS-API πŸ”. These are mainly for people who already know specific security tech, and they show how GSS-API functions can be used and implemented by those underlying mechanisms 🧠. They should not be regarded as constrictive to implementations, and they're not the only way GSS-API functions can be realized with a given technology. They also don't show every GSS-API feature with every technology πŸ™ˆ.

3.1. Kerberos V5, single-TGT πŸ‘‘

OS-specific login functions get a TGT for the local realm Kerberos server, and that TGT gets stored in a credentials structure for the client πŸ”‘. The client calls GSS_Acquire_cred() to grab a cred_handle, which is how it references those credentials when it sets up security contexts 🫧.

The client calls GSS_Init_sec_context(). If the service is in a different realm, GSS_Init_sec_context() fetches the TGT/key pairs needed to get from the local realm to the target realm πŸ—ΊοΈ. Those data get saved in the owner's TGT cache. After any remote realm resolution is done, GSS_Init_sec_context() produces a service ticket for the requested service, along with a matching session key 🎫. Those get stored together with the context. The GSS-API code sends KRB_TGS_REQ request(s) and gets back KRB_TGS_REP response(s) when things go well, or a KRB_ERROR when they don't 😬.

If everything works, GSS_Init_sec_context() builds a Kerberos-formatted KRB_AP_REQ message and returns it in output_token. The client then sends output_token to the service πŸ“¨.

The service passes the received token as the input_token argument to GSS_Accept_sec_context(). That call checks the authenticator, gives the service the client's authenticated name, and returns an output_context_handle πŸ›‚βœ¨.

Now both parties have the session key tied to the service ticket, and they can use it in later GSS_Sign(), GSS_Verify(), GSS_Seal(), and GSS_Unseal() operations πŸ”πŸ’œ.

3.2. Kerberos V5, double-TGT πŸ‘―β€β™€οΈ

TGT acquisition works the same as above πŸ”.

Note: To avoid unnecessary frequent invocations of error paths when implementing the GSS-API atop Kerberos V5, it seems appropriate to represent "single-TGT K-V5" and "double-TGT K-V5" with separate mech_types, and this discussion makes that assumption.

Based on the (specified or defaulted) mech_type, GSS_Init_sec_context() figures out that the double-TGT protocol should be used for the target. It returns a GSS_CONTINUE_NEEDED major_status, and its output_token holds a request to the service for the service's TGT πŸ™‹β€β™€οΈ. (If a service TGT with a suitably long remaining lifetime is already sitting in a cache, it might be usable, so this step isn't needed πŸ§ƒ.) The client passes output_token to the service.

Note: this scenario shows a different use for the GSS_CONTINUE_NEEDED status return facility than the one used to support mutual authentication. Both uses can coexist as successive operations within a single context establishment operation 🌈.

The service passes the received token as the input_token argument to GSS_Accept_sec_context(). That call recognizes the token as a request for a TGT πŸ‘€. (Heads up: current Kerberos V5 doesn't define any intra-protocol mechanism to represent a request like this πŸ€·β€β™€οΈ.) GSS_Accept_sec_context() returns a GSS_CONTINUE_NEEDED major_status and puts the service's TGT in its output_token. The service sends output_token to the client πŸ“¬.

The client passes the received token as the input_token argument to a continuation of GSS_Init_sec_context(). That call caches the received service TGT and uses it in a service ticket request to the Kerberos authentication server 🎟️. The returned service ticket and session key get stored together with the context. Then GSS_Init_sec_context() builds a Kerberos-formatted authenticator, returns it in output_token, and sets the major_status to GSS_COMPLETE πŸ’…. The client sends output_token to the service.

The service passes the received token as the input_token argument to a continuation call to GSS_Accept_sec_context(). That call verifies the authenticator, gives the service the client's authenticated name, and returns a major_status of GSS_COMPLETE πŸŽ‰βœ¨.

GSS_Sign(), GSS_Verify(), GSS_Seal(), and GSS_Unseal() all work just like they did above πŸ«ΆπŸ’–.

3.3. X.509 Authentication Framework ✨

okay bestie, this example shows the GSS-API teaming up with public-key mechanisms, consistent with the X.509 Directory Authentication Framework πŸ”πŸ’–

the client calls GSS_Acquire_cred() first πŸŽ€ this sets up a credentials structure, which makes the client's private key accessible so it can be used on the client's behalf πŸ—οΈ

next, the client calls GSS_Init_sec_context(), and this one is giving detective πŸ•΅οΈβ€β™€οΈ it checks the Directory to grab (and validate) a chain of public-key certificates, so the client can collect the service's public key. the validation makes sure the signatures were applied by trusted authorities and that the certificates haven't expired. no expired certs allowed, periodt πŸ’… GSS_Init_sec_context() also generates a secret key for per-message protection on the context, and then it encrypts (enciphers) that secret key under the service's public key πŸ”‘

the enciphered secret key goes into the output_token from GSS_Init_sec_context(), along with an authenticator quantity signed with the client's private key ✍️ the output_token also carries a certification path, which is a certificate chain leading from the service back to the client. a variant approach would leave this path resolution for the service to do, instead of having the client assert it 🧩 the client application then sends the output_token to the service πŸ“¨

the service passes the received token in as the input_token argument to GSS_Accept_sec_context() πŸ™Œ this call validates the certification path, and as a result it figures out a certified binding between the client's distinguished name and the client's public key. with that public key in hand, GSS_Accept_sec_context() can process the authenticator quantity in the input_token and verify that the client's private key was used to sign it. at this point the client is authenticated to the service πŸŽ‰ the service then uses its private key to decipher the enciphered secret key it was given for per-message protection on the context πŸ”“

finally, the client calls GSS_Sign() or GSS_Seal() on a data message. this applies per-message authentication, integrity, and (optional) confidentiality to that message πŸ’Œ the service uses the context's shared secret key to do the matching GSS_Verify() and GSS_Unseal() calls. and that's a wrap 🌸


okay so, to get the GSS-API working on top of existing, emerging, and future security mechanisms, a few things need to happen:

  • object identifiers must be assigned to candidate GSS-API mechanisms and to the name types they support 🏷️
  • concrete data element formats must be defined for candidate mechanisms 🧱

calling applications also need to come up with formatting conventions, so they can tell GSS-API tokens apart from other data carried in their application protocols πŸ‘€

concrete language bindings are required for each programming environment where the GSS-API is going to be used. the bindings for the C language are available in an associated RFC πŸ“š

5. Acknowledgments 🫢

this proposal was a collaborative effort, and it's giving teamwork 🀝 big thanks to the many members of the IETF Security Area Advisory Group (SAAG) and the Common Authentication Technology (CAT) Working Group for their contributions at meetings and over electronic mail πŸ’œ

thanks also to Kannan Alagappan, Doug Barlow, Bill Brown, Cliff Kahn, Charlie Kaufman, Butler Lampson, Richard Pitkin, Joe Tardo, and John Wray of Digital Equipment Corporation, and to John Carr, John Kohl, Jon Rochlis, Jeff Schiller, and Ted T'so of MIT and Project Athena 🌟 Joe Pato and Bill Sommerfeld of HP/Apollo, Walt Tuvell of OSF, and Bill Griffith and Mike Merritt of AT&T gave input that helped focus and clarify the directions 🎯

and the precursor work by Richard Pitkin, presented to meetings of the Trusted Systems Interoperability Group (TSIG), showed everyone the value of a generic, mechanism-independent security service API. iconic πŸ‘‘

6. Security Considerations πŸ”’

security issues are discussed throughout this memo. so pay attention, bestie, because this stuff matters a LOT πŸ˜­πŸ›‘οΈ

7. Author's Address πŸ–ŠοΈ

John Linn Geer Zolot Associates One Main St. Cambridge, MA 02142 USA

Phone: +1 617.374.3700 Email: Linn@gza.com


APPENDIX A. PACS AND AUTHORIZATION SERVICES πŸ’Ό

okay this one is a little spicy 🌢️ people have thought about changing the GSS-API service interface so it can recognize and manipulate Privilege Attribute Certificates (PACs) as in ECMA 138, carrying authorization data as a side effect of setting up a security context. but no such changes have been made so far. this appendix explains why, and it also talks about compatibility options between PACs and the GSS-API that don't require PACs to be visible to GSS-API callers 🧐

existing candidate mechanism types like Kerberos and X.509 don't have PAC manipulation features. leaving those mechanisms out of the set of candidates that fully support the GSS-API seems wrong. adding a feature (and making it GSS-API visible) that only a few mechanisms support could push people to build apps that look portable but really only work in limited places πŸ™ƒ

the current situation, where PACs aren't visible across the GSS-API interface, still allows for implementations where PACs are carried transparently inside the tokens defined and used for certain mech_types, and stored within peers' credentials and context-level data structures. even though API callers can't see them, these PACs could be used by operating system or other local functions as inputs when they're deciding on access requests from callers. this also allows dynamic selection of PAC contents, as long as that selection is administratively directed rather than caller directed πŸ—‚οΈ

in a distributed computing environment, authentication has to span different systems, and that need is the motivation for defining and using the GSS-API in the first place 🌐 heterogeneous systems can talk to each other, with globally authenticated names being the common bond between locally defined access control policies. those policies are often local, or specific to particular operating systems or environments. if the GSS-API made particular authorization models visible across its service interface, it would be less general, and honestly that's not the vibe πŸ™…β€β™€οΈ the current GSS-API approach follows the precedent Kerberos set: it doesn't define how authorization-related data is interpreted, and it doesn't enforce access controls based on that data.

the GSS-API is a general interface, and its callers may live inside or outside any defined TCB or NTCB boundaries. because of that, it makes more sense to offer "value-added" security services to callers than to offer facilities that enforce restrictions on them 🎁 authorization decisions often have to be made below the GSS-API level, locally, against (or in spite of) applications, and they can't be invoked or skipped at the application's discretion 🚫 since the GSS-API's placement means it can't fully solve the authorization issue, the value of a partial contribution specific to particular authorization models is debatable πŸ€·β€β™€οΈ


APPENDIX B. MECHANISM-INDEPENDENT TOKEN FORMAT 🧾

this appendix defines a mechanism-independent encapsulating format for the initial token of a GSS-API context establishment sequence. it includes an identifier for the mechanism type that will be used on that context πŸͺͺ the ASN.1-encoded data elements are represented in BER, but to keep parsing simple, they're constrained to the Distinguished Encoding Rule (DER) subset of BER defined in X.509, clause 8.7 ✨ this format is recommended for designers of GSS-API implementations based on various mechanisms, so that tokens can be read unambiguously by GSS-API peers. and there's no requirement that the mechanism-specific innerContextToken, innerMsgToken, and sealedUserData data elements be encoded in ASN.1 BER πŸ’…

          -- optional top-level token definitions to
          -- frame different mechanisms

          GSS-API DEFINITIONS ::=

          BEGIN

          MechType ::= OBJECT IDENTIFIER
          -- data structure definitions

          -- callers must be able to distinguish among
          -- InitialContextToken, SubsequentContextToken,
          -- PerMsgToken, and SealedMessage data elements
          -- based on the usage in which they occur

          InitialContextToken ::=
          -- option indication (delegation, etc.) indicated within
          -- mechanism-specific token
          [APPLICATION 0] IMPLICIT SEQUENCE {
                  thisMech MechType,
                  innerContextToken ANY DEFINED BY thisMech

                     -- contents mechanism-specific
                  }

          SubsequentContextToken ::= innerContextToken ANY
          -- interpretation based on predecessor InitialContextToken

          PerMsgToken ::=
          -- as emitted by GSS_Sign and processed by GSS_Verify
                  innerMsgToken ANY

          SealedMessage ::=
          -- as emitted by GSS_Seal and processed by GSS_Unseal
          -- includes internal, mechanism-defined indicator
          -- of whether or not encrypted
                  sealedUserData ANY

          END

APPENDIX C. MECHANISM DESIGN CONSTRAINTS πŸ“

okay last stop 🏁 these constraints on GSS-API mechanism designs were adopted because of observed caller protocol requirements. adherence to them is expected in later descriptions of GSS-API mechanisms documented in standards-track Internet specifications πŸ“œ

using the approach defined in Appendix B of this specification, which applies a mechanism type tag to the InitialContextToken, is required 🏷️

it's strongly recommended that mechanisms offering per-message protection services also offer at least one of the replay detection and sequencing services. mechanisms that offer neither of those will fail to satisfy recognized requirements of certain candidate caller protocols, and that's a whole mood πŸ˜­πŸ’€

πŸ“¦ where this page comes from