blob: 47754d738a43b8f2057093defcbe325cb2dd89ab [file] [log] [blame]
// Package gssapi implements Generic Security Services Application Program Interface required for SPNEGO kerberos authentication.
package gssapi
import (
"context"
"fmt"
"github.com/jcmturner/gofork/encoding/asn1"
)
// GSS-API OID names
const (
// GSS-API OID names
OIDKRB5 OIDName = "KRB5" // MechType OID for Kerberos 5
OIDMSLegacyKRB5 OIDName = "MSLegacyKRB5" // MechType OID for Kerberos 5
OIDSPNEGO OIDName = "SPNEGO"
)
// GSS-API status values
const (
StatusBadBindings = 1 << iota
StatusBadMech
StatusBadName
StatusBadNameType
StatusBadStatus
StatusBadSig
StatusBadMIC
StatusContextExpired
StatusCredentialsExpired
StatusDefectiveCredential
StatusDefectiveToken
StatusFailure
StatusNoContext
StatusNoCred
StatusBadQOP
StatusUnauthorized
StatusUnavailable
StatusDuplicateElement
StatusNameNotMN
StatusComplete
StatusContinueNeeded
StatusDuplicateToken
StatusOldToken
StatusUnseqToken
StatusGapToken
)
// ContextToken is an interface for a GSS-API context token.
type ContextToken interface {
Marshal() ([]byte, error)
Unmarshal(b []byte) error
Verify() (bool, Status)
Context() context.Context
}
/*
CREDENTIAL MANAGEMENT
GSS_Acquire_cred acquire credentials for use
GSS_Release_cred release credentials after use
GSS_Inquire_cred display information about credentials
GSS_Add_cred construct credentials incrementally
GSS_Inquire_cred_by_mech display per-mechanism credential information
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
GSS_Inquire_context display information about context
GSS_Wrap_size_limit determine GSS_Wrap token size limit
GSS_Export_sec_context transfer context to other process
GSS_Import_sec_context import transferred context
PER-MESSAGE CALLS
GSS_GetMIC apply integrity check, receive as token separate from message
GSS_VerifyMIC validate integrity check token along with message
GSS_Wrap sign, optionally encrypt, encapsulate
GSS_Unwrap decapsulate, decrypt if needed, validate integrity check
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 general GSS-allocated object
GSS_Release_OID_set free storage of OID set object
GSS_Create_empty_OID_set create empty OID set
GSS_Add_OID_set_member add member to OID set
GSS_Test_OID_set_member test if OID is member of OID set
GSS_Inquire_names_for_mech indicate name types supported by mechanism
GSS_Inquire_mechs_for_name indicates mechanisms supporting name type
GSS_Canonicalize_name translate name to per-mechanism form
GSS_Export_name externalize per-mechanism name
GSS_Duplicate_name duplicate name object
*/
// Mechanism is the GSS-API interface for authentication mechanisms.
type Mechanism interface {
OID() asn1.ObjectIdentifier
AcquireCred() error // acquire credentials for use (eg. AS exchange for KRB5)
InitSecContext() (ContextToken, error) // initiate outbound security context (eg TGS exchange builds AP_REQ to go into ContextToken to send to service)
AcceptSecContext(ct ContextToken) (bool, context.Context, Status) // service verifies the token server side to establish a context
MIC() MICToken // apply integrity check, receive as token separate from message
VerifyMIC(mt MICToken) (bool, error) // validate integrity check token along with message
Wrap(msg []byte) WrapToken // sign, optionally encrypt, encapsulate
Unwrap(wt WrapToken) []byte // decapsulate, decrypt if needed, validate integrity check
}
// OIDName is the type for defined GSS-API OIDs.
type OIDName string
// OID returns the OID for the provided OID name.
func OID(o OIDName) asn1.ObjectIdentifier {
switch o {
case OIDSPNEGO:
return asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 2}
case OIDKRB5:
return asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2}
case OIDMSLegacyKRB5:
return asn1.ObjectIdentifier{1, 2, 840, 48018, 1, 2, 2}
}
return asn1.ObjectIdentifier{}
}
// Status is the GSS-API status and implements the error interface.
type Status struct {
Code int
Message string
}
// Error returns the Status description.
func (s Status) Error() string {
var str string
switch s.Code {
case StatusBadBindings:
str = "channel binding mismatch"
case StatusBadMech:
str = "unsupported mechanism requested"
case StatusBadName:
str = "invalid name provided"
case StatusBadNameType:
str = "name of unsupported type provided"
case StatusBadStatus:
str = "invalid input status selector"
case StatusBadSig:
str = "token had invalid integrity check"
case StatusBadMIC:
str = "preferred alias for GSS_S_BAD_SIG"
case StatusContextExpired:
str = "specified security context expired"
case StatusCredentialsExpired:
str = "expired credentials detected"
case StatusDefectiveCredential:
str = "defective credential detected"
case StatusDefectiveToken:
str = "defective token detected"
case StatusFailure:
str = "failure, unspecified at GSS-API level"
case StatusNoContext:
str = "no valid security context specified"
case StatusNoCred:
str = "no valid credentials provided"
case StatusBadQOP:
str = "unsupported QOP valu"
case StatusUnauthorized:
str = "operation unauthorized"
case StatusUnavailable:
str = "operation unavailable"
case StatusDuplicateElement:
str = "duplicate credential element requested"
case StatusNameNotMN:
str = "name contains multi-mechanism elements"
case StatusComplete:
str = "normal completion"
case StatusContinueNeeded:
str = "continuation call to routine required"
case StatusDuplicateToken:
str = "duplicate per-message token detected"
case StatusOldToken:
str = "timed-out per-message token detected"
case StatusUnseqToken:
str = "reordered (early) per-message token detected"
case StatusGapToken:
str = "skipped predecessor token(s) detected"
default:
str = "unknown GSS-API error status"
}
if s.Message != "" {
return fmt.Sprintf("%s: %s", str, s.Message)
}
return str
}