Archives / Search ›

And now for something completely different…

More broken software.

I can’t get my RSS feed to rerender; it’s still stuck thinking it’s reStructuredText when it is HTML. Maybe, just once, PyDS would get it right and I wouldn’t have to rerender parts of my site every time I make a weblog post. I’m posting this as much to complain as to see if another post will cause the RSS to be regenerated.

For all its failings, Radio got this one right pretty much all the time. How I wish I had time to fix this…

Kerberized LDAP from a scripting language?

Any scripting language? Any scripting language at all?

My goal: to set up an virtual map in Postfix, mapping usernames to email addresses where present, using a LDAP server (Windows 2000 Active Directory) as a data source, in a reasonably secure fashion. Using OpenLDAP 2.0.27, Cyrus SASL 2.1.15, ldapsearch on the command line did exactly what I wanted, so I thought it’d be simple enough to script. Was I ever wrong!

  • Attempt 1, /etc/postfix/main.cf:
    virtual_mailbox_maps = ldap:medicine
    medicine_server_host = med-banting.med.uiuc.edu
    medicine_query_filter = userPrincipalName=%s@med.uiuc.edu
    medicine_search_base = dc=med,dc=uiuc,dc=edu
    medicine_result_attribute = mail
    [...]
    

    What to do for the [...]? Can’t use a simple bind: too insecure. The AD server is not configured to support SSL. Postfix doesn’t support GSSAPI. That leaves anonymous binding, which I couldn’t, after many hours with ADSI Edit, get to do what I wanted. Even if I accepted the security problem of allowing people to enumerate all the users at our site, I couldn’t get anything beyond a DN for domain administrators, some of whom require the above email mapping. It does not seem possible to limit access via IP address.

    So, I resigned myself to running a cron job to populate a hash map or similar with periodic dumps of the LDAP information.

  • Attempt 2, python-ldap 2.0.0, search.py:
    #!/usr/bin/env python2.3
    
    import ldap, ldap.sasl
    
    server = ldap.initialize("ldap://med-banting.med.uiuc.edu")
    server.sasl_interactive_bind_s("", ldap.sasl.gssapi(""))
    
    res = ldap.search_s("dc=med,dc=uiuc,dc=edu", ldap.SCOPE_BASE,
                        "(&(mail=*)(objectClass=user))")
    print res
    server.unbind()
    

    In competition for the least helpful error message of the century, up there with “An error has occurred: Success”:

    % ./search.py
    Traceback (most recent call last):  File "./search.py", line 8, in ?
        server.sasl_interactive_bind_s("", ldap.sasl.gssapi(""))
      File "/usr/lib/python2.3/site-packages/ldap/ldapobject.py", line 196, in sasl_interactive_bind_s
        return self._ldap_call(self._l.sasl_interactive_bind_s,who,auth,serverctrls,clientctrls)
      File "/usr/lib/python2.3/site-packages/ldap/ldapobject.py", line 94, in _ldap_call
        result = func(*args,**kwargs)
    ldap.LOCAL_ERROR: {'desc': 'Local error'}
    

    I am not the only person with this problem.

  • Attempt 3, Net::LDAP (part of perl-ldap 0.31), Authen::SASL::Cyrus 0.11, search.pl:
    #!/usr/bin/perl
    use Net::LDAP;
    use Authen::SASL;
    
    my \$sasl = Authen::SASL->new('GSSAPI', 'user' => '');
    my \$ldap = Net::LDAP->new('med-brevis.med.uiuc.edu', version => 3) || die "$@";
    my \$mesg = \$ldap->bind("", sasl => \$sasl);
    \$mesg->code && die \$mesg->error;
    \$mesg = \$ldap->search(filter => '(&(mail=*)(objectClass=user))',
                          base => 'dc=med,dc=uiuc,dc=edu',
                          attrs => ['mail', 'userPrincipalName']);
    \$mesg->code && die \$mesg->error;
    @entries = \$mesg->entries;
    foreach \$entry (@entries) {
        \$entry->dump;
    }
    \$ldap->unbind;
    

    This looks so good, as just a month ago, people claimed it worked. It doesn’t for me.

    % ./search.pl
    No SASL mechanism found
     at /usr/lib/perl5/site_perl/5.8.0/Authen/SASL.pm line 62
    

After over eight hours of work on this, and assuming I don’t hear back from anyone by tomorrow, attempt #4 is going to be parsing the output of ldapsearch. I was going to get research work done today, too…

Posting code from PyDS’s RPC interface is a complete nightmare; it unescapes everything constantly, tries to interpret $-macros, etc… I guess Georg just uses reStructuredText, but that’s no use until I have a weblog editor that supports it.

iSync: so good, yet so bad

The multi-modal synchronization iSync makes possible is a terrific idea. I have lots of mobile devices: my Palm, my hiptop, my PowerBook and my iPod. When it works, iSync keeps them all talking and with a consistent world view, which has saved me from missing many appointments and given me the information I need when I need it.

When it doesn’t work, I am at the mercy of a horrendously buggy implementation. I get meaningless conflict messages, impenetrable and programmer-centric errors, repeated duplication of items, and more. iSync has done far worse things, including getting itself to the point it crashes when it tries to do anything, or deleting all my address book entries without warning. iSync is slow, a huge CPU and memory hog, especially when compared to the Palm Desktop conduits, which have quietly and efficiently done their jobs for years.

All in all, not what I expect from Apple. Fixing the problems, which occur at least once a week, requires me to think like a programmer, which is just wrong. I’d never ever give the current version to my parents because I’m sure they’d run screaming.

The most annoying problem I have every few days (losing all the departments in my address book) I can at least identify because of the dialog box that appears. I blame it on a third-party conduit, but these kinds of errors are entirely Apple’s fault:

Another broken conflict message in iSync

The connection between these events is…? Also, the event on the right is in a subscribed calendar, i.e. something I can’t edit in iCal. iSync shouldn’t be trying to sync those at all! Finally, what the hell is a “’cluster’ UID”? (See above, about impenetrable and programmer-centric errors.)

One broken conflict message in iSync

The difference between these is…?

If I had just one request for Mac OS X 10.4, it would be: fix iSync. Better yet, open it up so anyone can add devices or applications, as having a bunch of developers pound on its interfaces can help flush out the problems. I wish it would happen in 10.3.5 or a separate iSync update, but that’s pretty remote at this point.

National SR-W10NA 5 Cup Keep Warm Rice-O-Mat Rice Cooker

In completely unrelated news, Steve and I bought a rice cooker tonight (well, Steve bought it and paid for it while I watched). I really have no idea why we didn’t get one months ago; it’s just so useful.

MacUser UK online

MacUser UK is considering a worldwide version for electronic distribution. It’s the only mainstream Mac publication I read any more, assuming you don’t count MWJ, and I’d happily pay for it. I hope it kicks US Macworld et al. into being more relevant. (I let my Macworld subscription lapse several years ago, and haven’t seen anything on their Web site in the meantime that makes me think they’ve improved much.)

Shell redirection pain

I’m still learning more about zsh every week, trying to solve various problems and improve my productivity using its many features. Of course, it doesn’t hurt to show off from time to time either. :-)

Here’s a seemingly simple thing that’s stumped me tonight: how to display stdout from a process as it’s generated, and pipe it to another program at the same time. The MULTIOS feature makes this simple if it were two files, but it isn’t. The closest I could get, which admittedly isn’t very close, is foo >&2 | bar, but that waits until foo finishes before displaying anything, in a way it doesn’t if the | bar is missing.

In actuality, bar is the bbedit tool—I’m wanting to open the results in a BBEdit window if foo successfully finishes. The ideal tool for this would be BBEdit’s shell worksheet, but it also waits until foo has finished before displaying any output.

Update: Duh, I’ve seen and solved this problem before. foo is actually a Python script, and something in Python or the C library’s standard I/O routines thought I was redirecting to something that wasn’t a terminal, therefore it should be more efficient about flushing. Adding a strategically placed instance of sys.stdout.flush() caused the above incantation to work fine.

‹ Newer Posts  •  Older Posts ›