Project

General

Profile

1 2341 sgarg
#!/usr/bin/perl -w
2
 #
3
 #  '$RCSfile$'
4
 #  Copyright: 2001 Regents of the University of California
5
 #
6
 #   '$Author$'
7
 #     '$Date$'
8
 # '$Revision$'
9
 #
10
 # This program is free software; you can redistribute it and/or modify
11
 # it under the terms of the GNU General Public License as published by
12
 # the Free Software Foundation; either version 2 of the License, or
13
 # (at your option) any later version.
14
 #
15
 # This program is distributed in the hope that it will be useful,
16
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 # GNU General Public License for more details.
19
 #
20
 # You should have received a copy of the GNU General Public License
21
 # along with this program; if not, write to the Free Software
22
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 #
24
25
#
26
# This is a web-based application for allowing users to register a new
27
# account for Metacat access.  We currently only support LDAP even
28
# though metacat could potentially support other types of directories.
29
#
30
use strict;       # turn on strict syntax checking.
31
use Template;     # load the template-toolkit module.
32
use CGI;          # load the CGI module.
33
use Net::LDAP;    # load the LDAP net libraries
34
use Net::SMTP;    # load the SMTP net libraries
35
use Digest::SHA1; # for creating the password hash
36
use MIME::Base64; # for creating the password hash
37
use URI;          # for parsing URL syntax
38
use AppConfig qw(:expand :argcount);
39
40
# Set up our default configuration
41
my $ldapurl = "@ldapurl@";
42
my $root = "@user@";
43
my $rootpw = "@password@";
44
my $searchBase = "@ldapSearchBase@";
45
my $templatesDir = "@templates.dir@";
46
my $mailhost = "@mailhost@";
47
my $sender = "@sender@";
48
49
# Get the CGI input variables
50
my $query = new CGI;
51
52
my $debug = 0;
53
54
#--------------------------------------------------------------------------80c->
55
# Set up the Template Toolkit to read html form templates
56
57
58
# set some configuration options for the template object
59
my $config_templates = {
60
             INCLUDE_PATH => $templatesDir,
61
             INTERPOLATE  => 0,
62
             POST_CHOMP   => 1,
63
             };
64
65
# create an instance of the template
66
my $template = Template->new($config_templates) || die $Template::ERROR, "\n";
67
68
# Read the ldapweb.cfg file
69
my $config = AppConfig->new({
70
    GLOBAL => { ARGCOUNT => ARGCOUNT_ONE, } });
71
72
$config->define("ldapurl", { ARGCOUNT => ARGCOUNT_HASH} );
73
$config->define("ldapsearchbase", { ARGCOUNT => ARGCOUNT_HASH} );
74
$config->define("dn", { ARGCOUNT => ARGCOUNT_HASH} );
75
$config->define("filter", { ARGCOUNT => ARGCOUNT_HASH} );
76
$config->define("user", { ARGCOUNT => ARGCOUNT_HASH} );
77
$config->define("password", { ARGCOUNT => ARGCOUNT_HASH} );
78
79
my $cfgfile = "ldapweb.cfg";
80
$config->file($cfgfile);
81
my $config_ldapurl = $config->get('ldapurl');
82
my $config_ldapsearchbase = $config->get('ldapsearchbase');
83
my $config_dn = $config->get('dn');
84
my $config_filter = $config->get('filter');
85
my $config_user = $config->get('user');
86
my $config_password = $config->get('password');
87
88
my @orglist;
89
foreach my $neworg (keys %$config_dn) {
90
    push(@orglist, $neworg);
91
    debug($neworg);
92
}
93
94
95
#--------------------------------------------------------------------------80c->
96
# Define the main program logic that calls subroutines to do the work
97
#--------------------------------------------------------------------------80c->
98
99
100
# The processing step we are handling
101
my $stage = $query->param('stage') || '@defaultStage@';
102
103
my $cfg = $query->param('cfg');
104
105
# define the possible stages
106
my %stages = (
107
              'initregister'      => \&handleInitRegister,
108
              'register'          => \&handleRegister,
109
              'registerconfirmed' => \&handleRegisterConfirmed,
110
              'changepass'        => \&handleChangePassword,
111
              'simplesearch'      => \&handleSimpleSearch,
112
              'initaddentry'      => \&handleInitAddEntry,
113
              'addentry'          => \&handleAddEntry,
114
              'initmodifyentry'   => \&handleInitModifyEntry,
115
              'modifyentry'       => \&handleModifyEntry,
116
              'resetpass'         => \&handleResetPassword,
117
             );
118
119
# call the appropriate routine based on the stage
120
if ( $stages{$stage} ) {
121
  $stages{$stage}->();
122
} else {
123
  &handleResponseMessage();
124
}
125
126
#--------------------------------------------------------------------------80c->
127
# Define the subroutines to do the work
128
#--------------------------------------------------------------------------80c->
129
130
131
#
132
# create the initial registration form
133
#
134
sub handleInitRegister {
135
  my $vars = shift;
136
137
  print "Content-type: text/html\n\n";
138
  # process the template files:
139
  my $templateVars = { stage => "register", cfg => $cfg };
140
  $$templateVars{'orgList'} = \@orglist;
141
  $template->process( "@defaultHeader@", $templateVars);
142
  $template->process( "@register@", $templateVars);
143
  $template->process( "@defaultFooter@", $templateVars);
144
145
  exit();
146
}
147
148
#
149
# process input from the register stage, which occurs when
150
# a user submits form data to create a new account
151
#
152
sub handleRegister {
153
154
    print "Content-type: text/html\n\n";
155
156
    my $allParams = { 'givenName' => $query->param('givenName'),
157
                      'sn' => $query->param('sn'),
158
                      'o' => $query->param('o'),
159
                      'mail' => $query->param('mail'),
160
                      'uid' => $query->param('uid'),
161
                      'userPassword' => $query->param('userPassword'),
162
                      'userPassword2' => $query->param('userPassword2'),
163
                      'title' => $query->param('title'),
164
                      'telephoneNumber' => $query->param('telephoneNumber') };
165
    # Check that all required fields are provided and not null
166
    my @requiredParams = ( 'givenName', 'sn', 'o', 'mail',
167
                           'uid', 'userPassword', 'userPassword2');
168
    if (! paramsAreValid(@requiredParams)) {
169
        my $errorMessage = "Required information is missing. " .
170
            "Please fill in all required fields and resubmit the form.";
171
        my $templateVars = { stage => "register",
172
                             cfg => $cfg,
173
                             allParams => $allParams,
174
                             errorMessage => $errorMessage };
175
	$$templateVars{'orgList'} = \@orglist;
176
        $template->process( "@defaultHeader@", $templateVars);
177
        $template->process( "@register@", $templateVars);
178
        $template->process( "@defaultFooter@", $templateVars);
179
        exit(0);
180
    } else {
181
	my $o = $query->param('o');
182
	$ldapurl = $config_ldapurl->{$o};
183
	$searchBase = $config_ldapsearchbase->{$o};
184
    }
185
186
    # Search LDAP for matching entries that already exist
187
    # Some forms use a single text search box, whereas others search per
188
    # attribute.
189
    my $filter;
190
    if ($query->param('searchField')) {
191
192
      $filter = "(|" .
193
                "(uid=" . $query->param('searchField') . ") " .
194
                "(mail=" . $query->param('searchField') . ")" .
195
                "(&(sn=" . $query->param('searchField') . ") " .
196
                "(givenName=" . $query->param('searchField') . "))" .
197
                ")";
198
    } else {
199
      $filter = "(|" .
200
                "(uid=" . $query->param('uid') . ") " .
201
                "(mail=" . $query->param('mail') . ")" .
202
                "(&(sn=" . $query->param('sn') . ") " .
203
                "(givenName=" . $query->param('givenName') . "))" .
204
                ")";
205
    }
206
207
    my @attrs = [ 'uid', 'o', 'cn', 'mail', 'telephoneNumber', 'title' ];
208
209
    my $found = findExistingAccounts($ldapurl, $searchBase, $filter, \@attrs);
210
211
    # If entries match, send back a request to confirm new-user creation
212
    if ($found) {
213
      my $templateVars = { stage => "registerconfirmed",
214
                           cfg => $cfg,
215
                           allParams => $allParams,
216
                           foundAccounts => $found };
217
      $$templateVars{'orgList'} = \@orglist;
218
      $template->process( "@defaultHeader@", $templateVars);
219
      $template->process( "@registerMatch@", $templateVars);
220
      $template->process( "@register@", $templateVars);
221
      $template->process( "@defaultFooter@", $templateVars);
222
223
    # Otherwise, create a new user in the LDAP directory
224
    } else {
225
        createAccount($allParams);
226
    }
227
228
    exit();
229
}
230
231
#
232
# process input from the registerconfirmed stage, which occurs when
233
# a user chooses to create an account despite similarities to other
234
# existing accounts
235
#
236
sub handleRegisterConfirmed {
237
238
    my $allParams = { 'givenName' => $query->param('givenName'),
239
                      'sn' => $query->param('sn'),
240
                      'o' => $query->param('o'),
241
                      'mail' => $query->param('mail'),
242
                      'uid' => $query->param('uid'),
243
                      'userPassword' => $query->param('userPassword'),
244
                      'userPassword2' => $query->param('userPassword2'),
245
                      'title' => $query->param('title'),
246
                      'telephoneNumber' => $query->param('telephoneNumber') };
247
    print "Content-type: text/html\n\n";
248
    createAccount($allParams);
249
250
    exit();
251
}
252
253
#
254
# change a user's password upon request
255
#
256
sub handleChangePassword {
257
258
    print "Content-type: text/html\n\n";
259
260
    my $allParams = { 'test' => "1", };
261
    if ($query->param('uid')) {
262
        $$allParams{'uid'} = $query->param('uid');
263
    }
264
    if ($query->param('o')) {
265
        $$allParams{'o'} = $query->param('o');
266
	my $o = $query->param('o');
267
268
	$ldapurl = $config_ldapurl->{$o};
269
        $searchBase = $config_ldapsearchbase->{$o};
270
    }
271
272
273
    # Check that all required fields are provided and not null
274
    my @requiredParams = ( 'uid', 'o', 'oldpass',
275
                           'userPassword', 'userPassword2');
276
    if (! paramsAreValid(@requiredParams)) {
277
        my $errorMessage = "Required information is missing. " .
278
            "Please fill in all required fields and submit the form.";
279
        my $templateVars = { stage => "changepass",
280
                             cfg => $cfg,
281
                             allParams => $allParams,
282
                             errorMessage => $errorMessage };
283
	$$templateVars{'orgList'} = \@orglist;
284
        $template->process( "@defaultHeader@", $templateVars);
285
        $template->process( "@defaultChangePass@", $templateVars);
286
        $template->process( "@defaultFooter@", $templateVars);
287
        exit(0);
288
    }
289
290
    # We have all of the info we need, so try to change the password
291
    if ($query->param('userPassword') =~ $query->param('userPassword2')) {
292
293
	my $o = $query->param('o');
294
	$ldapurl = $config_ldapurl->{$o};
295
        $searchBase = $config_ldapsearchbase->{$o};
296
	$root = $config_user->{$o};
297
	$rootpw = $config_password->{$o};
298
299
        my $dn = "uid=" . $query->param('uid') . "," . $config_dn->{$o};;
300
        if ($query->param('o') =~ "LTER") {
301
            $template->process( "@defaultHeader@");
302
            $template->process( "@registerLter@");
303
            $template->process( "@defaultFooter@");
304
        } else {
305
            my $errorMessage = changePassword(
306
                    $dn, $query->param('userPassword'),
307
                    $dn, $query->param('oldpass'), $query->param('o'));
308
            if ($errorMessage) {
309
                my $templateVars = { stage => "changepass",
310
                                     cfg => $cfg,
311
                                     allParams => $allParams,
312
                                     errorMessage => $errorMessage };
313
		$$templateVars{'orgList'} = \@orglist;
314
                $template->process( "@defaultHeader@", $templateVars);
315
                $template->process( "@defaultChangePass@", $templateVars);
316
                $template->process( "@defaultFooter@", $templateVars);
317
                exit(0);
318
            } else {
319
                $template->process( "@defaultHeader@");
320
                $template->process( "@changePassSuccess@");
321
                $template->process( "@defaultFooter@");
322
                exit(0);
323
            }
324
        }
325
    } else {
326
        my $errorMessage = "The passwords do not match. Try again.";
327
        my $templateVars = { stage => "changepass",
328
                             cfg => $cfg,
329
                             allParams => $allParams,
330
                             errorMessage => $errorMessage };
331
	$$templateVars{'orgList'} = \@orglist;
332
        $template->process( "@defaultHeader@", $templateVars);
333
        $template->process( "@defaultChangePass@", $templateVars);
334
        $template->process( "@defaultFooter@", $templateVars);
335
        exit(0);
336
    }
337
}
338
339
#
340
# reset a user's password upon request
341
#
342
sub handleResetPassword {
343
344
    print "Content-type: text/html\n\n";
345
346
    my $allParams = { 'test' => "1", };
347
    if ($query->param('uid')) {
348
        $$allParams{'uid'} = $query->param('uid');
349
    }
350
    if ($query->param('o')) {
351
        $$allParams{'o'} = $query->param('o');
352
	my $o = $query->param('o');
353
354
	$ldapurl = $config_ldapurl->{$o};
355
        $searchBase = $config_ldapsearchbase->{$o};
356
	$root = $config_user->{$o};
357
	$rootpw = $config_password->{$o};
358
    }
359
360
    # Check that all required fields are provided and not null
361
    my @requiredParams = ( 'uid', 'o' );
362
    if (! paramsAreValid(@requiredParams)) {
363
        my $errorMessage = "Required information is missing. " .
364
            "Please fill in all required fields and submit the form.";
365
        my $templateVars = { stage => "resetpass",
366
                             cfg => $cfg,
367
                             allParams => $allParams,
368
                             errorMessage => $errorMessage };
369
	$$templateVars{'orgList'} = \@orglist;
370
        $template->process( "@defaultHeader@", $templateVars);
371
        $template->process( "@defaultResetPass@", $templateVars);
372
        $template->process( "@defaultFooter@", $templateVars);
373
        exit(0);
374
    }
375
376
    # We have all of the info we need, so try to change the password
377
    my $o = $query->param('o');
378
    my $dn = "uid=" . $query->param('uid') . "," . $config_dn->{$o};
379
    if ($query->param('o') =~ "LTER") {
380
        $template->process( "@defaultHeader@");
381
        $template->process( "@registerLter@");
382
        $template->process( "@defaultFooter@");
383
        exit(0);
384
    } else {
385
        my $errorMessage = "";
386
        my $recipient;
387
        my $userPass;
388
        my $entry = getLdapEntry($ldapurl, $searchBase,
389
                $query->param('uid'), $query->param('o'));
390
391
        if ($entry) {
392
            $recipient = $entry->get_value('mail');
393
            $userPass = getRandomPassword();
394
            $errorMessage = changePassword($dn, $userPass, $root, $rootpw, $query->param('o'));
395
        } else {
396
            $errorMessage = "User not found in database.  Please try again.";
397
        }
398
399
        if ($errorMessage) {
400
            my $templateVars = { stage => "resetpass",
401
                                 cfg => $cfg,
402
                                 allParams => $allParams,
403
                                 errorMessage => $errorMessage };
404
	    $$templateVars{'orgList'} = \@orglist;
405
            $template->process( "@defaultHeader@", $templateVars);
406
            $template->process( "@defaultResetPass@", $templateVars);
407
            $template->process( "@defaultFooter@", $templateVars);
408
            exit(0);
409
        } else {
410
            my $errorMessage = sendPasswordNotification($query->param('uid'),
411
                    $query->param('o'), $userPass, $recipient);
412
            my $templateVars = { stage => "resetpass",
413
                                 cfg => $cfg,
414
                                 allParams => $allParams,
415
                                 errorMessage => $errorMessage };
416
	    $$templateVars{'orgList'} = \@orglist;
417
            $template->process( "@defaultHeader@", $templateVars);
418
            $template->process( "@resetPassSuccess@", $templateVars);
419
            $template->process( "@defaultFooter@", $templateVars);
420
            exit(0);
421
        }
422
    }
423
}
424
425
#
426
# Construct a random string to use for a newly reset password
427
#
428
sub getRandomPassword {
429
    my $length = shift;
430
    if (!$length) {
431
        $length = 8;
432
    }
433
    my $newPass = "";
434
435
    my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw(! @ $ ^) );
436
    $newPass = join("", @chars[ map { rand @chars } ( 1 .. $length ) ]);
437
    return $newPass;
438
}
439
440
#
441
# Change a password to a new value, binding as the provided user
442
#
443
sub changePassword {
444
    my $userDN = shift;
445
    my $userPass = shift;
446
    my $bindDN = shift;
447
    my $bindPass = shift;
448
    my $o = shift;
449
450
    my $ldapurl = $config_ldapurl->{$o};
451
    my $searchBase = $config_ldapsearchbase->{$o};
452
453
    my $errorMessage = 0;
454
    my $ldap = Net::LDAP->new($ldapurl) or die "$@";
455
    my $bindresult = $ldap->bind( version => 3, dn => $bindDN,
456
                                  password => $bindPass );
457
    if ($bindresult->code) {
458
        $errorMessage = "Failed to log in. Are you sure your old " .
459
                        "password is correct? Try again...";
460
        return $errorMessage;
461
    }
462
463
    # Find the user here and change their entry
464
    my $newpass = createSeededPassHash($userPass);
465
    my $modifications = { userPassword => $newpass };
466
    my $result = $ldap->modify( $userDN, replace => { %$modifications });
467
468
    if ($result->code()) {
469
        my $errorMessage = "There was an error changing the password." .
470
                           "<br />\n" . $result->error;
471
    }
472
    $ldap->unbind;   # take down session
473
474
    return $errorMessage;
475
}
476
477
#
478
# generate a Seeded SHA1 hash of a plaintext password
479
#
480
sub createSeededPassHash {
481
    my $secret = shift;
482
483
    my $salt = "";
484
    for (my $i=0; $i < 4; $i++) {
485
        $salt .= int(rand(10));
486
    }
487
488
    my $ctx = Digest::SHA1->new;
489
    $ctx->add($secret);
490
    $ctx->add($salt);
491
    my $hashedPasswd = '{SSHA}' . encode_base64($ctx->digest . $salt ,'');
492
493
    return $hashedPasswd;
494
}
495
496
#
497
# Look up an ldap entry for a user
498
#
499
sub getLdapEntry {
500
    my $ldapurl = shift;
501
    my $base = shift;
502
    my $username = shift;
503
    my $org = shift;
504
505
    my $entry = "";
506
    my $mesg;
507
    my $ldap = Net::LDAP->new($ldapurl) or die "$@";
508
    my $bindresult = $ldap->bind;
509
    if ($bindresult->code) {
510
        return $entry;
511
    }
512
513
    if($config_filter->{$org}){
514
	$mesg = $ldap->search ( base   => $base,
515
				   filter => "(&(uid=$username)($config_filter->{$org}))"
516
				   );
517
    } else {
518
	$mesg = $ldap->search ( base   => $base,
519
				   filter => "(&(uid=$username))"
520
				   );
521
    }
522
523
    if ($mesg->count > 0) {
524
        $entry = $mesg->pop_entry;
525
        $ldap->unbind;   # take down session
526
    } else {
527
        $ldap->unbind;   # take down session
528
        # Follow references by recursive call to self
529
        my @references = $mesg->references();
530
        for (my $i = 0; $i <= $#references; $i++) {
531
            my $uri = URI->new($references[$i]);
532
            my $host = $uri->host();
533
            my $path = $uri->path();
534
            $path =~ s/^\///;
535
            $entry = &getLdapEntry($host, $path, $username, $org);
536
            if ($entry) {
537
                return $entry;
538
            }
539
        }
540
    }
541
    return $entry;
542
}
543
544
#
545
# send an email message notifying the user of the pw change
546
#
547
sub sendPasswordNotification {
548
    my $username = shift;
549
    my $org = shift;
550
    my $newPass = shift;
551
    my $recipient = shift;
552
553
    my $errorMessage = "";
554
    if ($recipient) {
555
        # Send the email message to them
556
        my $smtp = Net::SMTP->new($mailhost);
557
        $smtp->mail($sender);
558
        $smtp->to($recipient);
559
560
        my $message = <<"        ENDOFMESSAGE";
561
        To: $recipient
562
        From: $sender
563
        Subject: KNB Password Reset
564
565
        Somebody (hopefully you) requested that your KNB password be reset.
566
        This is generally done when somebody forgets their password.  Your
567
        password can be changed by visiting the following URL:
568
569
        @cgiurl@?stage=changepass
570
571
            Username: $username
572
        Organization: $org
573
        New Password: $newPass
574
575
        Thanks,
576
            The KNB Development Team
577
578
        ENDOFMESSAGE
579
        $message =~ s/^[ \t\r\f]+//gm;
580
581
        $smtp->data($message);
582
        $smtp->quit;
583
    } else {
584
        $errorMessage = "Failed to send password because I " .
585
                        "couldn't find a valid email address.";
586
    }
587
    return $errorMessage;
588
}
589
590
#
591
# search the LDAP directory to see if a similar account already exists
592
#
593
sub findExistingAccounts {
594
    my $ldapurl = shift;
595
    my $base = shift;
596
    my $filter = shift;
597
    my $attref = shift;
598
599
    my $foundAccounts = 0;
600
601
    my $ldap = Net::LDAP->new($ldapurl) or die "$@";
602
    $ldap->bind( version => 3, anonymous => 1);
603
    my $mesg = $ldap->search (
604
        base   => $base,
605
        filter => $filter,
606
        attrs => @$attref,
607
    );
608
609
    if ($mesg->count() > 0) {
610
        $foundAccounts = "";
611
        my $entry;
612
        foreach $entry ($mesg->all_entries) {
613
            $foundAccounts .= "<p>\n<b><u>Account:</u> ";
614
            $foundAccounts .= $entry->dn();
615
            $foundAccounts .= "</b><br />\n";
616
            foreach my $attribute ($entry->attributes()) {
617
                $foundAccounts .= "$attribute: ";
618
                $foundAccounts .= $entry->get_value($attribute);
619
                $foundAccounts .= "<br />\n";
620
            }
621
            $foundAccounts .= "</p>\n";
622
        }
623
    }
624
    $ldap->unbind;   # take down session
625
626
    # Follow references
627
    my @references = $mesg->references();
628
    for (my $i = 0; $i <= $#references; $i++) {
629
        my $uri = URI->new($references[$i]);
630
        my $host = $uri->host();
631
        my $path = $uri->path();
632
        $path =~ s/^\///;
633
        my $refFound = &findExistingAccounts($host, $path, $filter, $attref);
634
        if ($refFound) {
635
            $foundAccounts .= $refFound;
636
        }
637
    }
638
639
    #print "<p>Checking referrals...</p>\n";
640
    #my @referrals = $mesg->referrals();
641
    #print "<p>Referrals count: ", scalar(@referrals), "</p>\n";
642
    #for (my $i = 0; $i <= $#referrals; $i++) {
643
        #print "<p>Referral: ", $referrals[$i], "</p>\n";
644
    #}
645
646
    return $foundAccounts;
647
}
648
649
#
650
# Validate that we have the proper set of input parameters
651
#
652
sub paramsAreValid {
653
    my @pnames = @_;
654
655
    my $allValid = 1;
656
    foreach my $parameter (@pnames) {
657
        if (!defined($query->param($parameter)) ||
658
            ! $query->param($parameter) ||
659
            $query->param($parameter) =~ /^\s+$/) {
660
            $allValid = 0;
661
        }
662
    }
663
664
    return $allValid;
665
}
666
667
#
668
# Bind to LDAP and create a new account using the information provided
669
# by the user
670
#
671
sub createAccount {
672
    my $allParams = shift;
673
674
    if ($query->param('o') =~ "LTER") {
675
        $template->process( "@defaultHeader@");
676
        $template->process( "@registerLter@");
677
        $template->process( "@defaultFooter@");
678
    } else {
679
680
        # Be sure the passwords match
681
        if ($query->param('userPassword') !~ $query->param('userPassword2')) {
682
            my $errorMessage = "The passwords do not match. Try again.";
683
            my $templateVars = { stage => "register",
684
                                 cfg => $cfg,
685
                                 allParams => $allParams,
686
                                 errorMessage => $errorMessage };
687
	    $$templateVars{'orgList'} = \@orglist;
688
            $template->process( "@defaultHeader@", $templateVars);
689
            $template->process( "@register@", $templateVars);
690
            $template->process( "@defaultFooter@", $templateVars);
691
            exit(0);
692
        }
693
694
	my $o = $query->param('o');
695
696
	my $ldapurl = $config_ldapurl->{$o};
697
	my $root = $config_user->{$o};
698
	my $rootpw = $config_password->{$o};
699
	my $searchBase = $config_ldapsearchbase->{$o};
700
	my $dnBase = $config_dn->{$o};
701
702
        my $ldap = Net::LDAP->new($ldapurl) or die "$@";
703
        $ldap->bind( version => 3, dn => $root, password => $rootpw );
704
        #print "Inserting new entry...\n";
705
        my $dn = 'uid=' . $query->param('uid') . ',' . $dnBase;
706
707
        # Create a hashed version of the password
708
        my $shapass = createSeededPassHash($query->param('userPassword'));
709
710
        # Do the insertion
711
        my $additions = [
712
                'uid'   => $query->param('uid'),
713
                'o'   => $query->param('o'),
714
                'cn'   => join(" ", $query->param('givenName'),
715
                                    $query->param('sn')),
716
                'sn'   => $query->param('sn'),
717
                'givenName'   => $query->param('givenName'),
718
                'mail' => $query->param('mail'),
719
                'userPassword' => $shapass,
720
                'objectclass' => ['top', 'person', 'organizationalPerson',
721
                                'inetOrgPerson', 'uidObject' ]
722
            ];
723
        if (defined($query->param('telephoneNumber')) &&
724
            $query->param('telephoneNumber') &&
725
            ! $query->param('telephoneNumber') =~ /^\s+$/) {
726
            $$additions[$#$additions + 1] = 'telephoneNumber';
727
            $$additions[$#$additions + 1] = $query->param('telephoneNumber');
728
        }
729
        if (defined($query->param('title')) &&
730
            $query->param('title') &&
731
            ! $query->param('title') =~ /^\s+$/) {
732
            $$additions[$#$additions + 1] = 'title';
733
            $$additions[$#$additions + 1] = $query->param('title');
734
        }
735
        my $result = $ldap->add ( 'dn' => $dn, 'attr' => [ @$additions ]);
736
737
        if ($result->code()) {
738
            my $templateVars = { stage => "register",
739
                                 cfg => $cfg,
740
                                 allParams => $allParams,
741
                                 errorMessage => $result->error };
742
	    $$templateVars{'orgList'} = \@orglist;
743
            $template->process( "@defaultHeader@");
744
            $template->process( "@registerFailed@", $templateVars);
745
            $templateVars    = { stage => "register",
746
                                 cfg => $cfg,
747
                                 allParams => $allParams };
748
	    $$templateVars{'orgList'} = \@orglist;
749
            $template->process( "@register@", $templateVars);
750
            $template->process( "@defaultFooter@");
751
        } else {
752
            $template->process( "@defaultHeader@");
753
            $template->process( "@registerSuccess@");
754
            $template->process( "@defaultFooter@");
755
        }
756
757
        $ldap->unbind;   # take down session
758
    }
759
}
760
761
sub handleResponseMessage {
762
763
  print "Content-type: text/html\n\n";
764
  my $errorMessage = "You provided invalid input to the script. " .
765
                     "Try again please.";
766
  my $templateVars = { stage => "@defaultStage@",
767
                       cfg => $cfg,
768
                       errorMessage => $errorMessage };
769
  $$templateVars{'orgList'} = \@orglist;
770
  $template->process( "@defaultHeader@", $templateVars);
771
  $template->process( "@defaultFooter@", $templateVars);
772
  exit(0);
773
}
774
775
#
776
# perform a simple search against the LDAP database using
777
# a small subset of attributes of each dn and return it
778
# as a table to the calling browser.
779
#
780
sub handleSimpleSearch {
781
782
    my $o = $query->param('o');
783
784
    my $ldapurl = $config_ldapurl->{$o};
785
    my $searchBase = $config_ldapsearchbase->{$o};
786
787
    print "Content-type: text/html\n\n";
788
789
    my $allParams = {
790
                      'cn' => $query->param('cn'),
791
                      'sn' => $query->param('sn'),
792
                      'gn' => $query->param('gn'),
793
                      'o'  => $query->param('o'),
794
                      'facsimiletelephonenumber'
795
                      => $query->param('facsimiletelephonenumber'),
796
                      'mail' => $query->param('cmail'),
797
                      'telephonenumber' => $query->param('telephonenumber'),
798
                      'title' => $query->param('title'),
799
                      'uid' => $query->param('uid'),
800
                      'ou' => $query->param('ou'),
801
                    };
802
803
    # Search LDAP for matching entries that already exist
804
    my $filter = "(" .
805
                 $query->param('searchField') . "=" .
806
                 "*" .
807
                 $query->param('searchValue') .
808
                 "*" .
809
                 ")";
810
811
    my @attrs = [ 'sn',
812
                  'gn',
813
                  'cn',
814
                  'o',
815
                  'facsimiletelephonenumber',
816
                  'mail',
817
                  'telephoneNumber',
818
                  'title',
819
                  'uid',
820
                  'labeledURI',
821
                  'ou' ];
822
823
    my $found = searchDirectory($ldapurl, $searchBase, $filter, \@attrs);
824
825
    # Send back the search results
826
    if ($found) {
827
      my $templateVars = { stage => "searchResults",
828
                           cfg => $cfg,
829
                           allParams => $allParams,
830
                           foundAccounts => $found };
831
      $$templateVars{'orgList'} = \@orglist;
832
      $template->process( "@defaultHeader@", $templateVars);
833
      $template->process( "@searchResults@", $templateVars);
834
      $template->process( "@defaultFooter@", $templateVars);
835
836
    } else {
837
      $found = "No entries matched your criteria.  Please try again\n";
838
839
      my $templateVars = { stage => "searchResults",
840
                           cfg => $cfg,
841
                           allParams => $allParams,
842
                           foundAccounts => $found };
843
      $$templateVars{'orgList'} = \@orglist;
844
      $template->process( "@defaultHeader@", $templateVars);
845
      $template->process( "@searchResults@", $templateVars);
846
      $template->process( "@defaultFooter@", $templateVars);
847
848
    }
849
850
    exit();
851
}
852
853
#
854
# search the LDAP directory to see if a similar account already exists
855
#
856
sub searchDirectory {
857
    my $ldapurl = shift;
858
    my $base = shift;
859
    my $filter = shift;
860
    my $attref = shift;
861
862
    my $foundAccounts = 0;
863
864
    my $ldap = Net::LDAP->new($ldapurl) or die "$@";
865
    $ldap->bind( version => 3, anonymous => 1);
866
    my $mesg = $ldap->search (
867
        base   => $base,
868
        filter => $filter,
869
        attrs => @$attref,
870
    );
871
872
    if ($mesg->count() > 0) {
873
        $foundAccounts = "";
874
        my $entry;
875
        foreach $entry ($mesg->sorted(['sn'])) {
876
          $foundAccounts .= "<tr>\n<td class=\"main\">\n";
877
          $foundAccounts .= "<a href=\"" unless
878
                    (!$entry->get_value('labeledURI'));
879
          $foundAccounts .= $entry->get_value('labeledURI') unless
880
                    (!$entry->get_value('labeledURI'));
881
          $foundAccounts .= "\">\n" unless
882
                    (!$entry->get_value('labeledURI'));
883
          $foundAccounts .= $entry->get_value('givenName');
884
          $foundAccounts .= "</a>\n" unless
885
                    (!$entry->get_value('labeledURI'));
886
          $foundAccounts .= "\n</td>\n<td class=\"main\">\n";
887
          $foundAccounts .= "<a href=\"" unless
888
                    (!$entry->get_value('labeledURI'));
889
          $foundAccounts .= $entry->get_value('labeledURI') unless
890
                    (!$entry->get_value('labeledURI'));
891
          $foundAccounts .= "\">\n" unless
892
                    (!$entry->get_value('labeledURI'));
893
          $foundAccounts .= $entry->get_value('sn');
894
          $foundAccounts .= "</a>\n";
895
          $foundAccounts .= "\n</td>\n<td class=\"main\">\n";
896
          $foundAccounts .= $entry->get_value('mail');
897
          $foundAccounts .= "\n</td>\n<td class=\"main\">\n";
898
          $foundAccounts .= $entry->get_value('telephonenumber');
899
          $foundAccounts .= "\n</td>\n<td class=\"main\">\n";
900
          $foundAccounts .= $entry->get_value('title');
901
          $foundAccounts .= "\n</td>\n<td class=\"main\">\n";
902
          $foundAccounts .= $entry->get_value('ou');
903
          $foundAccounts .= "\n</td>\n";
904
          $foundAccounts .= "</tr>\n";
905
        }
906
    }
907
    $ldap->unbind;   # take down session
908
    return $foundAccounts;
909
}
910
911
sub debug {
912
    my $msg = shift;
913
914
    if ($debug) {
915
        print STDERR "$msg\n";
916
    }
917
}