saslgssapi

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

go-sasl-gssapi

The SASL GSSAPI mechanism (RFC 4752) for Go — the Kerberos 5 GSS-API mechanism (OID 1.2.840.113554.1.2.2) exposed as a SASL client mechanism, so a Go program can authenticate to IMAP, SMTP, LDAP, XMPP, AMQP, and other SASL-protected services with a Kerberos credential.

No pure-Go SASL GSSAPI mechanism exists elsewhere: it is absent from emersion/go-sasl and from the gokrb5 family (which ship SPNEGO/HTTP-Negotiate and the raw krb5 primitives, but no SASL mechanism). This library fills that gap. The client is a thin wrapper over the Kerberos GSS context layer in github.com/hstern/krb5; what it adds is the RFC 4752 SASL framing.

Status: v0.x. The client works and is verified against the reference MIT krb5 implementation (see Interop). The API may change between minor versions until v1.0.0.

Install

go get github.com/hstern/go-sasl-gssapi

Requires Go 1.26+.

Quickstart

package main

import (
	"log"

	"github.com/emersion/go-imap/v2/imapclient"
	"github.com/hstern/krb5/credentials"

	"github.com/hstern/go-sasl-gssapi"
)

func main() {
	// A Kerberos credential cache already holding a service ticket for the
	// target (holder-of-key) — e.g. from kinit, KRB5CCNAME, or an
	// OAuth2-to-Kerberos exchange.
	cc, err := credentials.LoadCCache("/tmp/krb5cc_1000")
	if err != nil {
		log.Fatal(err)
	}
	krbClient, err := saslgssapi.FromCCache(cc)
	if err != nil {
		log.Fatal(err)
	}

	sc, err := saslgssapi.NewClient(saslgssapi.Config{
		Client:  krbClient,
		Service: "imap/mail.example.com", // the target service principal
	})
	if err != nil {
		log.Fatal(err)
	}

	// sc is an emersion/go-sasl Client — hand it straight to go-imap or go-smtp:
	c, err := imapclient.DialTLS("mail.example.com:993", nil)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.Authenticate(sc); err != nil { // go-smtp: c.Auth(sc)
		log.Fatal(err)
	}
}

Config.AuthzID sets an optional authorization identity; leaving it empty authenticates as the ticket's client principal. Consumers must run over TLS — v0 negotiates no security layer, so confidentiality comes from the transport.

Scope (v0)

  • Client (initiator) only — the caller is the SASL client.
  • Authentication only (no_security_layer) — transport confidentiality is expected from TLS. GSS integrity/confidentiality layers and GS2 (RFC 5801) channel binding are out of scope (the latter is destined for a separate GS2-KRB5 library).
  • Mutual authentication is always performed (the server's AP-REP is required and verified).
  • Satisfies the emersion/go-sasl client contract (Start/Next), so it drops straight into go-imap and go-smtp.

How it works

Kerberos credential (holder-of-key: service ticket + session key, from a ccache)
        │
        ▼  Start()  → GSSAPI initial-context token (AP-REQ, RFC 4121 GSS checksum, mutual)
        ▼  Next()   ← acceptor AP-REP  → verify mutual auth
        ▼  Next()   ← security-layer offer (GSS Wrap token)
        ▼           → selected layer + authzid (GSS Wrap token)
        ▼
   authenticated SASL session

The Kerberos GSS context establishment (the AP-REQ with its RFC 4121 §4.1.1 checksum, AP-REP verification, and the per-message Wrap tokens) is handled by hstern/krb5's krb5context.Initiator / gssapi.SecContext; this library adds the RFC 4752 SASL framing and the security-layer negotiation. FromCCache adapts an MIT credential cache for the holder-of-key case — the ccache already holds the service ticket, so no KDC is contacted.

Interop

Verified against the reference MIT krb5 C implementation: the client is driven through a full RFC 4752 handshake by an MIT python-gssapi acceptor over a real KDC — the ccache parse, the AP-REQ and its checksum, mutual authentication, and the security-layer GSS_Wrap/Unwrap are all accepted by MIT libgssapi_krb5. See test/interop/ (Docker).

License

Apache-2.0.

Documentation

Overview

Package saslgssapi implements the SASL GSSAPI mechanism (RFC 4752) — the Kerberos 5 GSS-API mechanism (OID 1.2.840.113554.1.2.2) exposed as a SASL mechanism — so a Go client can authenticate to IMAP, SMTP, LDAP, XMPP, and other SASL-protected services with a Kerberos credential.

v0 is the client (initiator) side only, negotiating the "no security layer" protection (authentication only); transport confidentiality is expected from TLS. It is built to satisfy the emersion/go-sasl client contract so it drops into go-imap and go-smtp.

Example

Example builds the SASL client from a holder-of-key credential cache. The result satisfies emersion/go-sasl's Client, so it plugs straight into go-imap's Authenticate or go-smtp's Auth.

// A ccache already holding a service ticket for the target — from kinit,
// KRB5CCNAME, or an OAuth2-to-Kerberos exchange. No KDC is contacted.
cc, err := credentials.LoadCCache("/tmp/krb5cc_1000")
if err != nil {
	log.Fatal(err)
}
krbClient, err := saslgssapi.FromCCache(cc)
if err != nil {
	log.Fatal(err)
}

var sc sasl.Client
sc, err = saslgssapi.NewClient(saslgssapi.Config{
	Client:  krbClient,
	Service: "imap/mail.example.com",
})
if err != nil {
	log.Fatal(err)
}

// Hand sc to a SASL-capable client, e.g. imapClient.Authenticate(sc).
_ = sc

Index

Examples

Constants

View Source
const Mechanism = "GSSAPI"

Mechanism is the SASL mechanism name this client advertises.

View Source
const SpecVersion = "v0 (SASL GSSAPI client; RFC 4752)"

SpecVersion is the SASL GSSAPI profile this build implements.

Variables

This section is empty.

Functions

func FromCCache

func FromCCache(cc *credentials.CCache) (*client.Client, error)

FromCCache builds a holder-of-key Kerberos client from an MIT credential cache for use as Config.Client. It is a thin wrapper over client.NewFromCCache: the ccache is expected to already hold the service ticket and its session key, so the client never contacts a KDC.

The returned *client.Client can also be built directly with client.NewFromCCache if the caller needs a non-default krb5 configuration (e.g. to allow a live TGS exchange for tickets not yet cached).

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the RFC 4752 SASL GSSAPI client (initiator). It implements github.com/emersion/go-sasl's Client interface, so it drops into go-imap and go-smtp. A Client is single-use: one authentication exchange per Client.

v0 performs authentication only ("no security layer") with mandatory mutual authentication; transport confidentiality is expected from TLS. The Kerberos GSS context establishment (AP-REQ / AP-REP / the RFC 4121 checksum) is handled by github.com/hstern/krb5's krb5context.Initiator; this type adds the RFC 4752 SASL framing and the security-layer negotiation on top.

func NewClient

func NewClient(cfg Config) (*Client, error)

NewClient returns a Client ready to Start an authentication exchange.

func (*Client) Next

func (c *Client) Next(challenge []byte) ([]byte, error)

Next continues the exchange. It is called twice: first with the acceptor's AP-REP (returning an empty token), then with the GSS-wrapped security-layer offer (returning the wrapped selection).

func (*Client) Start

func (c *Client) Start() (mech string, ir []byte, err error)

Start begins the exchange. It returns the mechanism name and the GSSAPI initial-context token (the AP-REQ) as the SASL initial response.

type Config

type Config struct {
	// Client is the Kerberos client holding the credential — typically from
	// FromCCache, or built directly with client.NewFromCCache. Required.
	Client *client.Client

	// Service is the target service principal name (SPN), e.g.
	// "imap/mail.example.com" or "imap/mail.example.com@EXAMPLE.COM". Required.
	Service string

	// AuthzID is the optional authorization identity (authzid) sent in the
	// final security-layer message. Empty means authenticate as the ticket's
	// client principal.
	AuthzID string
}

Config configures a Client.

Directories

Path Synopsis
internal
seclayer
Package seclayer marshals and unmarshals the RFC 4752 §3.3 security-layer negotiation tokens — the acceptor's offer and the client's selection.
Package seclayer marshals and unmarshals the RFC 4752 §3.3 security-layer negotiation tokens — the acceptor's offer and the client's selection.
test
interop/client command
Command interop-client drives the go-sasl-gssapi client for the interop harness.
Command interop-client drives the go-sasl-gssapi client for the interop harness.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL