aboutsummaryrefslogtreecommitdiff
path: root/goldap/message.go
blob: a227d16e09e9811206bb227878462f38c6f033fa (plain) (blame)
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
package message

import (
	"fmt"
	"reflect"
)

//   This appendix is normative.
//
//        Lightweight-Directory-Access-Protocol-V3 {1 3 6 1 1 18}
//        -- Copyright (C) The Internet Society (2006).  This version of
//        -- this ASN.1 module is part of RFC 4511; see the RFC itself
//        -- for full legal notices.
//        DEFINITIONS
//        IMPLICIT TAGS
//        EXTENSIBILITY IMPLIED ::=
//
//        BEGIN
//
//        LDAPMessage ::= SEQUENCE {
//             messageID       MessageID,
//             protocolOp      CHOICE {
//                  bindRequest           BindRequest,
//                  bindResponse          BindResponse,
//                  unbindRequest         UnbindRequest,
//                  searchRequest         SearchRequest,
//                  searchResEntry        SearchResultEntry,
//                  searchResDone         SearchResultDone,
//                  searchResRef          SearchResultReference,
//                  modifyRequest         ModifyRequest,
//                  modifyResponse        ModifyResponse,
//                  addRequest            AddRequest,
//                  addResponse           AddResponse,
//                  delRequest            DelRequest,
//                  delResponse           DelResponse,
//                  modDNRequest          ModifyDNRequest,
//                  modDNResponse         ModifyDNResponse,
//                  compareRequest        CompareRequest,
//                  compareResponse       CompareResponse,
//                  abandonRequest        AbandonRequest,
//                  extendedReq           ExtendedRequest,
//                  extendedResp          ExtendedResponse,
//                  ...,
//                  intermediateResponse  IntermediateResponse },
//             controls       [0] Controls OPTIONAL }
//

func NewLDAPMessage() *LDAPMessage { return &LDAPMessage{} }

func (message *LDAPMessage) readComponents(bytes *Bytes) (err error) {
	message.messageID, err = readMessageID(bytes)
	if err != nil {
		err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
		return
	}
	message.protocolOp, err = readProtocolOp(bytes)
	if err != nil {
		err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
		return
	}
	if bytes.HasMoreData() {
		var tag TagAndLength
		tag, err = bytes.PreviewTagAndLength()
		if err != nil {
			err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
			return
		}
		if tag.Tag == TagLDAPMessageControls {
			var controls Controls
			controls, err = readTaggedControls(bytes, classContextSpecific, TagLDAPMessageControls)
			if err != nil {
				err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
				return
			}
			message.controls = controls.Pointer()
		}
	}
	return
}

func (m *LDAPMessage) Write() (bytes *Bytes, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = LdapError{fmt.Sprintf("Error in LDAPMessage.Write: %s", e)}
		}
	}()
	// Compute the needed size
	totalSize := m.size()
	// Initialize the structure
	bytes = &Bytes{
		bytes:  make([]byte, totalSize),
		offset: totalSize,
	}

	// Go !
	size := 0
	if m.controls != nil {
		size += m.controls.writeTagged(bytes, classContextSpecific, TagLDAPMessageControls)
	}
	size += m.protocolOp.write(bytes)
	size += m.messageID.write(bytes)
	size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
	// Check
	if size != totalSize || bytes.offset != 0 {
		err = LdapError{fmt.Sprintf("Something went wrong while writing the message ! Size is %d instead of %d, final offset is %d instead of 0", size, totalSize, bytes.offset)}
	}
	return
}
func (m *LDAPMessage) size() (size int) {
	size += m.messageID.size()
	size += m.protocolOp.size()
	if m.controls != nil {
		size += m.controls.sizeTagged(TagLDAPMessageControls)
	}
	size += sizeTagAndLength(tagSequence, size)
	return
}
func (l *LDAPMessage) MessageID() MessageID {
	return l.messageID
}
func (l *LDAPMessage) SetMessageID(ID int) {
	l.messageID = MessageID(ID)
}
func (l *LDAPMessage) Controls() *Controls {
	return l.controls
}
func (l *LDAPMessage) ProtocolOp() ProtocolOp {
	return l.protocolOp
}
func (l *LDAPMessage) ProtocolOpName() string {
	return reflect.TypeOf(l.ProtocolOp()).Name()
}
func (l *LDAPMessage) ProtocolOpType() int {
	switch l.protocolOp.(type) {
	case BindRequest:
		return TagBindRequest
	}
	return 0
}