preliminary web config editor
[freeside.git] / FS / FS / svc_acct.pm
index 4b902ff..3e7230f 100644 (file)
@@ -2,10 +2,12 @@ package FS::svc_acct;
 
 use strict;
 use vars qw( @ISA $nossh_hack $conf $dir_prefix @shells $usernamemin
-             $usernamemax $passwordmin $username_letter $username_letterfirst
-             $username_noperiod
+             $usernamemax $passwordmin $passwordmax
+             $username_ampersand $username_letter $username_letterfirst
+             $username_noperiod $username_uppercase
              $shellmachine $useradd $usermod $userdel $mydomain
              $cyrus_server $cyrus_admin_user $cyrus_admin_pass
+             $dirhash
              $icradius_dbh
              @saltset @pw_set);
 use Carp;
@@ -32,6 +34,7 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
   $usernamemin = $conf->config('usernamemin') || 2;
   $usernamemax = $conf->config('usernamemax');
   $passwordmin = $conf->config('passwordmin') || 6;
+  $passwordmax = $conf->config('passwordmax') || 8;
   if ( $shellmachine ) {
     if ( $conf->exists('shellmachine-useradd') ) {
       $useradd = join("\n", $conf->config('shellmachine-useradd') )
@@ -56,6 +59,8 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
   $username_letter = $conf->exists('username-letter');
   $username_letterfirst = $conf->exists('username-letterfirst');
   $username_noperiod = $conf->exists('username-noperiod');
+  $username_uppercase = $conf->exists('username-uppercase');
+  $username_ampersand = $conf->exists('username-ampersand');
   $mydomain = $conf->config('domain');
   if ( $conf->exists('cyrus') ) {
     ($cyrus_server, $cyrus_admin_user, $cyrus_admin_pass) =
@@ -72,6 +77,7 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
   } else {
     $icradius_dbh = '';
   }
+  $dirhash = $conf->config('dirhash') || 0;
 };
 
 @saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
@@ -672,9 +678,16 @@ sub check {
   return $error if $error;
 
   my $ulen = $usernamemax || $self->dbdef_table->column('username')->length;
-  $recref->{username} =~ /^([a-z0-9_\-\.]{$usernamemin,$ulen})$/
-    or return "Illegal username";
-  $recref->{username} = $1;
+  if ( $username_uppercase ) {
+    $recref->{username} =~ /^([a-z0-9_\-\.\&]{$usernamemin,$ulen})$/i
+      or return "Illegal username: ". $recref->{username};
+    $recref->{username} = $1;
+  } else {
+    $recref->{username} =~ /^([a-z0-9_\-\.\&]{$usernamemin,$ulen})$/
+      or return "Illegal username: ". $recref->{username};
+    $recref->{username} = $1;
+  }
+
   if ( $username_letterfirst ) {
     $recref->{username} =~ /^[a-z]/ or return "Illegal username";
   } elsif ( $username_letter ) {
@@ -683,6 +696,9 @@ sub check {
   if ( $username_noperiod ) {
     $recref->{username} =~ /\./ and return "Illegal username";
   }
+  unless ( $username_ampersand ) {
+    $recref->{username} =~ /\&/ and return "Illegal username";
+  }
 
   $recref->{popnum} =~ /^(\d*)$/ or return "Illegal popnum: ".$recref->{popnum};
   $recref->{popnum} = $1;
@@ -703,15 +719,34 @@ sub check {
     return "Only root can have uid 0"
       if $recref->{uid} == 0 && $recref->{username} ne 'root';
 
-    $error = $self->ut_textn('finger');
-    return $error if $error;
+#    $error = $self->ut_textn('finger');
+#    return $error if $error;
+    $self->getfield('finger') =~
+      /^([\w \t\!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\*\<\>]*)$/
+        or return "Illegal finger: ". $self->getfield('finger');
+    $self->setfield('finger', $1);
 
-    $recref->{dir} =~ /^([\/\w\-]*)$/
+    $recref->{dir} =~ /^([\/\w\-\.\&]*)$/
       or return "Illegal directory";
-    $recref->{dir} = $1 || 
-      $dir_prefix . '/' . $recref->{username}
-      #$dir_prefix . '/' . substr($recref->{username},0,1). '/' . $recref->{username}
+    $recref->{dir} = $1;
+    return "Illegal directory"
+      if $recref->{dir} =~ /(^|\/)\.+(\/|$)/; #no .. component
+    return "Illegal directory"
+      if $recref->{dir} =~ /\&/ && ! $username_ampersand;
+    unless ( $recref->{dir} ) {
+      $recref->{dir} = $dir_prefix . '/';
+      if ( $dirhash > 0 ) {
+        for my $h ( 1 .. $dirhash ) {
+          $recref->{dir} .= substr($recref->{username}, $h-1, 1). '/';
+        }
+      } elsif ( $dirhash < 0 ) {
+        for my $h ( reverse $dirhash .. -1 ) {
+          $recref->{dir} .= substr($recref->{username}, $h, 1). '/';
+        }
+      }
+      $recref->{dir} .= $recref->{username};
     ;
+    }
 
     unless ( $recref->{username} eq 'sync' ) {
       if ( grep $_ eq $recref->{shell}, @shells ) {
@@ -761,7 +796,7 @@ sub check {
     unless ( $recref->{_password} );
 
   #if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{4,16})$/ ) {
-  if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{$passwordmin,8})$/ ) {
+  if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{$passwordmin,$passwordmax})$/ ) {
     $recref->{_password} = $1.$3;
     #uncomment this to encrypt password immediately upon entry, or run
     #bin/crypt_pw in cron to give new users a window during which their
@@ -777,7 +812,8 @@ sub check {
   } elsif ( $recref->{_password} eq '!!' ) {
     $recref->{_password} = '!!';
   } else {
-    return "Illegal password";
+    #return "Illegal password";
+    return "Illegal password: ". $recref->{_password};
   }
 
   ''; #no error
@@ -868,15 +904,34 @@ sub email {
 =cut
 
 sub ssh {
-  my @args = @_;
-  &Net::SSH::ssh(@args,">>/usr/local/etc/freeside/sshoutput 2>&1");
+  my ( $host, @cmd_and_args ) = @_;
+
+  use IO::File;
+  my $reader = IO::File->new();
+  my $writer = IO::File->new();
+  my $error = IO::File->new();
+
+  &Net::SSH::sshopen3( $host, $reader, $writer, $error, @cmd_and_args) or die $!;
+
+  local $/ = undef;
+  my $output_stream = <$writer>;
+  my $error_stream = <$error>;
+  if ( length $error_stream ) {
+    #warn "[FS::svc_acct::ssh] STDERR $error_stream";
+    die "[FS::svc_acct::ssh] STDERR $error_stream";
+  }
+  if ( length $output_stream ) {
+    warn "[FS::svc_acct::ssh] STDOUT $output_stream";
+  }
+
+#  &Net::SSH::ssh(@args,">>/usr/local/etc/freeside/sshoutput 2>&1");
 }
 
 =back
 
 =head1 VERSION
 
-$Id: svc_acct.pm,v 1.43 2001-09-19 19:28:17 ivan Exp $
+$Id: svc_acct.pm,v 1.52 2001-10-24 15:29:30 ivan Exp $
 
 =head1 BUGS