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 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
|
#! /usr/bin/perl -w
#
# ldap_mod_attr - change an attribute in someone's LDAP entry
#
# Author: Andrew J Cosgriff <ajc@bing.wattle.id.au>
# Created: Thu Dec 4 19:48:03 1997
# Version: $Id: ldap_mod_attr.pl,v 1.1.1.1 1998/01/30 19:10:06 jonl Exp $
# Keywords: ldap modify add remove attribute commmand-line useful really
#
########################################
#
### Commentary:
#
# Sick of typing in lines of ldapmodify stuff just to change one or
# two attributes ? This is for you...
#
### TO DO:
#
# - take note when dealing with multiple values for an attribute
#
########################################
#
### Code:
#
use Net::LDAPapi;
use Getopt::Std;
use File::Basename;
my $version = substr q$Revision: 1.1.1.1 $, 10;
chop $version;
##########
#
# Defaults
#
$ldap_server = "ldap.org.au";
$BASEDN = $ENV{'LDAP_BASEDN'} || "o=Org, c=AU";
$ROOTDN = "cn=admin, o=Org, c=AU";
$ROOTPW = "";
$batchmode = 0;
$verbosemode = 0;
$modify_all = 0;
$do_nothing = 0;
$UIDATTR = "uid";
#
# Parse command line options, explained here :
#
$usage_msg = "ldap_mod_attr version " . $version . " by Andrew J Cosgriff <ajc\@bing.wattle.id.au>
Usage : " . basename($0) . " [options] <search filter> <attr=value> <attr=value> ...
[options] being one or more of :
-a : modify all matching entries (rather than prompting for one)
-b <dn> : base DN for searches
[ default - $BASEDN ]
-D <dn> : bind as this DN to do the modifications
[ default - $ROOTDN ]
-h <host> : ldap server to talk to
[ default - $ldap_server ]
-n : do nothing, just show what would happen (implies -v)
-q : batch/quiet mode - no prompting for password
- no prompting if there are multiple matches
-v : verbose mode - print \"<attr> changed from <old> to <new>\"
-w <pwd> : the password for the DN we bind as with -D
<search filter> being either :
- a uid, eg. \"nate\"
- an RFC 1558-style LDAP search filter, eg. \"cn=Nathan Bailey\"
exitcodes are :
1 - general error
2 - no matches returned by ldap_search_s
3 - too many matches (for -q)
";
if (getopts('ab:D:h:nqvw:?', \%opt) == 0) {
print $usage_msg;
exit 1;
}
$modify_all = 1 if (defined $opt{'a'});
$BASEDN = $opt{'b'} if (defined $opt{'b'});
$ROOTDN = $opt{'D'} if (defined $opt{'D'});
$ldap_server = $opt{'h'} if (defined $opt{'h'});
$batchmode = 1 if (defined $opt{'q'});
$verbosemode = 1 if (defined $opt{'v'});
$do_nothing = 1 if (defined $opt{'n'});
$verbosemode = $do_nothing || $verbosemode;
$ROOTPW = $opt{'w'} if (defined $opt{'w'});
#
# Print help if they want/need it
#
if ($opt{'?'}) {
print $usage_msg;
exit 1;
}
if ($#ARGV == -1) {
print "Need to specify a search filter and attr=value pairs\n";
print $usage_msg;
exit 1;
}
if ($#ARGV <= 0) {
print "Need to specify attr=value pairs as well\n";
print $usage_msg;
exit 1;
}
print "Well hey, we\'re in DoNothing mode...\n" if $do_nothing;
#
# Ask for the Root DN's password if they didn't specify it
#
if ($ROOTPW eq "") {
print "Attempting to bind as $ROOTDN\nPassword : ";
system "stty -echo";
$ROOTPW = <STDIN>;
chomp $ROOTPW;
system "stty echo";
print "\n";
}
#
# Initialize Connection to LDAP Server
#
if (($ld = ldap_open($ldap_server,LDAP_PORT)) eq "")
{
die "ldap_init failed";
}
#
# Bind as the specified DN
#
if ((ldap_simple_bind_s($ld,$ROOTDN,$ROOTPW)) != LDAP_SUCCESS)
{
ldap_perror($ld,"ldap_simple_bind_s");
die "Failed to bind as $ROOTDN";
}
#
# Perform search
#
$filter = shift @ARGV;
if ($filter !~ /[\(\)\&\|=]/) {
$filter = "($UIDATTR=$filter)";
}
print "\nSearching for $filter\n" if ($verbosemode);
@attrs = ();
if (ldap_search_s($ld,$BASEDN,LDAP_SCOPE_SUBTREE,$filter,\@attrs,0,$result)
!= LDAP_SUCCESS)
{
$err = ldap_get_lderrno($ld,$errdn,$extramsg);
print &ldap_err2string($err),"\n";
print "DN $errdn\n" if defined $errdn;
print "extramsg $extramsg\n" if defined $extramsg;
ldap_unbind($ld);
die "Search for $filter failed\n";
}
$num_entries = ldap_count_entries($ld,$result);
#
# Die if we got no matches, or if we're in batch mode and got more
# than one match
#
exit 2 if ($num_entries == 0);
exit 3 if ($batchmode && ($num_entries > 1));
print "$num_entries matches\n" if ($verbosemode && ($num_entries > 1));
$entry = ldap_first_entry($ld, $result);
if ($num_entries == 1) {
#
# If we got just one match, just do it.
#
&do_mod_entry($entry);
} else {
#
# If we're modifying all entries, loop through and do each one in
# turn. Otherwise, make a list of entries so we can present a menu
# and ask the user which entry to modify.
#
while ($entry != 0) {
if ($modify_all) {
&do_mod_entry($entry);
} else {
push @entries, $entry;
}
$entry = ldap_next_entry($ld, $entry);
}
#
# Present a menu of matching entries, and ask which of them the user
# wants to modify.
#
if (! $modify_all) {
for $cnt (0 .. $#entries) {
print "$cnt : ", ldap_get_dn($ld, $entries[$cnt]), "\n";
}
$num = -1;
while (($num < 0) || ($num > $#entries)) {
print "Which entry ? : ";
$num = <STDIN>;
chomp $num;
}
&do_mod_entry($entries[$num]);
}
}
########################################
#
# do_mod_entry - Given an entry (as returned by
# ldap_first_entry/ldap_next_entry), apply all the modifications as
# specified in @ARGV
#
sub do_mod_entry {
my $entry = shift @_;
my $dn = ldap_get_dn($ld, $entry);
print "\nModifying ", ldap_get_dn($ld, $entry), " :\n" if $verbosemode;
foreach $mod (@ARGV) {
my ($attr, $val) = split('=',$mod);
@values = ldap_get_values($ld,$entry,$attr);
my (%mods) = ( $attr, $val );
if (($#values > -1) && ($val eq $values[0])) {
print "* (no change) $attr=$val\n" if $verbosemode;
next;
} elsif (($#values == -1) && ($val eq "")) {
print "* (no change) $attr not present\n";
next;
}
#
# Print out nice verbose info on what's going on
#
if ($verbosemode) {
if ($val eq "") {
if ($#values > -1) {
print "- $attr=", $values[0], "\n";
}
} elsif ($#values > -1) {
print "- $attr=", $values[0], "\n";
print "+ $attr=", $val, "\n";
} else {
print "+ $attr=$val\n";
}
}
#
# Apply this modification - it'd be groovier to assemble a list of
# modifications so we only call ldap_modify_s once per entry, but
# it's a bit fiddly to assemble said list properly, so i'm being
# lazy :)
#
if (! $do_nothing) {
if (ldap_modify_s($ld,$dn,\%mods) != LDAP_SUCCESS) {
ldap_perror($ld,"ldap_modify_s");
die "Failed to modify $dn\n";
} else {
print "* modifications successful.\n" if $verbosemode;
}
}
}
}
### ldap_mod_attr ends here
|