The directory information (department, company, etc.) can be changed from the defaults shown below. The changes will apply only to this user. END_TEXT esmith::cgi5::genHeaderNonCacheable ($q, \%conf, 'Create a new user account'); print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1)); print $q->table ({border => 0, cellspacing => 0, cellpadding => 4}, esmith::cgi5::genTextRow ($q, $q->p ($description)), esmith::cgi5::genNameValueRow ($q, "Account name", "acctName", ""), esmith::cgi5::genNameValueRow ($q, "First name", "firstName", ""), esmith::cgi5::genNameValueRow ($q, "Last name", "lastName", ""), esmith::cgi5::genNameValueRow ($q, "Department", "department", db_get_prop (\%conf, 'ldap', 'defaultDepartment')), esmith::cgi5::genNameValueRow ($q, "Company", "company", db_get_prop (\%conf, 'ldap', 'defaultCompany')), esmith::cgi5::genNameValueRow ($q, "Street address", "street", db_get_prop (\%conf, 'ldap', 'defaultStreet')), esmith::cgi5::genNameValueRow ($q, "City", "city", db_get_prop (\%conf, 'ldap', 'defaultCity')), esmith::cgi5::genNameValueRow ($q, "Phone number", "phone", db_get_prop (\%conf, 'ldap', 'defaultPhoneNumber')), $q->Tr (esmith::cgi5::genCell ($q, "E-mail delivery:"), genEmailForward ($q, '')), esmith::cgi5::genNameValueRow ($q, "Forwarding address", "forwardAddress", ""), esmith::cgi5::genWidgetRow ($q, "VPN Client Access", $q->popup_menu (-name => 'VPNClientAccess', -values => ['no','yes'])), esmith::cgi5::genTextRow ($q, $q->p ("This user will be added to the $fGroup Group")), esmith::cgi5::genButtonRow ($q, $q->submit (-name => 'action', -value => 'Create'))); print $q->hidden (-name => 'groupMemberships', -override => 1, -default => $fGroup); print $q->hidden (-name => 'state', -override => 1, -default => 'performCreate'); print $q->endform; print $q->endform; # print $q->p ($q->hr, $q->font ({size => "-1"}, "www.dungog.net/sme")); esmith::cgi::genFooter($q); print ''; print ''; print $q->end_html; #esmith::cgi5::genFooter ($q); return; } #------------------------------------------------------------ # #------------------------------------------------------------ sub performCreateUser ($) { my ($q) = @_; #------------------------------------------------------------ # Validate parameters and untaint them #------------------------------------------------------------ my $acctName = $q->param ('acctName'); if ($acctName =~ /^([a-z][\-a-z0-9]*)$/) { $acctName = $1; } else { showInitial ($q, "Error: unexpected characters in account name: " . "\"$acctName\". The account name should contain only " . "lower-case letters, numbers, and hyphens, and should " . "start with a lower-case letter. For example \"betty\", " . "\"hjohnson\", and \"mary-jane\" are all valid account " . "names, but \"3friends\", \"John Smith\" and " . "\"henry_miller\" are not.",""); return; } my $maxAcctNameLength = defined $conf{'maxAcctNameLength'} ? $conf{'maxAcctNameLength'} : 12; if (length $acctName > $maxAcctNameLength) { showInitial ($q, "Error: account name " . "\"$acctName\" is too long. " . "The maximum is $maxAcctNameLength characters.",""); return; } my $firstName = $q->param ('firstName'); if ($firstName =~ /^\s*([a-zA-Z0-9\'\.\-\s]+?)\s*$/) { $firstName = $1; } else { showInitial ($q, "Error: unexpected or missing characters in first name: " . "\"$firstName\". Did not create new account.",""); return; } my $lastName = $q->param ('lastName'); if ($lastName =~ /^\s*([a-zA-Z0-9\'\.\-\s]+?)\s*$/) { $lastName = $1; } else { showInitial ($q, "Error: unexpected or missing characters in last name: " . "\"$lastName\". Did not create new account.",""); return; } my $department = $q->param ('department'); if ($department =~ /^([^\|]*)$/) { $department = $1; } else { showInitial ($q, "Error: unexpected characters in department: " . "\"$department\". Did not create new account.",""); return; } my $company = $q->param ('company'); if ($company =~ /^([^\|]*)$/) { $company = $1; } else { showInitial ($q, "Error: unexpected characters in company: " . "\"$company\". Did not create new account.",""); return; } my $street = $q->param ('street'); if ($street =~ /^([^\|]*)$/) { $street = $1; } else { showInitial ($q, "Error: unexpected characters in street address: " . "\"$street\". Did not create new account.",""); return; } my $city = $q->param ('city'); if ($city =~ /^([^\|]*)$/) { $city = $1; } else { showInitial ($q, "Error: unexpected characters in city: " . "\"$city\". Did not create new account.",""); return; } my $phone = $q->param ('phone'); if ($phone =~ /^([^\|]*)$/) { $phone = $1; } else { showInitial ($q, "Error: unexpected characters in phone number: " . "\"$phone\". Did not create new account.",""); return; } my $emailForward = $q->param ('emailForward'); if ($emailForward =~ /^(.*)$/) { $emailForward = $1; } else { $emailForward = ""; } my $VPNClientAccess = $q->param ('VPNClientAccess'); my $forwardAddress = $q->param ('forwardAddress'); if (($emailForward eq 'local') && ($forwardAddress =~ /^([^\|]*)$/)) { $forwardAddress = $1; } elsif (($emailForward eq 'forward') && ($forwardAddress =~ /^([^\|]+)$/)) { $forwardAddress = $1; } elsif (($emailForward eq 'both') && ($forwardAddress =~ /^([^\|]+)$/)) { $forwardAddress = $1; } else { showInitial ($q, "Error: unexpected or missing characters in email forwarding address: " . "\"$forwardAddress\". Did not create new account.",""); return; } my ($dot_pseudonym, $underbar_pseudonym) = makePseudonyms($firstName, $lastName); #------------------------------------------------------------ # Looks good. Find out if this account has been taken or there is # a name clash with the pseudonyms #------------------------------------------------------------ if (db_get(\%accounts, $acctName)) { my $type = db_get_type(\%accounts, $acctName); if ($type eq "pseudonym") { my $acct = db_get_prop(\%accounts, $acctName, "Account"); my $acct_type = db_get_type(\%accounts, $acct); showInitial ($q, "Error: account \"$acctName\" clashes with pseudonym" . " details for $acct_type account \"$acct\"." . "
$acctName is a pseudonym for $acct.
","" ); } else { showInitial ($q, "Error: account \"$acctName\" is an existing" . " $type account.","" ); } return; } if (db_get(\%accounts, $dot_pseudonym)) { my $type = db_get_type(\%accounts, $dot_pseudonym); if ($type eq "pseudonym") { my $acct = db_get_prop(\%accounts, $dot_pseudonym, "Account"); my $acct_type = db_get_type(\%accounts, $acct); showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with pseudonym details for" . " $acct_type account \"$acct\"." . "$dot_pseudonym is a pseudonym for $acct.
","" ); } else { showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with an existing $type" . " account $dot_pseudonym.","" ); } return; } if (db_get(\%accounts, $underbar_pseudonym)) { my $type = db_get_type(\%accounts, $underbar_pseudonym); if ($type eq "pseudonym") { my $acct = db_get_prop(\%accounts, $underbar_pseudonym, "Account"); my $acct_type = db_get_type(\%accounts, $acct); showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with pseudonym details for" . " $acct_type account \"$acct\"." . "$underbar_pseudonym is a pseudonym for $acct.
","" ); } else { showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with an existing $type" . " account $underbar_pseudonym.","" ); } return; } my $userID = getNextFreeID(); #------------------------------------------------------------ # Account is available! Update accounts database. #------------------------------------------------------------ db_set(\%accounts, $acctName, "user", { 'FirstName' => $firstName, 'LastName' => $lastName, 'Phone' => $phone, 'Company' => $company, 'Dept' => $department, 'City' => $city, 'Street' => $street, 'EmailForward' => $emailForward, 'ForwardAddress' => $forwardAddress, 'VPNClientAccess' => $VPNClientAccess, 'PasswordSet' => "no", 'Uid' => $userID, 'Gid' => $userID } ); db_set(\%accounts, $dot_pseudonym, 'pseudonym', { Account => $acctName } ) or die ("Error occurred while creating pseudonym in database.\n"); db_set(\%accounts, $underbar_pseudonym, 'pseudonym', { Account => $acctName } ) or die ("Error occurred while creating pseudonym in database.\n"); #------------------------------------------------------------ # Signal the create-user event. #------------------------------------------------------------ untie %accounts; system ("/sbin/e-smith/signal-event", "user-create", "$acctName") == 0 or die ("Error occurred while creating user.\n"); tie %accounts, 'esmith::config', '/home/e-smith/db/accounts'; #------------------------------------------------------------ # Add user to any relevant groups #------------------------------------------------------------ my @groups = $q->param ('groupMemberships'); my $group; foreach $group (@groups) { # untaint group so that we can use it in "system" call later if ($group =~ /^(.*)$/) { $group = $1; } else { $group = ""; } db_set_prop(\%accounts, $group, "Members", db_get_prop(\%accounts, $group, "Members") . ",$acctName"); untie %accounts; system ("/sbin/e-smith/signal-event", "group-modify", "$group") == 0 or warn ("Error occurred while updating group.\n"); tie %accounts, 'esmith::config', '/home/e-smith/db/accounts'; } showInitial ($q, "Successfully created user account $acctName.",""); } #------------------------------------------------------------ # #------------------------------------------------------------ sub modifyUser ($) { my ($q) = @_; esmith::cgi5::genHeaderNonCacheable ($q, \%conf, 'Modify user account'); print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1)); my $acct = $q->param ('acct'); my $fGroup = $q->param ('fGroup'); db_set(\%conf, 'fGroup', $fGroup); my $acctN = $ENV{'REMOTE_USER'}; print $q->table ({border => 0, cellspacing => 0, cellpadding => 4}, $q->Tr (esmith::cgi5::genCell ($q, "Account name:"), esmith::cgi5::genCell ($q, $acct)), esmith::cgi5::genNameValueRow ($q, "First name", "firstName", db_get_prop(\%accounts, $acct, "FirstName") ), esmith::cgi5::genNameValueRow ($q, "Last name", "lastName", db_get_prop(\%accounts, $acct, "LastName") ), esmith::cgi5::genNameValueRow ($q, "Department", "department", db_get_prop(\%accounts, $acct, "Dept") ), esmith::cgi5::genNameValueRow ($q, "Company", "company", db_get_prop(\%accounts, $acct, "Company") ), esmith::cgi5::genNameValueRow ($q, "Street address", "street", db_get_prop(\%accounts, $acct, "Street") ), esmith::cgi5::genNameValueRow ($q, "City", "city", db_get_prop(\%accounts, $acct, "City") ), esmith::cgi5::genNameValueRow ($q, "Phone number", "phone", db_get_prop(\%accounts, $acct, "Phone") ), $q->Tr ( esmith::cgi5::genCell ($q, "E-mail delivery:"), genEmailForward ( $q, db_get_prop(\%accounts, $acct, "EmailForward") ) ), esmith::cgi5::genNameValueRow ($q, "Forwarding address", "forwardAddress", db_get_prop(\%accounts, $acct, "ForwardAddress") ), $q->Tr (esmith::cgi5::genWidgetRow ($q, "VPN Client Access", $q->popup_menu (-name => 'VPNClientAccess', -values => ['no','yes'] , -default => db_get_prop (\%accounts, $acct, "VPNClientAccess")))), #esmith::cgi5::genTextRow ($q, # $q->p ("This user is in the $fGroup Group.")), esmith::cgi5::genButtonRow ($q, $q->submit (-name => 'action', -value => 'Modify'))); #print $q->hidden (-name => 'groupMemberships', -override => 1, -default => 'nochange'); print $q->hidden (-name => 'fGroup', -override => 1, -default => $fGroup); print $q->hidden (-name => 'acctName', -override => 1, -default => $acct); print $q->hidden (-name => 'state', -override => 1, -default => 'performModify'); print $q->endform; # print $q->p ($q->hr, $q->font ({size => "-1"}, "www.dungog.net/sme")); esmith::cgi::genFooter($q); print ''; print ''; print $q->end_html; #esmith::cgi5::genFooter ($q); return; } #------------------------------------------------------------ # #------------------------------------------------------------ sub performModifyUser ($) { my ($q) = @_; #------------------------------------------------------------ # Validate parameters and untaint them #------------------------------------------------------------ my $acctName = $q->param ('acctName'); if ($acctName =~ /^([a-z][\-\_\.a-z0-9]*)$/) { $acctName = $1; } else { showInitial ($q, "Error: unexpected characters in account name:" . " \"$acctName\". The account name should contain only" . " lower-case letters, numbers, hyphens, periods, and" . " underscores, and should start with a lower-case" . " letter. For example \"betty\", \"hjohnson\", and" . " \"john.smith\" are all valid account names, but" . " \"3friends\", \"John Smith\" and \"Henry-Miller\"" . " are not.","" ); return; } #------------------------------------------------------------ # Looks good. Make sure this is a valid account #------------------------------------------------------------ unless (exists $accounts {$acctName}) { showInitial ($q, "Error: account \"$acctName\" is not an existing account.",""); return; } my $firstName = $q->param ('firstName'); if ($firstName =~ /^\s*([a-zA-Z0-9\'\.\-\s]+?)\s*$/) { $firstName = $1; } else { showInitial ($q, "Error: unexpected or missing characters in first name: " . "\"$firstName\". Did not modify account.",""); return; } my $lastName = $q->param ('lastName'); if ($lastName =~ /^\s*([a-zA-Z0-9\'\.\-\s]+?)\s*$/) { $lastName = $1; } else { showInitial ($q, "Error: unexpected or missing characters in last name: " . "\"$lastName\". Did not modify account.",""); return; } my $department = $q->param ('department'); if ($department =~ /^([^\|]*)$/) { $department = $1; } else { showInitial ($q, "Error: unexpected characters in department: " . "\"$department\". Did not modify account.",""); return; } my $company = $q->param ('company'); if ($company =~ /^([^\|]*)$/) { $company = $1; } else { showInitial ($q, "Error: unexpected characters in company: " . "\"$company\". Did not modify account.",""); return; } my $street = $q->param ('street'); if ($street =~ /^([^\|]*)$/) { $street = $1; } else { showInitial ($q, "Error: unexpected characters in street address: " . "\"$street\". Did not modify account.",""); return; } my $city = $q->param ('city'); if ($city =~ /^([^\|]*)$/) { $city = $1; } else { showInitial ($q, "Error: unexpected characters in city: " . "\"$city\". Did not modify account.",""); return; } my $phone = $q->param ('phone'); if ($phone =~ /^([^\|]*)$/) { $phone = $1; } else { showInitial ($q, "Error: unexpected characters in phone number: " . "\"$phone\". Did not modify account.",""); return; } my $emailForward = $q->param ('emailForward'); if ($emailForward =~ /^(.*)$/) { $emailForward = $1; } else { $emailForward = ""; } my $VPNClientAccess = $q->param ('VPNClientAccess'); my $forwardAddress = $q->param ('forwardAddress'); if (($emailForward eq 'local') && ($forwardAddress =~ /^([^\|]*)$/)) { $forwardAddress = $1; } elsif (($emailForward eq 'forward') && ($forwardAddress =~ /^([^\|]+)$/)) { $forwardAddress = $1; } elsif (($emailForward eq 'both') && ($forwardAddress =~ /^([^\|]+)$/)) { $forwardAddress = $1; } else { showInitial ($q, "Error: unexpected or missing characters in email forwarding address: " . "\"$forwardAddress\". Did not create new account.",""); return; } my ($dot_pseudonym, $underbar_pseudonym) = makePseudonyms($firstName, $lastName); unless (db_get_type(\%accounts, $acctName) eq "user") { showInitial ( $q, "Error: account \"$acctName\" is not an existing user account.","" ); return; } #------------------------------------------------------------ # Looks good. Find out if there is a name clash with the pseudonyms. #------------------------------------------------------------ if (db_get(\%accounts, $dot_pseudonym)) { my $type = db_get_type(\%accounts, $dot_pseudonym); if ($type eq "pseudonym") { my $acct = db_get_prop(\%accounts, $dot_pseudonym, "Account"); my $acct_type = db_get_type(\%accounts, $acct); unless ($acct eq $acctName) { showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with pseudonym details for" . " $acct_type account \"$acct\"." . "$dot_pseudonym is a pseudonym for $acct.
","" ); return; } } else { showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with an existing $type" . " account $dot_pseudonym.","" ); return; } } if (db_get(\%accounts, $underbar_pseudonym)) { my $type = db_get_type(\%accounts, $underbar_pseudonym); if ($type eq "pseudonym") { my $acct = db_get_prop(\%accounts, $underbar_pseudonym, "Account"); my $acct_type = db_get_type(\%accounts, $acct); unless ($acct eq $acctName) { showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with pseudonym details for" . " $acct_type account \"$acct\"." . "$underbar_pseudonym is a" . " pseudonym for $acct.
","" ); return; } } else { showInitial ($q, "Error: first and last name details for account" . " \"$acctName\" clash with an existing $type" . " account $underbar_pseudonym.","" ); return; } } #------------------------------------------------------------ # Update accounts database and signal the user-modify event. #------------------------------------------------------------ # First we need to remember the old first.last and first_last pseudonyms # for this user. my ($old_dot_pseudonym, $old_underbar_pseudonym) = makePseudonyms( db_get_prop(\%accounts, $acctName, 'FirstName'), db_get_prop(\%accounts, $acctName, 'LastName'), ); #------------------------------------------------------------ # Now we can update the user and the pseudonyms #------------------------------------------------------------ my ($acctType, %oldProperties) = db_get(\%accounts, $acctName); my %newProperties = ( 'FirstName' => $firstName, 'LastName' => $lastName, 'Phone' => $phone, 'Company' => $company, 'Dept' => $department, 'City' => $city, 'Street' => $street, 'EmailForward' => $emailForward, 'ForwardAddress' => $forwardAddress, 'VPNClientAccess' => $VPNClientAccess, ); db_set(\%accounts, $acctName, "user", { %oldProperties, %newProperties } ); unless ( $old_dot_pseudonym eq $dot_pseudonym ) { db_delete(\%accounts, $old_dot_pseudonym); db_set(\%accounts, $dot_pseudonym, 'pseudonym', { Account => $acctName } ) or die ("Error occurred while creating pseudonym in database.\n"); } unless ( $old_underbar_pseudonym eq $underbar_pseudonym ) { db_delete(\%accounts, $old_underbar_pseudonym); db_set(\%accounts, $underbar_pseudonym, 'pseudonym', { Account => $acctName } ) or die ("Error occurred while creating pseudonym in database.\n"); } untie %accounts; system ("/sbin/e-smith/signal-event", "user-modify", "$acctName") == 0 or die ("Error occurred while modifying user.\n"); esmith::cgi5::genHeaderNonCacheable ($q, \%conf, "Operation status report."); esmith::cgi5::genResult ($q, "Successfully modified user account $acctName. refresh"); } #------------------------------------------------------------ # #------------------------------------------------------------ sub deleteUser ($) { my ($q) = @_; my $fGroup = $q->param ('fGroup'); db_set(\%conf, 'fGroup', $fGroup); esmith::cgi5::genHeaderNonCacheable ($q, \%conf, 'Remove user account'); print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1)); my $acct = $q->param ('acct'); my $value = $accounts {$acct}; if ($value) { my ($type, %properties) = split (/\|/, $value, -1); my $name = $properties {'FirstName'} . ' ' . $properties {'LastName'}; print $q->p ('You are about to remove the user account "' . $acct . '" (user name "' . $name . '").'); print $q->p ('All files belonging to this user account will be', 'deleted. Also, any e-mail for this user account still', 'remaining on the server (i.e. that has not yet been', 'retrieved by the user) will be discarded.'); print $q->p ($q->b ('Are you sure you wish to remove this account?')); print $q->submit (-name => 'action', -value => 'Remove'); print $q->hidden (-name => 'acct', -override => 1, -default => $acct); print $q->hidden (-name => 'state', -override => 1, -default => 'performDelete'); } print $q->endform; esmith::cgi::genFooter($q); return; } #------------------------------------------------------------ # #------------------------------------------------------------ sub performDeleteUser ($) { my ($q) = @_; #------------------------------------------------------------ # Attempt to delete user #------------------------------------------------------------ my $acct = $q->param ('acct'); if ($acct =~ /^([a-z][\-\_\.a-z0-9]*)$/) { $acct = $1; } else { showInitial ($q, 'Error: internal failure while removing account "' . $acct . '".',""); return; } unless (db_get_type(\%accounts, $acct) eq "user") { showInitial ( $q, "Error: account \"$acct\" is not an existing user account." ,"" ); return; } db_set_type(\%accounts, $acct, "user-deleted"); #------------------------------------------------------------ # First, find all "group" entries in the e-smith accounts database # that contain this user. #------------------------------------------------------------ my $key; my $value; my @groups = (); while (($key,$value) = each %accounts) { my ($type, %properties) = split (/\|/, $value, -1); if ($type eq 'group') { #-------------------------------------------------- # Get a list of members and count the number of # occurrences of this username. If greater than zero, # add this group to the list. #-------------------------------------------------- my $count = grep (/^$acct$/, split (/,/, $properties {'Members'})); if ($count > 0) { push (@groups, $key); } } } #------------------------------------------------------------ # Next, for each group remove this user from the members list. # Then signal the group-modify event so that the group is brought # up to date. Make sure each group has at least one member; if # the list is empty, add in user "admin". #------------------------------------------------------------ my $group; foreach $group (@groups) { my $value = $accounts {$group}; my ($type, %properties) = split (/\|/, $value, -1); my @members = split (/,/, $properties {'Members'}); @members = grep (!/^$acct$/, @members); my $count = @members; if ($count == 0) { @members = ('admin'); } $properties{'Members'} = join(',', @members); $accounts {$group} = "group|" . join ('|', %properties); system ("/sbin/e-smith/signal-event", "group-modify", "$group") == 0 or warn ("Error occurred while updating group.\n"); } #------------------------------------------------------------ # Remove any pseudonyms associated with this user #------------------------------------------------------------ foreach (db_get(\%accounts)) { if (db_get_type(\%accounts, $_) eq "pseudonym") { if (db_get_prop(\%accounts, $_, "Account") eq $acct) { db_delete(\%accounts, $_); } } } #------------------------------------------------------------ # Finally signal user-delete event #------------------------------------------------------------ untie %accounts; system ("/sbin/e-smith/signal-event", "user-delete", "$acct");# == 0 #gives error, dunno why ? #or die ("Error occurred while deleting user.\n"); tie %accounts, 'esmith::config', '/home/e-smith/db/accounts'; delete $accounts {$acct}; showInitial ($q, "Successfully deleted user account $acct.",""); } #------------------------------------------------------------ # #------------------------------------------------------------ sub passwdUser ($) { my ($q) = @_; my $fGroup = $q->param ('fGroup'); db_set(\%conf, 'fGroup', $fGroup); esmith::cgi5::genHeaderNonCacheable ($q, \%conf, 'Reset password for user account'); print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1)); my $acct = $q->param ('acct'); my $value = $accounts {$acct}; if ($value) { my ($type, %properties) = split (/\|/, $value, -1); my $name = $properties {'FirstName'} . ' ' . $properties {'LastName'}; print $q->table ({border => 0, cellspacing => 0, cellpadding => 4}, esmith::cgi5::genTextRow ($q, $q->p ('You are about to change the password for the user', "account \"$acct\" (user name \"$name\").")), esmith::cgi5::genNamePasswdRow ($q, "New password", "newPass", ""), esmith::cgi5::genNamePasswdRow ($q, "New password (verify)", "newPassVerify", ""), esmith::cgi5::genButtonRow ($q, $q->submit (-name => 'action', -value => 'Change'))); print $q->hidden (-name => 'acct', -override => 1, -default => $acct); print $q->hidden (-name => 'state', -override => 1, -default => 'performPasswd'); } print $q->endform; esmith::cgi::genFooter($q); return; } #------------------------------------------------------------ # Attempt to change user password #------------------------------------------------------------ sub performPasswdUser ($) { my ($q) = @_; my $acct = $q->param ('acct') || "1" ; my $newPass = $q->param ('newPass') || "3"; my $newPassVerify = $q->param ('newPassVerify') || "4"; if ($acct =~ /^([a-z][\-\_\.a-z0-9]*)$/) { $acct = $1; } else { showInitial ($q, 'Error: invalid account "' . $acct . '".',""); return; } #verify data entry if ($newPass =~ /^([ -~]+)$/) { $newPass = $1; } else { showInitial ($q, 'Error: new password must contain only printable characters.',""); return; } if ($newPassVerify =~ /^([ -~]+)$/) { $newPassVerify = $1; } else { showInitial ($q, 'Error: duplicate password must contain only printable characters.',""); return; } if ($newPass ne $newPassVerify) { showInitial ($q, "Error: passwords are not identical.",""); return; } my $usermode = db_get_prop(\%conf,"passwordstrength", "Users") ||''; my $test = &validate_password($usermode,$newPass); if ($test ne 'OK') { showInitial ($q, "Error: Sorry the password is not good because $test.",""); return; } esmith::util::setUserPassword ($acct, $newPass); #------------------------------------------------------------ # update the user's PasswordSet field in the accounts database #------------------------------------------------------------ my $value = $accounts {$acct}; my ($type, %properties) = split (/\|/, $value, -1); $properties {'PasswordSet'} = 'yes'; $accounts {$acct} = "user|" . join('|', %properties); system("/sbin/e-smith/signal-event", "password-modify", "${acct}") == 0 or die ("Error occurred while modifying password for ${acct}.\n"); showInitial ($q, "Successfully changed password for user account $acct.",""); } #------------------------------------------------------------ # lock user #------------------------------------------------------------ sub lockUser ($) { my ($q) = @_; my $acct = $q->param ('acct'); my $fGroup = $q->param ('fGroup'); db_set(\%conf, 'fGroup', $fGroup); if ($acct =~ /^([a-z][\-\_\.a-z0-9]*)$/) { $acct = $1; } else { showInitial ($q, 'Error: internal failure while locking account "' . $acct . '".',""); return; } my ($type, %properties) = db_get(\%accounts, $acct); unless (defined $type) { showInitial ($q, "There is no user account called \"$acct\".",""); return; } unless ($type eq "user") { showInitial ($q, "Account \"$acct\" is of type \"$type\", not \"user\".",""); return; } esmith::cgi5::genHeaderNonCacheable ($q, \%conf, 'Lock user account verify'); print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1)); my $name = $properties {'FirstName'} . ' ' . $properties {'LastName'}; print $q->p ('You are about to remove the user account "' . $acct . '" (user name "' . $name . '").'); print $q->p ('This user account will be locked. This means that this', 'user will not be able to log in, and will not be able', 'to collect e-mail. Any e-mail arriving will still be', 'stored and/or forwarded to an external e-mail', 'address, as configured. The account may be activated', 'in the future by setting a new password. The current', 'password will not be retained.'); print $q->p ($q->b ('Are you sure you wish to lock this account?')); print $q->submit (-name => 'action', -value => 'Lock'); print $q->hidden (-name => 'acct', -override => 1, -default => $acct); print $q->hidden (-name => 'state', -override => 1, -default => 'performLock'); print $q->endform; esmith::cgi::genFooter($q); return; } #------------------------------------------------------------ # #------------------------------------------------------------ sub performlockUser($) { my ($q) = @_; #------------------------------------------------------------ # Attempt to lock user account #------------------------------------------------------------ my $acct = $q->param ('acct'); if ($acct =~ /^([a-z][\-\_\.a-z0-9]*)$/) { $acct = $1; } else { showInitial ($q, 'Error: internal failure while locking account "' . $acct . '".',""); return; } my $type = db_get_type(\%accounts, $acct); unless (defined $type) { showInitial ($q, "There is no user account called \"$acct\".",""); return; } unless ($type eq "user") { showInitial ($q, "Account \"$acct\" is of type \"$type\", not \"user\".",""); return; } untie %accounts; system("/sbin/e-smith/signal-event", "user-lock", "${acct}") == 0 or die ("Error occurred while locking account ${acct}.\n"); tie %accounts, 'esmith::config', '/home/e-smith/db/accounts'; showInitial ($q, "Successfully locked account $acct.",""); } sub makePseudonyms ($$) { #------------------------------------------------------------ # Generate First.Last and First_Last pseudonyms #------------------------------------------------------------ my ($firstName, $lastName) = @_; my $dot_pseudonym = "$firstName $lastName"; $dot_pseudonym =~ s/^\s+//; # Strip leading whitespace $dot_pseudonym =~ s/\s+$//; # Strip trailing whitespace $dot_pseudonym =~ s/\s+/ /g; # Multiple spaces become single spaces $dot_pseudonym =~ s/\s/./g; # Change all spaces to dots $dot_pseudonym = lc $dot_pseudonym; # Change to lower case my $underbar_pseudonym = $dot_pseudonym; $underbar_pseudonym =~ s/\./_/g; # Change dots to underbars return ($dot_pseudonym, $underbar_pseudonym); } sub getNextFreeID { my %id; my $minid = $conf{'MinUid'}; $minid = 5000 unless $minid; my $maxid = 1 << 31; # Take note of all the used uids and gids from the passwd entries while ((undef, undef, my $uid, my $gid) = getpwent) { ++$id{$uid} if ($uid > $minid); ++$id{$gid} if ($gid > $minid); } # Take note of all the used gids from the group entries while ((undef, undef, my $gid) = getgrent) { ++$id{$gid} if ($gid > $minid); } # Find the first free id my $count = $minid + 1; while ($count < $maxid) { return $count unless (exists $id{$count}); ++$count; } } sub performSelect ($) { my ($q) = @_; my $swap = $q->param ('swap'); showInitial ($q, "Group switched to $swap" ,"$swap"); } #------------------------------------------------------------ # Function to validate password with cracklib added by Lorenzo #------------------------------------------------------------ sub validate_password { my ($strength,$pass) = @_; my $reason = "Software error: password check failed"; if ($strength eq 'strong') { $reason = fascist_check($pass, '/usr/lib/cracklib_dict') if ( -e '/usr/lib/cracklib_dict.pwd'); $reason = fascist_check($pass, '/usr/lib64/cracklib_dict') if ( -e '/usr/lib64/cracklib_dict.pwd'); } elsif (($strength eq "none") || ($strength eq "normal")) { $reason = 'OK'; } if ($reason eq 'ok' || $reason eq 'OK') { return('OK'); } else { return $reason; } } sub showHelp ($) { my ($q) = @_; esmith::cgi5::genHeaderNonCacheable ($q, \%conf, 'User Account Help'); print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1)); print $q->table ({border => 0, cellspacing => 0, cellpadding => 4}, esmith::cgi5::genTextRow ($q, $q->p ('* Groups * Limits'))); print $q->endform; # print $q->p ($q->hr, $q->font ({size => "-1"}, "www.dungog.net/sme ", esmith::cgi::genFooter($q); return; }Groups
Create users in a selected groups Users will be created in the active group. The active groups can be toggled from the available groups that are listed. If you are only in one group this option is not displayed.Limits
Limits to the number of users that can be created Admin may place limits on the numbers of users that may be created /sbin/e-smith/db accounts setprop groupLimit support 15 setting the group support to a limit of 15 users /sbin/e-smith/db accounts get groupLimit displays current values > setting|support|15|spare|5