UNPKG

5.21 kBJavaScriptView Raw
1// Copyright 2011 Mark Cavage, Inc. All rights reserved.
2
3const EventEmitter = require('events').EventEmitter
4const util = require('util')
5
6const assert = require('assert-plus')
7const asn1 = require('asn1')
8// var VError = require('verror').VError
9const logger = require('../logger')
10
11const AbandonRequest = require('./abandon_request')
12const AddRequest = require('./add_request')
13const AddResponse = require('./add_response')
14const BindRequest = require('./bind_request')
15const BindResponse = require('./bind_response')
16const CompareRequest = require('./compare_request')
17const CompareResponse = require('./compare_response')
18const DeleteRequest = require('./del_request')
19const DeleteResponse = require('./del_response')
20const ExtendedRequest = require('./ext_request')
21const ExtendedResponse = require('./ext_response')
22const ModifyRequest = require('./modify_request')
23const ModifyResponse = require('./modify_response')
24const ModifyDNRequest = require('./moddn_request')
25const ModifyDNResponse = require('./moddn_response')
26const SearchRequest = require('./search_request')
27const SearchEntry = require('./search_entry')
28const SearchReference = require('./search_reference')
29const SearchResponse = require('./search_response')
30const UnbindRequest = require('./unbind_request')
31// var UnbindResponse = require('./unbind_response')
32
33const LDAPResult = require('./result')
34// var Message = require('./message')
35
36const Protocol = require('../protocol')
37
38/// --- Globals
39
40// var Ber = asn1.Ber
41const BerReader = asn1.BerReader
42
43/// --- API
44
45function Parser (options = {}) {
46 assert.object(options)
47
48 EventEmitter.call(this)
49
50 this.buffer = null
51 this.log = options.log || logger
52}
53util.inherits(Parser, EventEmitter)
54
55Parser.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 // ENOTENOUGH
80 return false
81 } else if (ber.remain > ber.length) {
82 // ETOOMUCH
83 // This is sort of ugly, but allows us to make miminal copies
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 // If we're here, ber holds the message, and nextMessage is temporarily
90 // pointing at the next sequence of data (if it exists)
91 self.buffer = null
92
93 let message
94 try {
95 // Bail here if peer isn't speaking protocol at all
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
111Parser.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/// --- Exports
220
221module.exports = Parser