Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
  • renovate/git.autistici.org-ai3-go-common-digest
  • renovate/github.com-go-ldap-ldap-v3-3.x
3 results

Target

Select target project
  • ai3/tools/postfix-policyd-proxy
  • svp-bot/postfix-policyd-proxy
2 results
Select Git revision
  • lintian-fixes
  • master
  • renovate/github.com-coreos-go-systemd-v22-22.x
  • renovate/github.com-go-ldap-ldap-v3-3.x
4 results
Show changes
Commits on Source (19)
Showing
with 742 additions and 46 deletions
include: "https://git.autistici.org/ai3/build-deb/raw/master/ci-common.yml" include: "https://git.autistici.org/pipelines/debian/raw/master/common.yml"
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"syscall" "syscall"
"git.autistici.org/ai3/go-common/unix" "git.autistici.org/ai3/go-common/unix"
"github.com/coreos/go-systemd/daemon" "github.com/coreos/go-systemd/v22/daemon"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"git.autistici.org/ai3/tools/postfix-policyd-proxy" "git.autistici.org/ai3/tools/postfix-policyd-proxy"
......
11
...@@ -2,12 +2,13 @@ Source: postfix-policyd-proxy ...@@ -2,12 +2,13 @@ Source: postfix-policyd-proxy
Section: unknown Section: unknown
Priority: optional Priority: optional
Maintainer: ale <ale@incal.net> Maintainer: ale <ale@incal.net>
Build-Depends: debhelper (>= 11), dh-golang, golang-any Build-Depends: debhelper-compat (= 12), dh-golang, golang-any
Standards-Version: 4.1.3 Standards-Version: 4.1.3
XS-Go-Import-Path: git.autistici.org/ai3/tools/postfix-policyd-proxy XS-Go-Import-Path: git.autistici.org/ai3/tools/postfix-policyd-proxy
Package: postfix-policyd-proxy Package: postfix-policyd-proxy
Architecture: any Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends} Depends: ${shlibs:Depends}, ${misc:Depends}
Built-Using: ${misc:Built-Using}
Description: Postfix policyd proxy Description: Postfix policyd proxy
Proxy for postfix policy services, directed by a LDAP backend. Proxy for postfix policy services, directed by a LDAP backend.
...@@ -2,13 +2,10 @@ ...@@ -2,13 +2,10 @@
export DH_VERBOSE := 1 export DH_VERBOSE := 1
export DH_GOLANG_EXCLUDES := vendor export DH_GOLANG_EXCLUDES := vendor
export DH_GOLANG_INSTALL_ALL := 1
export GO111MODULE := off export GO111MODULE := off
export GOCACHE := on
%: %:
dh $@ --with=golang dh $@ --with=golang --buildsystem=golang
override_dh_auto_install: override_dh_auto_install:
dh_auto_install -- --no-source dh_auto_install -- --no-source
module git.autistici.org/ai3/tools/postfix-policyd-proxy module git.autistici.org/ai3/tools/postfix-policyd-proxy
go 1.14
require ( require (
git.autistici.org/ai3/go-common v0.0.0-20200511175437-130368249b31 git.autistici.org/ai3/go-common v0.0.0-20210118064555-73f00db54723
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/coreos/go-systemd/v22 v22.5.0
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/go-ldap/ldap/v3 v3.2.4
github.com/modern-go/reflect2 v1.0.1 // indirect gopkg.in/yaml.v3 v3.0.1
gopkg.in/ldap.v3 v3.1.0
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86
) )
This diff is collapsed.
...@@ -6,7 +6,7 @@ import ( ...@@ -6,7 +6,7 @@ import (
"strings" "strings"
"git.autistici.org/ai3/go-common/ldap" "git.autistici.org/ai3/go-common/ldap"
"gopkg.in/ldap.v3" "github.com/go-ldap/ldap/v3"
) )
const poolSize = 3 const poolSize = 3
......
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}
...@@ -3,7 +3,7 @@ package ldaputil ...@@ -3,7 +3,7 @@ package ldaputil
import ( import (
"fmt" "fmt"
"gopkg.in/ldap.v3" "github.com/go-ldap/ldap/v3"
) )
// ParseScope parses a string representation of an LDAP scope into the // ParseScope parses a string representation of an LDAP scope into the
......
...@@ -7,10 +7,10 @@ import ( ...@@ -7,10 +7,10 @@ import (
"net/url" "net/url"
"time" "time"
"github.com/cenkalti/backoff" "github.com/cenkalti/backoff/v4"
"github.com/go-ldap/ldap/v3"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"gopkg.in/ldap.v3"
) )
// Parameters that define the exponential backoff algorithm used. // Parameters that define the exponential backoff algorithm used.
......
...@@ -14,7 +14,7 @@ import ( ...@@ -14,7 +14,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/coreos/go-systemd/activation" "github.com/coreos/go-systemd/v22/activation"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/theckman/go-flock" "github.com/theckman/go-flock"
) )
......
sudo: false
language: go
before_script:
- go get -u golang.org/x/lint/golint
go:
- 1.10.x
- master
script:
- test -z "$(gofmt -s -l . | tee /dev/stderr)"
- test -z "$(golint ./... | tee /dev/stderr)"
- go vet ./...
- go build -v ./...
- go test -v ./...
The MIT License (MIT)
Copyright (c) 2016 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# go-ntlmssp
Golang package that provides NTLM/Negotiate authentication over HTTP
[![GoDoc](https://godoc.org/github.com/Azure/go-ntlmssp?status.svg)](https://godoc.org/github.com/Azure/go-ntlmssp) [![Build Status](https://travis-ci.org/Azure/go-ntlmssp.svg?branch=dev)](https://travis-ci.org/Azure/go-ntlmssp)
Protocol details from https://msdn.microsoft.com/en-us/library/cc236621.aspx
Implementation hints from http://davenport.sourceforge.net/ntlm.html
This package only implements authentication, no key exchange or encryption. It
only supports Unicode (UTF16LE) encoding of protocol strings, no OEM encoding.
This package implements NTLMv2.
# Usage
```
url, user, password := "http://www.example.com/secrets", "robpike", "pw123"
client := &http.Client{
Transport: ntlmssp.Negotiator{
RoundTripper:&http.Transport{},
},
}
req, _ := http.NewRequest("GET", url, nil)
req.SetBasicAuth(user, password)
res, _ := client.Do(req)
```
-----
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
package ntlmssp
import (
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"errors"
"strings"
"time"
)
type authenicateMessage struct {
LmChallengeResponse []byte
NtChallengeResponse []byte
TargetName string
UserName string
// only set if negotiateFlag_NTLMSSP_NEGOTIATE_KEY_EXCH
EncryptedRandomSessionKey []byte
NegotiateFlags negotiateFlags
MIC []byte
}
type authenticateMessageFields struct {
messageHeader
LmChallengeResponse varField
NtChallengeResponse varField
TargetName varField
UserName varField
Workstation varField
_ [8]byte
NegotiateFlags negotiateFlags
}
func (m authenicateMessage) MarshalBinary() ([]byte, error) {
if !m.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEUNICODE) {
return nil, errors.New("Only unicode is supported")
}
target, user := toUnicode(m.TargetName), toUnicode(m.UserName)
workstation := toUnicode("go-ntlmssp")
ptr := binary.Size(&authenticateMessageFields{})
f := authenticateMessageFields{
messageHeader: newMessageHeader(3),
NegotiateFlags: m.NegotiateFlags,
LmChallengeResponse: newVarField(&ptr, len(m.LmChallengeResponse)),
NtChallengeResponse: newVarField(&ptr, len(m.NtChallengeResponse)),
TargetName: newVarField(&ptr, len(target)),
UserName: newVarField(&ptr, len(user)),
Workstation: newVarField(&ptr, len(workstation)),
}
f.NegotiateFlags.Unset(negotiateFlagNTLMSSPNEGOTIATEVERSION)
b := bytes.Buffer{}
if err := binary.Write(&b, binary.LittleEndian, &f); err != nil {
return nil, err
}
if err := binary.Write(&b, binary.LittleEndian, &m.LmChallengeResponse); err != nil {
return nil, err
}
if err := binary.Write(&b, binary.LittleEndian, &m.NtChallengeResponse); err != nil {
return nil, err
}
if err := binary.Write(&b, binary.LittleEndian, &target); err != nil {
return nil, err
}
if err := binary.Write(&b, binary.LittleEndian, &user); err != nil {
return nil, err
}
if err := binary.Write(&b, binary.LittleEndian, &workstation); err != nil {
return nil, err
}
return b.Bytes(), nil
}
//ProcessChallenge crafts an AUTHENTICATE message in response to the CHALLENGE message
//that was received from the server
func ProcessChallenge(challengeMessageData []byte, user, password string) ([]byte, error) {
if user == "" && password == "" {
return nil, errors.New("Anonymous authentication not supported")
}
var cm challengeMessage
if err := cm.UnmarshalBinary(challengeMessageData); err != nil {
return nil, err
}
if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATELMKEY) {
return nil, errors.New("Only NTLM v2 is supported, but server requested v1 (NTLMSSP_NEGOTIATE_LM_KEY)")
}
if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEKEYEXCH) {
return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
}
am := authenicateMessage{
UserName: user,
TargetName: cm.TargetName,
NegotiateFlags: cm.NegotiateFlags,
}
timestamp := cm.TargetInfo[avIDMsvAvTimestamp]
if timestamp == nil { // no time sent, take current time
ft := uint64(time.Now().UnixNano()) / 100
ft += 116444736000000000 // add time between unix & windows offset
timestamp = make([]byte, 8)
binary.LittleEndian.PutUint64(timestamp, ft)
}
clientChallenge := make([]byte, 8)
rand.Reader.Read(clientChallenge)
ntlmV2Hash := getNtlmV2Hash(password, user, cm.TargetName)
am.NtChallengeResponse = computeNtlmV2Response(ntlmV2Hash,
cm.ServerChallenge[:], clientChallenge, timestamp, cm.TargetInfoRaw)
if cm.TargetInfoRaw == nil {
am.LmChallengeResponse = computeLmV2Response(ntlmV2Hash,
cm.ServerChallenge[:], clientChallenge)
}
return am.MarshalBinary()
}
func ProcessChallengeWithHash(challengeMessageData []byte, user, hash string) ([]byte, error) {
if user == "" && hash == "" {
return nil, errors.New("Anonymous authentication not supported")
}
var cm challengeMessage
if err := cm.UnmarshalBinary(challengeMessageData); err != nil {
return nil, err
}
if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATELMKEY) {
return nil, errors.New("Only NTLM v2 is supported, but server requested v1 (NTLMSSP_NEGOTIATE_LM_KEY)")
}
if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEKEYEXCH) {
return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
}
am := authenicateMessage{
UserName: user,
TargetName: cm.TargetName,
NegotiateFlags: cm.NegotiateFlags,
}
timestamp := cm.TargetInfo[avIDMsvAvTimestamp]
if timestamp == nil { // no time sent, take current time
ft := uint64(time.Now().UnixNano()) / 100
ft += 116444736000000000 // add time between unix & windows offset
timestamp = make([]byte, 8)
binary.LittleEndian.PutUint64(timestamp, ft)
}
clientChallenge := make([]byte, 8)
rand.Reader.Read(clientChallenge)
hashParts := strings.Split(hash, ":")
if len(hashParts) > 1 {
hash = hashParts[1]
}
hashBytes, err := hex.DecodeString(hash)
if err != nil {
return nil, err
}
ntlmV2Hash := hmacMd5(hashBytes, toUnicode(strings.ToUpper(user)+cm.TargetName))
am.NtChallengeResponse = computeNtlmV2Response(ntlmV2Hash,
cm.ServerChallenge[:], clientChallenge, timestamp, cm.TargetInfoRaw)
if cm.TargetInfoRaw == nil {
am.LmChallengeResponse = computeLmV2Response(ntlmV2Hash,
cm.ServerChallenge[:], clientChallenge)
}
return am.MarshalBinary()
}
package ntlmssp
import (
"encoding/base64"
"strings"
)
type authheader string
func (h authheader) IsBasic() bool {
return strings.HasPrefix(string(h), "Basic ")
}
func (h authheader) IsNegotiate() bool {
return strings.HasPrefix(string(h), "Negotiate")
}
func (h authheader) IsNTLM() bool {
return strings.HasPrefix(string(h), "NTLM")
}
func (h authheader) GetData() ([]byte, error) {
p := strings.Split(string(h), " ")
if len(p) < 2 {
return nil, nil
}
return base64.StdEncoding.DecodeString(string(p[1]))
}
func (h authheader) GetBasicCreds() (username, password string, err error) {
d, err := h.GetData()
if err != nil {
return "", "", err
}
parts := strings.SplitN(string(d), ":", 2)
return parts[0], parts[1], nil
}
package ntlmssp
type avID uint16
const (
avIDMsvAvEOL avID = iota
avIDMsvAvNbComputerName
avIDMsvAvNbDomainName
avIDMsvAvDNSComputerName
avIDMsvAvDNSDomainName
avIDMsvAvDNSTreeName
avIDMsvAvFlags
avIDMsvAvTimestamp
avIDMsvAvSingleHost
avIDMsvAvTargetName
avIDMsvChannelBindings
)
package ntlmssp
import (
"bytes"
"encoding/binary"
"fmt"
)
type challengeMessageFields struct {
messageHeader
TargetName varField
NegotiateFlags negotiateFlags
ServerChallenge [8]byte
_ [8]byte
TargetInfo varField
}
func (m challengeMessageFields) IsValid() bool {
return m.messageHeader.IsValid() && m.MessageType == 2
}
type challengeMessage struct {
challengeMessageFields
TargetName string
TargetInfo map[avID][]byte
TargetInfoRaw []byte
}
func (m *challengeMessage) UnmarshalBinary(data []byte) error {
r := bytes.NewReader(data)
err := binary.Read(r, binary.LittleEndian, &m.challengeMessageFields)
if err != nil {
return err
}
if !m.challengeMessageFields.IsValid() {
return fmt.Errorf("Message is not a valid challenge message: %+v", m.challengeMessageFields.messageHeader)
}
if m.challengeMessageFields.TargetName.Len > 0 {
m.TargetName, err = m.challengeMessageFields.TargetName.ReadStringFrom(data, m.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEUNICODE))
if err != nil {
return err
}
}
if m.challengeMessageFields.TargetInfo.Len > 0 {
d, err := m.challengeMessageFields.TargetInfo.ReadFrom(data)
m.TargetInfoRaw = d
if err != nil {
return err
}
m.TargetInfo = make(map[avID][]byte)
r := bytes.NewReader(d)
for {
var id avID
var l uint16
err = binary.Read(r, binary.LittleEndian, &id)
if err != nil {
return err
}
if id == avIDMsvAvEOL {
break
}
err = binary.Read(r, binary.LittleEndian, &l)
if err != nil {
return err
}
value := make([]byte, l)
n, err := r.Read(value)
if err != nil {
return err
}
if n != int(l) {
return fmt.Errorf("Expected to read %d bytes, got only %d", l, n)
}
m.TargetInfo[id] = value
}
}
return nil
}
package ntlmssp
import (
"bytes"
)
var signature = [8]byte{'N', 'T', 'L', 'M', 'S', 'S', 'P', 0}
type messageHeader struct {
Signature [8]byte
MessageType uint32
}
func (h messageHeader) IsValid() bool {
return bytes.Equal(h.Signature[:], signature[:]) &&
h.MessageType > 0 && h.MessageType < 4
}
func newMessageHeader(messageType uint32) messageHeader {
return messageHeader{signature, messageType}
}