newline battles continue
This commit is contained in:
136
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go
generated
vendored
Executable file
136
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go
generated
vendored
Executable file
@@ -0,0 +1,136 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/address"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
|
||||
)
|
||||
|
||||
// AuthenticatorFactory constructs an authenticator.
|
||||
type AuthenticatorFactory func(cred *Cred) (Authenticator, error)
|
||||
|
||||
var authFactories = make(map[string]AuthenticatorFactory)
|
||||
|
||||
func init() {
|
||||
RegisterAuthenticatorFactory("", newDefaultAuthenticator)
|
||||
RegisterAuthenticatorFactory(SCRAMSHA1, newScramSHA1Authenticator)
|
||||
RegisterAuthenticatorFactory(SCRAMSHA256, newScramSHA256Authenticator)
|
||||
RegisterAuthenticatorFactory(MONGODBCR, newMongoDBCRAuthenticator)
|
||||
RegisterAuthenticatorFactory(PLAIN, newPlainAuthenticator)
|
||||
RegisterAuthenticatorFactory(GSSAPI, newGSSAPIAuthenticator)
|
||||
RegisterAuthenticatorFactory(MongoDBX509, newMongoDBX509Authenticator)
|
||||
}
|
||||
|
||||
// CreateAuthenticator creates an authenticator.
|
||||
func CreateAuthenticator(name string, cred *Cred) (Authenticator, error) {
|
||||
if f, ok := authFactories[name]; ok {
|
||||
return f(cred)
|
||||
}
|
||||
|
||||
return nil, newAuthError(fmt.Sprintf("unknown authenticator: %s", name), nil)
|
||||
}
|
||||
|
||||
// RegisterAuthenticatorFactory registers the authenticator factory.
|
||||
func RegisterAuthenticatorFactory(name string, factory AuthenticatorFactory) {
|
||||
authFactories[name] = factory
|
||||
}
|
||||
|
||||
// HandshakeOptions packages options that can be passed to the Handshaker()
|
||||
// function. DBUser is optional but must be of the form <dbname.username>;
|
||||
// if non-empty, then the connection will do SASL mechanism negotiation.
|
||||
type HandshakeOptions struct {
|
||||
AppName string
|
||||
Authenticator Authenticator
|
||||
Compressors []string
|
||||
DBUser string
|
||||
PerformAuthentication func(description.Server) bool
|
||||
}
|
||||
|
||||
// Handshaker creates a connection handshaker for the given authenticator.
|
||||
func Handshaker(h driver.Handshaker, options *HandshakeOptions) driver.Handshaker {
|
||||
return driver.HandshakerFunc(func(ctx context.Context, addr address.Address, conn driver.Connection) (description.Server, error) {
|
||||
desc, err := operation.NewIsMaster().
|
||||
AppName(options.AppName).
|
||||
Compressors(options.Compressors).
|
||||
SASLSupportedMechs(options.DBUser).
|
||||
Handshake(ctx, addr, conn)
|
||||
|
||||
if err != nil {
|
||||
return description.Server{}, newAuthError("handshake failure", err)
|
||||
}
|
||||
|
||||
performAuth := options.PerformAuthentication
|
||||
if performAuth == nil {
|
||||
performAuth = func(serv description.Server) bool {
|
||||
return serv.Kind == description.RSPrimary ||
|
||||
serv.Kind == description.RSSecondary ||
|
||||
serv.Kind == description.Mongos ||
|
||||
serv.Kind == description.Standalone
|
||||
}
|
||||
}
|
||||
if performAuth(desc) && options.Authenticator != nil {
|
||||
err = options.Authenticator.Auth(ctx, desc, conn)
|
||||
if err != nil {
|
||||
return description.Server{}, newAuthError("auth error", err)
|
||||
}
|
||||
|
||||
}
|
||||
if h == nil {
|
||||
return desc, nil
|
||||
}
|
||||
return h.Handshake(ctx, addr, conn)
|
||||
})
|
||||
}
|
||||
|
||||
// Authenticator handles authenticating a connection.
|
||||
type Authenticator interface {
|
||||
// Auth authenticates the connection.
|
||||
Auth(context.Context, description.Server, driver.Connection) error
|
||||
}
|
||||
|
||||
func newAuthError(msg string, inner error) error {
|
||||
return &Error{
|
||||
message: msg,
|
||||
inner: inner,
|
||||
}
|
||||
}
|
||||
|
||||
func newError(err error, mech string) error {
|
||||
return &Error{
|
||||
message: fmt.Sprintf("unable to authenticate using mechanism \"%s\"", mech),
|
||||
inner: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Error is an error that occurred during authentication.
|
||||
type Error struct {
|
||||
message string
|
||||
inner error
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
if e.inner == nil {
|
||||
return e.message
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", e.message, e.inner)
|
||||
}
|
||||
|
||||
// Inner returns the wrapped error.
|
||||
func (e *Error) Inner() error {
|
||||
return e.inner
|
||||
}
|
||||
|
||||
// Message returns the message.
|
||||
func (e *Error) Message() string {
|
||||
return e.message
|
||||
}
|
||||
16
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/cred.go
generated
vendored
Executable file
16
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/cred.go
generated
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
// Cred is a user's credential.
|
||||
type Cred struct {
|
||||
Source string
|
||||
Username string
|
||||
Password string
|
||||
PasswordSet bool
|
||||
Props map[string]string
|
||||
}
|
||||
67
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/default.go
generated
vendored
Executable file
67
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/default.go
generated
vendored
Executable file
@@ -0,0 +1,67 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
)
|
||||
|
||||
func newDefaultAuthenticator(cred *Cred) (Authenticator, error) {
|
||||
return &DefaultAuthenticator{
|
||||
Cred: cred,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DefaultAuthenticator uses SCRAM-SHA-1 or MONGODB-CR depending
|
||||
// on the server version.
|
||||
type DefaultAuthenticator struct {
|
||||
Cred *Cred
|
||||
}
|
||||
|
||||
// Auth authenticates the connection.
|
||||
func (a *DefaultAuthenticator) Auth(ctx context.Context, desc description.Server, conn driver.Connection) error {
|
||||
var actual Authenticator
|
||||
var err error
|
||||
|
||||
switch chooseAuthMechanism(desc) {
|
||||
case SCRAMSHA256:
|
||||
actual, err = newScramSHA256Authenticator(a.Cred)
|
||||
case SCRAMSHA1:
|
||||
actual, err = newScramSHA1Authenticator(a.Cred)
|
||||
default:
|
||||
actual, err = newMongoDBCRAuthenticator(a.Cred)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return newAuthError("error creating authenticator", err)
|
||||
}
|
||||
|
||||
return actual.Auth(ctx, desc, conn)
|
||||
}
|
||||
|
||||
// If a server provides a list of supported mechanisms, we choose
|
||||
// SCRAM-SHA-256 if it exists or else MUST use SCRAM-SHA-1.
|
||||
// Otherwise, we decide based on what is supported.
|
||||
func chooseAuthMechanism(desc description.Server) string {
|
||||
if desc.SaslSupportedMechs != nil {
|
||||
for _, v := range desc.SaslSupportedMechs {
|
||||
if v == SCRAMSHA256 {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return SCRAMSHA1
|
||||
}
|
||||
|
||||
if err := description.ScramSHA1Supported(desc.WireVersion); err == nil {
|
||||
return SCRAMSHA1
|
||||
}
|
||||
|
||||
return MONGODBCR
|
||||
}
|
||||
23
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/doc.go
generated
vendored
Executable file
23
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/doc.go
generated
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Package auth is not for public use.
|
||||
//
|
||||
// The API for packages in the 'private' directory have no stability
|
||||
// guarantee.
|
||||
//
|
||||
// The packages within the 'private' directory would normally be put into an
|
||||
// 'internal' directory to prohibit their use outside the 'mongo' directory.
|
||||
// However, some MongoDB tools require very low-level access to the building
|
||||
// blocks of a driver, so we have placed them under 'private' to allow these
|
||||
// packages to be imported by projects that need them.
|
||||
//
|
||||
// These package APIs may be modified in backwards-incompatible ways at any
|
||||
// time.
|
||||
//
|
||||
// You are strongly discouraged from directly using any packages
|
||||
// under 'private'.
|
||||
package auth
|
||||
60
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi.go
generated
vendored
Executable file
60
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi.go
generated
vendored
Executable file
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//+build gssapi
|
||||
//+build windows linux darwin
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
)
|
||||
|
||||
// GSSAPI is the mechanism name for GSSAPI.
|
||||
const GSSAPI = "GSSAPI"
|
||||
|
||||
func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) {
|
||||
if cred.Source != "" && cred.Source != "$external" {
|
||||
return nil, newAuthError("GSSAPI source must be empty or $external", nil)
|
||||
}
|
||||
|
||||
return &GSSAPIAuthenticator{
|
||||
Username: cred.Username,
|
||||
Password: cred.Password,
|
||||
PasswordSet: cred.PasswordSet,
|
||||
Props: cred.Props,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GSSAPIAuthenticator uses the GSSAPI algorithm over SASL to authenticate a connection.
|
||||
type GSSAPIAuthenticator struct {
|
||||
Username string
|
||||
Password string
|
||||
PasswordSet bool
|
||||
Props map[string]string
|
||||
}
|
||||
|
||||
// Auth authenticates the connection.
|
||||
func (a *GSSAPIAuthenticator) Auth(ctx context.Context, desc description.Server, conn driver.Connection) error {
|
||||
target := desc.Addr.String()
|
||||
hostname, _, err := net.SplitHostPort(target)
|
||||
if err != nil {
|
||||
return newAuthError(fmt.Sprintf("invalid endpoint (%s) specified: %s", target, err), nil)
|
||||
}
|
||||
|
||||
client, err := gssapi.New(hostname, a.Username, a.Password, a.PasswordSet, a.Props)
|
||||
|
||||
if err != nil {
|
||||
return newAuthError("error creating gssapi", err)
|
||||
}
|
||||
return ConductSaslConversation(ctx, conn, "$external", client)
|
||||
}
|
||||
16
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_enabled.go
generated
vendored
Executable file
16
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_enabled.go
generated
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//+build !gssapi
|
||||
|
||||
package auth
|
||||
|
||||
// GSSAPI is the mechanism name for GSSAPI.
|
||||
const GSSAPI = "GSSAPI"
|
||||
|
||||
func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) {
|
||||
return nil, newAuthError("GSSAPI support not enabled during build (-tags gssapi)", nil)
|
||||
}
|
||||
21
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_supported.go
generated
vendored
Executable file
21
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_supported.go
generated
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//+build gssapi,!windows,!linux,!darwin
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// GSSAPI is the mechanism name for GSSAPI.
|
||||
const GSSAPI = "GSSAPI"
|
||||
|
||||
func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) {
|
||||
return nil, newAuthError(fmt.Sprintf("GSSAPI is not supported on %s", runtime.GOOS), nil)
|
||||
}
|
||||
166
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss.go
generated
vendored
Executable file
166
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss.go
generated
vendored
Executable file
@@ -0,0 +1,166 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//+build gssapi
|
||||
//+build linux darwin
|
||||
|
||||
package gssapi
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -DGOOS_linux
|
||||
#cgo linux LDFLAGS: -lgssapi_krb5 -lkrb5
|
||||
#cgo darwin CFLAGS: -DGOOS_darwin
|
||||
#cgo darwin LDFLAGS: -framework GSS
|
||||
#include "gss_wrapper.h"
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// New creates a new SaslClient. The target parameter should be a hostname with no port.
|
||||
func New(target, username, password string, passwordSet bool, props map[string]string) (*SaslClient, error) {
|
||||
serviceName := "mongodb"
|
||||
|
||||
for key, value := range props {
|
||||
switch strings.ToUpper(key) {
|
||||
case "CANONICALIZE_HOST_NAME":
|
||||
return nil, fmt.Errorf("CANONICALIZE_HOST_NAME is not supported when using gssapi on %s", runtime.GOOS)
|
||||
case "SERVICE_REALM":
|
||||
return nil, fmt.Errorf("SERVICE_REALM is not supported when using gssapi on %s", runtime.GOOS)
|
||||
case "SERVICE_NAME":
|
||||
serviceName = value
|
||||
case "SERVICE_HOST":
|
||||
target = value
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown mechanism property %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
servicePrincipalName := fmt.Sprintf("%s@%s", serviceName, target)
|
||||
|
||||
return &SaslClient{
|
||||
servicePrincipalName: servicePrincipalName,
|
||||
username: username,
|
||||
password: password,
|
||||
passwordSet: passwordSet,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type SaslClient struct {
|
||||
servicePrincipalName string
|
||||
username string
|
||||
password string
|
||||
passwordSet bool
|
||||
|
||||
// state
|
||||
state C.gssapi_client_state
|
||||
contextComplete bool
|
||||
done bool
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Close() {
|
||||
C.gssapi_client_destroy(&sc.state)
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Start() (string, []byte, error) {
|
||||
const mechName = "GSSAPI"
|
||||
|
||||
cservicePrincipalName := C.CString(sc.servicePrincipalName)
|
||||
defer C.free(unsafe.Pointer(cservicePrincipalName))
|
||||
var cusername *C.char
|
||||
var cpassword *C.char
|
||||
if sc.username != "" {
|
||||
cusername = C.CString(sc.username)
|
||||
defer C.free(unsafe.Pointer(cusername))
|
||||
if sc.passwordSet {
|
||||
cpassword = C.CString(sc.password)
|
||||
defer C.free(unsafe.Pointer(cpassword))
|
||||
}
|
||||
}
|
||||
status := C.gssapi_client_init(&sc.state, cservicePrincipalName, cusername, cpassword)
|
||||
|
||||
if status != C.GSSAPI_OK {
|
||||
return mechName, nil, sc.getError("unable to initialize client")
|
||||
}
|
||||
|
||||
payload, err := sc.Next(nil)
|
||||
|
||||
return mechName, payload, err
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Next(challenge []byte) ([]byte, error) {
|
||||
|
||||
var buf unsafe.Pointer
|
||||
var bufLen C.size_t
|
||||
var outBuf unsafe.Pointer
|
||||
var outBufLen C.size_t
|
||||
|
||||
if sc.contextComplete {
|
||||
if sc.username == "" {
|
||||
var cusername *C.char
|
||||
status := C.gssapi_client_username(&sc.state, &cusername)
|
||||
if status != C.GSSAPI_OK {
|
||||
return nil, sc.getError("unable to acquire username")
|
||||
}
|
||||
defer C.free(unsafe.Pointer(cusername))
|
||||
sc.username = C.GoString((*C.char)(unsafe.Pointer(cusername)))
|
||||
}
|
||||
|
||||
bytes := append([]byte{1, 0, 0, 0}, []byte(sc.username)...)
|
||||
buf = unsafe.Pointer(&bytes[0])
|
||||
bufLen = C.size_t(len(bytes))
|
||||
status := C.gssapi_client_wrap_msg(&sc.state, buf, bufLen, &outBuf, &outBufLen)
|
||||
if status != C.GSSAPI_OK {
|
||||
return nil, sc.getError("unable to wrap authz")
|
||||
}
|
||||
|
||||
sc.done = true
|
||||
} else {
|
||||
if len(challenge) > 0 {
|
||||
buf = unsafe.Pointer(&challenge[0])
|
||||
bufLen = C.size_t(len(challenge))
|
||||
}
|
||||
|
||||
status := C.gssapi_client_negotiate(&sc.state, buf, bufLen, &outBuf, &outBufLen)
|
||||
switch status {
|
||||
case C.GSSAPI_OK:
|
||||
sc.contextComplete = true
|
||||
case C.GSSAPI_CONTINUE:
|
||||
default:
|
||||
return nil, sc.getError("unable to negotiate with server")
|
||||
}
|
||||
}
|
||||
|
||||
if outBuf != nil {
|
||||
defer C.free(outBuf)
|
||||
}
|
||||
|
||||
return C.GoBytes(outBuf, C.int(outBufLen)), nil
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Completed() bool {
|
||||
return sc.done
|
||||
}
|
||||
|
||||
func (sc *SaslClient) getError(prefix string) error {
|
||||
var desc *C.char
|
||||
|
||||
status := C.gssapi_error_desc(sc.state.maj_stat, sc.state.min_stat, &desc)
|
||||
if status != C.GSSAPI_OK {
|
||||
if desc != nil {
|
||||
C.free(unsafe.Pointer(desc))
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s: (%v, %v)", prefix, sc.state.maj_stat, sc.state.min_stat)
|
||||
}
|
||||
defer C.free(unsafe.Pointer(desc))
|
||||
|
||||
return fmt.Errorf("%s: %v(%v,%v)", prefix, C.GoString(desc), int32(sc.state.maj_stat), int32(sc.state.min_stat))
|
||||
}
|
||||
248
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.c
generated
vendored
Executable file
248
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.c
generated
vendored
Executable file
@@ -0,0 +1,248 @@
|
||||
//+build gssapi
|
||||
//+build linux darwin
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "gss_wrapper.h"
|
||||
|
||||
OM_uint32 gssapi_canonicalize_name(
|
||||
OM_uint32* minor_status,
|
||||
char *input_name,
|
||||
gss_OID input_name_type,
|
||||
gss_name_t *output_name
|
||||
)
|
||||
{
|
||||
OM_uint32 major_status;
|
||||
gss_name_t imported_name = GSS_C_NO_NAME;
|
||||
gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
|
||||
|
||||
buffer.value = input_name;
|
||||
buffer.length = strlen(input_name);
|
||||
major_status = gss_import_name(minor_status, &buffer, input_name_type, &imported_name);
|
||||
if (GSS_ERROR(major_status)) {
|
||||
return major_status;
|
||||
}
|
||||
|
||||
major_status = gss_canonicalize_name(minor_status, imported_name, (gss_OID)gss_mech_krb5, output_name);
|
||||
if (imported_name != GSS_C_NO_NAME) {
|
||||
OM_uint32 ignored;
|
||||
gss_release_name(&ignored, &imported_name);
|
||||
}
|
||||
|
||||
return major_status;
|
||||
}
|
||||
|
||||
int gssapi_error_desc(
|
||||
OM_uint32 maj_stat,
|
||||
OM_uint32 min_stat,
|
||||
char **desc
|
||||
)
|
||||
{
|
||||
OM_uint32 stat = maj_stat;
|
||||
int stat_type = GSS_C_GSS_CODE;
|
||||
if (min_stat != 0) {
|
||||
stat = min_stat;
|
||||
stat_type = GSS_C_MECH_CODE;
|
||||
}
|
||||
|
||||
OM_uint32 local_maj_stat, local_min_stat;
|
||||
OM_uint32 msg_ctx = 0;
|
||||
gss_buffer_desc desc_buffer;
|
||||
do
|
||||
{
|
||||
local_maj_stat = gss_display_status(
|
||||
&local_min_stat,
|
||||
stat,
|
||||
stat_type,
|
||||
GSS_C_NO_OID,
|
||||
&msg_ctx,
|
||||
&desc_buffer
|
||||
);
|
||||
if (GSS_ERROR(local_maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
if (*desc) {
|
||||
free(*desc);
|
||||
}
|
||||
|
||||
*desc = malloc(desc_buffer.length+1);
|
||||
memcpy(*desc, desc_buffer.value, desc_buffer.length+1);
|
||||
|
||||
gss_release_buffer(&local_min_stat, &desc_buffer);
|
||||
}
|
||||
while(msg_ctx != 0);
|
||||
|
||||
return GSSAPI_OK;
|
||||
}
|
||||
|
||||
int gssapi_client_init(
|
||||
gssapi_client_state *client,
|
||||
char* spn,
|
||||
char* username,
|
||||
char* password
|
||||
)
|
||||
{
|
||||
client->cred = GSS_C_NO_CREDENTIAL;
|
||||
client->ctx = GSS_C_NO_CONTEXT;
|
||||
|
||||
client->maj_stat = gssapi_canonicalize_name(&client->min_stat, spn, GSS_C_NT_HOSTBASED_SERVICE, &client->spn);
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
if (username) {
|
||||
gss_name_t name;
|
||||
client->maj_stat = gssapi_canonicalize_name(&client->min_stat, username, GSS_C_NT_USER_NAME, &name);
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
if (password) {
|
||||
gss_buffer_desc password_buffer;
|
||||
password_buffer.value = password;
|
||||
password_buffer.length = strlen(password);
|
||||
client->maj_stat = gss_acquire_cred_with_password(&client->min_stat, name, &password_buffer, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
|
||||
} else {
|
||||
client->maj_stat = gss_acquire_cred(&client->min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
OM_uint32 ignored;
|
||||
gss_release_name(&ignored, &name);
|
||||
}
|
||||
|
||||
return GSSAPI_OK;
|
||||
}
|
||||
|
||||
int gssapi_client_username(
|
||||
gssapi_client_state *client,
|
||||
char** username
|
||||
)
|
||||
{
|
||||
OM_uint32 ignored;
|
||||
gss_name_t name = GSS_C_NO_NAME;
|
||||
|
||||
client->maj_stat = gss_inquire_context(&client->min_stat, client->ctx, &name, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
gss_buffer_desc name_buffer;
|
||||
client->maj_stat = gss_display_name(&client->min_stat, name, &name_buffer, NULL);
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
gss_release_name(&ignored, &name);
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
*username = malloc(name_buffer.length+1);
|
||||
memcpy(*username, name_buffer.value, name_buffer.length+1);
|
||||
|
||||
gss_release_buffer(&ignored, &name_buffer);
|
||||
gss_release_name(&ignored, &name);
|
||||
return GSSAPI_OK;
|
||||
}
|
||||
|
||||
int gssapi_client_negotiate(
|
||||
gssapi_client_state *client,
|
||||
void* input,
|
||||
size_t input_length,
|
||||
void** output,
|
||||
size_t* output_length
|
||||
)
|
||||
{
|
||||
gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
|
||||
|
||||
if (input) {
|
||||
input_buffer.value = input;
|
||||
input_buffer.length = input_length;
|
||||
}
|
||||
|
||||
client->maj_stat = gss_init_sec_context(
|
||||
&client->min_stat,
|
||||
client->cred,
|
||||
&client->ctx,
|
||||
client->spn,
|
||||
GSS_C_NO_OID,
|
||||
GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
|
||||
0,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,
|
||||
&input_buffer,
|
||||
NULL,
|
||||
&output_buffer,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (output_buffer.length) {
|
||||
*output = malloc(output_buffer.length);
|
||||
*output_length = output_buffer.length;
|
||||
memcpy(*output, output_buffer.value, output_buffer.length);
|
||||
|
||||
OM_uint32 ignored;
|
||||
gss_release_buffer(&ignored, &output_buffer);
|
||||
}
|
||||
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
} else if (client->maj_stat == GSS_S_CONTINUE_NEEDED) {
|
||||
return GSSAPI_CONTINUE;
|
||||
}
|
||||
|
||||
return GSSAPI_OK;
|
||||
}
|
||||
|
||||
int gssapi_client_wrap_msg(
|
||||
gssapi_client_state *client,
|
||||
void* input,
|
||||
size_t input_length,
|
||||
void** output,
|
||||
size_t* output_length
|
||||
)
|
||||
{
|
||||
gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
|
||||
|
||||
input_buffer.value = input;
|
||||
input_buffer.length = input_length;
|
||||
|
||||
client->maj_stat = gss_wrap(&client->min_stat, client->ctx, 0, GSS_C_QOP_DEFAULT, &input_buffer, NULL, &output_buffer);
|
||||
|
||||
if (output_buffer.length) {
|
||||
*output = malloc(output_buffer.length);
|
||||
*output_length = output_buffer.length;
|
||||
memcpy(*output, output_buffer.value, output_buffer.length);
|
||||
|
||||
gss_release_buffer(&client->min_stat, &output_buffer);
|
||||
}
|
||||
|
||||
if (GSS_ERROR(client->maj_stat)) {
|
||||
return GSSAPI_ERROR;
|
||||
}
|
||||
|
||||
return GSSAPI_OK;
|
||||
}
|
||||
|
||||
int gssapi_client_destroy(
|
||||
gssapi_client_state *client
|
||||
)
|
||||
{
|
||||
OM_uint32 ignored;
|
||||
if (client->ctx != GSS_C_NO_CONTEXT) {
|
||||
gss_delete_sec_context(&ignored, &client->ctx, GSS_C_NO_BUFFER);
|
||||
}
|
||||
|
||||
if (client->spn != GSS_C_NO_NAME) {
|
||||
gss_release_name(&ignored, &client->spn);
|
||||
}
|
||||
|
||||
if (client->cred != GSS_C_NO_CREDENTIAL) {
|
||||
gss_release_cred(&ignored, &client->cred);
|
||||
}
|
||||
|
||||
return GSSAPI_OK;
|
||||
}
|
||||
66
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.h
generated
vendored
Executable file
66
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.h
generated
vendored
Executable file
@@ -0,0 +1,66 @@
|
||||
//+build gssapi
|
||||
//+build linux darwin
|
||||
#ifndef GSS_WRAPPER_H
|
||||
#define GSS_WRAPPER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef GOOS_linux
|
||||
#include <gssapi/gssapi.h>
|
||||
#include <gssapi/gssapi_krb5.h>
|
||||
#endif
|
||||
#ifdef GOOS_darwin
|
||||
#include <GSS/GSS.h>
|
||||
#endif
|
||||
|
||||
#define GSSAPI_OK 0
|
||||
#define GSSAPI_CONTINUE 1
|
||||
#define GSSAPI_ERROR 2
|
||||
|
||||
typedef struct {
|
||||
gss_name_t spn;
|
||||
gss_cred_id_t cred;
|
||||
gss_ctx_id_t ctx;
|
||||
|
||||
OM_uint32 maj_stat;
|
||||
OM_uint32 min_stat;
|
||||
} gssapi_client_state;
|
||||
|
||||
int gssapi_error_desc(
|
||||
OM_uint32 maj_stat,
|
||||
OM_uint32 min_stat,
|
||||
char **desc
|
||||
);
|
||||
|
||||
int gssapi_client_init(
|
||||
gssapi_client_state *client,
|
||||
char* spn,
|
||||
char* username,
|
||||
char* password
|
||||
);
|
||||
|
||||
int gssapi_client_username(
|
||||
gssapi_client_state *client,
|
||||
char** username
|
||||
);
|
||||
|
||||
int gssapi_client_negotiate(
|
||||
gssapi_client_state *client,
|
||||
void* input,
|
||||
size_t input_length,
|
||||
void** output,
|
||||
size_t* output_length
|
||||
);
|
||||
|
||||
int gssapi_client_wrap_msg(
|
||||
gssapi_client_state *client,
|
||||
void* input,
|
||||
size_t input_length,
|
||||
void** output,
|
||||
size_t* output_length
|
||||
);
|
||||
|
||||
int gssapi_client_destroy(
|
||||
gssapi_client_state *client
|
||||
);
|
||||
|
||||
#endif
|
||||
352
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi.go
generated
vendored
Executable file
352
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi.go
generated
vendored
Executable file
@@ -0,0 +1,352 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//+build gssapi,windows
|
||||
|
||||
package gssapi
|
||||
|
||||
// #include "sspi_wrapper.h"
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// New creates a new SaslClient. The target parameter should be a hostname with no port.
|
||||
func New(target, username, password string, passwordSet bool, props map[string]string) (*SaslClient, error) {
|
||||
initOnce.Do(initSSPI)
|
||||
if initError != nil {
|
||||
return nil, initError
|
||||
}
|
||||
|
||||
var err error
|
||||
serviceName := "mongodb"
|
||||
serviceRealm := ""
|
||||
canonicalizeHostName := false
|
||||
var serviceHostSet bool
|
||||
|
||||
for key, value := range props {
|
||||
switch strings.ToUpper(key) {
|
||||
case "CANONICALIZE_HOST_NAME":
|
||||
canonicalizeHostName, err = strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s must be a boolean (true, false, 0, 1) but got '%s'", key, value)
|
||||
}
|
||||
|
||||
case "SERVICE_REALM":
|
||||
serviceRealm = value
|
||||
case "SERVICE_NAME":
|
||||
serviceName = value
|
||||
case "SERVICE_HOST":
|
||||
serviceHostSet = true
|
||||
target = value
|
||||
}
|
||||
}
|
||||
|
||||
if canonicalizeHostName {
|
||||
// Should not canonicalize the SERVICE_HOST
|
||||
if serviceHostSet {
|
||||
return nil, fmt.Errorf("CANONICALIZE_HOST_NAME and SERVICE_HOST canonot both be specified")
|
||||
}
|
||||
|
||||
names, err := net.LookupAddr(target)
|
||||
if err != nil || len(names) == 0 {
|
||||
return nil, fmt.Errorf("unable to canonicalize hostname: %s", err)
|
||||
}
|
||||
target = names[0]
|
||||
if target[len(target)-1] == '.' {
|
||||
target = target[:len(target)-1]
|
||||
}
|
||||
}
|
||||
|
||||
servicePrincipalName := fmt.Sprintf("%s/%s", serviceName, target)
|
||||
if serviceRealm != "" {
|
||||
servicePrincipalName += "@" + serviceRealm
|
||||
}
|
||||
|
||||
return &SaslClient{
|
||||
servicePrincipalName: servicePrincipalName,
|
||||
username: username,
|
||||
password: password,
|
||||
passwordSet: passwordSet,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type SaslClient struct {
|
||||
servicePrincipalName string
|
||||
username string
|
||||
password string
|
||||
passwordSet bool
|
||||
|
||||
// state
|
||||
state C.sspi_client_state
|
||||
contextComplete bool
|
||||
done bool
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Close() {
|
||||
C.sspi_client_destroy(&sc.state)
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Start() (string, []byte, error) {
|
||||
const mechName = "GSSAPI"
|
||||
|
||||
var cusername *C.char
|
||||
var cpassword *C.char
|
||||
if sc.username != "" {
|
||||
cusername = C.CString(sc.username)
|
||||
defer C.free(unsafe.Pointer(cusername))
|
||||
if sc.passwordSet {
|
||||
cpassword = C.CString(sc.password)
|
||||
defer C.free(unsafe.Pointer(cpassword))
|
||||
}
|
||||
}
|
||||
status := C.sspi_client_init(&sc.state, cusername, cpassword)
|
||||
|
||||
if status != C.SSPI_OK {
|
||||
return mechName, nil, sc.getError("unable to intitialize client")
|
||||
}
|
||||
|
||||
payload, err := sc.Next(nil)
|
||||
|
||||
return mechName, payload, err
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Next(challenge []byte) ([]byte, error) {
|
||||
|
||||
var outBuf C.PVOID
|
||||
var outBufLen C.ULONG
|
||||
|
||||
if sc.contextComplete {
|
||||
if sc.username == "" {
|
||||
var cusername *C.char
|
||||
status := C.sspi_client_username(&sc.state, &cusername)
|
||||
if status != C.SSPI_OK {
|
||||
return nil, sc.getError("unable to acquire username")
|
||||
}
|
||||
defer C.free(unsafe.Pointer(cusername))
|
||||
sc.username = C.GoString((*C.char)(unsafe.Pointer(cusername)))
|
||||
}
|
||||
|
||||
bytes := append([]byte{1, 0, 0, 0}, []byte(sc.username)...)
|
||||
buf := (C.PVOID)(unsafe.Pointer(&bytes[0]))
|
||||
bufLen := C.ULONG(len(bytes))
|
||||
status := C.sspi_client_wrap_msg(&sc.state, buf, bufLen, &outBuf, &outBufLen)
|
||||
if status != C.SSPI_OK {
|
||||
return nil, sc.getError("unable to wrap authz")
|
||||
}
|
||||
|
||||
sc.done = true
|
||||
} else {
|
||||
var buf C.PVOID
|
||||
var bufLen C.ULONG
|
||||
if len(challenge) > 0 {
|
||||
buf = (C.PVOID)(unsafe.Pointer(&challenge[0]))
|
||||
bufLen = C.ULONG(len(challenge))
|
||||
}
|
||||
cservicePrincipalName := C.CString(sc.servicePrincipalName)
|
||||
defer C.free(unsafe.Pointer(cservicePrincipalName))
|
||||
|
||||
status := C.sspi_client_negotiate(&sc.state, cservicePrincipalName, buf, bufLen, &outBuf, &outBufLen)
|
||||
switch status {
|
||||
case C.SSPI_OK:
|
||||
sc.contextComplete = true
|
||||
case C.SSPI_CONTINUE:
|
||||
default:
|
||||
return nil, sc.getError("unable to negotiate with server")
|
||||
}
|
||||
}
|
||||
|
||||
if outBuf != C.PVOID(nil) {
|
||||
defer C.free(unsafe.Pointer(outBuf))
|
||||
}
|
||||
|
||||
return C.GoBytes(unsafe.Pointer(outBuf), C.int(outBufLen)), nil
|
||||
}
|
||||
|
||||
func (sc *SaslClient) Completed() bool {
|
||||
return sc.done
|
||||
}
|
||||
|
||||
func (sc *SaslClient) getError(prefix string) error {
|
||||
return getError(prefix, sc.state.status)
|
||||
}
|
||||
|
||||
var initOnce sync.Once
|
||||
var initError error
|
||||
|
||||
func initSSPI() {
|
||||
rc := C.sspi_init()
|
||||
if rc != 0 {
|
||||
initError = fmt.Errorf("error initializing sspi: %v", rc)
|
||||
}
|
||||
}
|
||||
|
||||
func getError(prefix string, status C.SECURITY_STATUS) error {
|
||||
var s string
|
||||
switch status {
|
||||
case C.SEC_E_ALGORITHM_MISMATCH:
|
||||
s = "The client and server cannot communicate because they do not possess a common algorithm."
|
||||
case C.SEC_E_BAD_BINDINGS:
|
||||
s = "The SSPI channel bindings supplied by the client are incorrect."
|
||||
case C.SEC_E_BAD_PKGID:
|
||||
s = "The requested package identifier does not exist."
|
||||
case C.SEC_E_BUFFER_TOO_SMALL:
|
||||
s = "The buffers supplied to the function are not large enough to contain the information."
|
||||
case C.SEC_E_CANNOT_INSTALL:
|
||||
s = "The security package cannot initialize successfully and should not be installed."
|
||||
case C.SEC_E_CANNOT_PACK:
|
||||
s = "The package is unable to pack the context."
|
||||
case C.SEC_E_CERT_EXPIRED:
|
||||
s = "The received certificate has expired."
|
||||
case C.SEC_E_CERT_UNKNOWN:
|
||||
s = "An unknown error occurred while processing the certificate."
|
||||
case C.SEC_E_CERT_WRONG_USAGE:
|
||||
s = "The certificate is not valid for the requested usage."
|
||||
case C.SEC_E_CONTEXT_EXPIRED:
|
||||
s = "The application is referencing a context that has already been closed. A properly written application should not receive this error."
|
||||
case C.SEC_E_CROSSREALM_DELEGATION_FAILURE:
|
||||
s = "The server attempted to make a Kerberos-constrained delegation request for a target outside the server's realm."
|
||||
case C.SEC_E_CRYPTO_SYSTEM_INVALID:
|
||||
s = "The cryptographic system or checksum function is not valid because a required function is unavailable."
|
||||
case C.SEC_E_DECRYPT_FAILURE:
|
||||
s = "The specified data could not be decrypted."
|
||||
case C.SEC_E_DELEGATION_REQUIRED:
|
||||
s = "The requested operation cannot be completed. The computer must be trusted for delegation"
|
||||
case C.SEC_E_DOWNGRADE_DETECTED:
|
||||
s = "The system detected a possible attempt to compromise security. Verify that the server that authenticated you can be contacted."
|
||||
case C.SEC_E_ENCRYPT_FAILURE:
|
||||
s = "The specified data could not be encrypted."
|
||||
case C.SEC_E_ILLEGAL_MESSAGE:
|
||||
s = "The message received was unexpected or badly formatted."
|
||||
case C.SEC_E_INCOMPLETE_CREDENTIALS:
|
||||
s = "The credentials supplied were not complete and could not be verified. The context could not be initialized."
|
||||
case C.SEC_E_INCOMPLETE_MESSAGE:
|
||||
s = "The message supplied was incomplete. The signature was not verified."
|
||||
case C.SEC_E_INSUFFICIENT_MEMORY:
|
||||
s = "Not enough memory is available to complete the request."
|
||||
case C.SEC_E_INTERNAL_ERROR:
|
||||
s = "An error occurred that did not map to an SSPI error code."
|
||||
case C.SEC_E_INVALID_HANDLE:
|
||||
s = "The handle passed to the function is not valid."
|
||||
case C.SEC_E_INVALID_TOKEN:
|
||||
s = "The token passed to the function is not valid."
|
||||
case C.SEC_E_ISSUING_CA_UNTRUSTED:
|
||||
s = "An untrusted certification authority (CA) was detected while processing the smart card certificate used for authentication."
|
||||
case C.SEC_E_ISSUING_CA_UNTRUSTED_KDC:
|
||||
s = "An untrusted CA was detected while processing the domain controller certificate used for authentication. The system event log contains additional information."
|
||||
case C.SEC_E_KDC_CERT_EXPIRED:
|
||||
s = "The domain controller certificate used for smart card logon has expired."
|
||||
case C.SEC_E_KDC_CERT_REVOKED:
|
||||
s = "The domain controller certificate used for smart card logon has been revoked."
|
||||
case C.SEC_E_KDC_INVALID_REQUEST:
|
||||
s = "A request that is not valid was sent to the KDC."
|
||||
case C.SEC_E_KDC_UNABLE_TO_REFER:
|
||||
s = "The KDC was unable to generate a referral for the service requested."
|
||||
case C.SEC_E_KDC_UNKNOWN_ETYPE:
|
||||
s = "The requested encryption type is not supported by the KDC."
|
||||
case C.SEC_E_LOGON_DENIED:
|
||||
s = "The logon has been denied"
|
||||
case C.SEC_E_MAX_REFERRALS_EXCEEDED:
|
||||
s = "The number of maximum ticket referrals has been exceeded."
|
||||
case C.SEC_E_MESSAGE_ALTERED:
|
||||
s = "The message supplied for verification has been altered."
|
||||
case C.SEC_E_MULTIPLE_ACCOUNTS:
|
||||
s = "The received certificate was mapped to multiple accounts."
|
||||
case C.SEC_E_MUST_BE_KDC:
|
||||
s = "The local computer must be a Kerberos domain controller (KDC)"
|
||||
case C.SEC_E_NO_AUTHENTICATING_AUTHORITY:
|
||||
s = "No authority could be contacted for authentication."
|
||||
case C.SEC_E_NO_CREDENTIALS:
|
||||
s = "No credentials are available."
|
||||
case C.SEC_E_NO_IMPERSONATION:
|
||||
s = "No impersonation is allowed for this context."
|
||||
case C.SEC_E_NO_IP_ADDRESSES:
|
||||
s = "Unable to accomplish the requested task because the local computer does not have any IP addresses."
|
||||
case C.SEC_E_NO_KERB_KEY:
|
||||
s = "No Kerberos key was found."
|
||||
case C.SEC_E_NO_PA_DATA:
|
||||
s = "Policy administrator (PA) data is needed to determine the encryption type"
|
||||
case C.SEC_E_NO_S4U_PROT_SUPPORT:
|
||||
s = "The Kerberos subsystem encountered an error. A service for user protocol request was made against a domain controller which does not support service for a user."
|
||||
case C.SEC_E_NO_TGT_REPLY:
|
||||
s = "The client is trying to negotiate a context and the server requires a user-to-user connection"
|
||||
case C.SEC_E_NOT_OWNER:
|
||||
s = "The caller of the function does not own the credentials."
|
||||
case C.SEC_E_OK:
|
||||
s = "The operation completed successfully."
|
||||
case C.SEC_E_OUT_OF_SEQUENCE:
|
||||
s = "The message supplied for verification is out of sequence."
|
||||
case C.SEC_E_PKINIT_CLIENT_FAILURE:
|
||||
s = "The smart card certificate used for authentication is not trusted."
|
||||
case C.SEC_E_PKINIT_NAME_MISMATCH:
|
||||
s = "The client certificate does not contain a valid UPN or does not match the client name in the logon request."
|
||||
case C.SEC_E_QOP_NOT_SUPPORTED:
|
||||
s = "The quality of protection attribute is not supported by this package."
|
||||
case C.SEC_E_REVOCATION_OFFLINE_C:
|
||||
s = "The revocation status of the smart card certificate used for authentication could not be determined."
|
||||
case C.SEC_E_REVOCATION_OFFLINE_KDC:
|
||||
s = "The revocation status of the domain controller certificate used for smart card authentication could not be determined. The system event log contains additional information."
|
||||
case C.SEC_E_SECPKG_NOT_FOUND:
|
||||
s = "The security package was not recognized."
|
||||
case C.SEC_E_SECURITY_QOS_FAILED:
|
||||
s = "The security context could not be established due to a failure in the requested quality of service (for example"
|
||||
case C.SEC_E_SHUTDOWN_IN_PROGRESS:
|
||||
s = "A system shutdown is in progress."
|
||||
case C.SEC_E_SMARTCARD_CERT_EXPIRED:
|
||||
s = "The smart card certificate used for authentication has expired."
|
||||
case C.SEC_E_SMARTCARD_CERT_REVOKED:
|
||||
s = "The smart card certificate used for authentication has been revoked. Additional information may exist in the event log."
|
||||
case C.SEC_E_SMARTCARD_LOGON_REQUIRED:
|
||||
s = "Smart card logon is required and was not used."
|
||||
case C.SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
|
||||
s = "The other end of the security negotiation requires strong cryptography"
|
||||
case C.SEC_E_TARGET_UNKNOWN:
|
||||
s = "The target was not recognized."
|
||||
case C.SEC_E_TIME_SKEW:
|
||||
s = "The clocks on the client and server computers do not match."
|
||||
case C.SEC_E_TOO_MANY_PRINCIPALS:
|
||||
s = "The KDC reply contained more than one principal name."
|
||||
case C.SEC_E_UNFINISHED_CONTEXT_DELETED:
|
||||
s = "A security context was deleted before the context was completed. This is considered a logon failure."
|
||||
case C.SEC_E_UNKNOWN_CREDENTIALS:
|
||||
s = "The credentials provided were not recognized."
|
||||
case C.SEC_E_UNSUPPORTED_FUNCTION:
|
||||
s = "The requested function is not supported."
|
||||
case C.SEC_E_UNSUPPORTED_PREAUTH:
|
||||
s = "An unsupported preauthentication mechanism was presented to the Kerberos package."
|
||||
case C.SEC_E_UNTRUSTED_ROOT:
|
||||
s = "The certificate chain was issued by an authority that is not trusted."
|
||||
case C.SEC_E_WRONG_CREDENTIAL_HANDLE:
|
||||
s = "The supplied credential handle does not match the credential associated with the security context."
|
||||
case C.SEC_E_WRONG_PRINCIPAL:
|
||||
s = "The target principal name is incorrect."
|
||||
case C.SEC_I_COMPLETE_AND_CONTINUE:
|
||||
s = "The function completed successfully"
|
||||
case C.SEC_I_COMPLETE_NEEDED:
|
||||
s = "The function completed successfully"
|
||||
case C.SEC_I_CONTEXT_EXPIRED:
|
||||
s = "The message sender has finished using the connection and has initiated a shutdown. For information about initiating or recognizing a shutdown"
|
||||
case C.SEC_I_CONTINUE_NEEDED:
|
||||
s = "The function completed successfully"
|
||||
case C.SEC_I_INCOMPLETE_CREDENTIALS:
|
||||
s = "The credentials supplied were not complete and could not be verified. Additional information can be returned from the context."
|
||||
case C.SEC_I_LOCAL_LOGON:
|
||||
s = "The logon was completed"
|
||||
case C.SEC_I_NO_LSA_CONTEXT:
|
||||
s = "There is no LSA mode context associated with this context."
|
||||
case C.SEC_I_RENEGOTIATE:
|
||||
s = "The context data must be renegotiated with the peer."
|
||||
default:
|
||||
return fmt.Errorf("%s: 0x%x", prefix, uint32(status))
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s: %s(0x%x)", prefix, s, uint32(status))
|
||||
}
|
||||
218
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.c
generated
vendored
Executable file
218
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.c
generated
vendored
Executable file
@@ -0,0 +1,218 @@
|
||||
//+build gssapi,windows
|
||||
|
||||
#include "sspi_wrapper.h"
|
||||
|
||||
static HINSTANCE sspi_secur32_dll = NULL;
|
||||
static PSecurityFunctionTable sspi_functions = NULL;
|
||||
static const LPSTR SSPI_PACKAGE_NAME = "kerberos";
|
||||
|
||||
int sspi_init(
|
||||
)
|
||||
{
|
||||
sspi_secur32_dll = LoadLibrary("secur32.dll");
|
||||
if (!sspi_secur32_dll) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
INIT_SECURITY_INTERFACE init_security_interface = (INIT_SECURITY_INTERFACE)GetProcAddress(sspi_secur32_dll, SECURITY_ENTRYPOINT);
|
||||
if (!init_security_interface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sspi_functions = (*init_security_interface)();
|
||||
if (!sspi_functions) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return SSPI_OK;
|
||||
}
|
||||
|
||||
int sspi_client_init(
|
||||
sspi_client_state *client,
|
||||
char* username,
|
||||
char* password
|
||||
)
|
||||
{
|
||||
TimeStamp timestamp;
|
||||
|
||||
if (username) {
|
||||
if (password) {
|
||||
SEC_WINNT_AUTH_IDENTITY auth_identity;
|
||||
|
||||
#ifdef _UNICODE
|
||||
auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
||||
#else
|
||||
auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
|
||||
#endif
|
||||
auth_identity.User = (LPSTR) username;
|
||||
auth_identity.UserLength = strlen(username);
|
||||
auth_identity.Password = (LPSTR) password;
|
||||
auth_identity.PasswordLength = strlen(password);
|
||||
auth_identity.Domain = NULL;
|
||||
auth_identity.DomainLength = 0;
|
||||
client->status = sspi_functions->AcquireCredentialsHandle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_identity, NULL, NULL, &client->cred, ×tamp);
|
||||
} else {
|
||||
client->status = sspi_functions->AcquireCredentialsHandle(username, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &client->cred, ×tamp);
|
||||
}
|
||||
} else {
|
||||
client->status = sspi_functions->AcquireCredentialsHandle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &client->cred, ×tamp);
|
||||
}
|
||||
|
||||
if (client->status != SEC_E_OK) {
|
||||
return SSPI_ERROR;
|
||||
}
|
||||
|
||||
return SSPI_OK;
|
||||
}
|
||||
|
||||
int sspi_client_username(
|
||||
sspi_client_state *client,
|
||||
char** username
|
||||
)
|
||||
{
|
||||
SecPkgCredentials_Names names;
|
||||
client->status = sspi_functions->QueryCredentialsAttributes(&client->cred, SECPKG_CRED_ATTR_NAMES, &names);
|
||||
|
||||
if (client->status != SEC_E_OK) {
|
||||
return SSPI_ERROR;
|
||||
}
|
||||
|
||||
int len = strlen(names.sUserName) + 1;
|
||||
*username = malloc(len);
|
||||
memcpy(*username, names.sUserName, len);
|
||||
|
||||
sspi_functions->FreeContextBuffer(names.sUserName);
|
||||
|
||||
return SSPI_OK;
|
||||
}
|
||||
|
||||
int sspi_client_negotiate(
|
||||
sspi_client_state *client,
|
||||
char* spn,
|
||||
PVOID input,
|
||||
ULONG input_length,
|
||||
PVOID* output,
|
||||
ULONG* output_length
|
||||
)
|
||||
{
|
||||
SecBufferDesc inbuf;
|
||||
SecBuffer in_bufs[1];
|
||||
SecBufferDesc outbuf;
|
||||
SecBuffer out_bufs[1];
|
||||
|
||||
if (client->has_ctx > 0) {
|
||||
inbuf.ulVersion = SECBUFFER_VERSION;
|
||||
inbuf.cBuffers = 1;
|
||||
inbuf.pBuffers = in_bufs;
|
||||
in_bufs[0].pvBuffer = input;
|
||||
in_bufs[0].cbBuffer = input_length;
|
||||
in_bufs[0].BufferType = SECBUFFER_TOKEN;
|
||||
}
|
||||
|
||||
outbuf.ulVersion = SECBUFFER_VERSION;
|
||||
outbuf.cBuffers = 1;
|
||||
outbuf.pBuffers = out_bufs;
|
||||
out_bufs[0].pvBuffer = NULL;
|
||||
out_bufs[0].cbBuffer = 0;
|
||||
out_bufs[0].BufferType = SECBUFFER_TOKEN;
|
||||
|
||||
ULONG context_attr = 0;
|
||||
|
||||
client->status = sspi_functions->InitializeSecurityContext(
|
||||
&client->cred,
|
||||
client->has_ctx > 0 ? &client->ctx : NULL,
|
||||
(LPSTR) spn,
|
||||
ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MUTUAL_AUTH,
|
||||
0,
|
||||
SECURITY_NETWORK_DREP,
|
||||
client->has_ctx > 0 ? &inbuf : NULL,
|
||||
0,
|
||||
&client->ctx,
|
||||
&outbuf,
|
||||
&context_attr,
|
||||
NULL);
|
||||
|
||||
if (client->status != SEC_E_OK && client->status != SEC_I_CONTINUE_NEEDED) {
|
||||
return SSPI_ERROR;
|
||||
}
|
||||
|
||||
client->has_ctx = 1;
|
||||
|
||||
*output = malloc(out_bufs[0].cbBuffer);
|
||||
*output_length = out_bufs[0].cbBuffer;
|
||||
memcpy(*output, out_bufs[0].pvBuffer, *output_length);
|
||||
sspi_functions->FreeContextBuffer(out_bufs[0].pvBuffer);
|
||||
|
||||
if (client->status == SEC_I_CONTINUE_NEEDED) {
|
||||
return SSPI_CONTINUE;
|
||||
}
|
||||
|
||||
return SSPI_OK;
|
||||
}
|
||||
|
||||
int sspi_client_wrap_msg(
|
||||
sspi_client_state *client,
|
||||
PVOID input,
|
||||
ULONG input_length,
|
||||
PVOID* output,
|
||||
ULONG* output_length
|
||||
)
|
||||
{
|
||||
SecPkgContext_Sizes sizes;
|
||||
|
||||
client->status = sspi_functions->QueryContextAttributes(&client->ctx, SECPKG_ATTR_SIZES, &sizes);
|
||||
if (client->status != SEC_E_OK) {
|
||||
return SSPI_ERROR;
|
||||
}
|
||||
|
||||
char *msg = malloc((sizes.cbSecurityTrailer + input_length + sizes.cbBlockSize) * sizeof(char));
|
||||
memcpy(&msg[sizes.cbSecurityTrailer], input, input_length);
|
||||
|
||||
SecBuffer wrap_bufs[3];
|
||||
SecBufferDesc wrap_buf_desc;
|
||||
wrap_buf_desc.cBuffers = 3;
|
||||
wrap_buf_desc.pBuffers = wrap_bufs;
|
||||
wrap_buf_desc.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
wrap_bufs[0].cbBuffer = sizes.cbSecurityTrailer;
|
||||
wrap_bufs[0].BufferType = SECBUFFER_TOKEN;
|
||||
wrap_bufs[0].pvBuffer = msg;
|
||||
|
||||
wrap_bufs[1].cbBuffer = input_length;
|
||||
wrap_bufs[1].BufferType = SECBUFFER_DATA;
|
||||
wrap_bufs[1].pvBuffer = msg + sizes.cbSecurityTrailer;
|
||||
|
||||
wrap_bufs[2].cbBuffer = sizes.cbBlockSize;
|
||||
wrap_bufs[2].BufferType = SECBUFFER_PADDING;
|
||||
wrap_bufs[2].pvBuffer = msg + sizes.cbSecurityTrailer + input_length;
|
||||
|
||||
client->status = sspi_functions->EncryptMessage(&client->ctx, SECQOP_WRAP_NO_ENCRYPT, &wrap_buf_desc, 0);
|
||||
if (client->status != SEC_E_OK) {
|
||||
free(msg);
|
||||
return SSPI_ERROR;
|
||||
}
|
||||
|
||||
*output_length = wrap_bufs[0].cbBuffer + wrap_bufs[1].cbBuffer + wrap_bufs[2].cbBuffer;
|
||||
*output = malloc(*output_length);
|
||||
|
||||
memcpy(*output, wrap_bufs[0].pvBuffer, wrap_bufs[0].cbBuffer);
|
||||
memcpy(*output + wrap_bufs[0].cbBuffer, wrap_bufs[1].pvBuffer, wrap_bufs[1].cbBuffer);
|
||||
memcpy(*output + wrap_bufs[0].cbBuffer + wrap_bufs[1].cbBuffer, wrap_bufs[2].pvBuffer, wrap_bufs[2].cbBuffer);
|
||||
|
||||
free(msg);
|
||||
|
||||
return SSPI_OK;
|
||||
}
|
||||
|
||||
int sspi_client_destroy(
|
||||
sspi_client_state *client
|
||||
)
|
||||
{
|
||||
if (client->has_ctx > 0) {
|
||||
sspi_functions->DeleteSecurityContext(&client->ctx);
|
||||
}
|
||||
|
||||
sspi_functions->FreeCredentialsHandle(&client->cred);
|
||||
|
||||
return SSPI_OK;
|
||||
}
|
||||
58
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.h
generated
vendored
Executable file
58
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.h
generated
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
//+build gssapi,windows
|
||||
|
||||
#ifndef SSPI_WRAPPER_H
|
||||
#define SSPI_WRAPPER_H
|
||||
|
||||
#define SECURITY_WIN32 1 /* Required for SSPI */
|
||||
|
||||
#include <windows.h>
|
||||
#include <sspi.h>
|
||||
|
||||
#define SSPI_OK 0
|
||||
#define SSPI_CONTINUE 1
|
||||
#define SSPI_ERROR 2
|
||||
|
||||
typedef struct {
|
||||
CredHandle cred;
|
||||
CtxtHandle ctx;
|
||||
|
||||
int has_ctx;
|
||||
|
||||
SECURITY_STATUS status;
|
||||
} sspi_client_state;
|
||||
|
||||
int sspi_init();
|
||||
|
||||
int sspi_client_init(
|
||||
sspi_client_state *client,
|
||||
char* username,
|
||||
char* password
|
||||
);
|
||||
|
||||
int sspi_client_username(
|
||||
sspi_client_state *client,
|
||||
char** username
|
||||
);
|
||||
|
||||
int sspi_client_negotiate(
|
||||
sspi_client_state *client,
|
||||
char* spn,
|
||||
PVOID input,
|
||||
ULONG input_length,
|
||||
PVOID* output,
|
||||
ULONG* output_length
|
||||
);
|
||||
|
||||
int sspi_client_wrap_msg(
|
||||
sspi_client_state *client,
|
||||
PVOID input,
|
||||
ULONG input_length,
|
||||
PVOID* output,
|
||||
ULONG* output_length
|
||||
);
|
||||
|
||||
int sspi_client_destroy(
|
||||
sspi_client_state *client
|
||||
);
|
||||
|
||||
#endif
|
||||
94
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbcr.go
generated
vendored
Executable file
94
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbcr.go
generated
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
|
||||
"io"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
|
||||
)
|
||||
|
||||
// MONGODBCR is the mechanism name for MONGODB-CR.
|
||||
//
|
||||
// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
|
||||
const MONGODBCR = "MONGODB-CR"
|
||||
|
||||
func newMongoDBCRAuthenticator(cred *Cred) (Authenticator, error) {
|
||||
return &MongoDBCRAuthenticator{
|
||||
DB: cred.Source,
|
||||
Username: cred.Username,
|
||||
Password: cred.Password,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MongoDBCRAuthenticator uses the MONGODB-CR algorithm to authenticate a connection.
|
||||
//
|
||||
// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
|
||||
type MongoDBCRAuthenticator struct {
|
||||
DB string
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
// Auth authenticates the connection.
|
||||
//
|
||||
// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
|
||||
func (a *MongoDBCRAuthenticator) Auth(ctx context.Context, _ description.Server, conn driver.Connection) error {
|
||||
|
||||
db := a.DB
|
||||
if db == "" {
|
||||
db = defaultAuthDB
|
||||
}
|
||||
|
||||
doc := bsoncore.BuildDocumentFromElements(nil, bsoncore.AppendInt32Element(nil, "getnonce", 1))
|
||||
cmd := operation.NewCommand(doc).Database(db).Deployment(driver.SingleConnectionDeployment{conn})
|
||||
err := cmd.Execute(ctx)
|
||||
if err != nil {
|
||||
return newError(err, MONGODBCR)
|
||||
}
|
||||
rdr := cmd.Result()
|
||||
|
||||
var getNonceResult struct {
|
||||
Nonce string `bson:"nonce"`
|
||||
}
|
||||
|
||||
err = bson.Unmarshal(rdr, &getNonceResult)
|
||||
if err != nil {
|
||||
return newAuthError("unmarshal error", err)
|
||||
}
|
||||
|
||||
doc = bsoncore.BuildDocumentFromElements(nil,
|
||||
bsoncore.AppendInt32Element(nil, "authenticate", 1),
|
||||
bsoncore.AppendStringElement(nil, "user", a.Username),
|
||||
bsoncore.AppendStringElement(nil, "nonce", getNonceResult.Nonce),
|
||||
bsoncore.AppendStringElement(nil, "key", a.createKey(getNonceResult.Nonce)),
|
||||
)
|
||||
cmd = operation.NewCommand(doc).Database(db).Deployment(driver.SingleConnectionDeployment{conn})
|
||||
err = cmd.Execute(ctx)
|
||||
if err != nil {
|
||||
return newError(err, MONGODBCR)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MongoDBCRAuthenticator) createKey(nonce string) string {
|
||||
h := md5.New()
|
||||
|
||||
_, _ = io.WriteString(h, nonce)
|
||||
_, _ = io.WriteString(h, a.Username)
|
||||
_, _ = io.WriteString(h, mongoPasswordDigest(a.Username, a.Password))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
56
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/plain.go
generated
vendored
Executable file
56
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/plain.go
generated
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
)
|
||||
|
||||
// PLAIN is the mechanism name for PLAIN.
|
||||
const PLAIN = "PLAIN"
|
||||
|
||||
func newPlainAuthenticator(cred *Cred) (Authenticator, error) {
|
||||
return &PlainAuthenticator{
|
||||
Username: cred.Username,
|
||||
Password: cred.Password,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PlainAuthenticator uses the PLAIN algorithm over SASL to authenticate a connection.
|
||||
type PlainAuthenticator struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
// Auth authenticates the connection.
|
||||
func (a *PlainAuthenticator) Auth(ctx context.Context, _ description.Server, conn driver.Connection) error {
|
||||
return ConductSaslConversation(ctx, conn, "$external", &plainSaslClient{
|
||||
username: a.Username,
|
||||
password: a.Password,
|
||||
})
|
||||
}
|
||||
|
||||
type plainSaslClient struct {
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
func (c *plainSaslClient) Start() (string, []byte, error) {
|
||||
b := []byte("\x00" + c.username + "\x00" + c.password)
|
||||
return PLAIN, b, nil
|
||||
}
|
||||
|
||||
func (c *plainSaslClient) Next(challenge []byte) ([]byte, error) {
|
||||
return nil, newAuthError("unexpected server challenge", nil)
|
||||
}
|
||||
|
||||
func (c *plainSaslClient) Completed() bool {
|
||||
return true
|
||||
}
|
||||
112
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/sasl.go
generated
vendored
Executable file
112
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/sasl.go
generated
vendored
Executable file
@@ -0,0 +1,112 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
|
||||
)
|
||||
|
||||
// SaslClient is the client piece of a sasl conversation.
|
||||
type SaslClient interface {
|
||||
Start() (string, []byte, error)
|
||||
Next(challenge []byte) ([]byte, error)
|
||||
Completed() bool
|
||||
}
|
||||
|
||||
// SaslClientCloser is a SaslClient that has resources to clean up.
|
||||
type SaslClientCloser interface {
|
||||
SaslClient
|
||||
Close()
|
||||
}
|
||||
|
||||
// ConductSaslConversation handles running a sasl conversation with MongoDB.
|
||||
func ConductSaslConversation(ctx context.Context, conn driver.Connection, db string, client SaslClient) error {
|
||||
|
||||
if db == "" {
|
||||
db = defaultAuthDB
|
||||
}
|
||||
|
||||
if closer, ok := client.(SaslClientCloser); ok {
|
||||
defer closer.Close()
|
||||
}
|
||||
|
||||
mech, payload, err := client.Start()
|
||||
if err != nil {
|
||||
return newError(err, mech)
|
||||
}
|
||||
|
||||
doc := bsoncore.BuildDocumentFromElements(nil,
|
||||
bsoncore.AppendInt32Element(nil, "saslStart", 1),
|
||||
bsoncore.AppendStringElement(nil, "mechanism", mech),
|
||||
bsoncore.AppendBinaryElement(nil, "payload", 0x00, payload),
|
||||
)
|
||||
saslStartCmd := operation.NewCommand(doc).Database(db).Deployment(driver.SingleConnectionDeployment{conn})
|
||||
|
||||
type saslResponse struct {
|
||||
ConversationID int `bson:"conversationId"`
|
||||
Code int `bson:"code"`
|
||||
Done bool `bson:"done"`
|
||||
Payload []byte `bson:"payload"`
|
||||
}
|
||||
|
||||
var saslResp saslResponse
|
||||
|
||||
err = saslStartCmd.Execute(ctx)
|
||||
if err != nil {
|
||||
return newError(err, mech)
|
||||
}
|
||||
rdr := saslStartCmd.Result()
|
||||
|
||||
err = bson.Unmarshal(rdr, &saslResp)
|
||||
if err != nil {
|
||||
return newAuthError("unmarshall error", err)
|
||||
}
|
||||
|
||||
cid := saslResp.ConversationID
|
||||
|
||||
for {
|
||||
if saslResp.Code != 0 {
|
||||
return newError(err, mech)
|
||||
}
|
||||
|
||||
if saslResp.Done && client.Completed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
payload, err = client.Next(saslResp.Payload)
|
||||
if err != nil {
|
||||
return newError(err, mech)
|
||||
}
|
||||
|
||||
if saslResp.Done && client.Completed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
doc := bsoncore.BuildDocumentFromElements(nil,
|
||||
bsoncore.AppendInt32Element(nil, "saslContinue", 1),
|
||||
bsoncore.AppendInt32Element(nil, "conversationId", int32(cid)),
|
||||
bsoncore.AppendBinaryElement(nil, "payload", 0x00, payload),
|
||||
)
|
||||
saslContinueCmd := operation.NewCommand(doc).Database(db).Deployment(driver.SingleConnectionDeployment{conn})
|
||||
|
||||
err = saslContinueCmd.Execute(ctx)
|
||||
if err != nil {
|
||||
return newError(err, mech)
|
||||
}
|
||||
rdr = saslContinueCmd.Result()
|
||||
|
||||
err = bson.Unmarshal(rdr, &saslResp)
|
||||
if err != nil {
|
||||
return newAuthError("unmarshal error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
102
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/scram.go
generated
vendored
Executable file
102
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/scram.go
generated
vendored
Executable file
@@ -0,0 +1,102 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Copyright (C) MongoDB, Inc. 2018-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/xdg/scram"
|
||||
"github.com/xdg/stringprep"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
)
|
||||
|
||||
// SCRAMSHA1 holds the mechanism name "SCRAM-SHA-1"
|
||||
const SCRAMSHA1 = "SCRAM-SHA-1"
|
||||
|
||||
// SCRAMSHA256 holds the mechanism name "SCRAM-SHA-256"
|
||||
const SCRAMSHA256 = "SCRAM-SHA-256"
|
||||
|
||||
func newScramSHA1Authenticator(cred *Cred) (Authenticator, error) {
|
||||
passdigest := mongoPasswordDigest(cred.Username, cred.Password)
|
||||
client, err := scram.SHA1.NewClientUnprepped(cred.Username, passdigest, "")
|
||||
if err != nil {
|
||||
return nil, newAuthError("error initializing SCRAM-SHA-1 client", err)
|
||||
}
|
||||
client.WithMinIterations(4096)
|
||||
return &ScramAuthenticator{
|
||||
mechanism: SCRAMSHA1,
|
||||
source: cred.Source,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newScramSHA256Authenticator(cred *Cred) (Authenticator, error) {
|
||||
passprep, err := stringprep.SASLprep.Prepare(cred.Password)
|
||||
if err != nil {
|
||||
return nil, newAuthError(fmt.Sprintf("error SASLprepping password '%s'", cred.Password), err)
|
||||
}
|
||||
client, err := scram.SHA256.NewClientUnprepped(cred.Username, passprep, "")
|
||||
if err != nil {
|
||||
return nil, newAuthError("error initializing SCRAM-SHA-256 client", err)
|
||||
}
|
||||
client.WithMinIterations(4096)
|
||||
return &ScramAuthenticator{
|
||||
mechanism: SCRAMSHA256,
|
||||
source: cred.Source,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ScramAuthenticator uses the SCRAM algorithm over SASL to authenticate a connection.
|
||||
type ScramAuthenticator struct {
|
||||
mechanism string
|
||||
source string
|
||||
client *scram.Client
|
||||
}
|
||||
|
||||
// Auth authenticates the connection.
|
||||
func (a *ScramAuthenticator) Auth(ctx context.Context, _ description.Server, conn driver.Connection) error {
|
||||
adapter := &scramSaslAdapter{conversation: a.client.NewConversation(), mechanism: a.mechanism}
|
||||
err := ConductSaslConversation(ctx, conn, a.source, adapter)
|
||||
if err != nil {
|
||||
return newAuthError("sasl conversation error", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type scramSaslAdapter struct {
|
||||
mechanism string
|
||||
conversation *scram.ClientConversation
|
||||
}
|
||||
|
||||
func (a *scramSaslAdapter) Start() (string, []byte, error) {
|
||||
step, err := a.conversation.Step("")
|
||||
if err != nil {
|
||||
return a.mechanism, nil, err
|
||||
}
|
||||
return a.mechanism, []byte(step), nil
|
||||
}
|
||||
|
||||
func (a *scramSaslAdapter) Next(challenge []byte) ([]byte, error) {
|
||||
step, err := a.conversation.Step(string(challenge))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(step), nil
|
||||
}
|
||||
|
||||
func (a *scramSaslAdapter) Completed() bool {
|
||||
return a.conversation.Done()
|
||||
}
|
||||
23
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/util.go
generated
vendored
Executable file
23
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/util.go
generated
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const defaultAuthDB = "admin"
|
||||
|
||||
func mongoPasswordDigest(username, password string) string {
|
||||
h := md5.New()
|
||||
_, _ = io.WriteString(h, username)
|
||||
_, _ = io.WriteString(h, ":mongo:")
|
||||
_, _ = io.WriteString(h, password)
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
49
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go
generated
vendored
Executable file
49
vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go
generated
vendored
Executable file
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/description"
|
||||
"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
|
||||
)
|
||||
|
||||
// MongoDBX509 is the mechanism name for MongoDBX509.
|
||||
const MongoDBX509 = "MONGODB-X509"
|
||||
|
||||
func newMongoDBX509Authenticator(cred *Cred) (Authenticator, error) {
|
||||
return &MongoDBX509Authenticator{User: cred.Username}, nil
|
||||
}
|
||||
|
||||
// MongoDBX509Authenticator uses X.509 certificates over TLS to authenticate a connection.
|
||||
type MongoDBX509Authenticator struct {
|
||||
User string
|
||||
}
|
||||
|
||||
// Auth implements the Authenticator interface.
|
||||
func (a *MongoDBX509Authenticator) Auth(ctx context.Context, desc description.Server, conn driver.Connection) error {
|
||||
requestDoc := bsoncore.AppendInt32Element(nil, "authenticate", 1)
|
||||
requestDoc = bsoncore.AppendStringElement(requestDoc, "mechanism", MongoDBX509)
|
||||
|
||||
if desc.WireVersion == nil || desc.WireVersion.Max < 5 {
|
||||
requestDoc = bsoncore.AppendStringElement(requestDoc, "user", a.User)
|
||||
}
|
||||
|
||||
authCmd := operation.
|
||||
NewCommand(bsoncore.BuildDocument(nil, requestDoc)).
|
||||
Database("$external").
|
||||
Deployment(driver.SingleConnectionDeployment{conn})
|
||||
err := authCmd.Execute(ctx)
|
||||
if err != nil {
|
||||
return newAuthError("round trip error", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user