[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: (ITS#6757) SASL canonicalize doesn't work as documented
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