Project

General

Profile

1
#!/usr/bin/perl -w
2
 #
3
 #  '$RCSfile$'
4
 #  Copyright: 2001 Regents of the University of California 
5
 #
6
 #   '$Author: sgarg $'
7
 #     '$Date: 2004-12-20 16:02:51 -0800 (Mon, 20 Dec 2004) $'
8
 # '$Revision: 2341 $' 
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
}
(2-2/5)