# Form header
print &ui_form_start("acl_save.cgi", "post");
+print &ui_hidden("new", $in{'new'});
+print &ui_hidden("idx", $in{'idx'});
print &ui_table_start($text{'eacl_header'}, undef, 2);
# Granting to what object
&ui_textbox("attrs", $p->{'attrs'}, 40) );
# Access rights table
-# XXX
+@tds = ( "width=40% nowrap", "width=30%", "width=30%" );
+$wtable = &ui_columns_start([ $text{'eacl_who'},
+ $text{'eacl_access'},
+ $text{'eacl_control'} ], 100, 0, \@tds);
+$i = 0;
+foreach $b (@{$p->{'by'}}, { }, { }, { }) {
+ $kwho = $b->{'who'} eq 'self' || $b->{'who'} eq 'users' ||
+ $b->{'who'} eq 'anonymous' || $b->{'who'} eq '*' ||
+ $b->{'who'} eq '';
+ $kacc = !$b->{'access'} ? 'read' :
+ &indexof($b->{'access'}, @acl_access_levels) >= 0 ?
+ $b->{'access'} : undef;
+ $wtable .= &ui_columns_row([
+ # Who are we granting?
+ &ui_select("wmode_$i",
+ $kwho ? $b->{'who'} : 'other',
+ [ [ '', " " ],
+ [ '*', $text{'eacl_every'} ],
+ [ 'self', $text{'eacl_self'} ],
+ [ 'users', $text{'eacl_users'} ],
+ [ 'anonymous', $text{'eacl_anonymous'} ],
+ [ 'other', $text{'eacl_other'} ] ],
+ 1, 0, 0, 0,
+ "style='width:45%' onChange='form.who_$i.disabled = (form.wmode_$i.value != \"other\")'").
+ &ui_textbox("who_$i", $kwho ? "" : $b->{'who'}, 30,
+ $kwho, undef, "style='width:45%'"),
+
+ # What access level? Show textbox if complex
+ $kacc ? &ui_select("access_$i", $kacc,
+ [ map { [ $_, $text{'access_l'.$_} ] }
+ @acl_access_levels ], 1, 0, 0, 0,
+ "style='width:90%'")
+ : &ui_textbox("access_$i", $b->{'access'}, 20,
+ 0, undef, "style='width:90%'"),
+
+ # Additional attrs
+ &ui_textbox("control_$i", join(" ", @{$b->{'control'}}), 30,
+ 0, undef, "style='width:90%'"),
+ ], \@tds);
+ # XXX http://www.openldap.org/faq/data/cache/452.html
+ $i++;
+ }
+$wtable .= &ui_columns_end();
+print &ui_table_row(undef, $wtable, 2);
# Form and page end
print &ui_table_end();
--- /dev/null
+#!/usr/local/bin/perl
+# Create, update or delete one access control rule
+
+require './ldap-server-lib.pl';
+&error_setup($text{'eacl_err'});
+&local_ldap_server() == 1 || &error($text{'slapd_elocal'});
+$access{'acl'} || &error($text{'acl_ecannot'});
+&ReadParse();
+
+# Get the current rule
+&lock_file($config{'config_file'});
+$conf = &get_config();
+@access = &find("access", $conf);
+if (!$in{'new'}) {
+ $acl = $access[$in{'idx'}];
+ $p = &parse_ldap_access($acl);
+ }
+
+if ($in{'delete'}) {
+ # Just take out of access list
+ @access = grep { $_ me $acl } @access;
+ }
+else {
+ # Validate and store inputs, starting with object
+ if ($in{'what'} == 0) {
+ $p->{'what'} = '*';
+ }
+ else {
+ $in{'dn'} =~ /^\S+=\S+$/ || &error($text{'eacl_edn'});
+ $p->{'what'} = 'dn='.($in{'style'} ? '.'.$in{'style'} : '').
+ $in{'dn'};
+ }
+
+ # Object filter and attribute list
+ delete($p->{'filter'});
+ if ($in{'filter_on'}) {
+ $in{'filter'} =~ /^\S+$/ || &error($text{'eacl_efilter'});
+ $p->{'filter'} = $in{'filter'};
+ }
+ delete($p->{'attrs'});
+ if ($in{'attrs_on'}) {
+ $in{'attrs'} =~ /^\S+$/ || &error($text{'eacl_eattrs'});
+ $p->{'attrs'} = $in{'attrs'};
+ }
+
+ # Each granted user
+ # XXX
+
+ # Add to access directive list
+ if ($in{'new'}) {
+ $acl = { 'name' => 'access',
+ 'values' => [ ] };
+ push(@access);
+ }
+ &store_ldap_access($acl, $p);
+ }
+
+# Write out access directives
+&save_directive($conf, "access", @access);
+&flush_file_lines($config{'config_file'});
+&unlock_file($config{'config_file'});
+
+# Log and return
+&webmin_log($in{'delete'} ? "delete" : $in{'new'} ? "create" : "modify",
+ "access", $p->{'who'});
+&redirect("edit_acl.cgi");
+
acl_none=No access control rules have been defined yet. All objects in the LDAP database will be readable by all users.
acl_delete=Delete Selected Rules
acl_add=Add a new access control rule.
+acl_return=access control rules
browser_title=Browse Database
browser_econn=The LDAP browser cannot be used : $1
access_self=self
access_users=authenticated users
access_anon=anonymous users
+access_none=no access
+access_auth=authenticate
+access_compare=compare
+access_search=search
access_read=read
access_write=write
-access_auth=authenticate
access_all=anyone
access_any=All objects
+access_lnone=No access
+access_lauth=Authenticate
+access_lcompare=Compare
+access_lsearch=Search
+access_lread=Read
+access_lwrite=Write
eacl_title1=Create Access Control Rule
eacl_title2=Edit Access Control Rule
eacl_header=LDAP database access control rule details
-eacl_what=Granting access to
+eacl_what=Objects being granted
eacl_what1=All objects
eacl_what0=Object with DN
eacl_mtype=match type
eacl_children=only children
eacl_filter=Limit with object filter :
eacl_attrs=Limit to listed attributes :
+eacl_who=Grant access to
+eacl_access=Access level
+eacl_control=Advanced options
+eacl_self=Self
+eacl_users=Authenticated users
+eacl_anonymous=Anonymous clients
+eacl_other=Other DN..
+eacl_every=Everyone
+eacl_err=Failed to save access control rule
+eacl_edn=Missing or invalid DN - should be like <tt>uid=joe,dc=my-domain,dc=com</tt>
+eacl_efilter=Missing or invalid filter - should be like <tt>(objectClass=posixAccount)</tt>
+eacl_eattrs=Missing or invalid comma-separated list of attributes
+
@search_attrs = ( 'objectClass', 'cn', 'dn', 'uid' );
@acl_dn_styles = ( 'regex', 'base', 'one', 'subtree', 'children' );
+@acl_access_levels = ( 'none', 'auth', 'compare', 'search', 'read', 'write' );
# connect_ldap_db()
# Attempts to connect to an LDAP server. Returns a handle on success or an
return wantarray ? @rv : $rv[0];
}
-# save_directive(&config, name, value, ...)
+# save_directive(&config, name, value|&values|&directive, ...)
# Update the value(s) of some entry in the config file
sub save_directive
{
for(my $i=0; $i<@old || $i<@values; $i++) {
local ($line, @unqvalues, @qvalues);
if (defined($values[$i])) {
- @unqvalues = ref($values[$i]) ? @{$values[$i]}
- : ( $values[$i] );
+ @unqvalues = ref($values[$i]) eq 'ARRAY' ?
+ @{$values[$i]} :
+ ref($values[$i]) eq 'HASH' ?
+ @{$values[$i]->{'values'}} :
+ ( $values[$i] );
@qvalues = map { /^[^'" ]+$/ ? $_ :
/"/ ? "'$_'" : "\"$_\"" } @unqvalues;
$line = join(" ", $name, @qvalues);
shift(@v); # Remove by
local $by = { 'who' => shift(@v),
'access' => shift(@v) };
- if (@v && $v[0] ne 'by') {
- $by->{'control'} = shift(@v);
+ while(@v && $v[0] ne 'by') {
+ push(@{$by->{'control'}}, shift(@v));
}
local $whodesc = $by->{'who'} eq 'self' ? $text{'access_self'} :
$by->{'who'} eq 'users' ? $text{'access_users'} :
return $p;
}
+# store_ldap_access(&directive, &acl-struct)
+# Updates the values of a directive from an ACL structure
+sub store_ldap_access
+{
+local ($a, $p) = @_;
+local @v = ( 'to' );
+push(@v, $p->{'what'});
+if ($p->{'filter'}) {
+ push(@v, "filter=$p->{'filter'}");
+ }
+if ($p->{'attrs'}) {
+ push(@v, "attrs=$p->{'attrs'}");
+ }
+foreach my $b (@{$p->{'by'}}) {
+ push(@v, "by");
+ push(@v, $b->{'who'});
+ push(@v, $b->{'access'});
+ push(@v, @{$b->{'control'}});
+ }
+$a->{'values'} = \@v;
+}
+
1;