I just whipped up another phonebook app since the one provided does not
work with certs on IE without more tweaking and uses ldapsearch.....
Would you be interested in placing it on the tools page?


Jason.


---- start  script
#!/usr/bin/perl -T

##################################################################################################

# This is a mini phonebook cgi I hacked up for getitng certs from a
directory
# There is a lot that can be done to improve it
# But it suits my needs. If you make changes please send me a copy for
the archive.
# Jason Brvenik - [EMAIL PROTECTED]
# Usual disclaimers...
# Released under GPL found at http://www.gnu.org/copyleft/gpl.txt
#################################################################################################

# TODO
# 1) Add decode cert to link certs to a specific email address when
multiple exist
#    instead of the user having to search for the correct one
# 2) Error checking and more Error checking
# 3) Better Input checking
# 4) use HTML::Template for simple customization
# 5) More consistent use of CGI;

use locale; # In case we strip out chars for input checking, this makes
sure we support non US locales
use Mozilla::LDAP::Conn; # All the LDAP stuff
use MIME::Base64; # Used to encode the certs for text display
use CGI; # easier to interact with www
use MD5; # Used to create a hash of the cert since LDAP can return
attributes in random order

$debug = 0;                             # Turns on debugging
$cgi = new CGI;                         # create the cgi object
$odd_color = "#EEEEEE";
$even_color = "#DDDDDD";
$ldap_host = "your.directory.server"; # what directory to search #
easier to interact with www
$ldap_port = "389";                     # what port to use
$ldap_scope = "subtree";                # what type of search to perform

$base_dn = "c=ww";                      # where to start the search from

$bind_dn = "";                          # authenticate as this user - ""
means anonymous
$bind_pw = "";                          # users password = "" means
anonymous or no password

# This is a hash for building the search results and defining the
attributes returned
# The format is like this
# "fieldname" => "Human Name"
# To be able to display a field you must specify an entry in this hash
and the display_order array.
# Placing it in attr_hash but not display_order will result in the
attribute being
# returned from the directory but not displayed to the user
# until the record is requested specifically by a clickthrough
%attr_hash = (  "telephonenumber"       => "Phone",
                "rfc822mailbox"         => "E-Mail",
                "commonname"            => "Full name"
             );

# The order is defined by placement in the display_order array.
# If it's not in this array it doesn't get displayed for the search
results
@display_order = ("commonname","rfc822mailbox","telephonenumber");

# Build the array specifying the attributes to fetch from the directory
here.
foreach $key ( %attr_hash ) { push(@attrs, $key); }

# get parameters passed
# for filter we remove common wildcards and search operators
# to prevent people circumventing our predefined search filter
# and doing searches for * or objectclasses...
# This one
# s/\*||\%||\|||\;||\'||\"||\&||\!||\\||\///g;
# removes the chars * % | ; ' " & ! \ /
$filter = $cgi->param('filter');                # The initial search
term
if ( defined $filter ) {
        $filter =~ s/\*||\%||\|||\;||\'||\"||\&||\!||\\||\///g;
        $print_filter = $filter;
        if ( $filter eq "" ){
                print_header();
                print_html_header();
                print 'You must enter a valid search string' . $cgi->br
. "\n";
                print_html_footer();
                exit;
        }
        $filter = '(|(cn=*' . $filter . '*)(rfc822mailbox=*' . $filter .
'*))';
}
$dn = $cgi->unescape($cgi->param('dn'));        # The DN of a requested
record
$getcert = $cgi->param('getcert');              # Flag to retrieve a
cert
$certhash = $cgi->param('certhash');            # Hash of specific cert
requested. Useful when there are multiple certs
$help = $cgi->param('help');                    # Flag to say when to
display help
$| = 1;                                         # No buffering;
print_header();                                 # Print the appropriate
header.
if ( defined $getcert ) { send_cert_bin(); exit; } # Send back the
binary certificate for import into a browser

# It isn't a get cert request. Handle as a search
print_html_header();

# Debugging code to spit out the parameters passed
if ($debug) {
        @vars = $cgi->param;
        foreach $var (@vars) {
                print $var . ":" . $cgi->param($var) . $cgi->br . "\n";
        }
        print $cgi->hr;
}

# It's a request for a specific record.
if ( defined $dn ) {
        send_record();
        print $cgi->end_html;
        exit;
}

# Not looking for a specific record.
# Present the search form.
print_search_form();

# Either you are just getting to the form or help has been requested
if ( (!defined $filter) || ($help==1) ) {
        print_help_text();
}

# Exit here on the initial request
if ( !defined $filter) { print_html_footer();exit; }

# There is a filter defined. Set up a table for the search results
start_table();
print_results();
end_table();
print_html_footer();

#####################################################################
#####################################################################
#                       End of main program.                        #
#####################################################################
#####################################################################

#####################################################################
# Determines what type header to return based on request.
#
# If it is the initial or record request we are sending back html
# If it is a getcert request we need to send back either a pkix or
# x509 depending on browser
#
#####################################################################
sub print_header() {

        if ( defined $getcert && defined $dn) {
                # return the appropriate header to the browser
                if ( $cgi->user_agent() =~ /MSIE/ ) {
                        # For IE
                        print
$cgi->header(-type=>'application/pkix-cert');
                } else {
                        # For Netscape
                        print
$cgi->header(-type=>'application/x-x509-email-cert');
                }
        } else {
                print $cgi->header();
        }
}

#####################################################################
# Send back the certificate requested in binary format
# So that the browser can import it directly.
#####################################################################
sub send_cert_bin() {
        @attrs = ("usercertificate");
        $ldap = new
Mozilla::LDAP::Conn($ldap_host,$ldap_port,$bind_dn,$bind_pw) ||
die("could not connect to directory\n");
        if ( $entry = $ldap->search($dn, $ldap_scope, "objectclass=*",
0, @attrs) ) {
                foreach $key (keys %{$entry}) {
                        foreach $value ( @{$entry->{$key}} ) {
                                $md5 = MD5->hexhash($value);
                                print $value if ( $md5 eq $certhash ); #
This ensures the requested cert is sent
                        }
                }
        } else {
                print "Could Not find entry $dn" . $cgi->br . "\n";
        }
        $ldap->close();
}

#####################################################################
# Send back a ldap record in html format
#####################################################################
sub send_record() {

        @attrs = ("commonname", "surname", "telephonenumber",
"rfc822mailbox", "usercertificate");
        $ldap = new
Mozilla::LDAP::Conn($ldap_host,$ldap_port,$bind_dn,$bind_pw) ||
die("could not connect to directory\n");
        if ( $entry = $ldap->search($dn, $ldap_scope, "objectclass=*",
0, @attrs) ) {
                print "<TABLE border=1>\n";
                $count = 0;
                foreach $key (keys %{$entry}) {
                        foreach $value ( @{$entry->{$key}} ) {
                                next if ( !defined $value );
                                print "<TR bgcolor=" . (($count % 2) ?
$even_color:$odd_color) . ">\n";
                                # use the pretty name if we know it
                                if ( defined %attr_hash->{$key} ) { $key
= %attr_hash->{$key}; }
                                if ( $key =~ /usercertificate/i ) {
                                        $md5 = MD5->hexhash($value);
                                        $value = encode_base64($value);
                                        $tkey = "<a href=" . $cgi->url .
"?dn=" . $cgi->escape($dn) .
                                                "&getcert=1&certhash=" .
$md5 . ">Get Certificate</a>\n";
                                } else {
                                        $tkey = $key;
                                }
                                # TESTING
                                # print "<TD>" . $tkey . "</TD><TD>" .
$value . "</TD></TR>\n";
                                print "<TD>" . $tkey . "</TD><TD>" .
$value . "</TD></TR>\n";
                                $count++;
                        }
                }
                print "</TABLE>\n";
        } else {
                print "Could Not find entry $dn<BR>\n";
        }
        $ldap->close();
}

#####################################################################
# Print a html page header.
# This is not the content header but the top of the page
# being returned to the browser.
# Place things you want to appear before the search form
# and any records returned here.
#####################################################################
sub print_html_header() {
        print $cgi->start_html(-title=>'Directory Search',
-author=>'[EMAIL PROTECTED]');
}

#####################################################################
# Print the bottom of the html content
# place things here you want to appear after the search form
# and any records returned.
#####################################################################
sub print_html_footer() {
        print $cgi->end_html;
}

#####################################################################
# Print the search form. This will appear between the html_header
# and the html_footer sections
#####################################################################
sub print_search_form() {
        print $cgi->startform(-method=>'POST', -action=>$cgi->url);
        print $cgi->textfield(-name=>'filter', -size=>50,
-maxlength=>80);
        print $cgi->submit;
        print $cgi->endform;
}

#####################################################################
# Print out some help text on usage
# This will only appear if requested or it's the forst invocation
# of this script.
# The placement is under the actual search form
#####################################################################
sub print_help_text() {
        print $cgi->hr . $cgi->br . "Type in a name or email address.
Partial matches are acceptable." . $cgi->br . "\n";

}


#####################################################################
# The table definition goes here.
#####################################################################

sub start_table() {
        print $cgi->hr . "Your search for " . $cgi->b($print_filter) . "
returned the following" . $cgi->br . "\n";
        print "<TABLE border=1><TR>\n";
        foreach $key (@display_order) {
                print "<TD>" . %attr_hash->{$key} . "</TD>\n";
        }
        print "</TR>\n";
}

#####################################################################
# This prints the results of the search in the table
#####################################################################
sub print_results() {
        $count = 0;
        $ldap = new
Mozilla::LDAP::Conn($ldap_host,$ldap_port,$bind_dn,$bind_pw) ||
die("could not connect to directory\n");
        if ( $entry = $ldap->search($base_dn, $ldap_scope, $filter, 0,
@attrs) ) {
          while ( $entry ) {
                print "<TR bgcolor=" . (($count % 2) ?
$even_color:$odd_color) . ">\n";
                $count++;
                # foreach $key (@attrs) {
                foreach $key (@display_order) {
                        $value = @{$entry->{$key}}[0];
                        if ( $key =~ /usercertificate/i ) {
                                $value = encode_base64($value);
                        }
                        if ( $key =~ /rfc822mailbox/i ) {
                                $value = "<a href=mailto:" . $value .
">" . $value . "</a>\n";
                        }
                        if ( $key =~ /commonname/i ) {
                                $value = "<a href=" . $cgi->url . "?dn="
. $cgi->escape($entry->getDN()) . ">" . $value . "</a>\n";
                        }
                        print "<TD>" . $value . "</TD>";
                }
                print "</TR>\n";
                $entry = $ldap->nextEntry();
          }
        } else {
          print("<TD>No entries returned</TD>" . $cgi->br . "\n");
        }
        $ldap->close();
}

sub end_table() {
        print "</TABLE>";
}

Reply via email to