Re: olcLimits and groupOfURLs dynlist

2024-02-12 Thread Norman Gray


Greetings.

A summary, for the archive and for google

The missing piece, from my point of view, is that it looks like the group 
selector, for the olcLimits option (which is what I started off looking at; and 
see slapd-config(5)) has similar semantics to that for the corresponding 
olcAccess option, more fully documented in slapd.access(5).

In the documentation of the  field there, we learn that 'The statement 
group= means that access is granted to requests whose DN is listed in 
the group entry whose DN is given by .'  But despite slapo-dynlist 
saying 'Any time an entry with a specific objectClass is being returned...', 
this does _not_ apply here, since the next paragraph of slapd.access says 'For 
dynamic groups the attributeType must be a subtype of the labeledURI 
attributeType. Only LDAP URIs of the form ldap:///??? will 
be evaluated in a dynamic group, by searching the local server only.'  That is, 
the olcAccess group processing is, in effect, restricted to the three-argument 
version of the attrset option of slapo-dynlist -- that's what I had missed.

Presuming the olcLimits option has the same restriction, then the effect I was 
initially aiming to achieve -- setting a limit for members of a particular 
group which is dynamically populated -- is not possible for me by this route.

The groups I'm aiming to set limits and access for are most naturally defined 
from the union of other groups.  Such groups are easy to define via the 
two-argument dynlist-attrset value (which uses 
ldap:///?member?sub?), but not, as far as I can see, via the 
three-argument one.  I can probably instead synthesise the groups I want, 
dynamically, by introducing a memberOf attribute attached to the groups' 
members, but I worry that has the potential to get a little messy in practice; 
I notice group.expand, which might help.

I notice that the documentation of olcAccess doesn't actually mention the 
dynlist overlay, and thus may be entirely independent of it.  Something for me 
to investigate.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: olcLimits and groupOfURLs dynlist

2024-02-08 Thread Norman Gray


Howard, hello.

On 8 Feb 2024, at 16:22, Howard Chu wrote:

>> And slapo-dynlist says:
>>
>> Any time an entry with a specific objectClass is being returned,
>> the LDAP URI-valued occurrences of a specific attribute are expanded
>> into the corresponding entries, and the values of the attributes listed
>> in the URI are added to the original entry.
>
> The text above is for a *dynamic list* - which is not a *dynamic group*.

Sure -- no dispute about that.

But we're talking about olcLimits.

The documentation for olcLimits includes the words

the oc group objectClass (default groupOfNames) whose DN exactly matches 
pattern.

That doesn't say anything about restricting these to 'dynamic groups' (in 
slapo-dynlist terminology).  Those words seem to cover any entry of the 
designated objectClass which has the designated DN.

The olcLimits declaration I quoted works one way when the entry with the given 
DN is a static/normal/explicit group, and works a different way when an entry 
with the same DN and the _same_ set of 'member' attributes is produced on 
expansion by dynlist.  The documentation of olcLimits doesn't suggest that's 
deliberate.

Again, if OpenLDAP/dynlist is incapable of generating this entry, then that's 
fine -- I'll bodge some different way of getting what I need.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: olcLimits and groupOfURLs dynlist

2024-02-08 Thread Norman Gray


Howard, hello.

On 8 Feb 2024, at 15:07, Howard Chu wrote:

>> Norman Gray wrote:
>>
>> Howard, hello.
>>
>> On 8 Feb 2024, at 0:34, Howard Chu wrote:
>>
>>> 65c3df21.21fc2a30 0x16cacf000 
>>> ldap_url_parse_ext(ldap:///ou=groups,o=example?member?sub?(|(cn=ldap-admins-*)(cn=ldap-techs)))
>>>
>>> The above URL is not valid for a dynamic group. The attrs portion of the 
>>> URL must be empty.
>>>
>>> Since it's invalid, after it is parsed it gets ignored.
>>
>> That's true when constructing what slapo-dynlist(5) calls a dynamic
>> group, but that's not what I'm constructing here, but instead a group
>> entry which is dynamically expanded, to a group, by a search.
>
> Whatever you've constructed is not a dynamic group, as defined in 
> slapo-dynlist.
> As such, it is not supported for the purpose you're asking.

Indeed -- it's not a 'dynamic group' in the terms of slapo-dynlist, but it is 
an entry which has a set of 'member' attributes, which is dynamically 
constructed (whatever one wants to call this).

But I can't see that matters, since the slapd-config(5) text covering the 
olcLimits configuration attribute seems to clearly indicate that

olcLimits: group/groupOfURLs/member="cn=ldap-operators,ou=groups,o=example" 
size=2

'sets the limits for any DN listed in the values of the [member] attribute of 
the [groupOfURLs] group whose DN exactly matches 
["cn=ldap-operators,ou=groups,o=example"]' (where [...] fills in the blanks in 
the text there as I understand it).  I can't see a way of interpreting this 
manpage text which doesn't match this situation.  This works as expected when 
cn=ldap-operators is an entry which is not dynamically expanded.

It doesn't say that that group has to be a 'dynamic group in the terms of 
slapo-dynlist', it just says 'group'.

And slapo-dynlist says:

> Any time an entry with a specific objectClass is being returned,
> the LDAP URI-valued occurrences of a specific attribute are expanded
> into the corresponding entries, and the values of the attributes listed
> in the URI are added to the original entry.

This is exactly what happens when I ldapsearch the directory for this 
cn=ldap-operators entry, and what does not happen (because slapd logs that it 
can't find an attribute 'member') when the same group is returned from a search 
during processing of olcLimits.

The slapo-dynlist text says 'Any time an entry with a specific objectClass is 
being returned...'.  It  doesn't say 'returned in response to an external 
query', it just says 'returned', which I of course take to include returned in 
response to an internal query such as this one.

Or, stepping back more, how _should_ I dynamically create an entry which 
olcLimits will respect?  I'm quite happy to be told I'm barking up the wrong 
tree here.  Is OpenLDAP simply unable to do this, or is dynlist expansion 
documented somewhere as happening only in restricted circumstances?

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: olcLimits and groupOfURLs dynlist

2024-02-08 Thread Norman Gray


Howard, hello.

On 8 Feb 2024, at 0:34, Howard Chu wrote:

>> 65c3df21.21fc2a30 0x16cacf000 
>> ldap_url_parse_ext(ldap:///ou=groups,o=example?member?sub?(|(cn=ldap-admins-*)(cn=ldap-techs)))
>
> The above URL is not valid for a dynamic group. The attrs portion of the URL 
> must be empty.
>
> Since it's invalid, after it is parsed it gets ignored.

That's true when constructing what slapo-dynlist(5) calls a dynamic
group, but that's not what I'm constructing here, but instead a group
entry which is dynamically expanded, to a group, by a search.

Hmm: I realise there's a collision of terminology here, and that I
used the specific phrase 'dynamic group' in the first message (but
managed to avoid it in the second).

slapo-dynlist(5) does indeed consistently use 'dynamic group' to refer
to the case where the olcDynListAttrSet has three values, and the
generated entry contains the DNs of the matching entries.

Here, however, I'm using the two-argument case, and defining a group
as the union of a number of groupOfNames groups.  That's a group which
is dynamic, but perhaps 'dynamically generated group' would be a less
colliding name than 'dynamic group'.

Anyway...

slapd.ldif:

dn: olcOverlay=dynlist,olcDatabase={3}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcDynlistConfig
olcOverlay: dynlist
olcDynListAttrSet: groupOfURLs memberURL

and group definition:

dn: cn=ldap-operators,ou=groups,o=example
cn: ldap-operators
objectClass: groupOfURLs
description: Members of all of the LDAP admin and tech groups
memberURL: 
ldap:///ou=groups,o=example?member?sub?(|(cn=ldap-admins-*)(cn=ldap-techs))

When I search for this, I do indeed get a group that looks as I'd hope:

% ldapsearch -x -H ldap://localhost:8389 -b o=example -LLL 
'(cn=ldap-operators)'
dn: cn=ldap-operators,ou=groups,o=example
cn: ldap-operators
objectClass: groupOfURLs
description: Members of all of the LDAP admin and tech groups
memberURL: 
ldap:///ou=groups,o=example?member?sub?(|(cn=ldap-admins-*)(cn=ldap-techs))
member: uid=norman,ou=staff,o=example
[...]

That is, the dynlist overlay has synthesised an entry which has a number of
'member' attributes.

That looks good, but this doesn't have the expected effect when I use
this group in the olcLimits directive.

olcLimits: 
group/groupOfURLs/memberURL="cn=ldap-operators,ou=groups,o=example" size=2

(or group/groupOfURLs/member).

Speculation: The objectClass of the above group is groupOfURLs, and
not groupOfNames, but the olcLimits documentation mentions
groupOfNames only as the default for the /oc element of this spec, and
not as a general requirement.

The short version is that if I look at the documentation for
olcLimits, it says:

> The term group, with the optional objectClass oc and attributeType at
> fields, followed by pattern, sets the limits for any DN listed in the
> values of the at attribute (default member) of the oc group
> objectClass (default groupOfNames) whose DN exactly matches pattern.

Using dynlist, I have synthesised a group with what appear to be the required
properties, but olcLimits isn't processing it as I expect.  The only
difference is that the group is dynamic rather than fixed.  What is
wrong with my expectation?

Best wishes,

Norman




-- 
Norman Gray  :  https://nxg.me.uk


Re: olcLimits and groupOfURLs dynlist

2024-02-07 Thread Norman Gray


Howard, hello.

On 7 Feb 2024, at 19:36, Howard Chu wrote:

>> If I then make a query which has a few results, I do not get this limit
>> imposed, and instead see in the logs
>>
>> 65c3ce83.0f52bea8 0x16e9d3000 => mdb_entry_get: found entry:
"cn=ldap-operators,ou=groups,o=example"
>> 65c3ce83.0f533f90 0x16e9d3000 <= mdb_entry_get: failed to find attribute 
>> member
>
> And those logs are correct, the group entry you specified has no member 
> attribute.
> What it has is a memberURL attribute, and that's what you should have 
> configured
> in your olcLimits statement.

Aha.  I had taken the description to refer to the synthesised 'member' 
attributes in the
dynamically generated group.  Thanks for this.

On changing this, though, to

olcLimits: 
group/groupOfURLs/memberURL="cn=ldap-operators,ou=groups,o=example" size=2

and making a query, I now see in the logs (with -d-1):

65c3df21.21fa70c8 0x16cacf000 ==> limits_get: conn=1000 op=1 
self="uid=norman,ou=staff,o=example" this="o=example"
65c3df21.21fa97d8 0x16cacf000 => mdb_entry_get: ndn: 
"cn=ldap-operators,ou=groups,o=example"
65c3df21.21fab718 0x16cacf000 => mdb_entry_get: oc: "groupOfURLs", at: 
"memberURL"
65c3df21.21fb1ca8 0x16cacf000 
mdb_dn2entry("cn=ldap-operators,ou=groups,o=example")
65c3df21.21fb4b88 0x16cacf000 => 
mdb_dn2id("cn=ldap-operators,ou=groups,o=example")
65c3df21.21fb8a08 0x16cacf000 <= mdb_dn2id: got id=0x2857
65c3df21.21fbb8e8 0x16cacf000 => mdb_entry_decode:
65c3df21.21fbd440 0x16cacf000 <= mdb_entry_decode
65c3df21.21fbef98 0x16cacf000 => mdb_entry_get: found entry: 
"cn=ldap-operators,ou=groups,o=example"
65c3df21.21fc0ed8 0x16cacf000 mdb_entry_get: rc=0
65c3df21.21fc2a30 0x16cacf000 
ldap_url_parse_ext(ldap:///ou=groups,o=example?member?sub?(|(cn=ldap-admins-*)(cn=ldap-techs)))
65c3df21.21fc7c38 0x16cacf000 => mdb_search
65c3df21.21fcb6d0 0x16cacf000 mdb_dn2entry("o=example")
65c3df21.21fcd9f8 0x16cacf000 => mdb_dn2id("o=example")
65c3df21.21fcf938 0x16cacf000 <= mdb_dn2id: got id=0x1
65c3df21.21fd1490 0x16cacf000 => mdb_entry_decode:
65c3df21.21fd2fe8 0x16cacf000 <= mdb_entry_decode
65c3df21.21fd4b40 0x16cacf000 => access_allowed: search access to 
"o=example" "entry" requested

There's no mention of 'limits' after this point in the log.

Thus it's finding the right entry and attribute, and parsing the URL
therein, but it's not clear what it's concluding.  When a search is
performed as a user who is included in the synthesised
cn=ldap-operators (confirmed by a search for that group), the query
results are not limited to 2 objects.

That 2-object limit is what I see in the corresponding configuration
when ldap-operators is a groupOfNames with explicit member attributes:

65c3e6ae.1da1a5c8 0x16e80b000 ==> limits_get: conn=1000 op=1 
self="uid=norman,ou=staff,o=example" this="o=example"
65c3e6ae.1da1c8f0 0x16e80b000 => mdb_entry_get: ndn: 
"cn=ldap-operators,ou=groups,o=example"
65c3e6ae.1da1e060 0x16e80b000 => mdb_entry_get: oc: "groupOfNames", at: 
"member"
65c3e6ae.1da226b0 0x16e80b000 
mdb_dn2entry("cn=ldap-operators,ou=groups,o=example")
65c3e6ae.1da24dc0 0x16e80b000 => 
mdb_dn2id("cn=ldap-operators,ou=groups,o=example")
65c3e6ae.1da28088 0x16e80b000 <= mdb_dn2id: got id=0x2857
65c3e6ae.1da2ab80 0x16e80b000 => mdb_entry_decode:
65c3e6ae.1da2c6d8 0x16e80b000 <= mdb_entry_decode
65c3e6ae.1da2de48 0x16e80b000 => mdb_entry_get: found entry: 
"cn=ldap-operators,ou=groups,o=example"
65c3e6ae.1da2fd88 0x16e80b000 mdb_entry_get: rc=0
65c3e6ae.1da31cc8 0x16e80b000 dnMatch 0
"uid=norman,ou=staff,o=example"
"uid=norman,ou=staff,o=example"
65c3e6ae.1da33c08 0x16e80b000 <== limits_get: type=GROUP match=EXACT 
dn="cn=ldap-operators,ou=groups,o=example" oc="groupOfNames" ad="member"
65c3e6ae.1da36700 0x16e80b000 => mdb_search
65c3e6ae.1da3bcf0 0x16e80b000 mdb_dn2entry("o=example")
65c3e6ae.1da3e018 0x16e80b000 => mdb_dn2id("o=example")
65c3e6ae.1da3fb70 0x16e80b000 <= mdb_dn2id: got id=0x1
65c3e6ae.1da41ab0 0x16e80b000 => mdb_entry_decode:
65c3e6ae.1da43220 0x16e80b000 <= mdb_entry_decode
65c3e6ae.1da44d78 0x16e80b000 => access_allowed: search access to 
"o=example" "entry" requested

(interestingly, the string 'limit' doesn't subsequently appear in this
-d-1 log, either)

So I'm afraid I'm still puzzled.

Norman




-- 
Norman Gray  :  https://nxg.me.uk


Re: The unique overlay: enforcing uniqueness in the union of trees

2024-02-07 Thread Norman Gray


Quanah, hello.

On 7 Feb 2024, at 19:26, Quanah Gibson-Mount wrote:

> Since it was historically done this way, yeah, best thing is to slowly fix 
> the data until it can be done correctly.

It's really a local case of NIS. Must. Die

Norman


-- 
Norman Gray  :  https://nxg.me.uk


olcLimits and groupOfURLs dynlist

2024-02-07 Thread Norman Gray


Greetings.

I have another puzzle with my OpenLDAP configuration, where I'm not
sure if what I'm seeing is unexpected.

Short version: should I expect a group in an olcLimits spec to work when the 
group is dynamic?

I have a dynamic group set up, using the dynlist overlay, which
expands to a set of DNs which should be allowed slightly privileged
access to a directory.  That group seems to be working OK:

% ldapsearch -x -H ldap://localhost:8389 -b o=example -LLL 
'(cn=ldap-operators)'
dn: cn=ldap-operators,ou=groups,o=example
cn: ldap-operators
objectClass: groupOfURLs
description: Members of all of the LDAP admin and tech groups
memberURL: 
ldap:///ou=groups,o=example?member?sub?(|(cn=ldap-admins-*)(cn=ldap-techs))
member: uid=norman,ou=staff,o=example
[...]

One goal here is to remove query limits for this group.  I can test
that by adding an artificially low limit:

olcLimits: group/groupOfURLs/member="cn=ldap-operators,ou=groups,o=example" 
size=2

If I then make a query which has a few results, I do not get this limit
imposed, and instead see in the logs

65c3ce83.0f52bea8 0x16e9d3000 => mdb_entry_get: found entry: 
"cn=ldap-operators,ou=groups,o=example"
65c3ce83.0f533f90 0x16e9d3000 <= mdb_entry_get: failed to find attribute 
member

(If, instead of this, I define an ldap-operators group of class
groupOfNames, with the above 'member' included explicitly, and make the
corresponding change to the olcLimits line, I get what I expect -- ie,
a restricted-size response to the query -- which reassures me I'm not
doing something stupid elsewhere.)

The slapo-dynlist(5) page says:

> Any time an entry with a specific objectClass is being returned, the
> LDAP URI-valued occurrences of a specific attribute are expanded into
> the corresponding entries, and the values of the attributes listed in
> the URI are added to the original entry.

I note the ‘any time’.

My configuration appears to be working for the ldapsearch lookup; I
don't see any text in that manpage that suggests this won't work for
the (somehow internal?) lookup being done when processing the
olcLimits expression.

The page slapd-config(5) says, under olcLimits:

> The term group, with the optional objectClass oc and attributeType at
> fields, followed by pattern, sets the limits for any DN listed in the
> values of the at attribute (default member) of the oc group
> objectClass (default groupOfNames) whose DN exactly matches pattern.

That text doesn't seem to me to exclude this entry lookup from the
‘any time’ in the slapo-dynlist text above.

This is OpenLDAP 2.6.7.

I am of course open to a frame-challenge about the best way of
achieving the underlying goal.

Best wishes,

Norman



-- 
Norman Gray  :  https://nxg.me.uk


Re: The unique overlay: enforcing uniqueness in the union of trees

2024-02-06 Thread Norman Gray


Quanah, hello.

On 6 Feb 2024, at 16:03, Quanah Gibson-Mount wrote:

> Questions about slapo-unique aside, this is a horrific way to organize your 
> data tree.  I'd strongly advise creating a tree for people, like:
>
> cn=people,dc=example,dc=com
>
> uid=x,cn=people,dc=example,dc=com
> uid=y,cn=people,dc=example,dc=com
>
> Store what department(s) they belong to as attribute in their user entry.

I take the point, and I certainly wouldn't organise things this way if _I_ were 
king.

In this case, though, dept1, dept2, and so on, are separate administrative 
domains, in both IT terms and real bureaucratic ones, and this is an attempt to 
bring some sort of coherence to a bit of historic anarchy (and yes, there is an 
ou=staff layer in the middle of the real trees).

Everyone more-or-less agrees on the names and uidNumbers in dept1, but there 
might be a local 'norman' in both dept2 and dept3, or people in those trees 
with historically colliding UIDs.  The result is that systems in dept2 will 
acknowledge users in ou=dept1 and ou=dept2, users in dept3 acknowledge ou=dept1 
and dept3 but ignore ou=dept2, and so on.  I expect that names will soon no 
longer be created in the deptN trees (pretty please?), in favour of the dept1 
tree, and the ou=staff parts of those will atrophy, but I'll be retired by then.

If there's a different way of approaching that particular problem, though, 
right now is the time for me to be rethinking this, so I'm open to challenge.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


The unique overlay: enforcing uniqueness in the union of trees

2024-02-06 Thread Norman Gray
d 2.6.7 (Jan  1 1980 00:00:00) $
openldap

Included static overlays:
    accesslog
syncprov
unique
Included static backends:
config
ldif
monitor
mdb
relay




-- 
Norman Gray  :  https://nxg.me.uk


Re: Transitioning from slapd.conf to slapd.d, best practices for maintaining configuration comments?

2023-11-16 Thread Norman Gray


Ben, hello.

On 15 Nov 2023, at 18:58, Ben Poliakoff wrote:

>  Looking for any tips about how
> best to annotate slapd configuration, in a slapd.d/olc world. Does anyone
> have a practice that they find works well for them?

What works for me (in a primary+replicas setup) is to maintain a slapd.ldif 
file with structured comments in it (ie, #@PRIMARY@ and #@REPLICA@ marking 
different variants), and when changes need to be made to the configuration, I 
stop the primary server (leaving things to replicas), slapcat the data, rebuild 
the slapd.d from scratch with the appropriate version of the configuration 
file, reload the data, and restart; then do the same with the replicas.

This isn't ideal, but it works for me because the window when no-one can write, 
because the primary is off, is acceptably small.

The advantages are

  * I can version-control (and of course densely comment) the configuration, 
with all the attendant advantages
  * I know exactly what the configuration of the server is, without querying 
the server
  * because they're both generated from the same source, I know for sure that 
the primary and replicas have compatible configurations
  * that means I can have a test server (including scratch regression-test 
servers) with a duplicate configuration

I can see how I could achieve most of these things using slapd.d as intended.  
But this route feels more direct, and thus more intelligible to me.  The first 
advantage seems the key one, to me.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: Proposal to strengthen slapd EXTERNAL authentication

2023-06-28 Thread Norman Gray


Greetings.

On 28 Jun 2023, at 3:41, Jordan Brown wrote:

> On 6/27/2023 7:14 PM, Quanah Gibson-Mount wrote:
>
>> Using a public CA for client certs seems very odd to me.
>
>  Depends on your use case.  Think of it as a form of federated login.

Indeed.  I've done something similar in the past (this was with access to a web 
service rather than an LDAP server, but the logic is the same).

Some of my users had, and knew how to use, X.509 certs issued by a large 
computing grid.  So I got my server to trust the CA's cert, and listed the DNs 
allowed access.  The grid CA did the legwork of setting up the PKI and checking 
the users, and I piggybacked on that, feeling rather smart.  Unfortunately, not 
_all_ of the relevant users had those certs, so I still had to set up a local 
CA, which meant it ended up more trouble than it was in fact worth.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: Tools parsing dc=foo URLs

2023-02-20 Thread Norman Gray


Uwe, helllo.

On 20 Feb 2023, at 13:28, Uwe Sauter wrote:

> ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)'
>
>  instead of
>
>  ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)'

No: the documentation for the -H option says that the SRV-lookup form, with the 
dc= components, is only tried when the host:port element of the URI is empty.

Looking at the code, the problem does appear to be that common.c:tool_args 
attempts to break the -H argument into multiple LDAP URIs by separating at 
commas, as well as spaces.  That's the right thing to do to match the first 
sentence of the ldapsearch(1) documentation of -H, but the second sentence 
there (the one starting 'As an exception...') doesn't mention a list of SRV 
names (sensibly, since an SRV record is implicitly a list anyway), so 
shouldn't, I think, attempt to split the argument.

As the code stands, you have to escape the ',' in order to trick the code into 
not splitting this argument.

I noted in the OP that there's a mild code change which would make this work as 
expected.

I'm raise this as a bugreport with suggested fix, since it doesn't sound from 
this discussion that there's something obvious I'm missing.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: Tools parsing dc=foo URLs

2023-02-20 Thread Norman Gray


Ede, hello.

On 20 Feb 2023, at 12:49, Ede Wolf wrote:

> Just guessing by the error message, but your DNS Server does have a valid 
> service record for that Base DN? As the error message suggests otherwise, but 
> I may as well be completely off here.

A good thought -- thanks -- but yes, the SRV records are set up correctly, and 
I can make the query if the ',' in the dc= list are escaped (even though RFC 
2396 doesn't require that).

>  Otherwise, but I am sure you know that, with only two "/" you can alway use 
> the hostname, in case the DNS serive record is missing:
>
>  ldapsearch -H ldap://server.example.net -b dc=example,dc=net"  'cn=foo'

Indeed, and that's what I do most of the time.  In fact, this is a case where a 
sequence of host+port LDAP URIs is useful.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Tools parsing dc=foo URLs

2023-02-10 Thread Norman Gray


Greetings.

This command fails in an unexpected way:

% ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)'
Could not parse LDAP URI(s)=ldap:///dc=example,dc=net (3)

It appears that ldapsearch wants me to escape the '=' and ',' in that URI:

% ldapsearch -x -H 'ldap:///dc%3dexample%2cdc%3dnet' '(cn=foo)'
DNS SRV: Could not turn domain=example.net into a hostlist

But why?  The manpage for ldapsearch says

   -H ldapuri
  Specify URI(s) referring to the ldap server(s); a list of URI,
  separated by whitespace or commas is expected; only the
  protocol/host/port fields are allowed.  As an exception, if no
  host/port is specified, but a DN is, the DN is used to look up
  the corresponding host(s) using the DNS SRV records, according
  to RFC 2782.  The DN must be a non-empty sequence of AVAs whose
  attribute type is "dc" (domain component), and must be escaped
  according to RFC 2396.

I read that as clearly saying (via the 'exception' branch of that paragraph) 
that the first -H argument is correct.



RFC digression:

According to RFC 2396, the /dc... is `"/" path_segments`, segments are composed 
of *pchar, and

  pchar = unreserved | escaped |
  ":" | "@" | "&" | "=" | "+" | "$" | ","

...which includes both '=' and ','.  Thus those characters don't need to be 
escaped, by RFC 2396.  Or, put another way, 'ldap:///dc=example,dc=net' _is_ 
escaped according to RFC2396, in the sense that nothing in it needs to be 
escaped.

Looking instead at RFC 4516, the 'dn' in the 'ldapurl' is a 'distinguishedName' 
from RFC 4514 which (Sect.3) permits '=' and ',' to be included.  Sect.2.1 of 
4516 requires that the URI must include ,  or 
 of RFC 3986, but if we look at that, then Sect.2.2 indicates that 
 includes both '=' and ','.

Thus the behaviour of ldapsearch, when parsing the -H option, doesn't appear to 
match the documentation.



Explanation:

Looking at common.c:tool_args and common.c line 1199, I see that it calls 
ldap_url_parselist to break the -H argument into a list of URIs, and this will 
separate dc=example,dc=net at the comma.  And sure enough, in practice it's 
only the ',' that has to be escaped by %2c.

I believe this behaviour doesn't match the manpage, which (clearly in my 
reading of it) requires either a list of protocol/host/port URIs OR (the 
exception) a single URI containing no host/port but only a DN.  That suggests 
that common.c:tool_args has to detect that exception/second case.  Apart from 
the documentation issue, having to escape commas is both repeatedly surprising 
and a pain in the neck on the occasions when I want to use the dc=... syntax 
with ldapsearch.

Re detecting that exception, searching for "///" in the ldapuri string would 
seem to be sufficient, and calling ldap_url_parselist_int in that case (instead 
of ldap_url_parselist) with a sep argument of " " looks like it would do the 
job with a minimal change to the code.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: using SRV-records in syncrepl

2023-01-20 Thread Norman Gray


Ondřej, hello.

On 20 Jan 2023, at 16:19, Ondřej Kuzník wrote:

> DNS retrieval and parsing of SRV records is the easy part, and libevent
>  has code to help us with that already. It's the management of the
>  backends on the tier (shutting down those that aren't listed anymore,
>  adding those that are new, rearranging the lists) all while the server
>  is still running unless we request a full server pause for it. And any
>  of the backends being removed might still have pending operations, what
>  do we do with those?
>
>  And then the code that uses those levels and weights for each request
>  that comes in, in an efficient way.

Ah, right -- fair enough.  I'd misunderstood where the gap was.

Looking at ldap_domain2hostlist, I still think my sort algorithm is more 
elegant, here, than use of the Fisher-Yates one (*cough*), but it's not like 
this is going to be a hotspot in the code!

Changing the subject slightly, since there is SRV support in libldap, is there 
any chance that it'll become possible to specify a SRV domain in ldap.conf, in 
place of the list of LDAP URIs in option 'URI'.  That is, it'd be useful to be 
able to say 'URI DNS:ldap.example.com' in there.  Supporting something similar 
to that is why I wrote this code.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: using SRV-records in syncrepl

2023-01-20 Thread Norman Gray

Quanah, hello.

On 20 Jan 2023, at 15:43, Quanah Gibson-Mount wrote:

> There is no license noted in this file, which would be a requirement to even 
> look at it.

No problem -- I've reattached a version with the BSD 2-clause licence included. 
 Is that an OK one for you?

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk
// DNS support -- return information about LDAP servers,
// by looking up a SRV record.
//
// SRV records, as discussed in RFC 2782, point to locations of
// services.  In the words of that RFC,
//
// If a SRV-cognizant LDAP client wants to discover a LDAP server that
// supports TCP protocol and provides LDAP service for the domain
// example.com., it does a lookup of
//
// _ldap._tcp.example.com
//
// The get_sorted_srv_records() function below will take a domain example.com,
// prepend the "_ldap._tcp",
// do the lookup to obtain the SRV record,
// and return a string containing the hosts and ports,
// sorted as described in the RFC.
//
// It's unexpectedly hard to find clear documentation about DNS lookups,
// but the following does seem to be portable,
// though without much in the way of intelligible manpages on any platform.
//
// See:
//   Scrappy documentation: 
https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch15_02.htm
//   Wikipedia: https://en.wikipedia.org/wiki/List_of_DNS_record_types
//   RFC 1035, Domain names -- implementation and specification
//
// This module exposes a function
//
//char* get_sorted_srv_records(const char* domain);
//
// which returns a space-separated list of ldap:// URIs obtained from
// the SRV record corresponding to the given domain, in a random order
// appropriate to the weights obtained.
//
// This can be compiled as a standalone (test?) program; see STANDALONE below.
//
// LICENCE: this is licensed under the terms of the BSD 2-clause licence.
// The licence text is at the bottom of the file.


// CentOS features.h requires _BSD_SOURCE in order to get types.h to define 
u_char,
// which resolv.h refers to.
#define _BSD_SOURCE 1
// Debian prefers _DEFAULT_SOURCE, and issues a deprecation warning
// if _BSD_SOURCE is defined and _DEFAULT_SOURCE isn't.
#define _DEFAULT_SOURCE 1
// ... and _XOPEN_SOURCE to get getopt
// (on eg CentOS, this also happens with _POSIX_C_SOURCE >= 2, but
// that _prevents_ macOS types.h from defining u_char).
#define _XOPEN_SOURCE 1

#include 
#include 
#include 
#include 
#include 

#include "config.h"

// See the docs for autoconf AC_HEADER_RESOLV
#ifdef HAVE_SYS_TYPES_H
#  include 
#endif
#ifdef HAVE_NETINET_IN_H
#  include/* inet_ functions / structs */
#endif
#ifdef HAVE_ARPA_NAMESER_H
#  include  /* DNS HEADER struct */
#endif
#ifdef HAVE_NETDB_H
#  include 
#endif
#include 

// There is a test main program at the bottom of this file.
// To compile:
//  cc -Wall -std=c99 -o dns-support -DSTANDALONE=1 -lresolv dns-support.c
//
#ifndef STANDALONE
#define STANDALONE 0
#endif

#if STANDALONE
#include 
#include 

// dummy out functions provided by the other modules in this kit
static int _chatter = 2;
int get_verbosity(void) { return _chatter; }
void change_verbosity(int inc) { _chatter += inc; }
void log_err_message(void* dummy, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#else
// we call get_verbosity and log_err_message
#include "ldaputil.h"
#include "ldap-config.h"
#endif

typedef unsigned char byte;

// Return a uniform random deviate in [0,1)
//
// random(3) returns a number in [0, 2^31-1].
// We convert this to a double by dividing it by 2^31 exactly.
// Thus the return value is always strictly less than one.
static double random_f(void)
{
static byte initialised_p = 0;
static double denom;

if (! initialised_p) {
srandom(time(NULL));
denom = ldexp(1, 31);
initialised_p = 1;

// Explore a few properties of 'denom'
// int exp;
// double mantissa = frexp(denom, );
// printf("%g -> %f.2^%d;  ", denom, mantissa, exp);
// double two31 = (double)2147483647; // 2^31-1 as an integer
// mantissa = frexp(two31, );
// printf("%g -> %f.2^%d;  ", two31, mantissa, exp);
// printf("ratio = %g, less than one? %s\n",
//two31/denom, two31/denom < 1.0 ? "yes" : "no");
}

double univariate = (double)random();
return univariate / denom;
}

// Uncompress a domain-name.
// The returned pointer points to storage which is reused on each invocation.
static const char* uncompress(ns_msg msg, const byte* p, int* skiplen_p)
{
static char ans[NS_MAXDNAME];
int skiplen = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
 p,
 ans, sizeof(ans));
if (skiplen_p != NULL) *skiplen_p = skiplen;

return (skip

Re: using SRV-records in syncrepl

2023-01-20 Thread Norman Gray


And...

On 20 Jan 2023, at 15:33, Norman Gray wrote:

> This exposes a function
>
>  char* get_sorted_srv_records(const char* domain);
>
>  which does a SRV lookup, and orders the records that come back according to 
> the specification of RFC 2782 (though in a single pass, rather than the 
> clumsy multiple pass algorithm that the RFC suggests).

I should mention that the way I use this is

ldap_server = "ldap://foo;;
// or
ldap_server = "DNS:ldap.example.com";

char* server_list;
if (strncmp(ldap_server, "DNS:", 4) == 0) {
server_list = get_sorted_srv_records(_server[4]);
} else {
server_list = ldap_server;
}

ldap_initialise(, server_list);

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: using SRV-records in syncrepl

2023-01-20 Thread Norman Gray

Ondřej, hello.

On 20 Jan 2023, at 10:47, Ondřej Kuzník wrote:

> That said, patches implementing some kind of SRV are welcome. The easiest
>  way might be to introduce an lloadd tier implementation that manages its
>  backend collection accordingly.

It's not an OpenLDAP patch, but I've attached a module which might be of 
interest here.  This exposes a function

char* get_sorted_srv_records(const char* domain);

which does a SRV lookup, and orders the records that come back according to the 
specification of RFC 2782 (though in a single pass, rather than the clumsy 
multiple pass algorithm that the RFC suggests).

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk
// DNS support -- return information about LDAP servers,
// by looking up a SRV record.
//
// SRV records, as discussed in RFC 2782, point to locations of
// services.  In the words of that RFC,
//
// If a SRV-cognizant LDAP client wants to discover a LDAP server that
// supports TCP protocol and provides LDAP service for the domain
// example.com., it does a lookup of
//
// _ldap._tcp.example.com
//
// The get_sorted_srv_records() function below will take a domain example.com,
// prepend the "_ldap._tcp",
// do the lookup to obtain the SRV record,
// and return a string containing the hosts and ports,
// sorted as described in the RFC.
//
// It's unexpectedly hard to find clear documentation about DNS lookups,
// but the following does seem to be portable,
// though without much in the way of intelligible manpages on any platform.
//
// See:
//   Scrappy documentation: 
https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch15_02.htm
//   Wikipedia: https://en.wikipedia.org/wiki/List_of_DNS_record_types
//   RFC 1035, Domain names -- implementation and specification
//
// This module exposes a function
//
//char* get_sorted_srv_records(const char* domain);
//
// which returns a space-separated list of ldap:// URIs obtained from
// the SRV record corresponding to the given domain, in a random order
// appropriate to the weights obtained.
//
// This can be compiled as a standalone (test?) program; see STANDALONE below.


// CentOS features.h requires _BSD_SOURCE in order to get types.h to define 
u_char,
// which resolv.h refers to.
#define _BSD_SOURCE 1
// Debian prefers _DEFAULT_SOURCE, and issues a deprecation warning
// if _BSD_SOURCE is defined and _DEFAULT_SOURCE isn't.
#define _DEFAULT_SOURCE 1
// ... and _XOPEN_SOURCE to get getopt
// (on eg CentOS, this also happens with _POSIX_C_SOURCE >= 2, but
// that _prevents_ macOS types.h from defining u_char).
#define _XOPEN_SOURCE 1

#include 
#include 
#include 
#include 
#include 

#include "config.h"

// See the docs for autoconf AC_HEADER_RESOLV
#ifdef HAVE_SYS_TYPES_H
#  include 
#endif
#ifdef HAVE_NETINET_IN_H
#  include/* inet_ functions / structs */
#endif
#ifdef HAVE_ARPA_NAMESER_H
#  include  /* DNS HEADER struct */
#endif
#ifdef HAVE_NETDB_H
#  include 
#endif
#include 

// There is a test main program at the bottom of this file.
// To compile:
//  cc -Wall -std=c99 -o dns-support -DSTANDALONE=1 -lresolv dns-support.c
//
#ifndef STANDALONE
#define STANDALONE 0
#endif

#if STANDALONE
#include 
#include 

// dummy out functions provided by the other modules in this kit
static int _chatter = 2;
int get_verbosity(void) { return _chatter; }
void change_verbosity(int inc) { _chatter += inc; }
void log_err_message(void* dummy, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#else
// we call get_verbosity and log_err_message
#include "ldaputil.h"
#include "ldap-config.h"
#endif

typedef unsigned char byte;

// Return a uniform random deviate in [0,1)
//
// random(3) returns a number in [0, 2^31-1].
// We convert this to a double by dividing it by 2^31 exactly.
// Thus the return value is always strictly less than one.
static double random_f(void)
{
static byte initialised_p = 0;
static double denom;

if (! initialised_p) {
srandom(time(NULL));
denom = ldexp(1, 31);
initialised_p = 1;

// Explore a few properties of 'denom'
// int exp;
// double mantissa = frexp(denom, );
// printf("%g -> %f.2^%d;  ", denom, mantissa, exp);
// double two31 = (double)2147483647; // 2^31-1 as an integer
// mantissa = frexp(two31, );
// printf("%g -> %f.2^%d;  ", two31, mantissa, exp);
// printf("ratio = %g, less than one? %s\n",
//two31/denom, two31/denom < 1.0 ? "yes" : "no");
}

double univariate = (double)random();
return univariate / denom;
}

// Uncompress a domain-name.
// The returned pointer points to storage which is reused on each invocation.
static const char* uncompress(ns_msg msg, const byte* p, int* skiplen_p)
{
static char ans[NS_MAXDNAME];

Discovering certificate locations from libldap

2023-01-17 Thread Norman Gray


Greetings.

Should I be able to discover the (default) locations of SSL certificates, via 
the libldap library?

This can be useful when debugging why cert checks are failing -- where is the 
library checking? (am I using the library I think I am...?!)  Of course dtruss 
and co can help here.

ldap_get_option with LDAP_OPT_X_TLS_CACERTDIR (and friends) looks like it 
should say this, but when I explore that, it appears to show only settings 
added with ldap_set_option, thus only settings overriding a default.  And this 
appears to be confirmed in libraries/libldap/tls_o.c:tlso_ctx_init.  That 
function hands over to SSL functions, and while in principle I could retrieve a 
TLS session context with LDAP_OPT_X_TLS_{,SSL_}CTX, there are clear warnings 
that I shouldn't be tinkering with this.  The fact that I'm this deep in the 
code suggests that either (a) this is not supported, or (b) I'm looking in the 
wrong place.

I could in principle use functions from the OpenSSL library, like 
X509_get_default_cert_dir_env(), but that requires me to know which SSL library 
the libldap library was linked against (and that it was indeed OpenSSL), which 
has its own complications.  Also, if I'm confident I know that, I have other 
ways to confirm the cert directory.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: [EXT] [OldapWS] ‑> Proposal of a REST Web Service for CRUD Operations

2022-09-20 Thread Norman Gray


Ulrich, hello.

On 20 Sep 2022, at 8:36, Ulrich Windl wrote:

>> Thus the 'JSON query string' sent to the server via HTTP POST wouldn't
>> qualify as 'REST'.
>
>  OTOH it will help to keep URIs short and allow easy encoding of structured
>  data.

True -- I wasn't primarily criticising the API design as such, merely noting 
that the term 'REST' has a fairly narrow definition.

That said, as a separate point, I think the REST design paradigm is a good one, 
in the sense that it decomposes the problem in a way that I, for one, find 
useful.  It does lead to longer URIs, yes, but that's surely a very minor 
inconvenience, if it's an inconvenience at all.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: [OldapWS] -> Proposal of a REST Web Service for CRUD Operations

2022-09-19 Thread Norman Gray


Greetings.

On 19 Sep 2022, at 17:54, Howard Chu wrote:

> Then, I would like to propose a full Open Source first realease of a CRUD 
> REST Web Service to manipulate OpenLDAP's Directory Objects.

This is a nice idea!

However, as something of a terminology quibble, I'd say this was a 'web 
service', rather than a 'REST web service'.

As I understand the term, I take 'REST' to refer to a web service which, at a 
minimum,

  * describes a URL-based scheme for _naming_ the things being manipulated, and
  * retrieves and manipulates those things via the HTTP verbs, GET, POST, PUT, 
DELETE, etc.

Thus the 'JSON query string' sent to the server via HTTP POST wouldn't qualify 
as 'REST'.

For a REST scheme, I can imagine something like supporting service objects 
named, eg

https://ldapcrud.service/dc=fr/dc=oldapws/cn=Olivier%20Chator

Calling GET on that obtains the attributes of the corresponding object; calling 
PUT on it replaces or creates it; calling DELETE deletes it, and so on.

One might also have

.../cn=Olivier%20Chator/cn

to name a single attribute of the object (retrieved or edited with 
GET/POST/PUT/DELETE).

Parameters such as 'nbbypage' might naturally fit in using URL path parameters. 
 RFC 3986, Sect.3.3 'Path', gestures towards these without committing itself to 
a particular standard, but

.../dc=fr/dc=oldapws;nbbypage=10;numpage=2

might work as a way of naming, and thus retrieving, the second 10 results which 
<.../dc=fr/dc=oldaps> would produce (ie, paging through the results of 
<.../dc=fr/dc=oldapws>).

The Accept header in the HTTP query, containing a MIME type, can be used to 
request a result format.

I'm not 100% sure that this scheme is optimal (is it unambiguous when 
distinguishing 'I want an entry' from 'I want attribute "x" from an entry'?), 
but this sort of scheme is very easy to use: no creating query strings, just 
retrieve a URL.  The obligation to think about the naming of objects, and to 
separate that from the understanding of the HTTP verbs, produces in my 
experience a great deal of design clarity.

It also gets a fair amount of specification for free, in that the semantics of 
the HTTP verbs are well-defined, in terms of idempotency and the like.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: Official way to import schema with cn=config

2022-04-05 Thread Norman Gray


Michael, hello.

On 5 Apr 2022, at 16:01, Michael Ströder wrote:

> On 4/5/22 08:10, David Timber wrote:
>
>> I know how to import schemas with cn=config. That was never a question. I 
>> was just complaining because it's a tedious process and I believe that it 
>> shouldn't be like this.
>
>  I also think that cn=config should not be so complicated. And I've looked 
> into supporting this schema in web2ldap.

Can you say a little more about how slapd.d is complicated?  I ask because I've 
never used slapd.conf, and I'm worried I'm missing something, or that there's 
an interestingly different perspective on how to configure openldap, which I 
could usefully learn about.

If I want to set up a new (testing?) instance, or test a tweaked configuration, 
then I blow away any pre-existing slapd.d, slapadd slapd.ldif, upload a dump of 
the live database (which takes a few seconds with -q), start slapd, and off we 
go.

All of the configuration is in that single slapd.ldif file.  I might 
occasionally make live tweaks to the configuration with ldapmodify, but after 
testing I would freeze them in the version-controlled slapd.ldif.

I can see that there's a way of working where the 'live' cn=config tree is the 
source of truth, and one backs that up carefully, but that doesn't seem an 
entirely comfortable way of working, to me.  And I can see that if there were a 
very high volume of writes, then the few seconds of primary-server downtime 
here could become intricate.  But if one had a setup like that, then presumably 
one has a multi-master configuration, so that the primaries could have their 
configurations updated from a single slapd.ldif in rotation.

>  For now I'm just happy that static slapd.conf is still supported. It's still 
> the most DevOps-friendly way to configure OpenLDAP.

I'm not really sure what devops-friendly means here.  I think my problem -- the 
source of my puzzlement -- is that I can't see much significant difference 
between slapd.conf and slapd.ldif other than details of the syntax (which to my 
eyes is less weird in the latter case than the former).

Or: what would I be losing if support for slapd.conf disappeared tomorrow?

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: STARTTLS vs LDAPS

2022-03-31 Thread Norman Gray


Quanah and all, hello.

On 30 Mar 2022, at 18:54, Quanah Gibson-Mount wrote:

> --On Wednesday, March 30, 2022 8:28 PM +0200 Stefan Kania 
>  wrote:
>
>> That's what can be found in the FAQ on openldap.org:
>>
>> https://www.openldap.org/faq/data/cache/605.html
>>
>> I would trust this more then any rumors on any stack page ;)
>
>  Unfortunately, the FAQ is dead weight we want to kill and not maintained in 
> any way, shape, or form.  It's currently provided for historical purposes.

Since the copyright dates at the bottom of that page are '1998-2013', so that 
the content of the site is now nearly a decade out of date, I feel the 
FAQ-o-matic now has negative utility, and that you should give in to the urge 
to kill it.

I respect and applaud the desire to preserve the content for historical 
reasons, but surely that goal can be served by making a tarball of the content 
available at whatever page https://www.openldap.org/faq/.../* were to redirect 
to (ie, the pages shouldn't be 404-ed, but neither should they be 200; 301 is 
good).

I have previously (indeed recently) looked at that page and, without thinking 
much about the question, taken its deprecation of LDAPS as current doctrine.

And ah, FAQ-o-matic I have fond memories of FAQ-o-matics, back when wikis 
were new...

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: STARTTLS vs LDAPS

2022-03-31 Thread Norman Gray


Thomas, hello..

On 31 Mar 2022, at 5:29, thomaswilliampritch...@gmail.com wrote:

>> As to this overall discussion, one of the primary issues with connections
>> over ldap:/// is that there's zero way with simple binds to prevent the
>> bind dn + password being sent in the clear by a client to the server.  With
>> ldaps:/// the encryption is set up before the BIND occurs so you don't run
>> this risk.
>
> Is that true? Surely I can
> 1. connect to the server
> 2. Send starttls
> 3. Then bind bind can't I?
> I'm fairly certain I've used LDAP Client operating in that order.

Yes, you _can_ and should do that, and most folk do.  The problem here is that, 
with LDAP+StartTLS, the server can't prevent a client doing it the other way 
around, and sending the bind credentials before StartTLS.  That's bad, from the 
server's point of view.

Best wishes,

Norman


-- 
Norman Gray  :  https://nxg.me.uk


Re: Documentation: mapping from slapd.conf to slapd database

2020-07-16 Thread Norman Gray



Quanah and Howard, hello.

On 16 Jul 2020, at 16:29, Quanah Gibson-Mount wrote:

Documentation such as [1] notes that there is a one-to-one 
correspondence

between slapd.conf directives and slapd-config database attributes.
However it's not always completely clear just what the mapping is.


See bugs: 5915, 6277, 7335, 8742


Right -- I see.  Thanks.

I appreciate the point in 
<https://bugs.openldap.org/show_bug.cgi?id=5915> that documenting both 
sets of directives would be quite a lot of work, which might have to be 
more-or-less redone when slapd.conf support is removed in 2.6/3.0 
(hooray).


As an interim alternative, it would probably be lowish-effort, but 
useful, if eg slapo-syncprov(5) and friends said something like the 
following, at the end of the '.SH CONFIGURATION' section:


Note that the above are
.B slapd.conf
configuration options.  These will be replaced by
.B slapd.d
options (see
.B slapd-config(5)
for details) in a forthcoming release.  Until then, you can deduce the 
names of the

.B slapd.d
attributes by examining the source files in [suitable URL, such as at 
git.openldap.org,

or simply a reference to servers/slapd/overlays in the distribution].

The same text could be dumped into all or most of the slapo-* manpages.  
It's incomplete, but it would be better than nothing, in that it would 
reassure the reader that there isn't some collection of documentation 
they've completely missed, and that the documentation isn't somehow out 
of date, by still referring to slapd.conf-style attributes.


I have an alternative, possibly better, suggestion below.


Patches welcome where appropriate.


If it were simply a case of the above, then yes, I could do the labour 
of the edit and send you a patch.  But I don't think I've the standing 
to be creative here (!).



Overlay objectClasses are defined in the code for the overlay.

<https://git.openldap.org/openldap/openldap/-/blob/master/servers/slapd/overlays/syncprov.c#L3160>


Thanks -- at least I'm not missing something obvious!

Separately, Howard Chu said:

All of the schema is always retrievable from slapd itself, either by 
querying cn=Subschema

or cn=schema,cn=config.


That looks perfect in principle, and I see you made a similar remark in 
<https://bugs.openldap.org/show_bug.cgi?id=7335>.  However the first way 
that occurred to me to search for this:


# slapcat -b cn=config | grep cn=schema
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config

...didn't produce the results I expected.

I find I can do

%  ldapsearch -x -b cn=schema,cn=config -D cn=config -w PASSWORD 
'(objectclass=*)'


and grub through the output to find

olcObjectClasses: ( OLcfgOvOc:1.1 NAME 'olcSyncProvConfig' DESC 
'SyncRepl Prov
 ider configuration' SUP olcOverlayConfig STRUCTURAL MAY ( 
olcSpCheckpoint $ o

 lcSpSessionlog $ olcSpNoPresent $ olcSpReloadHint ) )

Is that what you meant, Howard?  If so, then yes, a schema; but looking 
there really, really, isn't obvious from slapd-config(5).  It is 
described there under 'schema options', and there's nothing wrong with 
the text, but one  has to know it's there beforehand, in order to find 
it.


I think none of your users would feel at all insulted by being given 
slightly more of a hint there or in, say, slapd.overlays(5).


(I've spent enough time with OpenLDAP to be able to parse that attribute 
value by eye, and recognise it as not line-noise).


To be concrete, how about, in slapd.overlays,

.SH SCHEMAS
The schemas for these overlays are documented in the corresponding
.B slapo-
(5) manpages, in the form appropriate for
.B slapd.conf
configuration.  The schemas are loaded dynamically,
and can be found either in the overlay source code, or else searching
for the appropriate attributes under
.B cn=schema,cn=config
For example
.B ldapsearch -x -b cn=schema,cn=config -s base -D cn=config -w PASSWORD 
'(objectclass=*)' olcobjectclasses

See the
.B slapd-config
manpage for discussion of the olcObjectClasses attribute.

I found and read the slapd.overlays manpage early in my search for this 
information.  Something like the above would have led me to the 
information I needed very quickly.


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk


Documentation: mapping from slapd.conf to slapd database

2020-07-16 Thread Norman Gray



Greetings.

Documentation such as [1] notes that there is a one-to-one 
correspondence between slapd.conf directives and slapd-config database 
attributes.  However it's not always completely clear just what the 
mapping is.


For example, both [2] and slapo-syncprov(5) describe 
syncprov-checkpoint. This corresponds to the attribute olcSpCheckpoint, 
but I can't find where it is I learned that mapping (I probably stumbled 
across it via [3]), so can't point to chapter and verse in my own 
documentation and notes.


I would have thought the documentation for the olcSyncProvConfig 
objectClass would explain this, but I can't find any such documentation, 
nor even a schema for that objectClass [4].


The problem (and my puzzlement) is not unique to the syncprov overlay.

Best wishes,

Norman


[1] https://www.openldap.org/doc/admin24/slapdconf2.html
[2] https://openldap.org/doc/admin24/overlays.html
[3] 
https://mishikal.wordpress.com/2019/04/23/configuring-mmr-using-delta-syncrepl-in-openldap-updating-an-existing-standalone-configuration/
[4] Ie, grep -i syncprov /usr/local/etc/openldap/schema/* (and similar) 
produces nothing.


--
Norman Gray  :  https://nxg.me.uk


Re: slapo-unique spins its wheels on a non-trivial olcUniqueURI spec

2019-09-13 Thread Norman Gray



Greetings.

On 11 Sep 2019, at 11:09, Norman Gray wrote:


So there is at least a documentation gap here.



Of course slapd should not run crazy because of this.



Is there enough information in my previous message for me to add a 
reasonable ITS report, do you think?


I've added ITS#9486 and ITS#9488, referring to the wheel-spinning and 
the documentation, respectively.  I hope these are useful.


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



Re: slapo-unique spins its wheels on a non-trivial olcUniqueURI spec

2019-09-11 Thread Norman Gray



Michael, hello.

Thanks for your response.

On 10 Sep 2019, at 19:33, Michael Ströder wrote:

The above is invalid. Your LDIF should contain separate attribute 
values for each unique URI:


olcUniqueURI: ldap:///ou=dept-A,o=example?uidnumber?sub
olcUniqueURI: ldap:///ou=dept-B,o=example?uidnumber?sub


The problem is that both the manpage and the source-code comments seem 
to state that the attribute can take multiple values.  Quoting from the 
manpage:



 Multiple URIs may be specified within a domain,
allowing complex selections of objects. Multiple unique_uri
statements or olcUniqueURI attributes will create independent

domains


I interpret that as saying that each olcUniqueURI attribute corresponds 
to, or implies, an 'independent domain', and that 'Multiple URIs may be 
specified within a domain' indicates that a domain can be specified by 
multiple ldap:/// URIs (though it doesn't say, for example, whether 
these are composed using UNION or something else).  That is, if this 
text _isn't_ intended to say that there may be multiple olcUniqueURI 
attributes, each of which can have multiple URIs, then it should be 
rewritten.


I would interpret your rewritten version as saying that uidnumber 
attributes should be unique in ou=dept-A, and that they should be unique 
in ou=dept-B (ie, they are independent), but not that they should be 
unique in (ou=dept-A UNION ou=dept-B), which is what I want.


So there is at least a documentation gap here.


Of course slapd should not run crazy because of this.


Is there enough information in my previous message for me to add a 
reasonable ITS report, do you think?



You can look at a running example config (cn=config read-only):


Thanks -- this is very useful (and also nudges investigating Ædir 
further up my list).  I'll study those.


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



slapo-unique spins its wheels on a non-trivial olcUniqueURI spec

2019-09-10 Thread Norman Gray




Greetings.

I'm having difficulty creating a non-trivial olcUniqueURI spec.  Can
anyone advise me?

The problems are:

  * A plausible-looking spec in olcUniqueURI causes slapadd to spin
its wheels indefinitely.
  * The manpage doesn't make it terribly clear what I should expect
from a plausible-looking spec.

Details follow:

I want to specify something like

dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcUniqueConfig
olcOverlay: unique
olcUniqueURI: ldap:///ou=dept-A,o=example?uidnumber?sub
  ldap:///ou=dept-B,o=example?uidnumber?sub

The idea is that the uidnumber attribute should be unique across the two 
OUs,

ou=dept-A and ou=dept-B.

If I do this, however, then slapadd spins its wheels:

$ rm -R /usr/local/etc/openldap/slapd.d/*
$ su -m ldap -c "slapadd -d255 -n 0 -F 
/usr/local/etc/openldap/slapd.d -l /usr/local/etc/openldap/slapd.ldif"

...
...
5d77d377 >>> dnPrettyNormal: 

5d77d377 <<< dnPrettyNormal: 
, 

5d77d377 <= 
str2entry(olcOverlay=unique,olcDatabase={1}mdb,cn=config) -> 0x800d4eca8
5d77d377 oc_check_required entry 
(olcOverlay=unique,olcDatabase={1}mdb,cn=config), objectClass 
"olcUniqueConfig"

5d77d377 oc_check_allowed type "objectClass"
5d77d377 oc_check_allowed type "olcOverlay"
5d77d377 oc_check_allowed type "olcUniqueURI"
5d77d377 oc_check_allowed type "structuralObjectClass"
5d77d377 >>> dnNormalize: 
5d77d377 <<< dnNormalize: 
5d77d377 ==> unique_db_init
5d77d377 ==> unique_new_domain 
<ldap:///ou=dept-A,o=example?uidnumber?sub 
ldap:///ou=dept-B,o=example?uidnumber?sub>

5d77d377 >>> dnPrettyNormal: 
5d77d377 <<< dnPrettyNormal: , 


5d77d377 >>> dnPrettyNormal: 
5d77d377 <<< dnPrettyNormal: , 


5d77d377 >>> dnPrettyNormal: 
5d77d377 <<< dnPrettyNormal: , 


5d77d377 >>> dnPrettyNormal: 
5d77d377 <<< dnPrettyNormal: , 


5d77d377 >>> dnPrettyNormal: 
5d77d377 <<< dnPrettyNormal: , 


5d77d377 >>> dnPrettyNormal: 
5d77d377 <<< dnPrettyNormal: , 


...
^C

and so on and on and on, apparently indefinitely.

slapo-unique(5) says that the syntax here is:

unique_uri <[strict ][ignore ]URI[URI...]...>
  Configure the base, attributes, scope, and filter for 
uniqueness
  checking.  Multiple URIs may be specified within a 
domain,
  allowing complex selections of objects.  Multiple 
unique_uri
  statements or olcUniqueURI attributes will create 
independent
  domains, each with their own independent lists of URIs 
and

  ignore/strict settings.

  Keywords strict and ignore have to be enclosed in quotes 
(")

  together with the URI.

  The LDAP URI syntax is a subset of RFC-4516, and takes 
the form:


  ldap:///[base dn]?[attributes...]?scope[?filter]

(I'm taking it that there should be a space between those
`URI[URI...]`)

in servers/slapd/overlays/unique.c, the comment above
`unique_new_domain` says instead

* domain_specs look like
*
* [strict ][ignore ]uri[[ uri]...]
* e.g. "ldap:///ou=foo,o=bar?uid?sub ldap:///ou=baz,o=bar?uid?sub;
*  "strict ldap:///ou=accounts,o=bar?uid,uidNumber?one;
*  etc
*

So that's clearly permitting multiple URIs -- perhaps the quotes are
required (as the manpage hints).  But if I try

olcUniqueURI: "ldap:///ou=dept-A,o=example?uidnumber?sub
  ldap:///ou=dept-B,o=example?uidnumber?sub;

...then I get

5d77d617 ==> unique_new_domain 
<"ldap:///ou=dept-A,o=example?uidnumber?sub 
ldap:///ou=dept-B,o=example?uidnumber?sub;>
5d77d617 olcUniqueURI: value #0: 
<"ldap:///ou=dept-A,o=example?uidnumber?sub 
ldap:///ou=dept-B,o=example?uidnumber?sub;> invalid ldap urilist


from slapadd (so that's not the problem).  But the example there does
look VERY much like what I tried.

So:

  * I'm pretty sure I shouldn't be able to make slapadd spin its
wheels like that.
  * The manpage text might be a little too telegraphic.  While I'm sure
it's not _wrong_, it is quite hard to go from that text to a
working spec with any confidence.

Googling olcUniqueURI produces very little of use.  Is this not the 
correct way to do this?


This looks somewhat similar, in symptoms and module, to ITS#8162, but
it does seem distinct.

Thanks for any pointers.

Best wishes,

Norman





--
Norman Gray  :  https://nxg.me.uk



Re: slapo-memberof(5) confusing documentation

2019-09-09 Thread Norman Gray



Michael, hello.

On 9 Sep 2019, at 16:16, Michael Ströder wrote:


On 9/9/19 4:06 PM, Norman Gray wrote:



However, immediately after that, the text says:

Note that slapo-memberOf is not compatible with syncrepl based 
replication, and should not be used in a replicated environment. An 
alternative is to use slapo-dynlist to emulate slapo-memberOf 
behavior.


This seems to flatly contradict (my understanding of) the first part 
of the paragraph.


The problem is that in syncrepl refresh phase entries can be 
replicated in any order. So if a group entry comes in before the 
member entries are present you will see some warnings in the log and 
the entries may not be consistent.


See ITS#8613 for details:


Indeed: I quoted ITS#8613 which says 'slapo-memberOf overlay is not safe 
to use in a replicated environment', because of the ordering issue that 
you've mentioned here.


It seems that one can use the memberof overlay if-and-only-if one has 
separately done something to deal with the ordering (which would be 
tricky) or one has some means of completely avoiding 'refresh' mode in 
the sync (which would be tricky).  In practice, that looks very much 
like a 'no', and the contradiction in the manpage still seems to be 
present.


For what it's worth, the manpage text looks as if the 'Note that...' 
sentence were added at some point (possibly in response to ITS#8613?) 
without amending the text immediately before it, so that the result is a 
little garbled.


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



slapo-memberof(5) confusing documentation

2019-09-09 Thread Norman Gray



Greetings.

The slapo-memberof(5) manpage mentions limitations on when it can be 
used, in the context of replication.  The current text is very 
confusing, and possibly not self-consistent.


This message might be more appropriate as an ITS PR, but I'm sending it 
here first, partly in case I've got the wrong end of the stick, and 
partly as google-bait for the benefit of anyone as puzzled as I was.


The text currently says:

The memberof overlay may be used with any backend that provides full 
read-write functionality, but it is mainly intended for use with local 
storage backends. The maintenance operations it performs are internal 
to the server on which the overlay is configured and are never 
replicated. Replica servers should be configured with their own 
instances of the memberOf overlay if it is desired to maintain these 
memberOf attributes on the replicas.


Fine -- that seems to me to say very clearly that the memberof attribute 
is OK to use across replicas, as long as each replica has its own 
memberof overlay.


However, immediately after that, the text says:

Note that slapo-memberOf is not compatible with syncrepl based 
replication, and should not be used in a replicated environment. An 
alternative is to use slapo-dynlist to emulate slapo-memberOf 
behavior.


This seems to flatly contradict (my understanding of) the first part of 
the paragraph.


So which is it?

A 2009 list thread [1] seems to suggest that you can sort of get away 
with it, but only just. However another list thread (2015) [2] describes 
an apparently successful setup using simple syncrepl, with memberof in 
the provider and consumer, and where the memberof attribute is 
automatically excluded from the replication (there’s explicit advice 
not to exclude it using exattrs=memberof in the syncrepl setup). The 
latter posting refers to ITS issue 7400 [3], ‘Memberof and Syncrepl 
incompatibility’, which last had activity in 2012, but which still 
appears to be open.  The latter issue notes in passing that ‘memberof 
must be configured on each replica’, which implies that this is a 
feasible setup.


**However**: closed ITS 8613 (2017) [4] says baldly that

The slapo-memberOf overlay is not safe to use in a replicated 
environment due to the way in which replication occurs.


It also explains why, and gives a (compressed but complete) suggestion 
of how one might use the dynlist overlay to do something similar. A 2018 
list message [5] says in passing


Unfortunately, there is no defined standard for the “memberOf” 
functionality (it’s a MS hack) and so there’s nothing that details 
how it should or shouldn’t behave with replication.


Going with the most recent statement, therefore, it seems that this it's 
simply not possible to use memberOf in a replicated environment, unless 
(rather precariously, I'd have thought) you completely avoid 'refresh' 
mode in replication, as mentioned in [4].


I suggest adjusting the text in the slapo-memberof manpage.  If the 
third sentence (‘Replica servers should...’) were simply removed, 
that would remove most of the contradiction.  In the following sentence 
(‘Note that...’), the sentence first seems to suggest that it's only 
syncrepl replication that the overlay is incompatible with (ie, that 
there are other replication mechanisms which will work), but it goes on 
to state that it's incompatible with _all_ replication methods.  Which 
is it?


Finally, given the aside in [5], it might be worth indicating in the 
manpage that memberOf should only be used when other considerations 
force it, and should (by the sound of it) be avoided otherwise.


Have I misunderstood something?

Best wishes,

Norman



[1] 
https://www.openldap.org/lists/openldap-software/200910/msg00037.html
[2] 
https://www.openldap.org/lists/openldap-technical/201505/msg00127.html
[3] 
https://www.openldap.org/its/index.cgi/Software%20Bugs?id=7400;selectid=7400

[4] http://www.openldap.org/its/index.cgi/?findid=8613
[5] 
https://www.openldap.org/lists/openldap-technical/201809/msg00099.html



--
Norman Gray  :  https://nxg.me.uk



Re: SHA-2 and other hashes

2019-06-03 Thread Norman Gray



Howard, hello.

On 3 Jun 2019, at 15:07, Howard Chu wrote:

SHA-2 in any form is unsuitable for use as a password hash, simply 
because it is too easy to compute.
At this point the best choice is the one that won the Password Hashing 
Competition - Argon2.

https://github.com/P-H-C/phc-winner-argon2


That makes sense -- thanks.


Patches for adding this to OpenLDAP would of course be welcome.


I'm sure.  However I fear I'm not going to be able to oblige in the 
short term


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



Re: SHA-2 and other hashes

2019-06-03 Thread Norman Gray



Ulrich, hello.

On 3 Jun 2019, at 13:50, Ulrich Windl wrote:

ie, pretty much what I expected ‑‑ but in glibc's crypt(3), the 
$5$ and

$6$ hashes are the result of an unspecified number of rounds of such
hashing (the $1$/MD5 glibc hash does appear to be compatible with
OpenLDAP {SMD5}, though).  (Quite possibly everyone else in the world
already knew this, but I didn't!)



Hi!

First the number of rounds is NOT unspecified: It
s explicitly specified, it's optional, and (I think) it defaults to 
one.


Good point -- the number of rounds is indeed exposed.

If I'm correctly reading crypt/sha256-crypt.c in 
<https://ftp.gnu.org/gnu/glibc/>, then the default number of rounds is 
5000 and, as you say, the number of rounds can be indicated in a 
param=value clause in the passwd string (as gestured towards in 
<https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md>).


But I may have been unclear: by 'unspecified' I meant 'not described in 
a formal specification' (as far as I can see), so that I would not be 
comfortable trying to reimplement the glibc password-hashing process 
based on documentation alone.


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



SHA-2 and other hashes

2019-06-03 Thread Norman Gray



Greetings.

I've been doing some reading on password hashes, in OpenLDAP and 
elsewhere.  It's slightly harder to find explicit details about this, 
than I expected, and some of what I learned was unexpected to me, though 
probably familiar to many on this list.  In the expectation I'm not the 
only naive one, I'd like to log these on-list, with a broad query about 
whether I'm understanding things correctly.


There are very good discussions at [1] and [2].

SHA-256/SHA-512 on OpenLDAP doesn't mean the same as what is nominally 
the same hash function in glibc.  In OpenLDAP, the MD5 and SHA-whatever 
hash of a password is the result of hashing the password plus salt -- 
ie, pretty much what I expected -- but in glibc's crypt(3), the $5$ and 
$6$ hashes are the result of an unspecified number of rounds of such 
hashing (the $1$/MD5 glibc hash does appear to be compatible with 
OpenLDAP {SMD5}, though).  (Quite possibly everyone else in the world 
already knew this, but I didn't!)


While the glibc $5$ and $6$ hashes are therefore, in principle, somewhat 
resistant to brute-forcing, the OpenLDAP ones are not, and so should be 
managed as confidential data.


MD5 _isn't_ significantly worse than plain SHA-whatever for password 
hashing, since its discovered defects with respect to collisions are not 
a problem for this application (it's still resistant to 'preimages').  
However both are unsafe for secure password storage, simply because 
they're too fast (by design), and MD5 is unusable simply because 
'everyone knows MD5 is broken', so it would require tedious explanation.


Thus it would seem that the SHA-2 support optionally available in the 
OpenLDAP distribution (in contrib/slapd-modules/passwd/sha2) doesn't 
actually benefit me much, over and above the MD5 and SHA-1 support 
available by default.  However PBKDF2 (available in 
contrib/slapd-modules/passwd/pbkdf2) would be usable immediately, though 
this appears to be not the best such function available.


So the two options for password storage seem to be

  * use {SSHA} and -- as [3] stresses -- protect password attributes as 
if they were clear text; or
  * one way or another use a hash-stretching algorithm such as bcrypt 
(though [4] -- *sigh*) or scrypt [5] (maybe the best option?) or PBKDF2

  * (and don't worry about having to protect password attributes?).

Is that about right?

Is there a consensus OpenLDAP best practice here?

Best wishes,

Norman


[1] https://crackstation.net/hashing-security.htm
[2] 
https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846

[3] https://openldap.org/doc/admin24/security.html
[4] https://github.com/wclarie/openldap-bcrypt/issues/1
[5] https://github.com/Tarsnap/scrypt

--
Norman Gray  :  https://nxg.me.uk



Re: OpenLDAP instances crashes

2018-08-23 Thread Norman Gray



Saurabh, hello.

On 22 Aug 2018, at 19:25, Saurabh Lahoti wrote:

This is a custom overlay build in 2006 by our ex team mate & he did 
the
installation on older versions. This August we did a migration from 
old
version to 2.4.46 & lmdb backend. Is it that we skipped some steps in 
this

movement..?


Ah, that's _very_ relevant information.  Without knowing anything more 
about your setup, that custom overlay would be the very first thing you 
should look at.  There's very little a mailing list can help with, 
concerning a custom overlay.


Probably the best thing you can do in the immediate term is to revert to 
a backup of your previous system, presuming such a thing exists, and 
that the previous system is (at least) basically working.  Then you need 
to find someone who's able to look at the custom overlay code.  It might 
be worth trying to work out if you can do without the overlay.


I notice that there's an ongoing list thread 'help to get our openldap 
updated and replicated'.  That thread might be worth monitoring, on 
general principles.


Best wishes (and good luck),

Norman


--
Norman Gray  :  https://nxg.me.uk
SUPA School of Physics and Astronomy, University of Glasgow, UK



Re: ldapi and StartTLS

2018-08-07 Thread Norman Gray



Michael and Richard, hello.

On 16 Jul 2018, at 5:09, Richard Gray wrote:

Have a look at 'olcLocalSSF' in slapd-config(5), which lets you set 
the security strength factor for local (i.e. ldapi://) sessions. It 
defaults to 71, which is likely why you're seeing that error message. 
Personally, I bump it up to 256, to match the ssf=256 I have set in 
the olcSecurity attribute on cn=config.


Many thanks for this advice -- it works perfectly.  I've set olcLocalSSF 
to 256.


Hmm: 71 is an oddly-chosen default.  Is there a story there, I wonder?

(Apologies, also, for taking so long to respond: this project had 
swapped right out of my head, and it was only a couple of days ago that 
it was able to page back in).


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



ldapi and StartTLS

2018-07-15 Thread Norman Gray



Greetings.

I would have thought (possibly naively) that StartTLS was unnecessary 
when connecting to slapd through a unix socket -- the client and the 
server are on the same machine, and so don't need to be reassured about 
each other's identity.  However this seems not to be be the case:


% ldapsearch -LLL -H ldapi://%2Fvar%2Frun%2Fopenldap%2Fldapi 
'(uid=foo)'

ldap_sasl_interactive_bind_s: Confidentiality required (13)
 additional info: stronger confidentiality required

(same result with ldapi:///).

What am I misunderstanding?

In the slapd.ldif I have:

dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/openldap/slapd.args
olcPidFile: /var/run/openldap/slapd.pid
olcSecurity: ssf=128
olcTLSCertificateFile: /usr/local/etc/openldap/certs/XXX.crt
olcTLSCertificateKeyFile: /usr/local/etc/openldap/certs/XXX.key
olcTLSCACertificateFile: /usr/local/etc/openldap/certs/FOO
olcLogLevel: 0

The machine is also listening on ldap://0.0.0.0 and requiring TLS.  I 
don't see anything in the documentation which seems to suggest I can 
have different TLS rules on different interfaces or protocols (ie, ldap: 
vs ldapi:) -- am I just missing that?


The /usr/local/etc/ldap.conf doesn't mention TLS, so the TLS requirement 
isn't coming in from there.


My practical problem is that I'm trying to get nslcd (on the same 
machine) to talk to OpenLDAP locally.  If there's a certificate problem 
I can sort that out, but I can't help feeling that that ought to be 
unnecessary -- that I'm missing something simple.


This is 2.4.45 on FreeBSD.

Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



Re: Switching from bdb to lmdb with Openldap-2.4.46

2018-06-06 Thread Norman Gray



Saurabh, hello.

On 4 Jun 2018, at 19:56, Frank Swasey wrote:


you would shutdown your ldap server.
slapcat the bdb database out
change your slapd.conf file to use MDB instead of BDB
slapadd your database into mdb


As a parenthesis to Frank's advice, I'll mention that this is good 
advice not just for the sort of significant configuration change you're 
talking about.  The way I manage all such configuration changes, major 
and minor, is by keeping the server's config in a version-controlled 
slapd.ldif, and making almost no configuration changes to the running 
system.


Thus the way I make config changes is:

  * stop slapd (leaving the mirrors running)
  * slapcat >dump.ldif (all the non-configuration data)
  * nuke-and-reinitialise.sh (deletes slapd.d; copies into place 
slapd.ldif, certificates, and some schema mods; then calls slapadd to 
load slapd.ldif into slapd.d)

  * slapadd dump.ldif
  * start slapd

That way, I know exactly what configuration is running _and_ I can test 
_exactly_ the modified configuration in a VM, beforehand.


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



Re: Error Loading Schema

2018-04-18 Thread Norman Gray


Greetings.

On 16 Apr 2018, at 18:58, Net Warrior wrote:


Im trying to load this schema
http://pig.made-it.com/ldap-openssh.html

And I get this error.
ldapmodify: invalid format (line 1) entry: ""


ldapmodify will upload files in LDIF format (which you might be able to 
see documented using 'man ldif'), but the file at 
<http://pig.made-it.com/ldap-openssh/openssh-ldap.schema> is a schema 
file, which has a slightly different syntax.


That means:

  1. that you'll have to convert the schema file to a corresponding 
.ldif file; and


  2. that it has to be installed in the openldap directory on your LDAP 
server (you'll see other .schema and .ldif files in there), and included 
into your slapd configuration file (something like 
.../openldap/slapd.ldif) with a line like


include: file://blah/blah/blah/openldap/schema/openssh-ldap.ldif



Here is a variant of that file that I've used, in .ldif format:

#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE <e...@phear.org>
#
# Based on the proposal of : Mark Ruijter
#
# See https://github.com/jirutka/ssh-getkey-ldap
# Converted by hand from openssh-lpk.schema to .ldif format,
# following the advice in openldap.ldif.
#
#
#
dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
#
# octetString SYNTAX
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
  DESC 'OpenSSH Public key'
  EQUALITY octetStringMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
#
# printableString SYNTAX yes|no
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' 
SUP top AUXILIARY

  DESC 'OpenSSH LPK objectclass'
  MUST uid
  MAY sshPublicKey )



Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



Re: OpenLDAP: ACLs using sockname and DN?

2018-03-22 Thread Norman Gray


Qanah, hello.

On 22 Mar 2018, at 14:04, Quanah Gibson-Mount wrote:


Hi Norman,



  sockname.exact="/var/run/openldap/ldapi"
   write



ITS#3050 has an example of using both sockname and sockurl in an ACL.  
I'll see about having an example added to the admin guide.


<http://www.openldap.org/its/index.cgi/?findid=3050>


Ah, many thanks.

I've just confirmed that

  by dn.base="uid=pwreset,ou=service,dc=example,dc=edu"
 sockname.exact="PATH=/var/run/openldap/ldapi"
 =dxw

...does indeed work: the uid=pwreset DN does have write access with -H 
ldapi:///, but doesn't have that access when connecting over the 
network.


Looking again at the relevant paragraph in the slapd.access(5) manpage, 
I read it as indicating that the `PATH=` syntax applies only to 
`peername`, and that `sockname` should have 'the named pipe file name'.  
It might be worth checking that the manpage does still completely 
reflect the code.


If that manpage is being revisited, then it would be useful to be 
explicit that the various constraints in a  stanza are ANDed 
together.  This might naturally go near the text 'They may be specified 
in combination'.


And an example in the admin guide would indeed be most welcome.

Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk



OpenLDAP: ACLs using sockname and DN?

2018-03-22 Thread Norman Gray


Greetings.

In OpenLDAP (2.4.45, on FreeBSD), I'm trying to constrain the access of 
a DN to an attribute, by giving a DN access only when the connection is 
made via a socket; but without success.  I may just be looking for an 
example of correct use.


What I'm trying is

olcAccess: to attrs=userPassword
  by dn.base="uid=pwreset,ou=service,dc=example,dc=edu"
 sockname.exact="/var/run/openldap/ldapi"
  write

(the idea is that the pwreset DN can be used by an automatic 
password-reset script, but that that DN will have that access only when 
the script is running on the same machine as the LDAP server).


This `by` phrase appears to match the production in Sect. 8.3 of the 
OpenLDAP access control documentation, and the remark in slapd.access(5) 
that the items in the  field ‘may be specified in combination’. 
And indeed there are no syntax warnings generated. I'm presuming that 
the combination implies an AND rather than an OR – this isn't made 
explicit in the documentation. I can find no examples covering this in 
either OpenLDAP documentation or on the web.


This stanza works when the sockname element is absent, suggesting that 
the configuration is otherwise working as I expect.


When I try to write the userPassword attribute using this DN, I get an 
ldap_modify: Insufficient access (50) error.


The OpenLDAP documentation doesn't (somewhat surprisingly) explicitly 
state what the effect of this sockname element is, and the 
slapd.access(5) page says, rather obliquely, that:


The statements peername=, sockname=, 
domain=, and sockurl= mean that the contacting host 
IP (in the form IP=: for IPv4, or IP=[]: for 
IPv6) or the contacting host named pipe file name (in the form 
PATH= if connecting through a named pipe) for peername, the 
named pipe file name for sockname, the contacting host name for 
domain, and the contacting URL for sockurl are compared against 
pattern to determine access.


Saying 'determine access' doesn't actually say very much.

Have I completely misunderstood the point of this access specification, 
or is there another way to do this?


Best wishes,

Norman


--
Norman Gray  :  https://nxg.me.uk