diff options
Diffstat (limited to 'FS/FS/svc_acct.pm')
-rw-r--r-- | FS/FS/svc_acct.pm | 378 |
1 files changed, 105 insertions, 273 deletions
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 3a625f791..f7b76e7b4 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -8,6 +8,8 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles $username_noperiod $username_nounderscore $username_nodash $username_uppercase $username_percent $password_noampersand $password_noexclamation + $welcome_template $welcome_from + $welcome_subject $welcome_subject_template $welcome_mimetype $warning_template $warning_from $warning_subject $warning_mimetype $warning_cc $smtpmachine @@ -19,7 +21,6 @@ use Fcntl qw(:flock); use Date::Format; use Crypt::PasswdMD5 1.2; use Data::Dumper; -use Authen::Passphrase; use FS::UID qw( datasrc ); use FS::Conf; use FS::Record qw( qsearch qsearchs fields dbh dbdef ); @@ -64,6 +65,24 @@ $FS::UID::callback{'FS::svc_acct'} = sub { $password_noampersand = $conf->exists('password-noexclamation'); $password_noexclamation = $conf->exists('password-noexclamation'); $dirhash = $conf->config('dirhash') || 0; + if ( $conf->exists('welcome_email') ) { + $welcome_template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", $conf->config('welcome_email') ] + ) or warn "can't create welcome email template: $Text::Template::ERROR"; + $welcome_from = $conf->config('welcome_email-from'); # || 'your-isp-is-dum' + $welcome_subject = $conf->config('welcome_email-subject') || 'Welcome'; + $welcome_subject_template = new Text::Template ( + TYPE => 'STRING', + SOURCE => $welcome_subject, + ) or warn "can't create welcome email subject template: $Text::Template::ERROR"; + $welcome_mimetype = $conf->config('welcome_email-mimetype') || 'text/plain'; + } else { + $welcome_template = ''; + $welcome_from = ''; + $welcome_subject = ''; + $welcome_mimetype = ''; + } if ( $conf->exists('warning_email') ) { $warning_template = new Text::Template ( TYPE => 'ARRAY', @@ -152,8 +171,6 @@ FS::svc_Common. The following fields are currently supported: =item _password - generated if blank -=item _password_encoding - plain, crypt, ldap (or empty for autodetection) - =item sec_phrase - security phrase =item popnum - Point of presence (see L<FS::svc_acct_pop>) @@ -447,7 +464,6 @@ sub insert { if ( $cust_pkg ) { my $cust_main = $cust_pkg->cust_main; - my $agentnum = $cust_main->agentnum; if ( $conf->exists('emailinvoiceautoalways') || $conf->exists('emailinvoiceauto') @@ -459,25 +475,7 @@ sub insert { } #welcome email - my ($to,$welcome_template,$welcome_from,$welcome_subject,$welcome_subject_template,$welcome_mimetype) - = ('','','','','',''); - - if ( $conf->exists('welcome_email', $agentnum) ) { - $welcome_template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", $conf->config('welcome_email', $agentnum) ] - ) or warn "can't create welcome email template: $Text::Template::ERROR"; - $welcome_from = $conf->config('welcome_email-from', $agentnum); - # || 'your-isp-is-dum' - $welcome_subject = $conf->config('welcome_email-subject', $agentnum) - || 'Welcome'; - $welcome_subject_template = new Text::Template ( - TYPE => 'STRING', - SOURCE => $welcome_subject, - ) or warn "can't create welcome email subject template: $Text::Template::ERROR"; - $welcome_mimetype = $conf->config('welcome_email-mimetype', $agentnum) - || 'text/plain'; - } + my $to = ''; if ( $welcome_template && $cust_pkg ) { my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ); if ( $to ) { @@ -885,9 +883,6 @@ sub check { || $self->ut_snumbern('upbytes') || $self->ut_snumbern('downbytes') || $self->ut_snumbern('totalbytes') - || $self->ut_enum( '_password_encoding', - [ '', qw( plain crypt ldap ) ] - ) ; return $error if $error; @@ -919,6 +914,12 @@ sub check { unless ( $username_ampersand ) { $recref->{username} =~ /\&/ and return gettext('illegal_username'); } + if ( $password_noampersand ) { + $recref->{_password} =~ /\&/ and return gettext('illegal_password'); + } + if ( $password_noexclamation ) { + $recref->{_password} =~ /\!/ and return gettext('illegal_password'); + } unless ( $username_percent ) { $recref->{username} =~ /\%/ and return gettext('illegal_username'); } @@ -948,7 +949,7 @@ sub check { $recref->{shell} = (grep $_ eq $recref->{shell}, @shells)[0]; } else { return "Illegal shell \`". $self->shell. "\'; ". - "shells configuration value contains: @shells"; + $conf->dir. "/shells contains: @shells"; } } else { $recref->{shell} = '/bin/sync'; @@ -1026,92 +1027,36 @@ sub check { $self->ut_textn($_); } - if ( $recref->{_password_encoding} eq 'ldap' ) { - - if ( $recref->{_password} =~ /^(\{[\w\-]+\})(!?.{0,64})$/ ) { - $recref->{_password} = uc($1).$2; - } else { - return 'Illegal (ldap-encoded) password: '. $recref->{_password}; - } - - } elsif ( $recref->{_password_encoding} eq 'crypt' ) { - - if ( $recref->{_password} =~ - #/^(\$\w+\$.*|[\w\+\/]{13}|_[\w\+\/]{19}|\*)$/ - /^(!!?)?(\$\w+\$.*|[\w\+\/]{13}|_[\w\+\/]{19}|\*)$/ - ) { - - $recref->{_password} = $1.$2; - - } else { - return 'Illegal (crypt-encoded) password'; - } - - } elsif ( $recref->{_password_encoding} eq 'plain' ) { - - #generate a password if it is blank - $recref->{_password} = join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ) - unless length( $recref->{_password} ); - - if ( $recref->{_password} =~ /^([^\t\n]{$passwordmin,$passwordmax})$/ ) { - $recref->{_password} = $1; - } else { - return gettext('illegal_password'). " $passwordmin-$passwordmax ". - FS::Msgcat::_gettext('illegal_password_characters'). - ": ". $recref->{_password}; - } - - if ( $password_noampersand ) { - $recref->{_password} =~ /\&/ and return gettext('illegal_password'); - } - if ( $password_noexclamation ) { - $recref->{_password} =~ /\!/ and return gettext('illegal_password'); - } - + #generate a password if it is blank + $recref->{_password} = join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ) + unless ( $recref->{_password} ); + + #if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{4,16})$/ ) { + 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 + #password is available to techs, for faxing, etc. (also be aware of + #radius issues!) + #$recref->{password} = $1. + # crypt($3,$saltset[int(rand(64))].$saltset[int(rand(64))] + #; + } elsif ( $recref->{_password} =~ /^((\*SUSPENDED\* |!!?)?)([\w\.\/\$\;\+]{13,64})$/ ) { + $recref->{_password} = $1.$3; + } elsif ( $recref->{_password} eq '*' ) { + $recref->{_password} = '*'; + } elsif ( $recref->{_password} eq '!' ) { + $recref->{_password} = '!'; + } elsif ( $recref->{_password} eq '!!' ) { + $recref->{_password} = '!!'; } else { - - #carp "warning: _password_encoding unspecified\n"; - - #generate a password if it is blank - unless ( length( $recref->{_password} ) ) { - - $recref->{_password} = - join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ); - $recref->{_password_encoding} = 'plain'; - - } else { - - #if ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([^\t\n]{4,16})$/ ) { - if ( $recref->{_password} =~ /^((\*SUSPENDED\* |!!?)?)([^\t\n]{$passwordmin,$passwordmax})$/ ) { - $recref->{_password} = $1.$3; - $recref->{_password_encoding} = 'plain'; - } elsif ( $recref->{_password} =~ - /^((\*SUSPENDED\* |!!?)?)([\w\.\/\$\;\+]{13,64})$/ - ) { - $recref->{_password} = $1.$3; - $recref->{_password_encoding} = 'crypt'; - } elsif ( $recref->{_password} eq '*' ) { - $recref->{_password} = '*'; - $recref->{_password_encoding} = 'crypt'; - } elsif ( $recref->{_password} eq '!' ) { - $recref->{_password_encoding} = 'crypt'; - $recref->{_password} = '!'; - } elsif ( $recref->{_password} eq '!!' ) { - $recref->{_password} = '!!'; - $recref->{_password_encoding} = 'crypt'; - } else { - #return "Illegal password"; - return gettext('illegal_password'). " $passwordmin-$passwordmax ". - FS::Msgcat::_gettext('illegal_password_characters'). - ": ". $recref->{_password}; - } - - } - + #return "Illegal password"; + return gettext('illegal_password'). " $passwordmin-$passwordmax ". + FS::Msgcat::_gettext('illegal_password_characters'). + ": ". $recref->{_password}; } $self->SUPER::check; - } =item _check_system @@ -1963,42 +1908,23 @@ sub check_password { #self-service and pay up ( my $password = $self->_password ) =~ s/^\*SUSPENDED\* //; - if ( $self->_password_encoding eq 'ldap' ) { - - my $auth = from_rfc2307 Authen::Passphrase $self->_password; - return $auth->match($check_password); - - } elsif ( $self->_password_encoding eq 'crypt' ) { - - my $auth = from_crypt Authen::Passphrase $self->_password; - return $auth->match($check_password); - - } elsif ( $self->_password_encoding eq 'plain' ) { - - return $check_password eq $password; - + #eventually should check a "password-encoding" field + if ( $password =~ /^(\*|!!?)$/ ) { #no self-service login + return 0; + } elsif ( length($password) < 13 ) { #plaintext + $check_password eq $password; + } elsif ( length($password) == 13 ) { #traditional DES crypt + crypt($check_password, $password) eq $password; + } elsif ( $password =~ /^\$1\$/ ) { #MD5 crypt + unix_md5_crypt($check_password, $password) eq $password; + } elsif ( $password =~ /^\$2a?\$/ ) { #Blowfish + warn "Can't check password: Blowfish encryption not yet supported, svcnum". + $self->svcnum. "\n"; + 0; } else { - - #XXX this could be replaced with Authen::Passphrase stuff - - if ( $password =~ /^(\*|!!?)$/ ) { #no self-service login - return 0; - } elsif ( length($password) < 13 ) { #plaintext - $check_password eq $password; - } elsif ( length($password) == 13 ) { #traditional DES crypt - crypt($check_password, $password) eq $password; - } elsif ( $password =~ /^\$1\$/ ) { #MD5 crypt - unix_md5_crypt($check_password, $password) eq $password; - } elsif ( $password =~ /^\$2a?\$/ ) { #Blowfish - warn "Can't check password: Blowfish encryption not yet supported, ". - "svcnum ". $self->svcnum. "\n"; - 0; - } else { - warn "Can't check password: Unrecognized encryption for svcnum ". - $self->svcnum. "\n"; - 0; - } - + warn "Can't check password: Unrecognized encryption for svcnum ". + $self->svcnum. "\n"; + 0; } } @@ -2019,40 +1945,14 @@ database. sub crypt_password { my $self = shift; - - if ( $self->_password_encoding eq 'ldap' ) { - - if ( $self->_password =~ /^\{(PLAIN|CLEARTEXT)\}(.+)$/ ) { - my $plain = $2; - - #XXX this could be replaced with Authen::Passphrase stuff - - my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; - if ( $encryption eq 'crypt' ) { - crypt( - $self->_password, - $saltset[int(rand(64))].$saltset[int(rand(64))] - ); - } elsif ( $encryption eq 'md5' ) { - unix_md5_crypt( $self->_password ); - } elsif ( $encryption eq 'blowfish' ) { - croak "unknown encryption method $encryption"; - } else { - croak "unknown encryption method $encryption"; - } - - } elsif ( $self->_password =~ /^\{CRYPT\}(.+)$/ ) { - $1; - } - - } elsif ( $self->_password_encoding eq 'crypt' ) { - - return $self->_password; - - } elsif ( $self->_password_encoding eq 'plain' ) { - - #XXX this could be replaced with Authen::Passphrase stuff - + #eventually should check a "password-encoding" field + if ( length($self->_password) == 13 + || $self->_password =~ /^\$(1|2a?)\$/ + || $self->_password =~ /^(\*|NP|\*LK\*|!!?)$/ + ) + { + $self->_password; + } else { my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; if ( $encryption eq 'crypt' ) { crypt( @@ -2066,44 +1966,14 @@ sub crypt_password { } else { croak "unknown encryption method $encryption"; } - - } else { - - if ( length($self->_password) == 13 - || $self->_password =~ /^\$(1|2a?)\$/ - || $self->_password =~ /^(\*|NP|\*LK\*|!!?)$/ - ) - { - $self->_password; - } else { - - #XXX this could be replaced with Authen::Passphrase stuff - - my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; - if ( $encryption eq 'crypt' ) { - crypt( - $self->_password, - $saltset[int(rand(64))].$saltset[int(rand(64))] - ); - } elsif ( $encryption eq 'md5' ) { - unix_md5_crypt( $self->_password ); - } elsif ( $encryption eq 'blowfish' ) { - croak "unknown encryption method $encryption"; - } else { - croak "unknown encryption method $encryption"; - } - - } - } - } =item ldap_password [ DEFAULT_ENCRYPTION_TYPE ] Returns an encrypted password in "LDAP" format, with a curly-bracked prefix -describing the format, for example, "{PLAIN}himom", "{CRYPT}94pAVyK/4oIBk" or -"{MD5}5426824942db4253f87a1009fd5d2d4". +describing the format, for example, "{CRYPT}94pAVyK/4oIBk" or +"{PLAIN-MD5}5426824942db4253f87a1009fd5d2d4f". The optional DEFAULT_ENCRYPTION_TYPE is not yet used, but the idea is for it to work the same as the B</crypt_password> method. @@ -2113,71 +1983,33 @@ to work the same as the B</crypt_password> method. sub ldap_password { my $self = shift; #eventually should check a "password-encoding" field - - if ( $self->_password_encoding eq 'ldap' ) { - - return $self->_password; - - } elsif ( $self->_password_encoding eq 'crypt' ) { - - if ( length($self->_password) == 13 ) { #crypt - return '{CRYPT}'. $self->_password; - } elsif ( $self->_password =~ /^\$1\$(.*)$/ && length($1) == 31 ) { #passwdMD5 - return '{MD5}'. $1; - #} elsif ( $self->_password =~ /^\$2a?\$(.*)$/ ) { #Blowfish - # die "Blowfish encryption not supported in this context, svcnum ". - # $self->svcnum. "\n"; - } else { - warn "encryption method not (yet?) supported in LDAP context"; - return '{CRYPT}*'; #unsupported, should not auth - } - - } elsif ( $self->_password_encoding eq 'plain' ) { - + if ( length($self->_password) == 13 ) { #crypt + return '{CRYPT}'. $self->_password; + } elsif ( $self->_password =~ /^\$1\$(.*)$/ && length($1) == 31 ) { #passwdMD5 + return '{MD5}'. $1; + } elsif ( $self->_password =~ /^\$2a?\$(.*)$/ ) { #Blowfish + die "Blowfish encryption not supported in this context, svcnum ". + $self->svcnum. "\n"; + } elsif ( $self->_password =~ /^(\w{48})$/ ) { #LDAP SSHA + return '{SSHA}'. $1; + } elsif ( $self->_password =~ /^(\w{64})$/ ) { #LDAP NS-MTA-MD5 + return '{NS-MTA-MD5}'. $1; + } else { #plaintext return '{PLAIN}'. $self->_password; - - #return '{CLEARTEXT}'. $self->_password; #? - - } else { - - if ( length($self->_password) == 13 ) { #crypt - return '{CRYPT}'. $self->_password; - } elsif ( $self->_password =~ /^\$1\$(.*)$/ && length($1) == 31 ) { #passwdMD5 - return '{MD5}'. $1; - } elsif ( $self->_password =~ /^\$2a?\$(.*)$/ ) { #Blowfish - warn "Blowfish encryption not supported in this context, svcnum ". - $self->svcnum. "\n"; - return '{CRYPT}*'; - - #are these two necessary anymore? - } elsif ( $self->_password =~ /^(\w{48})$/ ) { #LDAP SSHA - return '{SSHA}'. $1; - } elsif ( $self->_password =~ /^(\w{64})$/ ) { #LDAP NS-MTA-MD5 - return '{NS-MTA-MD5}'. $1; - - } else { #plaintext - return '{PLAIN}'. $self->_password; - - #return '{CLEARTEXT}'. $self->_password; #? - - #XXX this could be replaced with Authen::Passphrase stuff if it gets used - #my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; - #if ( $encryption eq 'crypt' ) { - # return '{CRYPT}'. crypt( - # $self->_password, - # $saltset[int(rand(64))].$saltset[int(rand(64))] - # ); - #} elsif ( $encryption eq 'md5' ) { - # unix_md5_crypt( $self->_password ); - #} elsif ( $encryption eq 'blowfish' ) { - # croak "unknown encryption method $encryption"; - #} else { - # croak "unknown encryption method $encryption"; - #} - } - + #my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt'; + #if ( $encryption eq 'crypt' ) { + # return '{CRYPT}'. crypt( + # $self->_password, + # $saltset[int(rand(64))].$saltset[int(rand(64))] + # ); + #} elsif ( $encryption eq 'md5' ) { + # unix_md5_crypt( $self->_password ); + #} elsif ( $encryption eq 'blowfish' ) { + # croak "unknown encryption method $encryption"; + #} else { + # croak "unknown encryption method $encryption"; + #} } - } =item domain_slash_username |