|
This morning, I almost tried to gargle with after shave. An understandable
mistake, really, considering that they're both blue liquids, probably with some
non-potable alcohol in them.
I stood there for a moment and thought about it, and concluded that while
after shave probably gives decent results if you're looking for that menthol
breath (and do not swallow any), it's ruled out because I've long
worried that I'm slowly drinking my mouthwash, and I'm pretty sure you have to
call poison control if you swallow after shave.
Using mouthwash as an after shave, despite being way cheaper and leaving
your face all minty fresh, probably isn't a very good idea, either.
But it can't hurt to try, can it?
|
|
Thought about the offline authentication problem and pam_krb5 some more. If
we just let the helper contact the KDC, we double the number of round trips
made between the client and the KDC unless we provide some way for the helper
to pass the obtained credentials back to the calling process, which isn't
good. If we don't do that, then we may cost the user in terms of
failed logins, which could trigger a KDC-enforced lockout policy.
At least we've got another test release before we feature freeze for FC7, so
we've got time to think about this some more.
|
|
In summary, Connectathon totally ruled.
|
|
This is a digest of some notes I've had for a while, recorded here in
case someone else finds them useful. (Let me know if I'm wrong on any
of this.) No, there's not really much of a point to this.
When applications on Linux systems want to get information about a
user, they frequently call either getpwnam() or getpwuid(), passing in
the user's name or UID, respectively. Likewise, for groups, getgrnam()
and getgrgid().
When that happens, libc consults /etc/nsswitch.conf for the
configuration which describes how it will answer the application's
question. Absent any control flags, it will often look like this:
passwd: files hesiod nis ldap
For each module listed, libc constructs a soname
(libnss_foo.so.version), uses
dlopen() to load the named library, and calls into a function provided
by that library. On most systems (including all of the platforms Fedora
builds on), version is hard-coded to
2, but on a few, it's 1.
Exactly which function the shared library should export, and what its
signature should be, varies based on which function the application
actually called, but there's a pattern.
getpwnam(),getpwnam_r() → _nss_foo_getpwnam_r()
getpwuid(),getpwuid_r() → _nss_foo_getpwuid_r()
The exported functions don't return a pointer to some global result
structure. Rather, they fill in a passed-in structure and return a
result code. The function also gets a chunk of memory which it can use
to store items of which the structure will hold a pointer (for example,
all of the string members of a struct passwd).
For functions which only return one result (getpwnam, getpwuid, and
so on), libc by default stops at the first function which returns a
success. For enumeration functions, libc generally iterates through all
of the configured modules. There's more detail in the glibc info pages,
but that's the basic idea. Note that the details of how this fits
together varies among libc implementations.
Building a good module can be tricky.
The calling application may be multithreaded, so your module needs to
be thread-safe. But it may also not be multithreaded, so your module
can't be dependent on threading functions. This isn't so difficult as
it might sound because certain threading functions are also available,
in no-op stub form, to non-threaded applications. So long as you limit
yourself to these, you'll be fine in both cases.
pthread_mutex_lock()/pthread_mutex_unlock()
pthread_cond_init()/pthread_cond_destroy()
pthread_cond_broadcast()
pthread_cond_signal()
pthread_cond_timedwait()
pthread_cond_wait()
These days, you also have thread-local storage.
Because your module may be loaded by many, many processes (including
otherwise lightweight programs such as "ls" or
"find"), keep your code size and list of external dependencies
small. Ideally, link to nothing other than libc itself.
One popular strategy for achieving this is to make your module a stub
which contacts a local daemon, and to have that daemon do all of your
heavy lifting. This is the approach being considered by at least one
module named nss-mysql, and is the one used in Doug Nazar's nss_ldap2,
Arthur de Jong's nss_ldapd, and (probably the best-known example)
Samba's winbindd. Crutcher and I even took a stab at it a while back
with splatbind.
A slightly less popular strategy is to use linker flags and static
libraries to pull all of your module's dependencies into the module
itself. It's what we do with nss_db in Fedora, and made far easier
because upstream Berkeley DB packaging includes support for this sort of
scenario.
Your module may be called while the system is not yet fully
"up", and again while the system is in the midst of shutting
down. If you depend on the network, keep in mind that it may not be
there.
The calling application may fork() between calls into your module.
You must handle this gracefully, including making sure that parent and
child don't get tripped up by the fact that they're now sharing an open
connection to every resource the parent used to have.
Take care that the right thing happens when the calling application
calls exec(), whether or not it's preceded by fork().
If you call into libc's nsswitch subsystem (which happens most often
when a library which you're using needs to resolve a hostname), and
especially if you offer hostname resolution services, be
mindful that you may end up inadvertently calling yourself, either
directly or indirectly with the help of a daemon such as nscd.
|
|
The pkinit-nss module erroneously requires that the nonces in the request
body and the pkauthenticator match. There's at least one way to embed signed
data inside of enveloped data which I hadn't provided for, either.
|
|
Lunch at Asqew. Dinner at Tandoori Oven, which really should
open a location near where I work. Westford could totally support a third
Indian restaurant.
|
|
The pkinit-nss module's error reporting doesn't encode trusted-certifiers
right. Forgot to take the address of a pointer to a pointer to a struct when
passing it into the encoder.
Oh, and Heimdal seems to like using AES to encrypt enveloped data.
|
|
The pkinit-nss module's CMS implementation wasn't sorting signed attributes
correctly, because NSS's ASN.1 encoder is a BER encoder, and you only need to
sort for DER. Oops. So feed the "unordered" data into encoder in
the right order.
|
|
The pkinit-nss module wasn't supplying a list of invalid certificates if
it encountered a revoked certificate.
|
|
The pkinit-nss module wasn't correctly encoding or decoding the typed-data
of most errors. It wasn't correctly encoding the public numbers of the DH key
agreement process correctly, either. It wasn't correctly comparing the size
of the client's DH prime against the configured minimum.
|
|
Got into yet another conversation with Dan and Steve about being able to log
in while offline, and I think I convinced them that naively caching whatever
the user types in respones to a prompt while online, and then repeating the
prompt and comparing the answer to the cached value when offline, generally
doesn't work.
Why? Well for one, one-time passwords: if you cache the response, you've
taken the one-time property out. For another, smart cards: if you let
the user in with just the PIN (and remember, at this level you don't even
know that smart cards are being used), you've just removed one factor
from the two-factor authentication system.
What we hit on for Kerberos is a helper which transforms the password (not
using the usual string-to-key -- storing a keytab with your keys on every
system you ever type a password into would be... horrific) and stores the
result as a "key" in a local keytab file if the KDC says that that's good
enough. (Using the keytab manipulation facilities from libkrb5 saves us from
having to implement our own file format.)
At the Kerberos level, you can have some idea if the user-response you're
examining is a password or not, and whether the KDC is reachable or not, so
it's tougher to do stupid things. The helper can always attempt to contact the
KDC, parse the error code which is returned by libkrb5, recuse itself if a
password proves insufficient, check the cache if the KDC is unreachable, and
update or clear the cache entry if the KDC was able to return a response.
Anyway, that's the idea. Maybe I'll have time to code it up before the test
2 freeze.
|
|
The connection between Boston and San Jose went through Las Vegas. I've
never seen such a well-behaved and laid-back planeload of passengers. And I've
never seen so many people drinking cocktails before 9AM. Maybe those are
related somehow.
|
|
Wow, it's been a while since I made any notes here. I guess I've been busy.
Or just lazy. Some of both, more likely. Continued working on the
PKINIT plugin. It's weird, but I'm looking forward to doing some testing at
this year's Connectathon. I find
it somewhat unsettling that more people not only haven't heard of it, but
continue to think I'm making the whole thing up, but hey, I'm a nerd.
I missed out on National
Gorilla Suit Day again. Some people toast with "Next year, in Jerusalem."
I think I'm going to start toasting with "Next year, in a gorilla suit."
And of course, FUDCon was
this weekend. It was, as expected, muy awesome.
Dan suckered me into helping at the SSO (single sign-on) BOF (birds of a
feather session) by at first asking for help making sure the right packages
were installed on his freshly-reinstalled laptop, and then by making me find
that my PKINIT plugin didn't actually build correctly against MIT Kerberos 1.6.
Oops. So as I feverishly tried to make it build right on his laptop, first
using a recent tarball, then using a fresh CVS checkout, we whiled away the
better part of an hour. On the bright side, except for making sure the client
trusted the server, and making the plugin acceptable to libkrb5, it sort of
Just Worked, which after all was the whole point. Maybe I managed to share the
Vision of storing stuff in a directory and having various protocol servers
use it as a data store, maybe I didn't, but that's my goal anyway.
I caught hell when I got back from the BOF, though, because I'd volunteered
to staff the Welcome desk during that hour. From this I learned, again, that
YOU DO NOT WANT TO LET ROBIN DOWN. (Once
you've destroyed a house with someone, you just don't do that.) I spent
the rest of the day staffing the desk, which I find inexplicably enjoyable
(maybe I'm flashing back to the permasmile I developed while working the
Drive-Thru), and attempting to direct people to the important goings-on. To a
certain extent, you get to feel that you know what's going on in all of the
sessions, and the company is quite enjoyable. I even managed to get some work
done.
Several people have already made notes about FUDpub, the informal gathering
which invariably takes place after FUDCon at one of the local, erm, gathering
places. For the third time, the locale was woefully underprepared to handle
the mass of nerds, descending upon them, as we are wont to do, like a cloud of
locusts. I was not impressed. I'm thinking that maybe we should choose a
different destination for next year.
Oh yeah, Happy (belated) Birthday, Ryan!
|