tapmodo / node-ldif Goto Github PK
View Code? Open in Web Editor NEWNodejs LDIF (LDAP Data Interchange Format) parser based on RFC2849
Nodejs LDIF (LDAP Data Interchange Format) parser based on RFC2849
Example which throws an exception:
dn: cn=physics,ou=group,dc=example,dc=org
cn: physics
gidNumber: 2000
objectClass: posixGroup
objectClass: top
objectClass: groupOfNames
member:
On this subject, see https://www.openldap.org/lists/openldap-technical/201312/msg00048.html
Hello,
The problem is this library don't take in consideration if a user what to search the top of the ldap server.
I will show you the message that I receive when I use the ldapsearch:
And the error from this library:
Somehow this is not covered in this library.
To reproduce this error use this command to search and put the data into a file:
Then using the library take the data from the ldif and try to make it a JSON.
Hi,
the library doesn't understand unicode letters and fails horrible if characters outside of ASCII are used.
I tested with with the letters:
ß
, €
and 日
.
The problem is that the assigned RFC only seems to specify ASCII. Real LDAP Server are made up of various RFC and extend every time. So this library should either implement the ext RFCs as well, or write something at the top of the readme to only be able to parse ASCII letters.
The errormessage is rather criptic:
SyntaxError: Expected end of input or entry but "\u20AC" found.
at peg$buildException (/home/minime/code/work/my_cool_project/node_modules/ldif/lib/parser.js:416:14)
at Object.peg$parse [as parse] (/home/minime/code/work/my_cool_project/node_modules/ldif/lib/parser.js:2628:13)
at Object.parseFile (/home/minime/code/work/my_cool_project/node_modules/ldif/index.js:13:17)
at Object.<anonymous> (/home/minime/code/work/my_cool_project/sample_ldif.js:12:6)
at Module._compile (module.js:643:30)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Function.Module.runMain (module.js:684:10)
This generates a parse error with node-ldif, while being accepted by other ldif software:
console.log(require('ldif').parse(
'version: 1\n' +
'\n' + // <-- commenting out this line makes it work again
'dn: dc=test\n' +
'dc: test\n'
));
I ran an ldapsearch against AD, to dump all entries my account has permission to see.
(I am using OpenLDAP ldapsearch client.)
I get back an LDIF file which includes some entries with no attributes:
dn: CN=NTDS Quotas,DC=ad,DC=example,DC=com
dn: CN=VolumeTable,CN=FileLinks,CN=System,DC=ad,DC=example,DC=com
dn: CN=IP Security,CN=System,DC=ad,DC=example,DC=com
etc...
I am not sure why. Maybe I have permission to see the entry exists but not read it?
Now, I try to parse this LDIF file with node-ldif. And it gets a syntax error when it gets to these entries because the attributes are missing.
I realise that per RFC2849 this is invalid syntax and node-ldif is just following the RFC:
ldif-attrval-record = dn-spec SEP 1*attrval-spec
But, given real world LDIF files seem to violate the spec in this way, it would be nice if node-ldif could be a bit more forgiving, even if just as an option...
As a workaround, I use this script to pre-process my LDIF file:
var input = require('fs').readFileSync("/dev/stdin", 'utf8');
input = input.replace(/\r\n/g, "\n");
input = input.replace(/\n /g, "");
input = input.replace(/\n#[^\n]*\n/g, "\n");
while (input.match(/\ndn:[^\n]*\n\n/))
input = input.replace(/\ndn:[^\n]*\n\n/g, "\n");
process.stdout.write(input);
but would be nice if there was an out-of-the-box solution.
This library currently uses the deprecated Buffer function and should be updated to use Buffer.from instead
testcase:
dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
objectGUID;binary:: x7HAMN/oRNyn4w==
shift() result:
{ type: 'record',
dn: 'cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com',
attributes:
[ { attribute:
{ type: 'attribute',
options: [ 'binary' ],
attribute: 'objectGUID' },
value: { type: 'value', value: 'DZ�0��Dܧ�' } } ] }
toObject doesn't make it any better:
{ dn: 'cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com',
attributes: { 'objectGUID;binary': [ 'DZ�0��Dܧ�' ] } }
The above ldif output format is real life data from running ldapsearch against Microsoft AD, I only changed the dn and objectGUID value to protect the innocent. The ;binary option is not added automatically by AD, more on that below.
Guessing which attributes are truly binary and which can be decoded to string is a hard problem (read - probably no better solution that enumerate binary exceptions, spec doesn't say anything about it). Another product (node-LDAP) solves this by letting application code to "tag" attributes with ";binary" option when searching. AD server doesn't care and returns the same data in both cases, but parser library can use such tag and return the attributes as Buffer. Either Buffer or original base64 string would be fine, but binary data decoded into javascript string is definitely not fine.
Unfortunately I'm not in the position to learn peg and send a PR.
Thanks
The following record will fail to parse:
dn: cn=foo
bar: <BAZ
This is a valid LDIF because according to RFC it is part of SAFE-INIT-CHARS:
SAFE-INIT-CHAR = %x01-09 / %x0B-0C / %x0E-1F / %x21-39 / %x3B / %x3D-7F ; any value <= 127 except NUL, LF, CR, ; SPACE, colon (":", ASCII 58 decimal) ; and less-than ("<" , ASCII 60 decimal)
This started out as a bug report about node-ldif choking on LDIF input that had multiple comments separated by blank lines. It turns out the real root cause of this problem is the way the library defines whitespace:
whitespace "WHITESPACE"
= comment_line
/ [\s]* SEP
pegjs doesn't support regex character classes (pegjs/pegjs#247), so the second half of that does not end up meaning "lines containing only whitespace", it ends up meaning "lines containing only zero-or-more letter 's'".
You can see what happens if you look at the parser code that gets generated from that definition:
peg$c93 = { type: "other", description: "WHITESPACE" },
peg$c94 = /^[s]/,
According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp the \s
character class is equivalent to [ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]
(note that the first character of that class is a literal space). Since pegjs does understand literal character classes, you should be able to just use that instead of \s
and fix the problem (although you might want to leave \n\r
out since those are part of SEP
).
trying to parse CSCA master lists (country signing certificates) from https://pkddownloadsg.icao.int/ (need to go through captcha at the bottom to get to the download)
const ldif = require('ldif')
const file = ldif.parseFile('./CSCA Master Lists.ldif')
if (peg$c112.test(input.charAt(peg$currPos))) {
^
RangeError: Maximum call stack size exceeded
at RegExp.exec (native)
at RegExp.test (native)
at peg$parseBASE64_CHAR (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2463:20)
at peg$parseBASE64_STRING (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2439:12)
at peg$parsebase64_value_spec (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2146:12)
at peg$parsebase64_value_spec (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2152:18)
at peg$parsebase64_value_spec (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2152:18)
at peg$parsebase64_value_spec (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2152:18)
at peg$parsebase64_value_spec (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2152:18)
at peg$parsebase64_value_spec (/Users/tenaciousmv/Code/verifypassport/node_modules/ldif/lib/parser.js:2152:18)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.