Documentation
¶
Overview ¶
Package encryption implements the WS-Management Message Level Encryption (MLE) envelope used by NTLM, Kerberos/SPNEGO and (in future) CredSSP transports. The envelope construction and parsing are independent of the authentication mechanism: the auth-specific seal/unseal primitive is abstracted behind the Sealer interface.
Reference: pywinrm winrm/encryption.py.
Index ¶
Constants ¶
const ( ContentTypeEncrypted = "multipart/encrypted" ContentTypeMultiEncrypted = "multipart/x-multi-encrypted" )
Standard MIME Content-Type prefixes for the outer envelope.
const (
Boundary = "--Encrypted Boundary"
)
Boundary is the literal boundary used inside the request and response bodies. It matches the value produced by pywinrm and the existing masterzen/winrm encryption implementation. The HTTP Content-Type header advertises the boundary without the leading "--".
const KerberosProtocolHeader = "application/HTTP-SPNEGO-session-encrypted"
KerberosProtocolHeader is the protocol parameter advertised on the multipart/encrypted Content-Type for Kerberos/SPNEGO-sealed traffic. Windows WinRM uses the SPNEGO header value for both raw NTLM and Kerberos when MLE is engaged.
const MaxChunkSize = 16384
MaxChunkSize is the per-chunk plaintext limit used by CredSSP. Messages larger than this are split across multiple multipart parts and sent with Content-Type multipart/x-multi-encrypted.
const NTLMProtocolHeader = "application/HTTP-SPNEGO-session-encrypted"
NTLMProtocolHeader is the protocol parameter advertised on the multipart/encrypted Content-Type for NTLM-sealed traffic. Windows WinRM uses the SPNEGO header value for raw NTLM as well.
Variables ¶
This section is empty.
Functions ¶
func BuildEnvelope ¶
BuildEnvelope wraps a plaintext SOAP payload in the multipart MIME envelope expected by Windows WinRM with message-level encryption enabled. It returns the encoded body and the Content-Type header value to set on the outgoing HTTP request.
When useMultiEncrypted is true and the plaintext is larger than MaxChunkSize, the payload is split into MaxChunkSize-sized chunks and emitted as multipart/x-multi-encrypted. This path is currently only used by CredSSP. NTLM and Kerberos always send a single chunk.
func IsEncryptedContentType ¶
IsEncryptedContentType reports whether the given HTTP Content-Type header value advertises a message-level encrypted body for the supplied sealer's protocol. Use this on the response side before calling ParseEnvelope.
func ParseEnvelope ¶
ParseEnvelope reverses BuildEnvelope. It splits the multipart body on the boundary, extracts the OriginalContent length annotation and the sealed payload from each part, calls sealer.Unseal, validates the decrypted length and returns the concatenated plaintext.
The trailing closing boundary may or may not be glued to the last payload by the server; both layouts are handled.
Types ¶
type KerberosSealer ¶
type KerberosSealer struct {
// contains filtered or unexported fields
}
KerberosSealer implements Sealer using a Kerberos session/subkey. It produces RFC 4121 §4.2.6.2 sealed (confidential) GSS Wrap tokens.
Construction: caller supplies the EncryptionKey negotiated during the AP-REQ exchange and indicates whether AP-REP carried an acceptor subkey to use for replies. The WinRM client always acts as the initiator.
Sequence numbers are tracked separately for outbound and inbound directions per RFC 4121. Unseal validates that the token's seqnum matches the next expected incoming value, rejecting replays and reorders. Concurrent Seal/Unseal calls are serialised via mu.
func NewKerberosSealer ¶
func NewKerberosSealer(key types.EncryptionKey, acceptorSubkey bool) *KerberosSealer
NewKerberosSealer constructs a sealer ready for the WinRM client side.
func (*KerberosSealer) IncomingSeqNum ¶
func (k *KerberosSealer) IncomingSeqNum() uint64
IncomingSeqNum returns the next expected inbound sequence number.
func (*KerberosSealer) OutgoingSeqNum ¶
func (k *KerberosSealer) OutgoingSeqNum() uint64
OutgoingSeqNum returns the next outbound sequence number that Seal will stamp into a Wrap token. Visible for tests.
func (*KerberosSealer) ProtocolHeader ¶
func (k *KerberosSealer) ProtocolHeader() string
func (*KerberosSealer) Seal ¶
func (k *KerberosSealer) Seal(plaintext []byte) ([]byte, error)
Seal produces an RFC 4121 sealed Wrap token. The plaintext is encrypted with the GSSAPI_INITIATOR_SEAL key usage (from the WinRM client to the Windows host). A 16-byte header is appended to the plaintext before encryption per RFC 4121 §4.2.4. The transmitted token is:
Header (16 bytes) || rotate_right(ciphertext, RRC)
where RRC is the right-rotation count chosen by the sender. We use 0 for simplicity; both directions support arbitrary RRC during Unseal.
func (*KerberosSealer) Unseal ¶
func (k *KerberosSealer) Unseal(token []byte) ([]byte, error)
Unseal parses an RFC 4121 sealed Wrap token, validates the embedded header (constant-time) and the sequence number, decrypts the ciphertext and returns the plaintext payload. Replayed or reordered tokens are rejected based on incomingSeqNum.
type NTLMSealer ¶
type NTLMSealer struct {
// contains filtered or unexported fields
}
NTLMSealer adapts a bodgit/ntlmssp Client's SecuritySession to the Sealer interface. The session must be Complete (post Type-3 message exchange) before Seal/Unseal will produce valid output.
func NewNTLMSealer ¶
func NewNTLMSealer(client *ntlmssp.Client) (*NTLMSealer, error)
NewNTLMSealer constructs a NTLMSealer from an established ntlmssp.Client. Returns an error if the handshake has not completed or the client did not negotiate session security.
func (*NTLMSealer) ProtocolHeader ¶
func (n *NTLMSealer) ProtocolHeader() string
type Sealer ¶
type Sealer interface {
Seal(plaintext []byte) ([]byte, error)
Unseal(sealed []byte) ([]byte, error)
ProtocolHeader() string
}
Sealer is the auth-specific primitive consumed by the envelope.
Seal takes a plaintext SOAP payload and returns the auth-protocol specific byte sequence that gets placed inside the application/octet-stream MIME part. For NTLM this is: 4-byte little-endian signature length || signature || RC4-sealed payload. For Kerberos/SPNEGO this is the GSSAPI gss_wrap output framed identically.
Unseal performs the reverse on the sealed bytes received from the server.
ProtocolHeader returns the value used both as the Content-Type of the inner header part and as the protocol parameter on the outer multipart/encrypted Content-Type. Examples:
- application/HTTP-SPNEGO-session-encrypted (NTLM and Kerberos/SPNEGO)
- application/HTTP-Kerberos-session-encrypted (raw Kerberos)
- application/HTTP-CredSSP-session-encrypted (CredSSP)