Project

General

Profile

1 2341 sgarg
#!/usr/bin/perl -w
2 4865 walbridge
#
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 2341 sgarg
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 4394 walbridge
30
use lib '../WEB-INF/lib';
31 4080 daigle
use strict;             # turn on strict syntax checking
32
use Template;           # load the template-toolkit module
33 4394 walbridge
use CGI qw/:standard :html3/; # load the CGI module
34 4080 daigle
use Net::LDAP;          # load the LDAP net libraries
35
use Net::SMTP;          # load the SMTP net libraries
36
use Digest::SHA1;       # for creating the password hash
37
use MIME::Base64;       # for creating the password hash
38
use URI;                # for parsing URL syntax
39
use Config::Properties; # for parsing Java .properties files
40
use File::Basename;     # for path name parsing
41 8166 tao
use Captcha::reCAPTCHA; # for protection against spams
42 4394 walbridge
use Cwd 'abs_path';
43 2341 sgarg
44 4080 daigle
# Global configuration paramters
45 4394 walbridge
# This entire block (including skin parsing) could be pushed out to a separate .pm file
46 4080 daigle
my $cgiUrl = $ENV{'SCRIPT_FILENAME'};
47
my $workingDirectory = dirname($cgiUrl);
48
my $metacatProps = "${workingDirectory}/../WEB-INF/metacat.properties";
49
my $properties = new Config::Properties();
50
unless (open (METACAT_PROPERTIES, $metacatProps)) {
51 4394 walbridge
    print "Content-type: text/html\n\n";
52 4080 daigle
    print "Unable to locate Metacat properties. Working directory is set as " .
53
        $workingDirectory .", is this correct?";
54
    exit(0);
55
}
56 2341 sgarg
57 4080 daigle
$properties->load(*METACAT_PROPERTIES);
58 4010 tao
59 4394 walbridge
# local directory configuration
60
my $skinsDir = "${workingDirectory}/../style/skins";
61
my $templatesDir = abs_path("${workingDirectory}/../style/common/templates");
62
my $tempDir = $properties->getProperty('application.tempDir');
63
64
# url configuration
65
my $server = $properties->splitToTree(qr/\./, 'server');
66 7199 leinfelder
my $protocol = 'http://';
67
if ( $properties->getProperty('server.httpPort') eq '443' ) {
68
	$protocol = 'https://';
69
}
70
my $contextUrl = $protocol . $properties->getProperty('server.name');
71 4864 walbridge
if ($properties->getProperty('server.httpPort') ne '80') {
72
        $contextUrl = $contextUrl . ':' . $properties->getProperty('server.httpPort');
73
}
74
$contextUrl = $contextUrl . '/' .  $properties->getProperty('application.context');
75 4394 walbridge
76
my $metacatUrl = $contextUrl . "/metacat";
77
my $cgiPrefix = "/" . $properties->getProperty('application.context') . "/cgi-bin";
78
my $styleSkinsPath = $contextUrl . "/style/skins";
79
my $styleCommonPath = $contextUrl . "/style/common";
80
81 8169 tao
#recaptcha key information
82
my $recaptchaPublicKey=$properties->getProperty('ldap.recaptcha.publickey');
83
my $recaptchaPrivateKey=$properties->getProperty('ldap.recaptcha.privatekey');
84
85 4394 walbridge
my @errorMessages;
86
my $error = 0;
87
88
# Import all of the HTML form fields as variables
89
import_names('FORM');
90
91
# Must have a config to use Metacat
92
my $skinName = "";
93
if ($FORM::cfg) {
94
    $skinName = $FORM::cfg;
95
} elsif ($ARGV[0]) {
96
    $skinName = $ARGV[0];
97
} else {
98 4747 walbridge
    debug("No configuration set.");
99 4394 walbridge
    print "Content-type: text/html\n\n";
100 4749 walbridge
    print 'LDAPweb Error: The registry requires a skin name to continue.';
101 4394 walbridge
    exit();
102
}
103
104
# Metacat isn't initialized, the registry will fail in strange ways.
105
if (!($metacatUrl)) {
106 4747 walbridge
    debug("No Metacat.");
107 4394 walbridge
    print "Content-type: text/html\n\n";
108
    'Registry Error: Metacat is not initialized! Make sure' .
109 5214 walbridge
        ' MetacatUrl is set correctly in ' .  $skinName . '.properties';
110 4394 walbridge
    exit();
111
}
112
113
my $skinProperties = new Config::Properties();
114
if (!($skinName)) {
115
    $error = "Application misconfigured.  Please contact the administrator.";
116
    push(@errorMessages, $error);
117
} else {
118
    my $skinProps = "$skinsDir/$skinName/$skinName.properties";
119
    unless (open (SKIN_PROPERTIES, $skinProps)) {
120
        print "Content-type: text/html\n\n";
121
        print "Unable to locate skin properties at $skinProps.  Is this path correct?";
122
        exit(0);
123
    }
124
    $skinProperties->load(*SKIN_PROPERTIES);
125
}
126
127
my $config = $skinProperties->splitToTree(qr/\./, 'registry.config');
128
129 4870 walbridge
# XXX HACK: this is a temporary fix to pull out the UCNRS password property from the
130
#           NRS skin instead of metacat.properties. The intent is to prevent editing
131
#           of our core properties file, which is manipulated purely through the web.
132
#           Once organizations are editable, this section should be removed as should
133
#           the properties within nrs/nrs.properties.
134
my $nrsProperties = new Config::Properties();
135
my $nrsProps = "$skinsDir/nrs/nrs.properties";
136
unless (open (NRS_PROPERTIES, $nrsProps)) {
137
    print "Content-type: text/html\n\n";
138
    print "Unable to locate skin properties at $nrsProps.  Is this path correct?";
139
    exit(0);
140
}
141
$nrsProperties->load(*NRS_PROPERTIES);
142
143
my $nrsConfig = $nrsProperties->splitToTree(qr/\./, 'registry.config');
144
145
# XXX END HACK
146
147
148 4394 walbridge
my $searchBase;
149
my $ldapUsername;
150
my $ldapPassword;
151 4728 walbridge
# TODO: when should we use surl instead? Is there a setting promoting one over the other?
152
# TODO: the default tree for accounts should be exposed somewhere, defaulting to unaffiliated
153
my $ldapurl = $properties->getProperty('auth.url');
154 4080 daigle
155
# Java uses miliseconds, Perl expects whole seconds
156 4728 walbridge
my $timeout = $properties->getProperty('ldap.connectTimeLimit') / 1000;
157 4080 daigle
158 2341 sgarg
# Get the CGI input variables
159
my $query = new CGI;
160 4747 walbridge
my $debug = 1;
161 2341 sgarg
162
#--------------------------------------------------------------------------80c->
163
# Set up the Template Toolkit to read html form templates
164
165 4080 daigle
# templates hash, imported from ldap.templates tree in metacat.properties
166
my $templates = $properties->splitToTree(qr/\./, 'ldap.templates');
167 4394 walbridge
$$templates{'header'} = $skinProperties->getProperty("registry.templates.header");
168
$$templates{'footer'} = $skinProperties->getProperty("registry.templates.footer");
169 2341 sgarg
170
# set some configuration options for the template object
171 4394 walbridge
my $ttConfig = {
172
             INCLUDE_PATH => $templatesDir,
173
             INTERPOLATE  => 0,
174
             POST_CHOMP   => 1,
175
             DEBUG        => 1,
176 2341 sgarg
             };
177
178
# create an instance of the template
179 4394 walbridge
my $template = Template->new($ttConfig) || handleGeneralServerFailure($Template::ERROR);
180 2341 sgarg
181 4080 daigle
# custom LDAP properties hash
182
my $ldapCustom = $properties->splitToTree(qr/\./, 'ldap');
183 2341 sgarg
184 4394 walbridge
my $orgProps = $properties->splitToTree(qr/\./, 'organization');
185
my $orgNames = $properties->splitToTree(qr/\./, 'organization.name');
186
# pull out properties available e.g. 'name', 'base'
187
my @orgData = keys(%$orgProps);
188 4870 walbridge
189 4394 walbridge
my @orgList;
190
while (my ($oKey, $oVal) = each(%$orgNames)) {
191
    push(@orgList, $oKey);
192
}
193
194 4866 walbridge
my $authBase = $properties->getProperty("auth.base");
195 4080 daigle
my $ldapConfig;
196
foreach my $o (@orgList) {
197 4394 walbridge
    foreach my $d (@orgData) {
198
        $ldapConfig->{$o}{$d} = $properties->getProperty("organization.$d.$o");
199 4080 daigle
    }
200 4866 walbridge
201 4870 walbridge
    # XXX hack, remove after 1.9
202
    if ($o eq 'UCNRS') {
203
        $ldapConfig->{'UCNRS'}{'base'} = $nrsConfig->{'base'};
204
        $ldapConfig->{'UCNRS'}{'user'} = $nrsConfig->{'username'};
205
        $ldapConfig->{'UCNRS'}{'password'} = $nrsConfig->{'password'};
206
    }
207
208 4866 walbridge
    # set default base
209
    if (!$ldapConfig->{$o}{'base'}) {
210
        $ldapConfig->{$o}{'base'} = $authBase;
211
    }
212
213
    # include filter information. By default, our filters are 'o=$name', e.g. 'o=NAPIER'
214
    # these can be overridden by specifying them in metacat.properties. Non-default configs
215
    # such as UCNRS must specify all LDAP properties.
216
    if ($ldapConfig->{$o}{'base'} eq $authBase) {
217
        my $filter = "o=$o";
218
        if (!$ldapConfig->{$o}{'org'}) {
219
            $ldapConfig->{$o}{'org'} = $filter;
220
        }
221
        if (!$ldapConfig->{$o}{'filter'}) {
222
            $ldapConfig->{$o}{'filter'} = $filter;
223
        }
224
        # also include DN, which is just org + base
225
        if ($ldapConfig->{$o}{'org'}) {
226
            $ldapConfig->{$o}{'dn'} = $ldapConfig->{$o}{'org'} . "," . $ldapConfig->{$o}{'base'};
227
        }
228 4394 walbridge
    } else {
229
        $ldapConfig->{$o}{'dn'} = $ldapConfig->{$o}{'base'};
230
    }
231 4868 walbridge
232
    # set LDAP administrator user account
233 4866 walbridge
    if (!$ldapConfig->{$o}{'user'}) {
234
        $ldapConfig->{$o}{'user'} = $ldapConfig->{'unaffiliated'}{'user'};
235 4865 walbridge
    }
236 4868 walbridge
    # check for a fully qualified LDAP name. If it doesn't exist, append base.
237
    my @userParts = split(',', $ldapConfig->{$o}{'user'});
238
    if (scalar(@userParts) == 1) {
239
        $ldapConfig->{$o}{'user'} = $ldapConfig->{$o}{'user'} . "," . $ldapConfig->{$o}{'base'};
240
    }
241 4866 walbridge
242
    if (!$ldapConfig->{$o}{'password'}) {
243
        $ldapConfig->{$o}{'password'} = $ldapConfig->{'unaffiliated'}{'password'};
244
    }
245 2341 sgarg
}
246
247
#--------------------------------------------------------------------------80c->
248
# Define the main program logic that calls subroutines to do the work
249
#--------------------------------------------------------------------------80c->
250
251
# The processing step we are handling
252 4080 daigle
my $stage = $query->param('stage') || $templates->{'stage'};
253 2341 sgarg
254
my $cfg = $query->param('cfg');
255 4767 walbridge
debug("started with stage $stage, cfg $cfg");
256 2341 sgarg
257
# define the possible stages
258
my %stages = (
259
              'initregister'      => \&handleInitRegister,
260
              'register'          => \&handleRegister,
261
              'registerconfirmed' => \&handleRegisterConfirmed,
262
              'simplesearch'      => \&handleSimpleSearch,
263
              'initaddentry'      => \&handleInitAddEntry,
264
              'addentry'          => \&handleAddEntry,
265
              'initmodifyentry'   => \&handleInitModifyEntry,
266
              'modifyentry'       => \&handleModifyEntry,
267 2972 jones
              'changepass'        => \&handleChangePassword,
268
              'initchangepass'    => \&handleInitialChangePassword,
269 2341 sgarg
              'resetpass'         => \&handleResetPassword,
270 2414 sgarg
              'initresetpass'     => \&handleInitialResetPassword,
271 8175 tao
              'createtemppass'    => \&createTemporaryAccount,
272 2341 sgarg
             );
273 4394 walbridge
274 2341 sgarg
# call the appropriate routine based on the stage
275
if ( $stages{$stage} ) {
276
  $stages{$stage}->();
277
} else {
278
  &handleResponseMessage();
279
}
280
281
#--------------------------------------------------------------------------80c->
282
# Define the subroutines to do the work
283
#--------------------------------------------------------------------------80c->
284
285 4728 walbridge
sub fullTemplate {
286
    my $templateList = shift;
287
    my $templateVars = setVars(shift);
288 8166 tao
    my $c = Captcha::reCAPTCHA->new;
289
    my $captcha = 'captcha';
290
    #my $error=null;
291
    my $use_ssl= 1;
292
    #my $options=null;
293 8169 tao
    $templateVars->{$captcha} = $c->get_html($recaptchaPublicKey,undef, $use_ssl, undef);
294 4728 walbridge
    $template->process( $templates->{'header'}, $templateVars );
295
    foreach my $tmpl (@{$templateList}) {
296
        $template->process( $templates->{$tmpl}, $templateVars );
297
    }
298
    $template->process( $templates->{'footer'}, $templateVars );
299
}
300
301 2341 sgarg
#
302
# create the initial registration form
303
#
304
sub handleInitRegister {
305
  my $vars = shift;
306
  print "Content-type: text/html\n\n";
307
  # process the template files:
308 4080 daigle
  fullTemplate(['register'], {stage => "register"});
309 2341 sgarg
  exit();
310
}
311
312
#
313
# process input from the register stage, which occurs when
314
# a user submits form data to create a new account
315
#
316
sub handleRegister {
317
318
    print "Content-type: text/html\n\n";
319 8166 tao
320
321 2341 sgarg
    my $allParams = { 'givenName' => $query->param('givenName'),
322
                      'sn' => $query->param('sn'),
323
                      'o' => $query->param('o'),
324
                      'mail' => $query->param('mail'),
325
                      'uid' => $query->param('uid'),
326
                      'userPassword' => $query->param('userPassword'),
327
                      'userPassword2' => $query->param('userPassword2'),
328
                      'title' => $query->param('title'),
329
                      'telephoneNumber' => $query->param('telephoneNumber') };
330 8166 tao
331
    # Check the recaptcha
332
    my $c = Captcha::reCAPTCHA->new;
333
    my $challenge = $query->param('recaptcha_challenge_field');
334
    my $response = $query->param('recaptcha_response_field');
335
    # Verify submission
336
    my $result = $c->check_answer(
337 8169 tao
        $recaptchaPrivateKey, $ENV{'REMOTE_ADDR'},
338 8166 tao
        $challenge, $response
339
    );
340
341
    if ( $result->{is_valid} ) {
342
        #print "Yes!";
343
        #exit();
344
    }
345
    else {
346
        my $errorMessage = "The verification code is wrong. Please input again.";
347
        fullTemplate(['register'], { stage => "register",
348
                                     allParams => $allParams,
349
                                     errorMessage => $errorMessage });
350
        exit();
351
    }
352
353
354 2341 sgarg
    # Check that all required fields are provided and not null
355
    my @requiredParams = ( 'givenName', 'sn', 'o', 'mail',
356
                           'uid', 'userPassword', 'userPassword2');
357
    if (! paramsAreValid(@requiredParams)) {
358
        my $errorMessage = "Required information is missing. " .
359
            "Please fill in all required fields and resubmit the form.";
360 4080 daigle
        fullTemplate(['register'], { stage => "register",
361
                                     allParams => $allParams,
362
                                     errorMessage => $errorMessage });
363
        exit();
364 2341 sgarg
    } else {
365 2972 jones
        my $o = $query->param('o');
366 4080 daigle
        $searchBase = $ldapConfig->{$o}{'base'};
367 2341 sgarg
    }
368
369
    # Search LDAP for matching entries that already exist
370
    # Some forms use a single text search box, whereas others search per
371
    # attribute.
372
    my $filter;
373
    if ($query->param('searchField')) {
374
375
      $filter = "(|" .
376
                "(uid=" . $query->param('searchField') . ") " .
377
                "(mail=" . $query->param('searchField') . ")" .
378
                "(&(sn=" . $query->param('searchField') . ") " .
379
                "(givenName=" . $query->param('searchField') . "))" .
380
                ")";
381
    } else {
382
      $filter = "(|" .
383
                "(uid=" . $query->param('uid') . ") " .
384
                "(mail=" . $query->param('mail') . ")" .
385
                "(&(sn=" . $query->param('sn') . ") " .
386
                "(givenName=" . $query->param('givenName') . "))" .
387
                ")";
388
    }
389
390
    my @attrs = [ 'uid', 'o', 'cn', 'mail', 'telephoneNumber', 'title' ];
391
    my $found = findExistingAccounts($ldapurl, $searchBase, $filter, \@attrs);
392
393
    # If entries match, send back a request to confirm new-user creation
394
    if ($found) {
395 4080 daigle
      fullTemplate( ['registerMatch', 'register'], { stage => "registerconfirmed",
396
                                                     allParams => $allParams,
397
                                                     foundAccounts => $found });
398 2341 sgarg
    # Otherwise, create a new user in the LDAP directory
399
    } else {
400
        createAccount($allParams);
401
    }
402
403
    exit();
404
}
405
406
#
407
# process input from the registerconfirmed stage, which occurs when
408
# a user chooses to create an account despite similarities to other
409
# existing accounts
410
#
411
sub handleRegisterConfirmed {
412
413
    my $allParams = { 'givenName' => $query->param('givenName'),
414
                      'sn' => $query->param('sn'),
415 4080 daigle
                      'o' => 'unaffiliated', # only accept unaffiliated registration
416 2341 sgarg
                      'mail' => $query->param('mail'),
417
                      'uid' => $query->param('uid'),
418
                      'userPassword' => $query->param('userPassword'),
419
                      'userPassword2' => $query->param('userPassword2'),
420
                      'title' => $query->param('title'),
421
                      'telephoneNumber' => $query->param('telephoneNumber') };
422
    print "Content-type: text/html\n\n";
423
    createAccount($allParams);
424
    exit();
425
}
426
427
#
428
# change a user's password upon request
429
#
430
sub handleChangePassword {
431
432
    print "Content-type: text/html\n\n";
433
434
    my $allParams = { 'test' => "1", };
435
    if ($query->param('uid')) {
436
        $$allParams{'uid'} = $query->param('uid');
437
    }
438
    if ($query->param('o')) {
439
        $$allParams{'o'} = $query->param('o');
440 2972 jones
        my $o = $query->param('o');
441
442 4080 daigle
        $searchBase = $ldapConfig->{$o}{'base'};
443 2341 sgarg
    }
444
445
446
    # Check that all required fields are provided and not null
447
    my @requiredParams = ( 'uid', 'o', 'oldpass',
448
                           'userPassword', 'userPassword2');
449
    if (! paramsAreValid(@requiredParams)) {
450
        my $errorMessage = "Required information is missing. " .
451
            "Please fill in all required fields and submit the form.";
452 4080 daigle
        fullTemplate( ['changePass'], { stage => "changepass",
453
                                        allParams => $allParams,
454
                                        errorMessage => $errorMessage });
455
        exit();
456 2341 sgarg
    }
457
458
    # We have all of the info we need, so try to change the password
459
    if ($query->param('userPassword') =~ $query->param('userPassword2')) {
460
461 2972 jones
        my $o = $query->param('o');
462 4080 daigle
        $searchBase = $ldapConfig->{$o}{'base'};
463
        $ldapUsername = $ldapConfig->{$o}{'user'};
464
        $ldapPassword = $ldapConfig->{$o}{'password'};
465 2341 sgarg
466 4080 daigle
        my $dn = "uid=" . $query->param('uid') . "," . $ldapConfig->{$o}{'dn'};;
467 2341 sgarg
        if ($query->param('o') =~ "LTER") {
468 4080 daigle
            fullTemplate( ['registerLter'] );
469 2341 sgarg
        } else {
470
            my $errorMessage = changePassword(
471
                    $dn, $query->param('userPassword'),
472
                    $dn, $query->param('oldpass'), $query->param('o'));
473 2972 jones
            if ($errorMessage) {
474 4080 daigle
                fullTemplate( ['changePass'], { stage => "changepass",
475
                                                allParams => $allParams,
476
                                                errorMessage => $errorMessage });
477
                exit();
478 2341 sgarg
            } else {
479 4080 daigle
                fullTemplate( ['changePassSuccess'], { stage => "changepass",
480
                                                       allParams => $allParams });
481
                exit();
482 2341 sgarg
            }
483
        }
484
    } else {
485
        my $errorMessage = "The passwords do not match. Try again.";
486 4080 daigle
        fullTemplate( ['changePass'], { stage => "changepass",
487
                                        allParams => $allParams,
488
                                        errorMessage => $errorMessage });
489
        exit();
490 2341 sgarg
    }
491
}
492
493
#
494 2414 sgarg
# change a user's password upon request - no input params
495
# only display chagepass template without any error
496
#
497
sub handleInitialChangePassword {
498
    print "Content-type: text/html\n\n";
499
500
    my $allParams = { 'test' => "1", };
501
    my $errorMessage = "";
502 4080 daigle
    fullTemplate( ['changePass'], { stage => "changepass",
503
                                    errorMessage => $errorMessage });
504
    exit();
505 2414 sgarg
}
506
507
#
508 2341 sgarg
# reset a user's password upon request
509
#
510
sub handleResetPassword {
511
512
    print "Content-type: text/html\n\n";
513
514
    my $allParams = { 'test' => "1", };
515
    if ($query->param('uid')) {
516
        $$allParams{'uid'} = $query->param('uid');
517
    }
518
    if ($query->param('o')) {
519
        $$allParams{'o'} = $query->param('o');
520 2972 jones
        my $o = $query->param('o');
521
522 4080 daigle
        $searchBase = $ldapConfig->{$o}{'base'};
523 4868 walbridge
        $ldapUsername = $ldapConfig->{$o}{'user'};
524 4080 daigle
        $ldapPassword = $ldapConfig->{$o}{'password'};
525 2341 sgarg
    }
526
527
    # Check that all required fields are provided and not null
528
    my @requiredParams = ( 'uid', 'o' );
529
    if (! paramsAreValid(@requiredParams)) {
530
        my $errorMessage = "Required information is missing. " .
531
            "Please fill in all required fields and submit the form.";
532 4080 daigle
        fullTemplate( ['resetPass'],  { stage => "resetpass",
533
                                        allParams => $allParams,
534
                                        errorMessage => $errorMessage });
535
        exit();
536 2341 sgarg
    }
537
538
    # We have all of the info we need, so try to change the password
539
    my $o = $query->param('o');
540 4080 daigle
    my $dn = "uid=" . $query->param('uid') . "," . $ldapConfig->{$o}{'dn'};
541 4866 walbridge
    debug("handleResetPassword: dn: $dn");
542 2341 sgarg
    if ($query->param('o') =~ "LTER") {
543 4080 daigle
        fullTemplate( ['registerLter'] );
544
        exit();
545 2341 sgarg
    } else {
546
        my $errorMessage = "";
547
        my $recipient;
548
        my $userPass;
549
        my $entry = getLdapEntry($ldapurl, $searchBase,
550
                $query->param('uid'), $query->param('o'));
551
552
        if ($entry) {
553
            $recipient = $entry->get_value('mail');
554
            $userPass = getRandomPassword();
555 4080 daigle
            $errorMessage = changePassword($dn, $userPass, $ldapUsername, $ldapPassword, $query->param('o'));
556 2341 sgarg
        } else {
557
            $errorMessage = "User not found in database.  Please try again.";
558
        }
559
560
        if ($errorMessage) {
561 4080 daigle
            fullTemplate( ['resetPass'], { stage => "resetpass",
562
                                           allParams => $allParams,
563
                                           errorMessage => $errorMessage });
564
            exit();
565 2341 sgarg
        } else {
566
            my $errorMessage = sendPasswordNotification($query->param('uid'),
567 2972 jones
                    $query->param('o'), $userPass, $recipient, $cfg);
568 4080 daigle
            fullTemplate( ['resetPassSuccess'], { stage => "resetpass",
569
                                                  allParams => $allParams,
570
                                                  errorMessage => $errorMessage });
571
            exit();
572 2341 sgarg
        }
573
    }
574
}
575
576
#
577 2414 sgarg
# reset a user's password upon request- no initial params
578
# only display resetpass template without any error
579
#
580
sub handleInitialResetPassword {
581
    print "Content-type: text/html\n\n";
582
    my $errorMessage = "";
583 4080 daigle
    fullTemplate( ['resetPass'], { stage => "resetpass",
584
                                   errorMessage => $errorMessage });
585
    exit();
586 2414 sgarg
}
587
588
#
589 2341 sgarg
# Construct a random string to use for a newly reset password
590
#
591
sub getRandomPassword {
592
    my $length = shift;
593
    if (!$length) {
594
        $length = 8;
595
    }
596
    my $newPass = "";
597
598
    my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw(! @ $ ^) );
599
    $newPass = join("", @chars[ map { rand @chars } ( 1 .. $length ) ]);
600
    return $newPass;
601
}
602
603
#
604
# Change a password to a new value, binding as the provided user
605
#
606
sub changePassword {
607
    my $userDN = shift;
608
    my $userPass = shift;
609
    my $bindDN = shift;
610
    my $bindPass = shift;
611
    my $o = shift;
612
613 4080 daigle
    my $searchBase = $ldapConfig->{$o}{'base'};
614 4868 walbridge
615 2341 sgarg
    my $errorMessage = 0;
616 3177 tao
    my $ldap;
617 4868 walbridge
618 4771 walbridge
    #if main ldap server is down, a html file containing warning message will be returned
619
    $ldap = Net::LDAP->new($ldapurl, timeout => $timeout) or handleLDAPBindFailure($ldapurl);
620 4394 walbridge
621 4849 daigle
    if ($ldap) {
622 4868 walbridge
        #$ldap->start_tls( verify => 'require',
623 2972 jones
                      #cafile => '/usr/share/ssl/ldapcerts/cacert.pem');
624 4868 walbridge
        $ldap->start_tls( verify => 'none');
625
        debug("changePassword: attempting to bind to $bindDN");
626
        my $bindresult = $ldap->bind( version => 3, dn => $bindDN,
627 2341 sgarg
                                  password => $bindPass );
628 4868 walbridge
        if ($bindresult->code) {
629
            $errorMessage = "Failed to log in. Are you sure your connection credentails are " .
630
                            "correct? Please correct and try again...";
631
            return $errorMessage;
632
        }
633 2341 sgarg
634 4849 daigle
    	# Find the user here and change their entry
635
    	my $newpass = createSeededPassHash($userPass);
636
    	my $modifications = { userPassword => $newpass };
637 4868 walbridge
      debug("changePass: setting password for $userDN to $newpass");
638 4849 daigle
    	my $result = $ldap->modify( $userDN, replace => { %$modifications });
639 2341 sgarg
640 4849 daigle
    	if ($result->code()) {
641 4866 walbridge
            debug("changePass: error changing password: " . $result->error);
642
        	$errorMessage = "There was an error changing the password:" .
643 2341 sgarg
                           "<br />\n" . $result->error;
644 4849 daigle
    	}
645
    	$ldap->unbind;   # take down session
646
    }
647 2341 sgarg
648
    return $errorMessage;
649
}
650
651
#
652
# generate a Seeded SHA1 hash of a plaintext password
653
#
654
sub createSeededPassHash {
655
    my $secret = shift;
656
657
    my $salt = "";
658
    for (my $i=0; $i < 4; $i++) {
659
        $salt .= int(rand(10));
660
    }
661
662
    my $ctx = Digest::SHA1->new;
663
    $ctx->add($secret);
664
    $ctx->add($salt);
665
    my $hashedPasswd = '{SSHA}' . encode_base64($ctx->digest . $salt ,'');
666
667
    return $hashedPasswd;
668
}
669
670
#
671
# Look up an ldap entry for a user
672
#
673
sub getLdapEntry {
674
    my $ldapurl = shift;
675
    my $base = shift;
676
    my $username = shift;
677
    my $org = shift;
678
679
    my $entry = "";
680
    my $mesg;
681 3177 tao
    my $ldap;
682 4749 walbridge
    debug("ldap server: $ldapurl");
683 4394 walbridge
684
    #if main ldap server is down, a html file containing warning message will be returned
685 4771 walbridge
    $ldap = Net::LDAP->new($ldapurl, timeout => $timeout) or handleLDAPBindFailure($ldapurl);
686 4849 daigle
687
    if ($ldap) {
688
    	$ldap->start_tls( verify => 'none');
689
    	my $bindresult = $ldap->bind;
690
    	if ($bindresult->code) {
691
        	return $entry;
692
    	}
693 2341 sgarg
694 4849 daigle
    	if($ldapConfig->{$org}{'filter'}){
695 4865 walbridge
            debug("getLdapEntry: filter set, searching for base=$base, " .
696
                  "(&(uid=$username)($ldapConfig->{$org}{'filter'})");
697 4849 daigle
        	$mesg = $ldap->search ( base   => $base,
698 4080 daigle
                filter => "(&(uid=$username)($ldapConfig->{$org}{'filter'}))");
699 4849 daigle
    	} else {
700 4865 walbridge
            debug("getLdapEntry: no filter, searching for $base, (uid=$username)");
701 4849 daigle
        	$mesg = $ldap->search ( base   => $base, filter => "(uid=$username)");
702
    	}
703 3177 tao
704 4849 daigle
    	if ($mesg->count > 0) {
705
        	$entry = $mesg->pop_entry;
706
        	$ldap->unbind;   # take down session
707
    	} else {
708
        	$ldap->unbind;   # take down session
709
        	# Follow references by recursive call to self
710
        	my @references = $mesg->references();
711
        	for (my $i = 0; $i <= $#references; $i++) {
712
            	my $uri = URI->new($references[$i]);
713
            	my $host = $uri->host();
714
            	my $path = $uri->path();
715
            	$path =~ s/^\///;
716
            	$entry = &getLdapEntry($host, $path, $username, $org);
717
            	if ($entry) {
718 4865 walbridge
                    debug("getLdapEntry: recursion found $host, $path, $username, $org");
719 4849 daigle
                	return $entry;
720
            	}
721
        	}
722
    	}
723 2341 sgarg
    }
724
    return $entry;
725
}
726
727
#
728
# send an email message notifying the user of the pw change
729
#
730
sub sendPasswordNotification {
731
    my $username = shift;
732
    my $org = shift;
733
    my $newPass = shift;
734
    my $recipient = shift;
735 2972 jones
    my $cfg = shift;
736 2341 sgarg
737
    my $errorMessage = "";
738
    if ($recipient) {
739 4771 walbridge
        my $mailhost = $properties->getProperty('email.mailhost');
740
        my $sender =  $properties->getProperty('email.sender');
741 2341 sgarg
        # Send the email message to them
742
        my $smtp = Net::SMTP->new($mailhost);
743
        $smtp->mail($sender);
744
        $smtp->to($recipient);
745
746
        my $message = <<"        ENDOFMESSAGE";
747
        To: $recipient
748
        From: $sender
749
        Subject: KNB Password Reset
750
751
        Somebody (hopefully you) requested that your KNB password be reset.
752
        This is generally done when somebody forgets their password.  Your
753
        password can be changed by visiting the following URL:
754
755 4864 walbridge
        $contextUrl/cgi-bin/ldapweb.cgi?stage=changepass&cfg=$cfg
756 2341 sgarg
757
            Username: $username
758
        Organization: $org
759
        New Password: $newPass
760
761
        Thanks,
762
            The KNB Development Team
763
764
        ENDOFMESSAGE
765
        $message =~ s/^[ \t\r\f]+//gm;
766
767
        $smtp->data($message);
768
        $smtp->quit;
769
    } else {
770
        $errorMessage = "Failed to send password because I " .
771
                        "couldn't find a valid email address.";
772
    }
773
    return $errorMessage;
774
}
775
776
#
777
# search the LDAP directory to see if a similar account already exists
778
#
779
sub findExistingAccounts {
780
    my $ldapurl = shift;
781
    my $base = shift;
782
    my $filter = shift;
783
    my $attref = shift;
784 3175 tao
    my $ldap;
785 4847 daigle
    my $mesg;
786 2341 sgarg
787
    my $foundAccounts = 0;
788 4749 walbridge
789 4394 walbridge
    #if main ldap server is down, a html file containing warning message will be returned
790 4868 walbridge
    debug("findExistingAccounts: connecting to $ldapurl, $timeout");
791 4771 walbridge
    $ldap = Net::LDAP->new($ldapurl, timeout => $timeout) or handleLDAPBindFailure($ldapurl);
792 4845 daigle
    if ($ldap) {
793
    	$ldap->start_tls( verify => 'none');
794
    	$ldap->bind( version => 3, anonymous => 1);
795 4848 daigle
		$mesg = $ldap->search (
796 4845 daigle
			base   => $base,
797
			filter => $filter,
798
			attrs => @$attref,
799
		);
800 2341 sgarg
801 4845 daigle
	    if ($mesg->count() > 0) {
802
			$foundAccounts = "";
803
			my $entry;
804
			foreach $entry ($mesg->all_entries) {
805 5650 walbridge
                # a fix to ignore 'ou=Account' properties which are not usable accounts within Metacat.
806
                # this could be done directly with filters on the LDAP connection, instead.
807
                if ($entry->dn !~ /ou=Account/) {
808
                    $foundAccounts .= "<p>\n<b><u>Account:</u> ";
809
                    $foundAccounts .= $entry->dn();
810
                    $foundAccounts .= "</b><br />\n";
811
                    foreach my $attribute ($entry->attributes()) {
812
                        my $value = $entry->get_value($attribute);
813
                        $foundAccounts .= "$attribute: ";
814
                        $foundAccounts .= $value;
815
                        $foundAccounts .= "<br />\n";
816
                    }
817
                    $foundAccounts .= "</p>\n";
818
                }
819 4845 daigle
			}
820 2341 sgarg
        }
821 4845 daigle
    	$ldap->unbind;   # take down session
822 2341 sgarg
823 4848 daigle
    	# Follow references
824
    	my @references = $mesg->references();
825
    	for (my $i = 0; $i <= $#references; $i++) {
826
        	my $uri = URI->new($references[$i]);
827
        	my $host = $uri->host();
828
        	my $path = $uri->path();
829
        	$path =~ s/^\///;
830
        	my $refFound = &findExistingAccounts($host, $path, $filter, $attref);
831
        	if ($refFound) {
832
            	$foundAccounts .= $refFound;
833
        	}
834
    	}
835 2341 sgarg
    }
836
837
    #print "<p>Checking referrals...</p>\n";
838
    #my @referrals = $mesg->referrals();
839
    #print "<p>Referrals count: ", scalar(@referrals), "</p>\n";
840
    #for (my $i = 0; $i <= $#referrals; $i++) {
841
        #print "<p>Referral: ", $referrals[$i], "</p>\n";
842
    #}
843
844
    return $foundAccounts;
845
}
846
847
#
848
# Validate that we have the proper set of input parameters
849
#
850
sub paramsAreValid {
851
    my @pnames = @_;
852
853
    my $allValid = 1;
854
    foreach my $parameter (@pnames) {
855
        if (!defined($query->param($parameter)) ||
856
            ! $query->param($parameter) ||
857
            $query->param($parameter) =~ /^\s+$/) {
858
            $allValid = 0;
859
        }
860
    }
861
862
    return $allValid;
863
}
864
865
#
866 8175 tao
# Create a temporary account for a user and send an email with a link which can click for the
867
# verification. This is used to protect the ldap server against spams.
868
#
869
sub createTemporaryAccount {
870
    my $allParams = shift;
871
    #my $org = $query->param('o');
872 8177 tao
    my $org = 'unaffiliated';
873 8176 tao
    my $ou = $query->param('ou');
874
    #my $ou = 'LTER';
875 8175 tao
    my $uid = $query->param('uid');
876
877
    #to see if the organizaton exist
878 8176 tao
    my $tmpSearchBase = 'dc=tmp,' . $authBase;
879 8175 tao
    print "Content-type: text/html\n\n";
880
881 8176 tao
    my $filter;
882
    # Search LDAP for matching o or ou that already exist
883
    if($org) {
884
        $filter = "(o"
885 8175 tao
                  . "=" . $org .
886
                 ")";
887 8176 tao
    } else {
888
        $filter = "(ou"
889
                  . "=" . $ou .
890
                 ")";
891
    }
892
    debug("search filer " . $filter);
893
    debug("ldap server ". $ldapurl);
894
    debug("sesarch base " . $tmpSearchBase);
895 8175 tao
    my @attrs = ['o', 'ou' ];
896
    my $found = searchDirectory($ldapurl, $tmpSearchBase, $filter, \@attrs);
897 8176 tao
    if(!$found) {
898
        #need to generate the subtree o or ou
899
        my $ldapUsername = $ldapConfig->{$org}{'user'};
900
        my $ldapPassword = $ldapConfig->{$org}{'password'};
901
        debug("LDAP connection to $ldapurl...");
902
        #if main ldap server is down, a html file containing warning message will be returned
903
        my $ldap = Net::LDAP->new($ldapurl, timeout => $timeout) or handleLDAPBindFailure($ldapurl);
904 8177 tao
        my $dn;
905 8176 tao
        if ($ldap) {
906
            $ldap->start_tls( verify => 'none');
907
            debug("Attempting to bind to LDAP server with dn = $ldapUsername, pwd = $ldapPassword");
908
            $ldap->bind( version => 3, dn => $ldapUsername, password => $ldapPassword );
909 8175 tao
910 8176 tao
            # Do the insertion
911
            my $additions;
912
             if($org) {
913
                $additions = [
914
                'o'   => $org,
915
                'objectclass' => ['top', 'organization']
916
                ];
917 8177 tao
                $dn='o=' . $org . ',' . $tmpSearchBase;
918 8176 tao
             } else {
919
                $additions = [
920
                'ou'   => $ou,
921
                'objectclass' => ['top', 'organizationalUnit']
922
                ];
923 8177 tao
                $dn='ou=' . $ou . ',' . $tmpSearchBase;
924 8176 tao
             }
925
926 8177 tao
            my $result = $ldap->add ( 'dn' => $dn, 'attr' => [ @$additions ]);
927 8176 tao
            if ($result->code()) {
928
                fullTemplate( ['registerFailed', 'register'], { stage => "register",
929
                                                            allParams => $allParams,
930
                                                            errorMessage => $result->error });
931
                # TODO SCW was included as separate errors, test this
932
                #$templateVars    = setVars({ stage => "register",
933
                #                     allParams => $allParams });
934
                #$template->process( $templates->{'register'}, $templateVars);
935
            }
936
            $ldap->unbind;   # take down session
937
         } else {
938
            fullTemplate( ['registerFailed', 'register'], { stage => "register",
939
                                                            allParams => $allParams,
940
                                                            errorMessage => "The ldap server is not available now. Please try it later"});
941
            exit(0);
942
         }
943
    }
944 8175 tao
945 8176 tao
946
947 8175 tao
    #$query->param('o','tmp');
948
    #createAccount($allParams);
949
    #$query->param('o',$org);
950
    #constrct url
951
    #my $link =
952
    #print "Content-type: text/html\n\n";
953
    #print $query->param('o');
954
}
955
956
#
957 2341 sgarg
# Bind to LDAP and create a new account using the information provided
958
# by the user
959
#
960
sub createAccount {
961
    my $allParams = shift;
962
963
    if ($query->param('o') =~ "LTER") {
964 4080 daigle
        fullTemplate( ['registerLter'] );
965 2341 sgarg
    } else {
966
967
        # Be sure the passwords match
968
        if ($query->param('userPassword') !~ $query->param('userPassword2')) {
969
            my $errorMessage = "The passwords do not match. Try again.";
970 4080 daigle
            fullTemplate( ['registerFailed', 'register'], { stage => "register",
971
                                                            allParams => $allParams,
972
                                                            errorMessage => $errorMessage });
973
            exit();
974 2341 sgarg
        }
975
976 2972 jones
        my $o = $query->param('o');
977 2341 sgarg
978 4080 daigle
        my $searchBase = $ldapConfig->{$o}{'base'};
979
        my $dnBase = $ldapConfig->{$o}{'dn'};
980 8177 tao
        debug("the dn is " . $dnBase);
981 4868 walbridge
        my $ldapUsername = $ldapConfig->{$o}{'user'};
982 4749 walbridge
        my $ldapPassword = $ldapConfig->{$o}{'password'};
983 4771 walbridge
        debug("LDAP connection to $ldapurl...");
984 3177 tao
        #if main ldap server is down, a html file containing warning message will be returned
985 4771 walbridge
        my $ldap = Net::LDAP->new($ldapurl, timeout => $timeout) or handleLDAPBindFailure($ldapurl);
986 3177 tao
987 4849 daigle
        if ($ldap) {
988
        	$ldap->start_tls( verify => 'none');
989
        	debug("Attempting to bind to LDAP server with dn = $ldapUsername, pwd = $ldapPassword");
990
        	$ldap->bind( version => 3, dn => $ldapUsername, password => $ldapPassword );
991 3177 tao
992 4849 daigle
        	my $dn = 'uid=' . $query->param('uid') . ',' . $dnBase;
993
        	debug("Inserting new entry for: $dn");
994 2341 sgarg
995 4849 daigle
        	# Create a hashed version of the password
996
        	my $shapass = createSeededPassHash($query->param('userPassword'));
997 2341 sgarg
998 4849 daigle
        	# Do the insertion
999
        	my $additions = [
1000 2341 sgarg
                'uid'   => $query->param('uid'),
1001
                'o'   => $query->param('o'),
1002
                'cn'   => join(" ", $query->param('givenName'),
1003
                                    $query->param('sn')),
1004
                'sn'   => $query->param('sn'),
1005
                'givenName'   => $query->param('givenName'),
1006
                'mail' => $query->param('mail'),
1007
                'userPassword' => $shapass,
1008
                'objectclass' => ['top', 'person', 'organizationalPerson',
1009
                                'inetOrgPerson', 'uidObject' ]
1010 4849 daigle
            	];
1011
        	if (defined($query->param('telephoneNumber')) &&
1012
            	$query->param('telephoneNumber') &&
1013
            	! $query->param('telephoneNumber') =~ /^\s+$/) {
1014
            	$$additions[$#$additions + 1] = 'telephoneNumber';
1015
            	$$additions[$#$additions + 1] = $query->param('telephoneNumber');
1016
        	}
1017
        	if (defined($query->param('title')) &&
1018
            	$query->param('title') &&
1019
            	! $query->param('title') =~ /^\s+$/) {
1020
            	$$additions[$#$additions + 1] = 'title';
1021
            	$$additions[$#$additions + 1] = $query->param('title');
1022
        	}
1023
        	my $result = $ldap->add ( 'dn' => $dn, 'attr' => [ @$additions ]);
1024 2341 sgarg
1025 4849 daigle
        	if ($result->code()) {
1026
            	fullTemplate( ['registerFailed', 'register'], { stage => "register",
1027 4080 daigle
                                                            allParams => $allParams,
1028
                                                            errorMessage => $result->error });
1029 4849 daigle
            	# TODO SCW was included as separate errors, test this
1030
           	 	#$templateVars    = setVars({ stage => "register",
1031
           	 	#                     allParams => $allParams });
1032
            	#$template->process( $templates->{'register'}, $templateVars);
1033
        	} else {
1034
            	fullTemplate( ['success'] );
1035
        	}
1036
1037
        	$ldap->unbind;   # take down session
1038 2341 sgarg
        }
1039
    }
1040
}
1041
1042
sub handleResponseMessage {
1043
1044
  print "Content-type: text/html\n\n";
1045
  my $errorMessage = "You provided invalid input to the script. " .
1046
                     "Try again please.";
1047 4080 daigle
  fullTemplate( [], { stage => $templates->{'stage'},
1048
                      errorMessage => $errorMessage });
1049
  exit();
1050 2341 sgarg
}
1051
1052
#
1053
# perform a simple search against the LDAP database using
1054
# a small subset of attributes of each dn and return it
1055
# as a table to the calling browser.
1056
#
1057
sub handleSimpleSearch {
1058
1059
    my $o = $query->param('o');
1060
1061 4080 daigle
    my $ldapurl = $ldapConfig->{$o}{'url'};
1062
    my $searchBase = $ldapConfig->{$o}{'base'};
1063 2341 sgarg
1064
    print "Content-type: text/html\n\n";
1065
1066
    my $allParams = {
1067
                      'cn' => $query->param('cn'),
1068
                      'sn' => $query->param('sn'),
1069
                      'gn' => $query->param('gn'),
1070
                      'o'  => $query->param('o'),
1071
                      'facsimiletelephonenumber'
1072
                      => $query->param('facsimiletelephonenumber'),
1073
                      'mail' => $query->param('cmail'),
1074
                      'telephonenumber' => $query->param('telephonenumber'),
1075
                      'title' => $query->param('title'),
1076
                      'uid' => $query->param('uid'),
1077
                      'ou' => $query->param('ou'),
1078
                    };
1079
1080
    # Search LDAP for matching entries that already exist
1081
    my $filter = "(" .
1082
                 $query->param('searchField') . "=" .
1083
                 "*" .
1084
                 $query->param('searchValue') .
1085
                 "*" .
1086
                 ")";
1087
1088
    my @attrs = [ 'sn',
1089
                  'gn',
1090
                  'cn',
1091
                  'o',
1092
                  'facsimiletelephonenumber',
1093
                  'mail',
1094
                  'telephoneNumber',
1095
                  'title',
1096
                  'uid',
1097
                  'labeledURI',
1098
                  'ou' ];
1099
1100
    my $found = searchDirectory($ldapurl, $searchBase, $filter, \@attrs);
1101
1102
    # Send back the search results
1103
    if ($found) {
1104 4080 daigle
      fullTemplate( ('searchResults'), { stage => "searchresults",
1105
                                         allParams => $allParams,
1106
                                         foundAccounts => $found });
1107 2341 sgarg
    } else {
1108
      $found = "No entries matched your criteria.  Please try again\n";
1109
1110 4080 daigle
      fullTemplate( ('searchResults'), { stage => "searchresults",
1111
                                         allParams => $allParams,
1112
                                         foundAccounts => $found });
1113 2341 sgarg
    }
1114
1115
    exit();
1116
}
1117
1118
#
1119
# search the LDAP directory to see if a similar account already exists
1120
#
1121
sub searchDirectory {
1122
    my $ldapurl = shift;
1123
    my $base = shift;
1124
    my $filter = shift;
1125
    my $attref = shift;
1126
1127 4849 daigle
	my $mesg;
1128 2341 sgarg
    my $foundAccounts = 0;
1129 3177 tao
1130
    #if ldap server is down, a html file containing warning message will be returned
1131 4771 walbridge
    my $ldap = Net::LDAP->new($ldapurl, timeout => $timeout) or handleLDAPBindFailure($ldapurl);
1132 3177 tao
1133 4849 daigle
    if ($ldap) {
1134
    	$ldap->start_tls( verify => 'none');
1135
    	$ldap->bind( version => 3, anonymous => 1);
1136
    	my $mesg = $ldap->search (
1137
        	base   => $base,
1138
        	filter => $filter,
1139
        	attrs => @$attref,
1140
    	);
1141 2341 sgarg
1142 4849 daigle
    	if ($mesg->count() > 0) {
1143
        	$foundAccounts = "";
1144
        	my $entry;
1145
        	foreach $entry ($mesg->sorted(['sn'])) {
1146
          		$foundAccounts .= "<tr>\n<td class=\"main\">\n";
1147
          		$foundAccounts .= "<a href=\"" unless
1148 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1149 4849 daigle
         		 $foundAccounts .= $entry->get_value('labeledURI') unless
1150 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1151 4849 daigle
          		$foundAccounts .= "\">\n" unless
1152 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1153 4849 daigle
          		$foundAccounts .= $entry->get_value('givenName');
1154
          		$foundAccounts .= "</a>\n" unless
1155 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1156 4849 daigle
          		$foundAccounts .= "\n</td>\n<td class=\"main\">\n";
1157
          		$foundAccounts .= "<a href=\"" unless
1158 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1159 4849 daigle
          		$foundAccounts .= $entry->get_value('labeledURI') unless
1160 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1161 4849 daigle
          		$foundAccounts .= "\">\n" unless
1162 2341 sgarg
                    (!$entry->get_value('labeledURI'));
1163 4849 daigle
          		$foundAccounts .= $entry->get_value('sn');
1164
          		$foundAccounts .= "</a>\n";
1165
          		$foundAccounts .= "\n</td>\n<td class=\"main\">\n";
1166
          		$foundAccounts .= $entry->get_value('mail');
1167
          		$foundAccounts .= "\n</td>\n<td class=\"main\">\n";
1168
          		$foundAccounts .= $entry->get_value('telephonenumber');
1169
          		$foundAccounts .= "\n</td>\n<td class=\"main\">\n";
1170
          		$foundAccounts .= $entry->get_value('title');
1171
          		$foundAccounts .= "\n</td>\n<td class=\"main\">\n";
1172
          		$foundAccounts .= $entry->get_value('ou');
1173
          		$foundAccounts .= "\n</td>\n";
1174
          		$foundAccounts .= "</tr>\n";
1175
        	}
1176
    	}
1177
    	$ldap->unbind;   # take down session
1178 2341 sgarg
    }
1179
    return $foundAccounts;
1180
}
1181
1182
sub debug {
1183
    my $msg = shift;
1184
1185
    if ($debug) {
1186 4747 walbridge
        print STDERR "LDAPweb: $msg\n";
1187 2341 sgarg
    }
1188
}
1189 3175 tao
1190 4771 walbridge
sub handleLDAPBindFailure {
1191
    my $ldapAttemptUrl = shift;
1192
    my $primaryLdap =  $properties->getProperty('auth.url');
1193
1194
    if ($ldapAttemptUrl eq  $primaryLdap) {
1195
        handleGeneralServerFailure("The main LDAP server $ldapurl is down!");
1196
    } else {
1197
        debug("attempted to bind to nonresponsive LDAP server $ldapAttemptUrl, skipped.");
1198
    }
1199
}
1200
1201 3177 tao
sub handleGeneralServerFailure {
1202
    my $errorMessage = shift;
1203 4728 walbridge
    fullTemplate( ['mainServerFailure'], { errorMessage => $errorMessage });
1204 3175 tao
    exit(0);
1205
   }
1206
1207 4080 daigle
sub setVars {
1208
    my $paramVars = shift;
1209
    # initialize default parameters
1210
    my $templateVars = { cfg => $cfg,
1211 4394 walbridge
                         styleSkinsPath => $contextUrl . "/style/skins",
1212
                         styleCommonPath => $contextUrl . "/style/common",
1213
                         contextUrl => $contextUrl,
1214 4770 daigle
                         cgiPrefix => $cgiPrefix,
1215 4080 daigle
                         orgList => \@orgList,
1216 4394 walbridge
                         config  => $config,
1217 4080 daigle
    };
1218
1219
    # append customized params
1220
    while (my ($k, $v) = each (%$paramVars)) {
1221
        $templateVars->{$k} = $v;
1222
    }
1223
1224
    return $templateVars;
1225
}