# If a user DB is enabled, get users from it too
if ($miniserv{'userdb'}) {
- my ($dbh, $proto) = &connect_userdb($miniserv{'userdb'});
+ my ($dbh, $proto, $prefix, $args) =&connect_userdb($miniserv{'userdb'});
&error("Failed to connect to user database : $dbh") if (!ref($dbh));
if ($proto eq "mysql" || $proto eq "postgresql") {
# Fetch users with SQL
}
elsif ($proto eq "ldap") {
# Find users with LDAP query
- # XXX
+ my $rv = $dbh->search(
+ base => $prefix,
+ filter => '(objectClass='.$args->{'userclass'}.')',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ &error("Failed to search users : ".
+ ($rv ? $rv->error : "Unknown error"));
+ }
+ foreach my $l ($rv->all_entries) {
+ my $u = { 'name' => $l->get_value('cn'),
+ 'pass' => $l->get_value('webminPass'),
+ 'proto' => $proto,
+ 'id' => $l->dn() };
+ foreach my $la ($l->get_value('webminAttr')) {
+ my ($attr, $value) = split(/=/, $la, 2);
+ if ($attr eq "olds" || $attr eq "ownmods") {
+ $value = [ split(/\s+/, $value) ];
+ }
+ $u->{$attr} = $value;
+ }
+ $u->{'modules'} = [ $l->get_value('webminModule') ];
+ push(@rv, $u);
+ }
}
&disconnect_userdb($miniserv{'userdb'}, $dbh);
}
if ($attr eq "members" || $attr eq "ownmods") {
$value = [ split(/\s+/, $value) ];
}
+ $g->{$attr} = $value;
}
$g->{'modules'} = [ $l->get_value('webminModule') ];
push(@rv, $g);
if ($miniserv{'userdb'} && !$miniserv{'userdb_addto'}) {
# Adding to user database
- my ($dbh, $proto) = &connect_userdb($miniserv{'userdb'});
+ my ($dbh, $proto, $prefix, $args) =&connect_userdb($miniserv{'userdb'});
&error("Failed to connect to user database : $dbh") if (!ref($dbh));
if ($proto eq "mysql" || $proto eq "postgresql") {
# Add user with SQL
}
elsif ($proto eq "ldap") {
# Add user to LDAP
- # XXX
+ my $dn = "cn=".$user{'name'}.",".$prefix;
+ my @attrs = ( "objectClass", $args->{'userclass'},
+ "cn", $user{'name'},
+ "webminPass", $user{'pass'} );
+ my @webminattrs;
+ foreach my $attr (keys %user) {
+ next if ($attr eq "name" || $attr eq "pass" ||
+ $attr eq "modules");
+ my $value = $user{$attr};
+ if ($attr eq "olds" || $attr eq "ownmods") {
+ $value = join(" ", @$value);
+ }
+ push(@webminattrs,
+ defined($value) ? $attr."=".$value : $attr);
+ }
+ if (@webminattrs) {
+ push(@attrs, "webminAttr", \@webminattrs);
+ }
+ if (@{$user{'modules'}}) {
+ push(@attrs, "webminModule", $user{'modules'});
+ }
+ my $rv = $dbh->add($dn, attr => \@attrs);
+ if (!$rv || $rv->code) {
+ &error("Failed to add user to LDAP : ".
+ ($rv ? $rv->error : "Unknown error"));
+ }
+
}
&disconnect_userdb($miniserv{'userdb'}, $dbh);
$user{'proto'} = $proto;
}
}
elsif ($proto eq "ldap") {
- # XXX update in ldap
+ # Rename in LDAP if needed
+ if ($user{'name'} ne $username) {
+ my $newdn = $user{'id'};
+ $newdn =~ s/^cn=\Q$username\E,/cn=$user{'name'},/;
+ my $rv = $dbh->moddn($user{'id'},
+ newrdn => "cn=$user{'name'}");
+ if (!$rv || $rv->code) {
+ &error("Failed to rename user : ".
+ ($rv ? $rv->error : "Unknown error"));
+ }
+ $user{'id'} = $newdn;
+ }
+
+ # Re-save all the attributes
+ my @attrs = ( "cn", $user{'name'},
+ "webminPass", $user{'pass'} );
+ my @webminattrs;
+ foreach my $attr (keys %user) {
+ next if ($attr eq "name" || $attr eq "desc" ||
+ $attr eq "modules");
+ my $value = $user{$attr};
+ if ($attr eq "olds" || $attr eq "ownmods") {
+ $value = join(" ", @$value);
+ }
+ push(@webminattrs,
+ defined($value) ? $attr."=".$value : $attr);
+ }
+ push(@attrs, "webminAttr", \@webminattrs);
+ push(@attrs, "webminModule", $user{'modules'});
+ my $rv = $dbh->modify($user{'id'}, replace => { @attrs });
+ if (!$rv || $rv->code) {
+ &error("Failed to modify user : ".
+ ($rv ? $rv->error : "Unknown error"));
+ }
}
}
else {
if ($miniserv{'userdb'}) {
# Also delete from user database
- my ($dbh, $proto) = &connect_userdb($miniserv{'userdb'});
+ my ($dbh, $proto, $prefix, $args) =&connect_userdb($miniserv{'userdb'});
&error("Failed to connect to user database : $dbh") if (!ref($dbh));
if ($proto eq "mysql" || $proto eq "postgresql") {
# Find the user with SQL query
}
elsif ($proto eq "ldap") {
# Find user with LDAP query
- # XXX
+ my $rv = $dbh->search(
+ base => $prefix,
+ filter => '(&(cn='.$username.')(objectClass='.
+ $args->{'userclass'}.'))',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ &error("Failed to find user : ".
+ ($rv ? $rv->error : "Unknown error"));
+ }
+ my ($user) = $rv->all_entries;
+
+ if ($user) {
+ # Delete the user from LDAP
+ my $rv = $dbh->delete($user->dn());
+ if (!$rv || $rv->code) {
+ &error("Failed to delete user : ".
+ ($rv ? $rv->error : "Unknown error"));
+ }
+ }
}
&disconnect_userdb($miniserv{'userdb'}, $dbh);
}
# Find group with LDAP query
my $rv = $dbh->search(
base => $prefix,
- filter => '(cn='.$groupname.')',
+ filter => '(&(cn='.$groupname.')(objectClass='.
+ $args->{'groupclass'}.'))',
scope => 'one');
if (!$rv || $rv->code) {
&error("Failed to find group : ".
return $get_user_details_cache{$username};
}
print DEBUG "get_user_details: Connecting to user database\n";
- my ($dbh, $proto) = &connect_userdb($config{'userdb'});
+ my ($dbh, $proto, $prefix, $args) = &connect_userdb($config{'userdb'});
my $user;
+ my %attrs;
if (!ref($dbh)) {
print DEBUG "get_user_details: Failed : $dbh\n";
print STDERR "Failed to connect to user database : $dbh\n";
}
elsif ($proto eq "mysql" || $proto eq "postgresql") {
# Fetch user ID and password with SQL
- print DEBUG "get_user_details: Looking for $username\n";
+ print DEBUG "get_user_details: Looking for $username in SQL\n";
my $cmd = $dbh->prepare(
"select id,pass from webmin_user where name = ?");
if (!$cmd || !$cmd->execute($username)) {
'id' => $id,
'pass' => $pass,
'proto' => $proto };
- my %attrs;
while(my ($attr, $value) = $cmd->fetchrow()) {
$attrs{$attr} = $value;
}
+ $cmd->finish();
+ }
+ elsif ($proto eq "ldap") {
+ # Fetch user DN with LDAP
+ print DEBUG "get_user_details: Looking for $username in LDAP\n";
+ my $rv = $dbh->search(
+ base => $prefix,
+ filter => '(&(cn='.$username.')(objectClass='.
+ $args->{'userclass'}.'))',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ print STDERR "Failed to lookup user : ",
+ ($rv ? $rv->error : "Unknown error"),"\n";
+ return undef;
+ }
+ my ($u) = $rv->all_entries();
+ if (!$u) {
+ &disconnect_userdb($config{'userdb'}, $dbh);
+ $get_user_details_cache{$username} = undef;
+ print DEBUG "get_user_details: User not found\n";
+ return undef;
+ }
+
+ # Extract attributes
+ $user = { 'name' => $username,
+ 'id' => $u->dn(),
+ 'pass' => $u->get_value('pass'),
+ 'proto' => $proto };
+ my %attrs;
+ foreach my $la ($u->get_value('webminAttr')) {
+ my ($attr, $value) = split(/=/, $la, 2);
+ $attrs{$attr} = $value;
+ }
+ }
+
+ # Convert DB attributes into user object fields
+ if ($user) {
print DEBUG "get_user_details: got ",scalar(keys %attrs),
" attributes\n";
- $cmd->finish();
$user->{'certs'} = $attrs{'cert'};
if ($attrs{'allow'}) {
$user->{'allow'} = $config{'alwaysresolve'} ?
$user->{'temppass'} = $attrs{'temppass'};
$user->{'preroot'} = $attrs{'theme'};
}
- elsif ($proto eq "ldap") {
- # Fetch with LDAP
- # XXX
- }
&disconnect_userdb($config{'userdb'}, $dbh);
$get_user_details_cache{$user->{'name'}} = $user;
return $user;
my $dbh = $drh->connect($cstr, $user, $pass, { });
$dbh || return &text('sql_emysqlconnect', $drh->errstr);
print DEBUG "connect_userdb: Connected OK\n";
- return wantarray ? ($dbh, $proto) : $dbh;
+ return wantarray ? ($dbh, $proto, $prefix, $args) : $dbh;
}
elsif ($proto eq "postgresql") {
# Connect to PostgreSQL with DBI
my $dbh = $drh->connect($cstr, $user, $pass);
$dbh || return &text('sql_epostgresqlconnect', $drh->errstr);
print DEBUG "connect_userdb: Connected OK\n";
- return wantarray ? ($dbh, $proto) : $dbh;
+ return wantarray ? ($dbh, $proto, $prefix, $args) : $dbh;
}
elsif ($proto eq "ldap") {
# Connect with perl LDAP module
return &text('sql_eldaplogin', $user,
$mesg ? $mesg->error : "Unknown error");
}
- return wantarray ? ($ldap, $proto) : $ldap;
+ return wantarray ? ($ldap, $proto, $prefix, $args) : $ldap;
}
else {
return "Unknown protocol $proto";
# Read from user DB
my $userdb = &get_userdb_string();
- my ($dbh, $proto) = $userdb ? &connect_userdb($userdb) : ( );
+ my ($dbh, $proto, $prefix, $args) =
+ $userdb ? &connect_userdb($userdb) : ( );
if (ref($dbh)) {
if ($proto eq "mysql" || $proto eq "postgresql") {
# Select usernames and modules from SQL DB
$cmd->finish() if ($cmd);
}
elsif ($proto eq "ldap") {
- # XXX read from LDAP
+ # Find users in LDAP
+ # XXX limit attrs?
+ my $rv = $dbh->search(
+ base => $prefix,
+ filter => '(objectClass='.
+ $args->{'userclass'}.')',
+ scope => 'one');
+ if ($rv && !$rv->code) {
+ foreach my $u ($rv->all_entries) {
+ my $user = $u->get_value('cn');
+ my @mods =$u->get_value('webminModule');
+ foreach my $m (@mods) {
+ $main::acl_hash_cache{$user,
+ $m}++;
+ }
+ $main::acl_array_cache{$user} = \@mods;
+ }
+ }
}
&disconnect_userdb($userdb, $dbh);
}
if ($userdb && ($u ne $base_remote_user || $remote_user_proto)) {
# Look for this user in the user/group DB, if one is defined
# and if the user might be in the DB
- my ($dbh, $proto) = &connect_userdb($userdb);
+ my ($dbh, $proto, $prefix, $args) = &connect_userdb($userdb);
ref($dbh) || &error(&text('euserdbacl', $dbh));
if ($proto eq "mysql" || $proto eq "postgresql") {
# Find the user in the SQL DB
}
}
elsif ($proto eq "ldap") {
- # Fetch ACLs from LDAP
- # XXX
+ # Find user in LDAP
+ my $rv = $dbh->search(
+ base => $prefix,
+ filter => '(&(cn='.$u.')(objectClass='.
+ $args->{'userclass'}.'))',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ &error(&text('euserdbacl',
+ $rv ? $rv->error : "Unknown error"));
+ }
+ my ($user) = $rv->all_entries;
+
+ # Find ACL sub-object for the module
+ my $ldapm = $m || "global";
+ if ($user) {
+ my $rv = $dbh->search(
+ base => $user->dn(),
+ filter => '(cn='.$ldapm.')',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ &error(&text('euserdbacl',
+ $rv ? $rv->error : "Unknown error"));
+ }
+ my ($acl) = $rv->all_entries;
+ if ($acl) {
+ foreach my $av ($acl->get_value(
+ 'webminAcl')) {
+ my ($a, $v) = split(/=/, $av,2);
+ $rv{$a} = $v;
+ }
+ }
+ }
}
&disconnect_userdb($userdb, $dbh);
}
# Find group in LDAP
my $rv = $dbh->search(
base => $prefix,
- filter => '(cn='.$g.')',
+ filter => '(&(cn='.$g.')(objectClass='.
+ $args->{'groupclass'}.'))',
scope => 'one');
if (!$rv || $rv->code) {
&error(&text('egroupdbacl',
my ($group) = $rv->all_entries;
# Find ACL sub-object for the module
+ my $ldapm = $m;
if ($group) {
my $rv = $dbh->search(
base => $group->dn(),
- filter => '(cn='.$m.')',
+ filter => '(cn='.$ldapm.')',
scope => 'one');
if (!$rv || $rv->code) {
&error(&text('egroupdbacl',
my $foundindb = 0;
if ($userdb && ($u ne $base_remote_user || $remote_user_proto)) {
# Look for this user in the user/group DB
- my ($dbh, $proto) = &connect_userdb($userdb);
+ my ($dbh, $proto, $prefix, $args) = &connect_userdb($userdb);
ref($dbh) || &error(&text('euserdbacl', $dbh));
if ($proto eq "mysql" || $proto eq "postgresql") {
# Find the user in the SQL DB
}
}
elsif ($proto eq "ldap") {
- # Update ACLs in LDAP
- # XXX
+ # Find the user in LDAP
+ my $rv = $dbh->search(
+ base => $prefix,
+ filter => '(&(cn='.$u.')(objectClass='.
+ $args->{'userclass'}.'))',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ &error(&text('euserdbacl',
+ $rv ? $rv->error : "Unknown error"));
+ }
+ my ($user) = $rv->all_entries;
+
+ if ($user) {
+ # Find the ACL sub-object for the module
+ my $ldapm = $m || "global";
+ my $rv = $dbh->search(
+ base => $user->dn(),
+ filter => '(cn='.$ldapm.')',
+ scope => 'one');
+ if (!$rv || $rv->code) {
+ &error(&text('euserdbacl',
+ $rv ? $rv->error : "Unknown error"));
+ }
+ my ($acl) = $rv->all_entries;
+
+ my @attrs;
+ foreach my $a (keys %{$_[0]}) {
+ push(@attrs, "webminAclEntry",
+ $a."=".$_[0]->{$a});
+ }
+ if ($acl) {
+ # Update attributes
+ $rv = $dbh->modify($acl->dn(),
+ replace => { @attrs });
+ }
+ else {
+ # Add a sub-object
+ push(@attrs, "cn", $ldapm,
+ "objectClass", "webminAcl");
+ $rv = $dbh->add("cn=".$ldapm.",".$user->dn(),
+ attr => \@attrs);
+ }
+ if (!$rv || $rv->code) {
+ &error(&text('euserdbacl2',
+ $rv ? $rv->error : "Unknown error"));
+ }
+ }
}
&disconnect_userdb($userdb, $dbh);
}
# Find the group in LDAP
my $rv = $dbh->search(
base => $prefix,
- filter => '(cn='.$g.')',
+ filter => '(&(cn='.$g.')(objectClass='.
+ $args->{'groupclass'}.'))',
scope => 'one');
if (!$rv || $rv->code) {
&error(&text('egroupdbacl',
}
my ($group) = $rv->all_entries;
+ my $ldapm = $m;
if ($group) {
# Find the ACL sub-object for the module
my $rv = $dbh->search(
base => $group->dn(),
- filter => '(cn='.$m.')',
+ filter => '(cn='.$ldapm.')',
scope => 'one');
if (!$rv || $rv->code) {
&error(&text('egroupdbacl',
}
else {
# Add a sub-object
- push(@attrs, "cn", $m,
+ push(@attrs, "cn", $ldapm,
"objectClass", "webminAcl");
- $rv = $dbh->add("cn=".$m.",".$group->dn(),
+ $rv = $dbh->add("cn=".$ldapm.",".$group->dn(),
attr => \@attrs);
}
if (!$rv || $rv->code) {