This file is indexed.

/usr/share/perl5/Jifty/Plugin/AuthzLDAP.pm is in libjifty-plugin-authzldap-perl 0.90000-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
use strict;
use warnings;

=head1 NAME

Jifty::Plugin::AuthzLDAP - Jifty plugin to a add dynamic ldap authorization

=head1 DESCRIPTION

Jifty plugin.
Provide ldap authorization with filters table and cache.

=head1 CONFIGURATION NOTES

in etc/config.yml
  Plugins: 
    - AuthzLDAP: 
       LDAPbind: cn=testldap,ou=admins,dc=myorg,dc=org #
       LDAPpass: test                   # password
       LDAPhost: ldap.myorg.org         # ldap host
       LDAPbase: ou=people,dc=myorg..   # ldap base
       LDAPuid: uid                     # optional
       CacheTimout: 20                  # minutes, optional, default 20 minutes

in application create a LDAPFilter model
        use base qw/Jifty::Plugin::AuthzLDAP::Model::LDAPFilter/;

in LDAPFilter model create your filters, something like
 name    |filter                         |is_group
 is_admin|(!eduPersonAffiliation=STUDENT)|0
 in_admin|cn=admin,ou=groups,dc=my.org   |1

to protect access to /admin
in "TestApp" application create a lib/TestApp/Dispatcher.pm 

    use strict;
    use warnings;

    package TestApp::Dispatcher;
    use Jifty::Dispatcher -base;

    before '/admin/*' => run {
       # Authentication
       Jifty->web->tangent(url => '/login')
            if (! Jifty->web->current_user->id);
       # Authorization
       my $user = Jifty->web->current_user->user_object->name;
       Jifty->web->tangent(url => '/error/AccessDenied')
            if (! Jifty::Plugin::AuthzLDAP->ldapvalidate($user,'is_admin') );
    };

    1

=head1 SEE ALSO

L<Net::LDAP>

=cut


package Jifty::Plugin::AuthzLDAP;
use base qw/Jifty::Plugin/;

our $VERSION = '0.9';

use Net::LDAP;
use Cache::MemoryCache;

{
    my ($LDAPFilterClass, $LDAP, $cache, %params);

=head1 METHODS

=head2 init

load config parameters, connect to ldap, create memory cache

=cut

    sub init {
        my $self = shift;
        my %args = @_;

        my $appname = Jifty->config->framework('ApplicationName');
        $LDAPFilterClass = "Jifty::Plugin::AuthzLDAP::Model::LDAPFilter";

        $params{'Hostname'} = $args{LDAPhost};
        $params{'base'} = $args{LDAPbase};
        $params{'uid'} = $args{LDAPuid} || "uid";
        $params{'dn'} = $args{LDAPbind};
        $params{'pass'} = $args{LDAPpass};
        $params{'timeout'} = $args{CacheTimout} || "20 minutes";

        $LDAP = Net::LDAP->new($params{Hostname},async=>1,onerror => 'undef', debug => 0);

        $cache = new Cache::MemoryCache( { 'namespace' => $appname.'AuthzLDAP',
                                            'default_expires_in' => $params{'timeout'} } );
    }

=head2 BASE CACHE DN  LDAP BASE UID PASS LDAPFilterClass

accesors to conf parametres

=cut

    sub LDAPFilterClass {
        return $LDAPFilterClass;
    }

    sub LDAP {
        return $LDAP;
    }

    sub DN {
        return $params{'dn'};
    }

    sub PASS {
        return $params{'pass'};
    }

    sub UID {
        return $params{'uid'};
    }

    sub BASE {
        return $params{'base'};
    }
    
    sub CACHE {
        return $cache;
    }

}

=head2 bind

Bind to ldap

=cut

sub bind {
    my $self = shift;
    my $msg = $self->LDAP()->bind($self->DN() ,'password' =>$self->PASS());
    unless (not $msg->code) {
        Jifty->log->error("Bind to ldap server failed"); 
        return;
    }
}

=head2 ldapvalidate NAME FILTERNAME

return 1 if NAME validate FILTER or NAME-FILTERNAME in cache
else return 0

If FILTERNAME is flagged as is_group, search if user is uniquemember of this group
as supported by the Netscape Directory Server

=cut

sub ldapvalidate {
    my ($self, $user, $filtername) = @_;
    my $response  = 'nok';
    
    my $cachekey = $user.'-'.$filtername;
    my $cache = $self->CACHE->get($cachekey);
    return ($cache eq 'ok')?1:0 if (defined $cache);
   
    my $record = $self->LDAPFilterClass()->new();
    $record->load_by_cols( name => $filtername);

    # (?) allow use of writing filter in filtername
    # TODO: filtername must be cleanned
    # my $filter = ($record->filter)?$record->filter:$filtername;
    my $filter = $record->ldapfilter;

    $user = $self->UID().'='.$user.','.$self->BASE();
    
    # (??) how to catch AuthLDAP bind if it's used?
    $self->bind();

    my $msg;
    # manage group as supported by the Netscape Directory Server 
    if ($record->is_group) {
        $msg = $self->LDAP()->compare( $filter, attr=>"uniquemember", value=>$user );
        Jifty->log->debug("search grp: ".$msg->code); 
        $response = 'ok' if ( $msg->code == 6 );
    } else {
            $filter = '('. $filter .')' if ( $filter !~ /^\(/ );
            $msg = $self->LDAP()->search( base => $user, filter => $filter );
            Jifty->log->debug("search: ".$msg->count); 
            $response = 'ok' if (! $msg->code &&  $msg->count );
    }

    $self->CACHE->set($cachekey,$response);

    return ( $response eq 'ok' )?1:0; 
}

=head1 AUTHOR

Yves Agostini, <yvesago@cpan.org>

=head1 LICENSE

Copyright 2007-2009 Yves Agostini. All Rights Reserved.

This program is free software and may be modified and distributed under the same terms as Perl itself.

=cut

1;