Apache-AuthenN2

 view release on metacpan or  search on metacpan

AuthenN2.pm  view on Meta::CPAN

   unless($name){
      $r->note_basic_auth_failure;
      $r->log_reason($self . ': no username supplied', $r->uri);
      return AUTH_REQUIRED;
   }

   # load apache config vars
   my $dir_config = $r->dir_config;   

   # get nt controllers
   my $controllers = $r->dir_config('NT_Controllers') || '';
   $r->log_reason(
      $self . ': no NT_Controllers specified in config', $r->uri
   ) unless $controllers;
   my @controllers = split /\s+/, $controllers;
   
   # get nt domain name
   my @domains;
   if ($name =~ /^.*\\/){
      # user-specified domain name
      @domains = split /\\/, $name;
      $name = pop @domains;
   }
   else{
      # get list of default domains from config
      @domains = split /\s+/, $r->dir_config('NT_Default_Domains');
      $r->log_reason(
         $self . 
         ': user did not specify domain, and there are no NT_Default_Domains specified in config', $r->uri
      ) unless @domains;
   }

   # try nt
   my ($pdc, $bdc);
   foreach my $domain (@domains){
      foreach my $controller (@controllers){
         ($pdc, $bdc) = split /:/, $controller;
         $bdc = $pdc unless $bdc;
         unless (Authen::Smb::authen($name, $sent_pwd, $pdc, $bdc, $domain)){
            $r->push_handlers(PerlAuthzHandler => \&authz);
            return OK;
         }
      }
   }

   # try nis+
   # get passwd table name
   my $passwd_table = $dir_config->get('NISPlus_Passwd_Table');
   # get user password entry
   my $pwd_table = Net::NISPlus::Table->new($passwd_table);
   unless ($pwd_table){
      $r->note_basic_auth_failure;
      $r->log_reason($self . ': cannot get nis+ passwd table', $r->uri);
      return AUTH_REQUIRED;
   }
   my $pwd = '';
   my $group = '';
   # look for name match
   foreach ($pwd_table->lookup('[name=' . $name . ']')){
      $pwd = $_->{'passwd'};
      $group = $_->{'gid'};
      last;
   }
   # stash group id lookup for authorization check 
   $r->notes($name . 'Group', $group);
   unless($pwd){
      $r->note_basic_auth_failure;
      $r->log_reason(
         $self . ': user ' . $name .
         ' failed to authenticate in the nt domain(s) ' .
         join(' ', @domains) . ', and is not in ' . $passwd_table .
         ', either', $r->uri
      );
      return AUTH_REQUIRED;
   }
   unless(crypt($sent_pwd, $pwd) eq $pwd) {
      $r->note_basic_auth_failure;
      $r->log_reason(
         $self . ': user ' . $name .
         ' failed to authenticate in the nt domain(s) ' .
         join(' ', @domains) . ', or ' . $passwd_table, $r->uri
      );
      return AUTH_REQUIRED;
   }

   $r->push_handlers(PerlAuthzHandler => \&authz);
   return OK;
}

sub authz {
 
   # get request object
   my $r = shift;
   my $requires = $r->requires;
   return OK unless $requires;

   # get user name
   my $name = $r->connection->user;

   # get group table name
   my $dir_config = $r->dir_config;   
   my $group_table=$dir_config->get('NISPlus_Group_Table');

   for my $req (@$requires) {
      my($require, @rest) = split /\s+/, $req->{requirement};

      # ok if user is simply authenticated
      if($require eq 'valid-user'){return OK}

      # ok if user is one of these users
      elsif($require eq 'user') {return OK if grep $name eq $_, @rest}

      # ok if user is member of a required group. warning: this will fail 
      # if user is not in the nis+ domain, because there is no current
      # concept of nt domain groups in Authen::Smb
      elsif($require eq 'group') {
         my $group_table = Net::NISPlus::Table->new($group_table);
         unless ($group_table){
            $r->note_basic_auth_failure;
            $r->log_reason($self . ': cannot get nis+ group table', $r->uri);
            return AUTH_REQUIRED;
         }
         my %groups_to_gids;
         foreach ($group_table->list()){$groups_to_gids{@{$_}[0]} = @{$_}[2]}
         for my $group (@rest) {
            next unless exists $groups_to_gids{$group};
            return OK if $r->notes($name . 'Group') == $groups_to_gids{$group};
         }
      }
   }

   $r->note_basic_auth_failure;
   $r->log_reason(
      $self . ': user ' . $name . 
      ' not member of required group in ' . $group_table, $r->uri
   );
   return AUTH_REQUIRED;

}

1;

__END__

=pod

=head1 NAME

Apache::AuthenN2 - Authenticate into the NT and NIS+ domains

=head1 SYNOPSIS

Allow windows and unix users to use their familiar credentials to
gain authenticated access to restricted applications and files
offered via apache.

   #httpd.conf
   <Files *challenge*>
      AuthName 'your nt or nis+ account'
      AuthType Basic
      PerlSetVar NISPlus_Passwd_Table passwd.org_dir.yoyodyne.com
      PerlSetVar NISPlus_Group_Table group.org_dir.yoyodyne.com
      PerlSetVar NT_Default_Domains 'eng corporate'
      PerlSetVar NT_Controllers 'bapdc:babdc njpdc:njbdc'
      PerlAuthenHandler Apache::AuthenN2
      require group eng
      require user john larry
   </Files>

=head1 DESCRIPTION

Authenticate to one or more pdc:bdc controller pairs; these can be
true nt controllers or properly configured samba servers.  Only one
pdc:bdc pair is required by the module; you can add pairs to increase
reliability, or to circumvent domain trust wars.  If the user has
specified a domain, e.g., sales\john, then just try against that
domain; if no domain was specified by the user, try all of the
default domains listed in the above config.  Failing nt
authentication, try nis+.  This order (nt then nis+) is simply to
boost average apparent performance because the nt population is much
larger than the unix population at the author's company.  If your
population has an opposite demographic, feel free to reverse the
order of checking.

Note that this scheme is quite permissive.  Valid nt credentials
against any of the controllers or domains, or valid nis+ credentials
will allow access.  This multiplies exposure to poorly selected



( run in 1.310 second using v1.01-cache-2.11-cpan-ceb78f64989 )