Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions apps/meerkat/src/app/init/loadMatchingRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
MatchingRuleInfo,
SortKeyGetter,
SortKey,
ValueNormalizer,
} from "@wildboar/meerkat-types";
import type {
MATCHING_RULE,
Expand Down Expand Up @@ -611,6 +612,9 @@ import {
getPolicySpecificationMatcher,
} from "../matching/equality/policySpecificationMatch";
import * as norms from "../matching/normalizers";
import { prepString } from "../native/index";
import { teletexToString } from "@wildboar/x500";
import { betterDS } from "../utils/directoryStringToString";

const caseIgnoreSortKeyGetter: SortKeyGetter = (element: ASN1Element): SortKey | null => {
const ds = _decode_UnboundedDirectoryString(element);
Expand Down Expand Up @@ -652,6 +656,43 @@ const relaxations: [ OBJECT_IDENTIFIER, OBJECT_IDENTIFIER ][] = [
[ x500mr.caseIgnoreMatch["&id"], x500mr.wordMatch["&id"] ],
];

const betterCaseIgnoreMatch: EqualityMatcher = (
assertion: ASN1Element,
value: ASN1Element
): boolean => {
const a_str = betterDS(assertion);
if (!a_str) {
throw new Error("7dba8a5b-8481-4ffb-9490-0c8be4c37756");
}
const v_str = betterDS(value);
if (!v_str) {
return false;
}
const a: string | null = prepString(a_str, true);
const v: string | null = prepString(v_str, true);
if (a === undefined) {
return false;
// throw new Error("cdf4ca97-db0c-450c-87e7-74d826b9ed2a: Invalid characters in caseIgnoreMatch assertion.");
}
if (v === undefined) {
return false;
}
// The specification specifically says that you lowercase prior to comparison.
return a === v;
};

const betterCaseIgnoreNormalizer: ValueNormalizer = (ctx: Context, value: ASN1Element): string | undefined => {
const v_str = betterDS(value);
if (!v_str) {
return undefined;
}
const v: string | null = prepString(v_str, true);
if (!v) {
return undefined;
}
return prepString(v, true) ?? undefined;
};

/**
* @summary Initialize Meerkat DSA's internal index of known matching rules.
* @description
Expand Down Expand Up @@ -680,7 +721,7 @@ function loadMatchingRules (ctx: Context): void {
[ x500mr.caseExactMatch, caseExactMatch ],
[ x500mr.caseIgnoreIA5Match, caseIgnoreIA5Match ],
[ x500mr.caseIgnoreListMatch, caseIgnoreListMatch ],
[ x500mr.caseIgnoreMatch, caseIgnoreMatch ],
[ x500mr.caseIgnoreMatch, betterCaseIgnoreMatch ], // This didn't seem to make the search faster...
[ x500mr.certificateExactMatch, certificateExactMatch ],
[ x500mr.certificateListExactMatch, certificateListExactMatch ],
[ x500mr.certificateListMatch, certificateListMatch ],
Expand Down Expand Up @@ -929,7 +970,7 @@ function loadMatchingRules (ctx: Context): void {
ctx.orderingMatchingRules.get(x500mr.caseExactOrderingMatch["&id"]!.toString())!.sortKeyGetter = caseExactSortKeyGetter;
ctx.orderingMatchingRules.get(x500mr.caseIgnoreOrderingMatch["&id"]!.toString())!.sortKeyGetter = caseIgnoreSortKeyGetter;

ctx.equalityMatchingRules.get(x500mr.caseIgnoreMatch["&id"].toString())!.normalizer = norms.caseIgnoreMatch;
ctx.equalityMatchingRules.get(x500mr.caseIgnoreMatch["&id"].toString())!.normalizer = betterCaseIgnoreNormalizer;
ctx.equalityMatchingRules.get(x500mr.caseExactMatch["&id"].toString())!.normalizer = norms.caseExactMatch;
ctx.equalityMatchingRules.get(x500mr.booleanMatch["&id"].toString())!.normalizer = norms.booleanMatch;
ctx.equalityMatchingRules.get(x500mr.integerMatch["&id"].toString())!.normalizer = norms.integerMatch;
Expand Down
19 changes: 6 additions & 13 deletions apps/meerkat/src/app/ldap/LDAPConnection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Vertex, ClientAssociation, OperationStatistics } from "@wildboar/meerkat-types";
import { ClientAssociation, OperationStatistics } from "@wildboar/meerkat-types";
import * as errors from "@wildboar/meerkat-types";
import type { MeerkatContext } from "../ctx";
import * as net from "net";
Expand Down Expand Up @@ -177,8 +177,6 @@ async function handleRequest (
association_id: assn.id,
});
}
// let toWriteBuffer: Buffer = Buffer.alloc(0);
// let resultsBuffered: number = 0;
const onEntry = (searchResEntry: SearchResultEntry): void => {
const resultMessage = new LDAPMessage(
message.messageID,
Expand All @@ -187,16 +185,11 @@ async function handleRequest (
},
undefined,
);
// resultsBuffered++;
// toWriteBuffer = Buffer.concat([
// toWriteBuffer,
// _encode_LDAPMessage(resultMessage, BER).toBytes(),
// ]);
// if (resultsBuffered >= 100) {
// conn.socket.write(toWriteBuffer);
// toWriteBuffer = Buffer.alloc(0);
// }
assn.socket.write(_encode_LDAPMessage(resultMessage, BER).toBytes());
assn.socket.cork();
for (const buf of _encode_LDAPMessage(resultMessage, BER).toBuffers()) {
assn.socket.write(buf);
}
assn.socket.uncork();
};
if (
("searchRequest" in message.protocolOp)
Expand Down
3 changes: 0 additions & 3 deletions apps/meerkat/src/app/ldap/getPartialAttributeFromAttribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ function getPartialAttributeFromAttribute (ctx: Context, attr: Attribute): Parti
return undefined;
}
const ldapSyntax = getLDAPSyntax(ctx, spec.id);
if (!ldapSyntax?.decoder) {
return undefined;
}
const encoder = ldapSyntax?.encoder;
if (!encoder) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,32 +51,33 @@ function getPartialAttributesFromEntryInformation (
ctx: Context,
infoItems: EntryInformation_information_Item[],
): PartialAttribute[] {
return infoItems.flatMap((einfo) => {
const ret: PartialAttribute[] = [];
for (const einfo of infoItems) {
if ("attributeType" in einfo) {
const attrType = einfo.attributeType;
const attrSpec = ctx.attributeTypes.get(attrType.toString());
if (!attrSpec) {
return undefined;
continue;
}
const nonDupedName = attrSpec.ldapNames?.find((name) => !ctx.duplicatedLDAPNames.has(name));
const descriptor: Uint8Array = nonDupedName
? Buffer.from(nonDupedName, "utf-8")
: encodeLDAPOID(attrType);
return new PartialAttribute(
ret.push(new PartialAttribute(
descriptor,
[],
);
));
} else if ("attribute" in einfo) {
const attrType = einfo.attribute.type_;
const attrSpec = ctx.attributeTypes.get(attrType.toString());
if (!attrSpec?.ldapSyntax) {
// ctx.log.warn(`No LDAP syntax defined for attribute ${attrType.toString()}.`);
return undefined;
continue;
}
const ldapSyntax = ctx.ldapSyntaxes.get(attrSpec.ldapSyntax.toString());
if (!ldapSyntax?.encoder) {
// ctx.log.warn(`LDAP Syntax ${attrSpec.ldapSyntax} not understood or had no encoder.`);
return undefined;
continue;
}

// Wrap the encoder in error handling so we can ignore attributes that don't encode successfully.
Expand Down Expand Up @@ -149,7 +150,7 @@ function getPartialAttributesFromEntryInformation (
const descriptor: Uint8Array = nonDupedName
? Buffer.from(nonDupedName, "utf-8")
: encodeLDAPOID(attrType);
return [
ret.push(
new PartialAttribute(
descriptor,
[
Expand All @@ -170,12 +171,12 @@ function getPartialAttributesFromEntryInformation (
]),
values.map(encoder).filter((v): v is Uint8Array => !!v),
)),
];
);
} else {
return undefined;
continue;
}
})
.filter((attr): attr is PartialAttribute => !!attr);
}
return ret;
}

export default getPartialAttributesFromEntryInformation;
13 changes: 10 additions & 3 deletions apps/meerkat/src/app/ldap/getSearchResultEntryFromEntryInfo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Context } from "@wildboar/meerkat-types";
import {
PartialAttributeList,
SearchResultEntry,
} from "@wildboar/ldap/src/lib/modules/Lightweight-Directory-Access-Protocol-V3/SearchResultEntry.ta";
import type {
Expand Down Expand Up @@ -29,11 +30,17 @@ function getSearchResultEntryFromEntryInfo (
ctx: Context,
einfo: EntryInformation,
): SearchResultEntry {
const attrs: PartialAttributeList = [];
for (const info of einfo.information ?? []) {
const pattr = getPartialAttributeFromEntryInfoItem(ctx, info);
if (!pattr) {
continue;
}
attrs.push(pattr);
}
return new SearchResultEntry(
encodeLDAPDN(ctx, einfo.name.rdnSequence),
einfo.information
?.map((item) => getPartialAttributeFromEntryInfoItem(ctx, item))
.filter((item): item is PartialAttribute => !!item) ?? [],
attrs,
);
}

Expand Down
8 changes: 8 additions & 0 deletions apps/meerkat/src/app/native/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* tslint:disable */
/* eslint-disable */

/* auto-generated by NAPI-RS */

export function oidFromStr(s: string): Array<number> | null
export function oidFromBytes(b: Uint8Array): Array<number> | null
export function prepString(s: string, caseFold: boolean): string | null
Loading