-
Notifications
You must be signed in to change notification settings - Fork 1
/
result.go
163 lines (154 loc) · 5.23 KB
/
result.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package ldapserver
import "bytes"
// LDAP result code
type LDAPResultCode uint32
// Defined result codes
const (
ResultSuccess LDAPResultCode = 0
ResultOperationsError LDAPResultCode = 1
ResultProtocolError LDAPResultCode = 2
ResultTimeLimitExceeded LDAPResultCode = 3
ResultSizeLimitExceeded LDAPResultCode = 4
ResultCompareFalse LDAPResultCode = 5
ResultCompareTrue LDAPResultCode = 6
ResultAuthMethodNotSupported LDAPResultCode = 7
ResultStrongerAuthRequired LDAPResultCode = 8
// 9 reserved
ResultReferral LDAPResultCode = 10
ResultAdminLimitExceeded LDAPResultCode = 11
ResultUnavailableCriticalExtension LDAPResultCode = 12
ResultConfidentialityRequired LDAPResultCode = 13
ResultSaslBindInProgress LDAPResultCode = 14
// 15 ???
ResultNoSuchAttribute LDAPResultCode = 16
ResultUndefinedAttributeType LDAPResultCode = 17
ResultInappropriateMatching LDAPResultCode = 18
ResultConstraintViolation LDAPResultCode = 19
ResultAttributeOrValueExists LDAPResultCode = 20
ResultInvalidAttributeSyntax LDAPResultCode = 21
// 22-31 unused
ResultNoSuchObject LDAPResultCode = 32
ResultAliasProblem LDAPResultCode = 33
ResultInvalidDNSyntax LDAPResultCode = 34
// 35 reserved
ResultAliasDereferencingProblem LDAPResultCode = 36
// 37-47 unused
ResultInappropriateAuthentication LDAPResultCode = 48
ResultInvalidCredentials LDAPResultCode = 49
ResultInsufficientAccessRights LDAPResultCode = 50
ResultBusy LDAPResultCode = 51
ResultUnavailable LDAPResultCode = 52
ResultUnwillingToPerform LDAPResultCode = 53
ResultLoopDetect LDAPResultCode = 54
// 55-63 unused
ResultNamingViolation LDAPResultCode = 64
ResultObjectClassViolation LDAPResultCode = 65
ResultNotAllowedOnNonLeaf LDAPResultCode = 66
ResultNotAllowedOnRDN LDAPResultCode = 67
ResultEntryAlreadyExists LDAPResultCode = 68
ResultObjectClassModsProhibited LDAPResultCode = 69
// 70 reserved
ResultAffectsMultibleDSAs LDAPResultCode = 70
// 72-79 unused
ResultOther LDAPResultCode = 80
// extensible, more codes possible
)
// LDAPResult ::= SEQUENCE {
// resultCode ENUMERATED {
// -- Defined result codes --
// ... },
// matchedDN LDAPDN,
// diagnosticMessage LDAPString,
// referral [3] Referral OPTIONAL }
type Result struct {
ResultCode LDAPResultCode
MatchedDN string
DiagnosticMessage string
Referral []string
}
// IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
// responseName [0] LDAPOID OPTIONAL,
// responseValue [1] OCTET STRING OPTIONAL }
type IntermediateResponse struct {
Name string
Value string
}
// Return a Result from BER-encoded data
func GetResult(data []byte) (*Result, error) {
seq, err := BerGetSequence(data)
if err != nil {
return nil, err
}
if len(seq) != 3 && len(seq) != 4 {
return nil, ErrWrongSequenceLength.WithInfo("LDAPResult sequence length", len(seq))
}
if seq[0].Type != BerTypeEnumerated {
return nil, ErrWrongElementType.WithInfo("LDAPResult result code type", seq[0].Type)
}
resultCode, err := BerGetInteger(seq[0].Data)
if err != nil {
return nil, err
}
if seq[1].Type != BerTypeOctetString {
return nil, ErrWrongElementType.WithInfo("LDAPResult matched DN type", seq[1].Type)
}
matchedDN := BerGetOctetString(seq[1].Data)
if seq[2].Type != BerTypeOctetString {
return nil, ErrWrongElementType.WithInfo("LDAPResult diagnostic message type", seq[2].Type)
}
diagnosticMsg := BerGetOctetString(seq[2].Data)
var referral []string
if len(seq) == 4 {
if seq[3].Type.Class() != BerClassContextSpecific ||
seq[3].Type.TagNumber() != 3 {
return nil, ErrWrongElementType.WithInfo("LDAPResult referral type", seq[3].Type)
}
r_seq, err := BerGetSequence(seq[3].Data)
if err != nil {
return nil, err
}
for _, rr := range r_seq {
referral = append(referral, BerGetOctetString(rr.Data))
}
}
res := &Result{
ResultCode: LDAPResultCode(resultCode),
MatchedDN: matchedDN,
DiagnosticMessage: diagnosticMsg,
Referral: referral,
}
return res, nil
}
// Return the BER-encoded struct (without element header)
func (r *Result) Encode() []byte {
w := bytes.NewBuffer(nil)
w.Write(BerEncodeEnumerated(int64(r.ResultCode)))
w.Write(BerEncodeOctetString(r.MatchedDN))
w.Write(BerEncodeOctetString(r.DiagnosticMessage))
if len(r.Referral) > 0 {
referrals := bytes.NewBuffer(nil)
for _, ref := range r.Referral {
referrals.Write(BerEncodeOctetString(ref))
}
w.Write(BerEncodeSequence(referrals.Bytes()))
}
return w.Bytes()
}
// Return the BER-encoded struct (without element header)
func (r *IntermediateResponse) Encode() []byte {
w := bytes.NewBuffer(nil)
if r.Name != "" {
w.Write(BerEncodeElement(BerContextSpecificType(0, false), BerEncodeOctetString(r.Name)))
}
if r.Value != "" {
w.Write(BerEncodeElement(BerContextSpecificType(1, false), BerEncodeOctetString(r.Value)))
}
return w.Bytes()
}
func (r LDAPResultCode) AsResult(diagnosticMessage string) *Result {
res := &Result{
ResultCode: r,
DiagnosticMessage: diagnosticMessage,
}
return res
}