On Sun, Jan 02, 2011 at 07:40:25PM -0800, Howard Chu wrote:
(1) Stick more or less with the current behaviour, and change the documentation to say that you'll get uid=ursula/admin@foreign.realm,cn=gssapi,cn=auth for foreign realms.
However, the odd thing about the current behaviour is that setting olcSaslRealm always sticks a static value (...,cn=<olcSaslRealm>,...) into the auth DN, regardless of whether it's local or foreign. That's not very useful.
Note that it's not the OpenLDAP code that's sticking this in there; it's the Cyrus code that's returning this realm in the callback. IMO our job is to faithfully return what the Cyrus library gave us.
The Cyrus library is faithfully passing on the *default* user_realm that you originally passed to sasl_server_new() in servers/slapd/sasl.c
(which is global_realm, a.k.a. olcSaslRealm)
Then OpenLDAP is sticking it into the authDN, in slap_sasl_getdn()
I think it would make more sense, if olcSaslRealm is present, to use it to *qualify* usernames which don't have a realm.
That decision is made by the Cyrus library, not us.
It does not mandate what you do with the user_realm. You are free to ignore it, use it to qualify usernames which have no realm, or whatever.
The documentation for canon_user (in include/sasl.h) says:
* If user_realm is non-empty and an * unqualified user name is supplied, then the canon_user facility is * expected to append "@" and user_realm to the user name. The canon_user * facility may treat other characters such as "%" as equivalent to "@".
Here is _canonuser_internal from lib/canonusr.c in Cyrus SASL:
static int _canonuser_internal(const sasl_utils_t *utils, const char *user, unsigned ulen, unsigned flags __attribute__((unused)), char *out_user, unsigned out_umax, unsigned *out_ulen) ... /* Need to append realm if necessary (see sasl.h) */ if(sconn && sconn->user_realm && !strchr(user, '@')) { u_apprealm = (unsigned) strlen(sconn->user_realm) + 1; }
/* Now Copy */ memcpy(out_user, begin_u, MIN(ulen, out_umax)); if(sconn && u_apprealm) { if(ulen >= out_umax) return SASL_BUFOVER; out_user[ulen] = '@'; memcpy(&(out_user[ulen+1]), sconn->user_realm, MIN(u_apprealm-1, out_umax-ulen-1)); } out_user[MIN(ulen + u_apprealm,out_umax)] = '\0';
(2) Change the OpenLDAP behaviour so that it matches the documentation at http://www.openldap.org/doc/admin24/sasl.html#GSSAPI
To do this, the canonicalize function would have to parse the username, splitting it on '@' to separate username from realm, so that you would get
uid=ursula/admin,cn=foreign.realm,cn=gssapi,cn=auth
If the username doesn't contain '@', but olcSaslRealm is set, then I suggest you insert that instead:
uid=kurt,cn=<olcsaslrealm>,cn=gssapi,cn=auth
And if there's no '@' and no olcSaslRealm, then just leave it alone:
uid=kurt,cn=gssapi,cn=auth
This has been discussed at great length, read the -devel archives from 9 or 10 years ago. The fact is that the SASL specification doesn't reserve '@' as a special character and there is no guarantee that this is actually a realm separator. There are plenty of authentication mechanisms where '@' is an integral part of the username. This suggestion simply won't fly.
I suspect that's why canon_user was made pluggable in the first place; if you have your own idea of what constitutes a username with or without a realm then you code for it there.
In Cyrus-SASL, plugins/gssapi.c has it hard-coded:
if (strchr((char *) name_token.value, (int) '@') != NULL) { ... /* cut off string at '@' */ (strchr(name_without_realm.value,'@'))[0] = '\0';
I agree that non-Kerberos SASL mechanisms might have different username formats; and hence, without additional configuration, OpenLDAP cannot split arbitrary SASL usernames into uid=user,cn=realm.
However the current behaviour of olcSaslRealm isn't useful either, since it just gives you uid=user[@realm],cn=olcSaslRealm.
I think the most appropriate behaviour for olcSaslRealm would be for it to qualify usernames that don't contain '@' - and if your app doesn't use usernames with '@', then don't set olcSaslRealm.
I don't believe we have any freedom to make any code changes here; feel free to suggest verbiage changes for the documentation.
No problem. I propose the following to bring the docs in line with behaviour.
--- sasl.sdf.orig 2011-01-03 09:45:55.754879001 +0000 +++ sasl.sdf 2011-01-03 10:07:34.808208000 +0000 @@ -135,25 +135,35 @@ For the purposes of authentication and authorization, {{slapd}}(8) associates an authentication request DN of the form:
-> uid=<primary[/instance]>,cn=<realm>,cn=gssapi,cn=auth +> uid=<primary[/instance][@realm]>,cn=gssapi,cn=auth + +The realm is omitted by Cyrus SASL if it's equal to the default realm of the +server in {{FILE:/etc/krb5.conf}}.
Continuing our example, a user with the Kerberos principal {{EX:kurt@EXAMPLE.COM}} would have the associated DN:
-> uid=kurt,cn=example.com,cn=gssapi,cn=auth +> uid=kurt,cn=gssapi,cn=auth
and the principal {{EX:ursula/admin@FOREIGN.REALM}} would have the associated DN:
-> uid=ursula/admin,cn=foreign.realm,cn=gssapi,cn=auth +> uid=ursula/admin@foreign.realm,cn=gssapi,cn=auth
-The authentication request DN can be used directly ACLs and +The authentication request DN can be used directly in ACLs and {{EX:groupOfNames}} "member" attributes, since it is of legitimate LDAP DN format. Or alternatively, the authentication DN could be mapped before use. See the section {{SECT:Mapping Authentication Identities}} for details.
+If you configure olcSaslRealm then it is always inserted as an extra +component in the authorization DN, regardless of the realm of the client. +For example, if you set olcSaslRealm to {{EX:example.com}} then you will +get: + +> uid=kurt,cn=example.com,cn=gssapi,cn=auth +> uid=ursula/admin@foreign.realm,cn=example.com,cn=gssapi,cn=auth
H3: KERBEROS_V4