1 |
|
2 |
|
3 | const EventEmitter = require('events').EventEmitter
|
4 | const util = require('util')
|
5 |
|
6 | const assert = require('assert-plus')
|
7 | const asn1 = require('asn1')
|
8 |
|
9 | const logger = require('../logger')
|
10 |
|
11 | const AbandonRequest = require('./abandon_request')
|
12 | const AddRequest = require('./add_request')
|
13 | const AddResponse = require('./add_response')
|
14 | const BindRequest = require('./bind_request')
|
15 | const BindResponse = require('./bind_response')
|
16 | const CompareRequest = require('./compare_request')
|
17 | const CompareResponse = require('./compare_response')
|
18 | const DeleteRequest = require('./del_request')
|
19 | const DeleteResponse = require('./del_response')
|
20 | const ExtendedRequest = require('./ext_request')
|
21 | const ExtendedResponse = require('./ext_response')
|
22 | const ModifyRequest = require('./modify_request')
|
23 | const ModifyResponse = require('./modify_response')
|
24 | const ModifyDNRequest = require('./moddn_request')
|
25 | const ModifyDNResponse = require('./moddn_response')
|
26 | const SearchRequest = require('./search_request')
|
27 | const SearchEntry = require('./search_entry')
|
28 | const SearchReference = require('./search_reference')
|
29 | const SearchResponse = require('./search_response')
|
30 | const UnbindRequest = require('./unbind_request')
|
31 |
|
32 |
|
33 | const LDAPResult = require('./result')
|
34 |
|
35 |
|
36 | const Protocol = require('../protocol')
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | const BerReader = asn1.BerReader
|
42 |
|
43 |
|
44 |
|
45 | function Parser (options = {}) {
|
46 | assert.object(options)
|
47 |
|
48 | EventEmitter.call(this)
|
49 |
|
50 | this.buffer = null
|
51 | this.log = options.log || logger
|
52 | }
|
53 | util.inherits(Parser, EventEmitter)
|
54 |
|
55 | Parser.prototype.write = function (data) {
|
56 | if (!data || !Buffer.isBuffer(data)) { throw new TypeError('data (buffer) required') }
|
57 |
|
58 | let nextMessage = null
|
59 | const self = this
|
60 |
|
61 | function end () {
|
62 | if (nextMessage) { return self.write(nextMessage) }
|
63 |
|
64 | return true
|
65 | }
|
66 |
|
67 | self.buffer = (self.buffer ? Buffer.concat([self.buffer, data]) : data)
|
68 |
|
69 | const ber = new BerReader(self.buffer)
|
70 |
|
71 | let foundSeq = false
|
72 | try {
|
73 | foundSeq = ber.readSequence()
|
74 | } catch (e) {
|
75 | this.emit('error', e)
|
76 | }
|
77 |
|
78 | if (!foundSeq || ber.remain < ber.length) {
|
79 |
|
80 | return false
|
81 | } else if (ber.remain > ber.length) {
|
82 |
|
83 |
|
84 | nextMessage = self.buffer.slice(ber.offset + ber.length)
|
85 | ber._size = ber.offset + ber.length
|
86 | assert.equal(ber.remain, ber.length)
|
87 | }
|
88 |
|
89 |
|
90 |
|
91 | self.buffer = null
|
92 |
|
93 | let message
|
94 | try {
|
95 |
|
96 | message = this.getMessage(ber)
|
97 |
|
98 | if (!message) {
|
99 | return end()
|
100 | }
|
101 | message.parse(ber)
|
102 | } catch (e) {
|
103 | this.emit('error', e, message)
|
104 | return false
|
105 | }
|
106 |
|
107 | this.emit('message', message)
|
108 | return end()
|
109 | }
|
110 |
|
111 | Parser.prototype.getMessage = function (ber) {
|
112 | assert.ok(ber)
|
113 |
|
114 | const self = this
|
115 |
|
116 | const messageID = ber.readInt()
|
117 | const type = ber.readSequence()
|
118 |
|
119 | let Message
|
120 | switch (type) {
|
121 | case Protocol.LDAP_REQ_ABANDON:
|
122 | Message = AbandonRequest
|
123 | break
|
124 |
|
125 | case Protocol.LDAP_REQ_ADD:
|
126 | Message = AddRequest
|
127 | break
|
128 |
|
129 | case Protocol.LDAP_REP_ADD:
|
130 | Message = AddResponse
|
131 | break
|
132 |
|
133 | case Protocol.LDAP_REQ_BIND:
|
134 | Message = BindRequest
|
135 | break
|
136 |
|
137 | case Protocol.LDAP_REP_BIND:
|
138 | Message = BindResponse
|
139 | break
|
140 |
|
141 | case Protocol.LDAP_REQ_COMPARE:
|
142 | Message = CompareRequest
|
143 | break
|
144 |
|
145 | case Protocol.LDAP_REP_COMPARE:
|
146 | Message = CompareResponse
|
147 | break
|
148 |
|
149 | case Protocol.LDAP_REQ_DELETE:
|
150 | Message = DeleteRequest
|
151 | break
|
152 |
|
153 | case Protocol.LDAP_REP_DELETE:
|
154 | Message = DeleteResponse
|
155 | break
|
156 |
|
157 | case Protocol.LDAP_REQ_EXTENSION:
|
158 | Message = ExtendedRequest
|
159 | break
|
160 |
|
161 | case Protocol.LDAP_REP_EXTENSION:
|
162 | Message = ExtendedResponse
|
163 | break
|
164 |
|
165 | case Protocol.LDAP_REQ_MODIFY:
|
166 | Message = ModifyRequest
|
167 | break
|
168 |
|
169 | case Protocol.LDAP_REP_MODIFY:
|
170 | Message = ModifyResponse
|
171 | break
|
172 |
|
173 | case Protocol.LDAP_REQ_MODRDN:
|
174 | Message = ModifyDNRequest
|
175 | break
|
176 |
|
177 | case Protocol.LDAP_REP_MODRDN:
|
178 | Message = ModifyDNResponse
|
179 | break
|
180 |
|
181 | case Protocol.LDAP_REQ_SEARCH:
|
182 | Message = SearchRequest
|
183 | break
|
184 |
|
185 | case Protocol.LDAP_REP_SEARCH_ENTRY:
|
186 | Message = SearchEntry
|
187 | break
|
188 |
|
189 | case Protocol.LDAP_REP_SEARCH_REF:
|
190 | Message = SearchReference
|
191 | break
|
192 |
|
193 | case Protocol.LDAP_REP_SEARCH:
|
194 | Message = SearchResponse
|
195 | break
|
196 |
|
197 | case Protocol.LDAP_REQ_UNBIND:
|
198 | Message = UnbindRequest
|
199 | break
|
200 |
|
201 | default:
|
202 | this.emit('error',
|
203 | new Error('Op 0x' + (type ? type.toString(16) : '??') +
|
204 | ' not supported'),
|
205 | new LDAPResult({
|
206 | messageID: messageID,
|
207 | protocolOp: type || Protocol.LDAP_REP_EXTENSION
|
208 | }))
|
209 |
|
210 | return false
|
211 | }
|
212 |
|
213 | return new Message({
|
214 | messageID: messageID,
|
215 | log: self.log
|
216 | })
|
217 | }
|
218 |
|
219 |
|
220 |
|
221 | module.exports = Parser
|