RFC 1508
Generic Security Service Application Program Interface
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:
GSS_COMPLETEmeans 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 βGSS_DUPLICATE_TOKENmeans the signature on the received message was correct, but the message was recognized as a duplicate of a previously-processed message π―GSS_OLD_TOKENmeans 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:
GSS_COMPLETEmeans 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 βGSS_DUPLICATE_TOKENmeans the signature on the received message was correct, but the message was recognized as a duplicate of a previously-processed message π―GSS_OLD_TOKENmeans the signature on the received message was correct, but the token is too old to be checked for duplication β°GSS_UNSEQ_TOKENmeans 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_nameINTERNAL NAME, -NULL requests locally-determined defaultlifetime_reqINTEGER,-in seconds; 0 requests defaultdesired_mechsSET OF OBJECT IDENTIFIER,-empty set requests system-selected defaultcred_usageINTEGER-0=INITIATE-AND-ACCEPT, 1=INITIATE-ONLY, 2=ACCEPT-ONLY
Outputs:
major_statusINTEGER,minor_statusINTEGER,output_cred_handleOCTET STRING,actual_mechsSET OF OBJECT IDENTIFIER,lifetime_recINTEGER -in seconds, or reserved value for INDEFINITE
Return major_status codes:
GSS_COMPLETEmeans the creds were successfully established β . They last for the duration inlifetime_rec, work for the usage incred_usage, and cover the mech_types listed inactual_mechs. You can refer to them later using the handle inoutput_cred_handle.GSS_BAD_MECHmeans a mech_type the GSS-API implementation doesn't support was requested, so creds couldn't be set up π.GSS_BAD_NAMETYPEmeansdesired_nameis either uninterpretable or a type the GSS-API implementation doesn't support, so no creds could be made for it π .GSS_BAD_NAMEmeansdesired_namedoesn't match up with its own internal type specifier info, so again, no creds π.GSS_FAILUREmeans 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 indesired_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_handleOCTET STRING-NULL specifies default credentials
Outputs:
major_statusINTEGER,minor_statusINTEGER
Return major_status codes:
GSS_COMPLETEmeans the creds referenced bycred_handlewere 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_CREDmeans nothing got released, either becausecred_handlewas invalid or because the caller isn't authorized to access those creds π .GSS_FAILUREmeans 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_handleOCTET STRING -NULL specifies default credentials
Outputs:
major_statusINTEGER,minor_statusINTEGER,cred_nameINTERNAL NAME,lifetime_recINTEGER -in seconds, or reserved value for INDEFINITEcred_usageINTEGER, -0=INITIATE-AND-ACCEPT, 1=INITIATE-ONLY, 2=ACCEPT-ONLYmech_setSET OF OBJECT IDENTIFIER
Return major_status codes:
GSS_COMPLETEmeans the creds referenced bycred_handleare valid β¨. The outputcred_name,lifetime_rec, andcred_usagevalues give you, in order, the creds' associated principal name, remaining lifetime, suitable usage modes, and supported mechanism types.GSS_NO_CREDmeans no info could be returned about those creds, either becausecred_handlewas invalid or because the caller isn't authorized to access them π.GSS_FAILUREmeans 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 NAMEmech_type OBJECT IDENTIFIER: a NULL parameter specifies "use default"deleg_req_flag BOOLEANmutual_req_flag BOOLEANreplay_det_req_flag BOOLEANsequence_req_flag BOOLEANlifetime_req INTEGER: 0 specifies default lifetime β°chan_bindings OCTET STRINGinput_token OCTET STRING: NULL, or a token received from the target
Outputs:
major_status INTEGERminor_status INTEGERoutput_context_handle INTEGERmech_type OBJECT IDENTIFIER: the actual mechanism is always indicated, never NULL πoutput_token OCTET STRING: NULL, or a token to pass to the context targetdeleg_state BOOLEANmutual_state BOOLEANreplay_det_state BOOLEANsequence_state BOOLEANconf_avail BOOLEANinteg_avail BOOLEANlifetime_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_COMPLETEmeans the context-level info was set up successfully, and the returnedoutput_tokengives the target enough info to do per-message processing on the newly established context πGSS_CONTINUE_NEEDEDmeans the control info in the returnedoutput_tokenhas to be sent to the target, and a reply has to come back and get passed in as theinput_tokenargument to a continuation call toGSS_Init_sec_context(). Only after that can per-message processing happen with this context πGSS_DEFECTIVE_TOKENmeans the consistency checks on theinput_tokenfailed, so no further processing based on that token π«GSS_DEFECTIVE_CREDENTIALmeans the consistency checks on the credential structure referenced byclaimant_cred_handlefailed, so no further processing with that credential structure π ββοΈGSS_BAD_SIGmeans the receivedinput_tokenhas an incorrect signature, so context setup can't be done πGSS_NO_CREDmeans no context got established. That could be because the inputcred_handlewas invalid, because the credentials are only valid for context acceptor use, or because the caller isn't authorized to access those credentials πGSS_CREDENTIALS_EXPIREDmeans the credentials passed in throughclaimant_cred_handleare no longer valid, so context establishment can't finish βGSS_BAD_BINDINGSmeans there's a mismatch between the caller-providedchan_bindingsand the ones pulled out of theinput_token. That's a security-relevant event, and it stops context establishment π¨ (This result is only returned byGSS_Init_sec_contextfor contexts wheremutual_stateis TRUE.)GSS_NO_CONTEXTmeans no valid context was recognized for the inputcontext_handleprovided. This major status only shows up for successor calls followingGSS_CONTINUE_NEEDEDreturns π§GSS_BAD_NAMETYPEmeans the providedtarg_namehas a type that's either uninterpretable or unsupported by the GSS-API implementation, so context establishment can't finish πGSS_BAD_NAMEmeans the providedtarg_nameis inconsistent in terms of its internally-incorporated type specifier info, so context establishment can't be done π΅GSS_FAILUREmeans 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_handleOCTET STRING, NULL specifies "use default"input_context_handleINTEGER, 0 specifies "not yet assigned"chan_bindingsOCTET STRINGinput_tokenOCTET STRING
Outputs:
major_statusINTEGERminor_statusINTEGERsrc_nameINTERNAL NAMEmech_typeOBJECT IDENTIFIERoutput_context_handleINTEGERdeleg_stateBOOLEANmutual_stateBOOLEANreplay_det_stateBOOLEANsequence_stateBOOLEANconf_availBOOLEANinteg_availBOOLEANlifetime_recINTEGER - in seconds, or reserved value for INDEFINITEdelegated_cred_handleOCTET STRINGoutput_tokenOCTET 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_COMPLETEmeans the context-level data structures got set up successfully, and per-message processing can now happen with this context βGSS_CONTINUE_NEEDEDmeans the control info in the returnedoutput_tokenhas to go back to the initiator, and a response has to come back and be passed in as theinput_tokento a continuation call toGSS_Accept_sec_context(). Only then can per-message processing happen with this context πGSS_DEFECTIVE_TOKENmeans the consistency checks on theinput_tokenfailed, so no further processing based on that token π«GSS_DEFECTIVE_CREDENTIALmeans the consistency checks on the credential structure referenced byacceptor_cred_handlefailed, so no further processing with that credential structure π«GSS_BAD_SIGmeans the receivedinput_tokenhas an incorrect signature, so context setup can't be done π ββοΈGSS_DUPLICATE_TOKENmeans the signature on theinput_tokenwas correct, but the token got recognized as a duplicate of one already processed. No new context is established π―GSS_OLD_TOKENmeans the signature was correct, but theinput_tokenis too old to be checked for duplication against previously-processed tokens. No new context is established πΈοΈGSS_NO_CREDmeans 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_EXPIREDmeans the credentials given throughacceptor_cred_handleare no longer valid, so context establishment can't be completed β°GSS_BAD_BINDINGSmeans the caller-providedchan_bindingsdidn't match the ones pulled out of theinput_token. That's a security-relevant event, and it stops context establishment π¨GSS_NO_CONTEXTmeans no valid context was recognized for the inputcontext_handle. This status only shows up on successor calls after aGSS_CONTINUE_NEEDEDreturn π«₯GSS_FAILUREmeans 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-levelinput_token, which gets passed toGSS_Accept_sec_context(), from the per-message data elements passed toGSS_Verify()orGSS_Unseal(). These data elements might arrive in a single application message, andGSS_Accept_sec_context()has to be performed before per-message processing can work successfully π
2.2.3. GSS_Delete_sec_context call ποΈ
Input:
context_handleINTEGER
Outputs:
major_statusINTEGERminor_statusINTEGERoutput_context_tokenOCTET STRING
Return major_status codes:
GSS_COMPLETEmeans the context was recognized, the relevant context-specific info got flushed, and the returnedoutput_context_tokenis ready to go to the context's peer π§ΉGSS_NO_CONTEXTmeans no valid context was recognized for the inputcontext_handleprovided, so no deletion happened π€·ββοΈGSS_FAILUREmeans the context is recognized, butGSS_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_handleINTEGER,input_context_tokenOCTET STRING
Outputs:
major_statusINTEGER,minor_statusINTEGER,
Return major_status codes:
GSS_COMPLETEmeans theinput_context_tokengot processed successfully in conjunction with the context referenced bycontext_handleπGSS_DEFECTIVE_TOKENmeans the consistency checks on the received context_token failed, so no further processing with that token π«GSS_NO_CONTEXTmeans no valid context was recognized for the inputcontext_handleprovided π«₯GSS_FAILUREmeans the context is recognized, butGSS_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_handleINTEGER,
Outputs:
major_statusINTEGER,minor_statusINTEGER,lifetime_recINTEGER - in seconds, or reserved value for INDEFINITE
Return major_status codes:
GSS_COMPLETEmeans the referenced context is valid, and it'll stay valid for the amount of time shown inlifetime_recπ¦GSS_CONTEXT_EXPIREDmeans data items related to the referenced context have expired πGSS_CREDENTIALS_EXPIREDmeans the context is recognized, but its associated credentials have expired π₯GSS_NO_CONTEXTmeans no valid context was recognized for the inputcontext_handleprovided π«₯GSS_FAILUREmeans 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 QOPmessage OCTET STRING
Outputs:
major_status INTEGER,minor_status INTEGER,per_msg_token OCTET STRING
Return major_status codes:
GSS_COMPLETEindicates that a signature, suitable for an established security context, was successfully applied and that the message and correspondingper_msg_tokenare ready for transmission. πGSS_CONTEXT_EXPIREDindicates that context-related data items have expired, so that the requested operation cannot be performed. πGSS_CREDENTIALS_EXPIREDindicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. π₯GSS_NO_CONTEXTindicates that no valid context was recognized for the inputcontext_handleprovided. πGSS_FAILUREindicates 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_COMPLETEindicates that the message was successfully verified. βGSS_DEFECTIVE_TOKENindicates that consistency checks performed on the receivedper_msg_tokenfailed, preventing further processing from being performed with that token. π«GSS_BAD_SIGindicates that the receivedper_msg_tokencontains an incorrect signature for the message. π©GSS_DUPLICATE_TOKEN,GSS_OLD_TOKEN, andGSS_UNSEQ_TOKENvalues 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_EXPIREDindicates that context-related data items have expired, so that the requested operation cannot be performed. πGSS_CREDENTIALS_EXPIREDindicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. π₯GSS_NO_CONTEXTindicates that no valid context was recognized for the inputcontext_handleprovided. πGSS_FAILUREindicates that the context is recognized, but that theGSS_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 QOPinput_message OCTET STRING
Outputs:
major_status INTEGER,minor_status INTEGER,conf_state BOOLEAN,output_message OCTET STRING
Return major_status codes:
GSS_COMPLETEindicates that theinput_messagewas successfully processed and that theoutput_messageis ready for transmission. πGSS_CONTEXT_EXPIREDindicates that context-related data items have expired, so that the requested operation cannot be performed. πGSS_CREDENTIALS_EXPIREDindicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. π₯GSS_NO_CONTEXTindicates that no valid context was recognized for the inputcontext_handleprovided. πGSS_FAILUREindicates that the context is recognized, but that theGSS_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_COMPLETEindicates that theinput_messagewas successfully processed and that the resultingoutput_messageis available. π₯³GSS_DEFECTIVE_TOKENindicates that consistency checks performed on theper_msg_tokenextracted from theinput_messagefailed, preventing further processing from being performed. π«GSS_BAD_SIGindicates that an incorrect signature was detected for the message. π©GSS_DUPLICATE_TOKEN,GSS_OLD_TOKEN, andGSS_UNSEQ_TOKENvalues 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_EXPIREDindicates that context-related data items have expired, so that the requested operation cannot be performed. πGSS_CREDENTIALS_EXPIREDindicates that the context is recognized, but that its associated credentials have expired, so that the requested operation cannot be performed. π₯GSS_NO_CONTEXTindicates that no valid context was recognized for the inputcontext_handleprovided. πGSS_FAILUREindicates that the context is recognized, but that theGSS_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 valuestatus_type INTEGER,-1 if major_status, 2 if minor_statusmech_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_COMPLETEindicates that a valid printable status representation (possibly representing more than one status event encoded within thestatus_value) is available in the returnedstatus_string_set. π¨οΈGSS_BAD_MECHindicates that translation in accordance with an unsupported mech_type was requested, so translation could not be performed. π ββοΈGSS_BAD_STATUSindicates that the inputstatus_valuewas invalid, or that the inputstatus_typecarried a value other than 1 or 2, so translation could not be performed. π€¨GSS_FAILUREindicates 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_COMPLETEindicates that a set of available mechanisms has been returned inmech_set. πGSS_FAILUREindicates 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_COMPLETEmeans name1 and name2 were comparable π, and thename_equalresult tells you whether they're equal or unequal.GSS_BAD_NAMETYPEmeans 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_NAMEmeans one or both input names were ill-formed based on their internal type specifier, so the equality check couldn't finish π.GSS_FAILUREmeans 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_COMPLETEmeans a valid printable name representation is ready to go inname_stringπ.GSS_BAD_NAMETYPEmeans the name's type isn't something the GSS-API implementation can read, so there's no printable version it can make π€.GSS_BAD_NAMEmeans the name's contents don't match its internal name type, so again, no printable version π.GSS_FAILUREmeans 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_COMPLETEmeans a valid name representation is output inoutput_nameβ , and it's described by the type value inoutput_name_type.GSS_BAD_NAMETYPEmeans theinput_name_typeisn't supported by the GSS-API implementation, so the import couldn't happen π«.GSS_BAD_NAMEmeans theinput_name_stringis ill-formed for theinput_name_type, so the import couldn't happen either π.GSS_FAILUREmeans 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_COMPLETEmeans the storage tied to the input name was released successfully π«§.GSS_BAD_NAMEmeans the input name argument didn't hold a valid name π.GSS_FAILUREmeans 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_COMPLETEmeans the storage tied to the input buffer was released successfully π·.GSS_FAILUREmeans 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_COMPLETEmeans the storage tied to the input object identifier set was released successfully π.GSS_FAILUREmeans 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 πΈ
4. Related Activities π
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
- ietf: rfc1508 1993-09
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms