DOSC TWiki snapshot as of mid-2005

Top

TwikiAuthenticationViaKerberos


I'm the administrator for a TWiki in Dartmouth's Administrative Computing dept. I already require Kerberos authentication for people to view pages. And rather than have people have another password to remember, I'd like to have it automatically get their Kerberos username and authenticate them that way.

I've started learning Perl to be able to do this myself, and tried it, but to no avail.

Maybe in return, I can offer some assistance in administering a TWiki, since I've had one running since May???

Goal

Authenticate Advance TWiki users via Dartmouth's Kerberos authentication implementation.

Optionally authenticate via Dartmouth LDAP directly.

Problems

Standard TWiki Authentication failed

Before I tried customizing the TWiki code, I tried using the standard Apache authentication scheme that's included w/ TWiki.

TWiki software supports the Apache basic authentication scheme, which populates the CGI environmental variable REMOTE_USER, which TWiki looks for. Unfortunately, the Apache basic authentication routine is never run when editing TWiki pages (when authentication is normally done). At least I've never seen the basic authentication prompt window for username/password display when editing a page. And the REMOTE_USER variable does not get set.

My testing of this issue lead me to conclude the following possible causes for that.

Attempted Solutions

Calling Kerberos to populate CGI variable

Modified perl_mod module: \lib\TWiki.pm to set the =$remoteUser as Kerberos username.

Couldn't figure how to compile(?) revised TWiki.pm source.

The modified source follows here, and Kerberos section is marked via comments.

sub initializeRemoteUser
{
    my( $theRemoteUser ) = @_;

# START Kerberos add-in - 20 Sep 2002
    my ($rc, $em, %tckt, $key, $val $KerberosName);
    my ($cgi) = new CGI;
    my ($url) = $cgi->self_url;

    ($rc, $em, %tckt) = CUSSP::GetK4Ticket("WWW-agent", "WWW",
                                           $cgi->remote_addr(), undef,
                                           $ENV{'REMOTE_PORT'});

    if ($rc) {
        print($cgi->header(-type => "text/html"),
              $cgi->start_html(-title => "KClient Error",
                               -author => "none",
                               -base => undef),
              "<center><h2>KClient Error</h2></center>\n<p>\n",
              CUSSP::K4Error($rc, $em),
              "<p>\n<center><a href=\"$url\">Try again</a></center>\n<p>\n",
              "GetK4Ticket(): $em/$rc\n", $cgi->end_html());
        exit($rc);
    }

    $KerberosName = $tckt{'name'};

    my $remoteUser = $KerberosName || $defaultUserName;
#    my $remoteUser = $theRemoteUser || $defaultUserName;
# END Kerberos add-in - 20 Sep 2002

    $remoteUser =~ s/$securityFilter//go;
    $remoteUser =~ /(.*)/;
    $remoteUser = $1;  # untaint variable

    my $remoteAddr = $ENV{'REMOTE_ADDR'} || "";

    if( ( ! $doRememberRemoteUser ) || ( ! $remoteAddr ) ) {
        # do not remember IP address
        return $remoteUser;
    }

    my $text = &TWiki::Store::readFile( $remoteUserFilename );
    my %AddrToName = map { split( /\|/, $_ ) }
                   grep { /[^\|]*\|[^\|]*\|$/ }
                   split( /\n/, $text );

    my $rememberedUser = "";
    if( exists( $AddrToName{ $remoteAddr } ) ) {
        $rememberedUser = $AddrToName{ $remoteAddr };
    }

    if( $theRemoteUser ) {
        if( $theRemoteUser ne $rememberedUser ) {
            $AddrToName{ $remoteAddr } = $theRemoteUser;
            # create file as "$remoteAddr|$theRemoteUser|" lines
            $text = "# This is a generated file, do not modify.\n";
            foreach my $usrAddr ( sort keys %AddrToName ) {
                my $usrName = $AddrToName{ $usrAddr };
                # keep $userName unique
                if(  ( $usrName ne $theRemoteUser )
                  || ( $usrAddr eq $remoteAddr ) ) {
                    $text .= "$usrAddr|$usrName|\n";
                }
            }
            &TWiki::Store::saveFile( $remoteUserFilename, $text );
        }
    } else {
        # get user name from AddrToName table
        $remoteUser = $rememberedUser || $defaultUserName;
    }

    return $remoteUser;
}

Thanks,

StewStryker - 21 Nov 2002