template-ns-accountstatus.pl 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. #{{PERL-EXEC}}
  2. #
  3. # BEGIN COPYRIGHT BLOCK
  4. # This Program is free software; you can redistribute it and/or modify it under
  5. # the terms of the GNU General Public License as published by the Free Software
  6. # Foundation; version 2 of the License.
  7. #
  8. # This Program is distributed in the hope that it will be useful, but WITHOUT
  9. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  10. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License along with
  13. # this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  14. # Place, Suite 330, Boston, MA 02111-1307 USA.
  15. #
  16. # In addition, as a special exception, Red Hat, Inc. gives You the additional
  17. # right to link the code of this Program with code not covered under the GNU
  18. # General Public License ("Non-GPL Code") and to distribute linked combinations
  19. # including the two, subject to the limitations in this paragraph. Non-GPL Code
  20. # permitted under this exception must only link to the code of this Program
  21. # through those well defined interfaces identified in the file named EXCEPTION
  22. # found in the source code files (the "Approved Interfaces"). The files of
  23. # Non-GPL Code may instantiate templates or use macros or inline functions from
  24. # the Approved Interfaces without causing the resulting work to be covered by
  25. # the GNU General Public License. Only Red Hat, Inc. may make changes or
  26. # additions to the list of Approved Interfaces. You must obey the GNU General
  27. # Public License in all respects for all of the Program code and other code used
  28. # in conjunction with the Program except the Non-GPL Code covered by this
  29. # exception. If you modify this file, you may extend this exception to your
  30. # version of the file, but you are not obligated to do so. If you do not wish to
  31. # provide this exception without modification, you must delete this exception
  32. # statement from your version and license this file solely under the GPL without
  33. # exception.
  34. #
  35. #
  36. # Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  37. # Copyright (C) 2005 Red Hat, Inc.
  38. # All rights reserved.
  39. # END COPYRIGHT BLOCK
  40. #
  41. ###############################
  42. # SUB-ROUTINES
  43. ###############################
  44. sub usage_and_exit
  45. {
  46. print (STDERR "$cmd [-D rootdn] { -w password | -w - | -j filename } \n");
  47. print (STDERR " [-p port] [-h host] -I DN-to-$operation\n\n");
  48. print (STDERR "May be used to $operation a user or a domain of users\n\n");
  49. print (STDERR "Arguments:\n");
  50. print (STDERR " -? - help\n");
  51. print (STDERR " -D rootdn - Provide a Directory Manager DN. Default= '$defrootdn'\n");
  52. print (STDERR " -w password - Provide a password for the Directory Manager DN\n");
  53. print (STDERR " -w - - Prompt for the Directory Manager's password\n");
  54. print (STDERR " -j filename - Read the Directory Manager's password from file\n");
  55. print (STDERR " -p port - Provide a port. Default= '$defport'\n");
  56. print (STDERR " -h host - Provide a host name. Default= '$defhost'\n");
  57. print (STDERR " -I DN-to-$operation - Single entry DN or role DN to $operation\n");
  58. exit 100;
  59. }
  60. sub debug
  61. {
  62. # print " ==> @_";
  63. }
  64. sub out
  65. {
  66. print "@_";
  67. }
  68. # --------------------------
  69. # Check if the entry is part of a locked role:
  70. # i.e.: for each role member (nsroledn) of nsdisabledrole, check if
  71. # * it is the same as the entry
  72. # * the entry is member of role (==has nsroledn attributes), compare each of
  73. # them with the nsroledn of nsdisabledrole
  74. # * if nsroledn of nsdisabledrole are complex, go through each of them
  75. # argv[0] is the local file handler
  76. # argv[1] is the entry (may be a single entry DN or a role DN)
  77. # argv[2] is the base for the search
  78. # --------------------------
  79. $throughRole="";
  80. sub indirectLock
  81. {
  82. # For recursivity, file handler must be local
  83. my $L_filehandle=$_[0];
  84. $L_filehandle++;
  85. my $L_entry=$_[1];
  86. # Remove useless space
  87. my @L_intern=split /([,])/,$L_entry;
  88. my $L_result="";
  89. foreach $L_part (@L_intern)
  90. {
  91. $L_part=~s/^ +//;
  92. $L_part=~ tr/A-Z/a-z/;
  93. $L_result="$L_result$L_part";
  94. }
  95. $L_entry=$L_result;
  96. my $L_base=$_[2];
  97. my $L_search;
  98. my $L_currentrole;
  99. my $L_retCode;
  100. my $L_local;
  101. `$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn >> {{DEV-NULL}} 2>&1 `;
  102. $retCode=$?;
  103. if ( $retCode != 0 )
  104. {
  105. $retCode=$?>>8;
  106. return 1;
  107. }
  108. # Check if the role is a nested role
  109. @L_Nested="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=nsNestedRoleDefinition)(objectclass=ldapsubentry))\" ";
  110. # L_isNested == 1 means that we are going through a nested role, so for each member of that
  111. # nested role, check that the member is below the scope of the nested
  112. $L_isNested=@L_Nested;
  113. # Not Direct Lock, Go through roles if any
  114. $L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn ";
  115. debug("\t-->indirectLock: check if $L_entry is part of a locked role from base $L_base\n\n");
  116. unless (open ($L_filehandle, "$L_search |"))
  117. {
  118. out("Can't open file $L_filehandle\n");
  119. exit;
  120. }
  121. while (<$L_filehandle>) {
  122. s/\n //g;
  123. if (/^nsroledn: (.*)\n/) {
  124. $L_currentrole = $1;
  125. # Remove useless space
  126. my @L_intern=split /([,])/,$L_currentrole;
  127. my $L_result="";
  128. foreach $L_part (@L_intern)
  129. {
  130. $L_part=~s/^ +//;
  131. $L_part=~ tr/A-Z/a-z/;
  132. $L_result="$L_result$L_part";
  133. }
  134. $L_currentrole=$L_result;
  135. debug("\t-- indirectLock loop: current nsroledn $L_currentrole of base $L_base\n");
  136. if ( $L_isNested == 1 )
  137. {
  138. if ( checkScope($L_currentrole, $L_base) == 0 )
  139. {
  140. # Scope problem probably a bad conf, skip the currentrole
  141. next;
  142. }
  143. }
  144. if ( $L_currentrole eq $L_entry )
  145. {
  146. # the entry is a role that is directly locked
  147. # i.e, nsroledn of nsdisabledrole contains the entry
  148. $throughRole=$L_base;
  149. $throughRole=~ tr/A-Z/a-z/;
  150. # skipDisabled means that we've just found that the entry (which is a role)
  151. # is locked directly (==its DN is part of nsroledn attributes)
  152. # we just want to know now, if it is locked through another role
  153. # at least, one
  154. if ( $skipDisabled == 1 )
  155. {
  156. # direct inactivation
  157. $directLocked=1;
  158. # just go through that test once
  159. $skipDisabled=0;
  160. next;
  161. }
  162. debug("\t-- 1 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
  163. return 0;
  164. }
  165. $L_retCode=memberOf($L_currentrole, $L_entry);
  166. if ( $L_retCode == 0 && $single == 1 )
  167. {
  168. $throughRole=$L_currentrole;
  169. $throughRole=~ tr/A-Z/a-z/;
  170. if ( $skipManaged == 1 )
  171. {
  172. if ( $L_currentrole eq $nsManagedDisabledRole)
  173. {
  174. # Try next nsroledn
  175. $directLocked=1;
  176. $skipManaged=0;
  177. next;
  178. }
  179. }
  180. debug("\t-- 2 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
  181. return 0;
  182. }
  183. # Only for the first iteration
  184. # the first iteration is with nsdisabledrole as base, other
  185. # loops are deeper
  186. $L_local=$skipDisabled;
  187. $skipDisabled=0;
  188. # the current nsroledn may be a complex role, just go through
  189. # its won nsroledn
  190. $L_retCode=indirectLock($L_filehandle,$L_entry, $L_currentrole);
  191. # Because of recursivity, to keep the initial value for the first level
  192. $skipDisabled=$L_local;
  193. if ( $L_retCode == 0 )
  194. {
  195. $throughRole=$L_currentrole;
  196. $throughRole=~ tr/A-Z/a-z/;
  197. debug("\t-- 3 indirectLock: $L_entry locked throughRole == $throughRole\n");
  198. return 0;
  199. }
  200. }
  201. }
  202. close($L_filehandle);
  203. debug("\t<--indirectLock: no more nsroledn to process\n");
  204. return 1;
  205. }
  206. # --------------------------
  207. # Check if nsroledn is part of the entry attributes
  208. # argv[0] is a role DN (nsroledn attribute)
  209. # argv[1] is the entry
  210. # --------------------------
  211. sub memberOf
  212. {
  213. my $L_nsroledn=$_[0];
  214. $L_nsroledn=~ tr/A-Z/a-z/;
  215. my $L_entry=$_[1];
  216. my $L_search;
  217. my $L_currentrole;
  218. $L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_entry\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsrole";
  219. debug("\t\t-->memberOf: $L_search: check if $L_entry has $L_nsroledn as nsroledn attribute\n");
  220. open (LDAP2, "$L_search |");
  221. while (<LDAP2>) {
  222. s/\n //g;
  223. if (/^nsrole: (.*)\n/) {
  224. $L_currentrole = $1;
  225. $L_currentrole=~ tr/A-Z/a-z/;
  226. if ( $L_currentrole eq $L_nsroledn )
  227. {
  228. # the parm is part of the $L_entry nsroledn
  229. debug("\t\t<--memberOf: $L_entry locked through $L_nsroledn\n");
  230. return 0;
  231. }
  232. }
  233. }
  234. close(LDAP2);
  235. # the parm is not part of the $L_entry nsroledn
  236. debug("\t\t<--memberOf: $L_entry not locked through $L_nsroledn\n");
  237. return 1;
  238. }
  239. # --------------------------
  240. # Remove the rdn of a DN
  241. # argv[0] is a DN
  242. # --------------------------
  243. sub removeRdn
  244. {
  245. $L_entry=$_[0];
  246. @L_entryToTest=split /([,])/,$L_entry;
  247. debug("removeRdn: entry to split: $L_entry**@L_entryToTest\n");
  248. $newDN="";
  249. $removeRDN=1;
  250. foreach $part (@L_entryToTest)
  251. {
  252. $part=~ s/^ +//;
  253. $part=~ tr/A-Z/a-z/;
  254. if ( $removeRDN <= 2 )
  255. {
  256. $removeRDN=$removeRDN+1;
  257. }
  258. else
  259. {
  260. $newDN="$newDN$part";
  261. }
  262. }
  263. debug("removeRdn: new DN **$newDN**\n");
  264. }
  265. # --------------------------
  266. # Check if L_current is below the scope of
  267. # L_nestedRole
  268. # argv[0] is a role
  269. # argv[1] is the nested role
  270. # --------------------------
  271. sub checkScope
  272. {
  273. $L_current=$_[0];
  274. $L_nestedRole=$_[1];
  275. debug("checkScope: check if $L_current is below $L_nestedRole\n");
  276. removeRdn($L_nestedRole);
  277. $L_nestedRoleSuffix=$newDN;
  278. debug("checkScope: nested role based: $L_nestedRoleSuffix\n");
  279. $cont=1;
  280. while ( ($cont == 1) && ($L_current ne "") )
  281. {
  282. removeRdn($L_current);
  283. $currentDn=$newDN;
  284. debug("checkScope: current DN to check: $currentDn\n");
  285. if ( $currentDn eq $L_nestedRoleSuffix )
  286. {
  287. debug("checkScope: DN match!!!\n");
  288. $cont = 0;
  289. }
  290. else
  291. {
  292. $L_current=$currentDn;
  293. }
  294. }
  295. if ( $cont == 1 )
  296. {
  297. debug("checkScope: $_[0] and $_[1] are not compatible\n");
  298. return 0;
  299. }
  300. else
  301. {
  302. debug("checkScope: $_[0] and $_[1] are compatible\n");
  303. return 1;
  304. }
  305. }
  306. ###############################
  307. # MAIN ROUTINE
  308. ###############################
  309. # Generated variable
  310. $prefix="{{DS-ROOT}}";
  311. # Determine which command we are running
  312. if ( $0 =~ /ns-inactivate(.pl)?$/ )
  313. {
  314. $cmd="ns-inactivate.pl";
  315. $operation="inactivate";
  316. $state="inactivated";
  317. $modrole="add";
  318. $already="already";
  319. }
  320. elsif ( $0 =~ /ns-activate(.pl)?$/ )
  321. {
  322. $cmd="ns-activate.pl";
  323. $operation="activate";
  324. $state="activated";
  325. $modrole="delete";
  326. $already="already";
  327. }
  328. elsif ( $0 =~ /ns-accountstatus(.pl)?$/ )
  329. {
  330. $cmd="ns-accountstatus.pl";
  331. $operation="get status of";
  332. $state="activated";
  333. # no need for $modrole as no operation is performed
  334. $already="";
  335. }
  336. else
  337. {
  338. out("$0: unknown command\n");
  339. exit 100;
  340. }
  341. debug("Running ** $cmd ** $operation\n");
  342. $dsbinroot="$prefix{{SEP}}shared{{SEP}}bin";
  343. $ldapsearch="$dsbinroot{{SEP}}ldapsearch -1";
  344. $ldapmodify="$dsbinroot{{SEP}}ldapmodify";
  345. # Default values
  346. $defrootdn= "{{ROOT-DN}}";
  347. $defhost= "{{SERVER-NAME}}";
  348. $defport= "{{SERVER-PORT}}";
  349. # User values
  350. $rootdn= "{{ROOT-DN}}";
  351. $rootpw= "";
  352. $pwfile= "";
  353. $host= "{{SERVER-NAME}}";
  354. $port= "{{SERVER-PORT}}";
  355. $entry= "";
  356. $single=0;
  357. $role=0;
  358. chdir("$dsbinroot");
  359. # Process the command line arguments
  360. while( $arg = shift)
  361. {
  362. if($arg eq "-?")
  363. {
  364. usage_and_exit();
  365. }
  366. elsif($arg eq "-D")
  367. {
  368. $rootdn= shift @ARGV;
  369. }
  370. elsif($arg eq "-w")
  371. {
  372. $rootpw= shift @ARGV;
  373. }
  374. elsif($arg eq "-j")
  375. {
  376. $pwfile= shift @ARGV;
  377. }
  378. elsif($arg eq "-p")
  379. {
  380. $port= shift @ARGV;
  381. }
  382. elsif($arg eq "-h")
  383. {
  384. $host= shift @ARGV;
  385. }
  386. elsif($arg eq "-I")
  387. {
  388. $entry= shift @ARGV;
  389. }
  390. else
  391. {
  392. print "$arg: Unknown command line argument.\n";
  393. usage_and_exit();
  394. }
  395. }
  396. if ($pwfile ne ""){
  397. # Open file and get the password
  398. unless (open (RPASS, $pwfile)) {
  399. die "Error, cannot open password file $passwdfile\n";
  400. }
  401. $rootpw = <RPASS>;
  402. chomp($rootpw);
  403. close(RPASS);
  404. } elsif ($rootpw eq "-"){
  405. # Read the password from terminal
  406. die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
  407. "part of the standard perl distribution. If you want to use it, you must\n",
  408. "download and install the module. You can find it at\n",
  409. "http://www.perl.com/CPAN/CPAN.html\n";
  410. # Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
  411. # use Term::ReadKey;
  412. # print "Bind Password: ";
  413. # ReadMode('noecho');
  414. # $rootpw = ReadLine(0);
  415. # chomp($rootpw);
  416. # ReadMode('normal');
  417. }
  418. if( $rootpw eq "" )
  419. {
  420. usage_and_exit();
  421. }
  422. if( $entry eq "" )
  423. {
  424. usage_and_exit();
  425. }
  426. #
  427. # Check the actual existence of the entry to inactivate/activate
  428. # and at the same time, validate the various parm: port, host, rootdn, rootpw
  429. #
  430. @exist=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" dn`;
  431. $retCode1=$?;
  432. if ( $retCode1 != 0 )
  433. {
  434. $retCode1=$?>>8;
  435. exit $retCode1;
  436. }
  437. @isRole=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(&(objectclass=LDAPsubentry)(objectclass=nsRoleDefinition))\" dn`;
  438. $nbLineRole=@isRole;
  439. $retCode2=$?;
  440. if ( $retCode2 != 0 )
  441. {
  442. $retCode2=$?>>8;
  443. exit $retCode2;
  444. }
  445. if ( $nbLineRole == 1 )
  446. {
  447. debug("Groups of users\n");
  448. $role=1;
  449. }
  450. else
  451. {
  452. debug("Single user\n");
  453. $single=1;
  454. }
  455. #
  456. # First of all, check the existence of the nsaccountlock attribute in the entry
  457. #
  458. $isLocked=0;
  459. if ( $single == 1 )
  460. {
  461. $searchAccountLock="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" nsaccountlock";
  462. open (LDAP1, "$searchAccountLock |");
  463. while (<LDAP1>) {
  464. s/\n //g;
  465. if (/^nsaccountlock: (.*)\n/) {
  466. $L_currentvalue = $1;
  467. $L_currentvalue=~ tr/A-Z/a-z/;
  468. if ( $L_currentvalue eq "true")
  469. {
  470. $isLocked=1;
  471. }
  472. elsif ( $L_currentvalue eq "false" )
  473. {
  474. $isLocked=0;
  475. }
  476. }
  477. }
  478. close(LDAP1);
  479. }
  480. debug("Is the entry already locked? ==> $isLocked\n");
  481. #
  482. # Get the suffix name of that entry
  483. #
  484. # Remove the space at the beginning (just in case...)
  485. # -I "uid=jvedder , ou=People , o=sun.com"
  486. @suffix=split /([,])/,$entry;
  487. $result="";
  488. foreach $part (@suffix)
  489. {
  490. $part=~s/^ +//;
  491. $part=~ tr/A-Z/a-z/;
  492. $result="$result$part";
  493. }
  494. @suffixN=$result;
  495. debug("Entry to $operation: #@suffix#\n");
  496. debug("Entry to $operation: #@suffixN#\n");
  497. # Get the suffix
  498. $cont=0;
  499. while ($cont == 0)
  500. {
  501. # Look if suffix is the suffix of the entry
  502. # ldapsearch -s one -b "cn=mapping tree,cn=config" "cn=\"uid=jvedder,ou=People,o=sun.com\""
  503. #
  504. debug("\tSuffix from the entry: #@suffixN#\n");
  505. @mapping=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s one -b \"cn=mapping tree, cn=config\" \"cn=\\"@suffixN\\"\" cn `;
  506. $retCode=$?;
  507. if ( $retCode != 0 )
  508. {
  509. $retCode=$?>>8;
  510. exit $retCode;
  511. }
  512. # If we get a result, remove the dn:
  513. # dn: cn="o=sun.com",cn=mapping tree,cn=config
  514. # cn: "o=sun.com"
  515. #
  516. shift @mapping;
  517. foreach $res (@mapping)
  518. {
  519. # Break the string cn: "o=sun.com" into pieces
  520. @cn= split(/ /,$res);
  521. # And remove the cn: part
  522. shift @cn;
  523. # Now compare the suffix we extract from the mapping tree
  524. # with the suffix derived from the entry
  525. debug("\tSuffix from mapping tree: #@cn#\n");
  526. if ( @cn eq @suffixN ) {
  527. debug("Found matching suffix\n");
  528. $cont=1;
  529. }
  530. }
  531. if ( $cont == 0 )
  532. {
  533. # Remove the current rdn to try another suffix
  534. shift @suffix;
  535. $result="";
  536. foreach $part (@suffix)
  537. {
  538. $part=~ s/^ +//;
  539. $part=~ tr/A-Z/a-z/;
  540. $result="$result$part";
  541. }
  542. @suffixN=$result;
  543. debug("\t\tNothing found => go up one level in rdn #@suffix#\n");
  544. $len=@suffix;
  545. if ( $len == 0 )
  546. {
  547. debug("Can not find suffix. Problem\n");
  548. $cont=2;
  549. }
  550. }
  551. }
  552. if ( $cont == 2)
  553. {
  554. out("Can not find suffix for entry $entry\n");
  555. exit 100;
  556. }
  557. if ( $operation eq "inactivate" )
  558. {
  559. #
  560. # Now that we have the suffix and we know if we deal with a single entry or
  561. # a role, just try to create the COS and roles associated.
  562. #
  563. @base=(
  564. "cn=nsManagedDisabledRole,@suffixN",
  565. "cn=nsDisabledRole,@suffixN",
  566. "cn=nsAccountInactivationTmp,@suffixN",
  567. "\'cn=\"cn=nsDisabledRole,@suffixN\",cn=nsAccountInactivationTmp,@suffixN\'",
  568. "cn=nsAccountInactivation_cos,@suffixN" );
  569. $addrolescos="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c -a >> {{DEV-NULL}} 2>&1 ";
  570. @role1=(
  571. "dn: cn=nsManagedDisabledRole,@suffixN\n",
  572. "objectclass: LDAPsubentry\n",
  573. "objectclass: nsRoleDefinition\n",
  574. "objectclass: nsSimpleRoleDefinition\n",
  575. "objectclass: nsManagedRoleDefinition\n",
  576. "cn: nsManagedDisabledRole\n\n" );
  577. @role2=(
  578. "dn: cn=nsDisabledRole,@suffixN\n",
  579. "objectclass: top\n",
  580. "objectclass: LDAPsubentry\n",
  581. "objectclass: nsRoleDefinition\n",
  582. "objectclass: nsComplexRoleDefinition\n",
  583. "objectclass: nsNestedRoleDefinition\n",
  584. "nsRoleDN: cn=nsManagedDisabledRole,@suffixN\n",
  585. "cn: nsDisabledRole\n\n" );
  586. @cos1=(
  587. "dn: cn=nsAccountInactivationTmp,@suffixN\n",
  588. "objectclass: top\n",
  589. "objectclass: nsContainer\n\n" );
  590. @cos2=(
  591. "dn: cn=\"cn=nsDisabledRole,@suffixN\",cn=nsAccountInactivationTmp,@suffixN\n",
  592. "objectclass: top\n",
  593. "objectclass: extensibleObject\n",
  594. "objectclass: costemplate\n",
  595. "objectclass: ldapsubentry\n",
  596. "cosPriority: 1\n",
  597. "nsAccountLock: true\n\n" );
  598. @cos3=(
  599. "dn: cn=nsAccountInactivation_cos,@suffixN\n",
  600. "objectclass: top\n",
  601. "objectclass: LDAPsubentry\n",
  602. "objectclass: cosSuperDefinition\n",
  603. "objectclass: cosClassicDefinition\n",
  604. "cosTemplateDn: cn=nsAccountInactivationTmp,@suffixN\n",
  605. "cosSpecifier: nsRole\n",
  606. "cosAttribute: nsAccountLock operational\n\n" );
  607. @all=(\@role1, \@role2, \@cos1, \@cos2, \@cos3);
  608. $i=0;
  609. foreach $current (@base)
  610. {
  611. debug("Creating $current ??\n");
  612. open(FD,"| $addrolescos ");
  613. print FD @{$all[$i]};
  614. close(FD);
  615. if ( $? != 0 )
  616. {
  617. $retCode=$?>>8;
  618. if ( $retCode == 68 )
  619. {
  620. debug("Entry $current already exists, ignore error\n");
  621. }
  622. else
  623. {
  624. # Probably a more serious problem.
  625. # Exit with LDAP error
  626. exit $retCode;
  627. }
  628. }
  629. else
  630. {
  631. debug("Entry $current created\n");
  632. }
  633. $i=$i+1;
  634. }
  635. }
  636. $skipManaged=0;
  637. $skipDisabled=0;
  638. $directLocked=0;
  639. $nsDisabledRole="cn=nsDisabledRole,@suffixN";
  640. $nsDisabledRole=~ tr/A-Z/a-z/;
  641. $nsManagedDisabledRole="cn=nsManagedDisabledRole,@suffixN";
  642. $nsManagedDisabledRole=~ tr/A-Z/a-z/;
  643. if ( $operation eq "inactivate" )
  644. {
  645. # Go through all the roles part of nsdisabledrole to check if the entry
  646. # is a member of one of those roles
  647. $ret=indirectLock("LDAP00", $entry, $nsDisabledRole);
  648. if ( $ret == 0 )
  649. {
  650. if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
  651. {
  652. # indirect lock
  653. out("$entry already $state through $throughRole.\n");
  654. }
  655. else
  656. {
  657. # direct lock
  658. out("$entry already $state.\n");
  659. }
  660. exit 100;
  661. }
  662. elsif ( $isLocked == 1 )
  663. {
  664. # the entry is not locked through a role, may be nsaccountlock is "hardcoded" ?
  665. out("$entry already $state (probably directly).\n");
  666. exit 103;
  667. }
  668. }
  669. elsif ( $operation eq "activate" || $operation eq "get status of" )
  670. {
  671. $skipManaged=$single;
  672. $skipDisabled=$role;
  673. $ret=indirectLock("LDAP00",$entry, $nsDisabledRole);
  674. if ( $ret == 0 )
  675. {
  676. # undirectly locked
  677. if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
  678. {
  679. if ( $operation eq "activate" )
  680. {
  681. out("$entry inactivated through $throughRole. Can not activate it individually.\n");
  682. exit 100;
  683. }
  684. else
  685. {
  686. out("$entry inactivated through $throughRole.\n");
  687. exit 104;
  688. }
  689. }
  690. debug("$entry locked individually\n");
  691. if ( $operation ne "activate" )
  692. {
  693. out("$entry inactivated.\n");
  694. exit 103;
  695. }
  696. }
  697. elsif ( $directLocked == 0 )
  698. {
  699. if ( $operation eq "activate" && $isLocked != 1 )
  700. {
  701. out("$entry $already $state.\n");
  702. exit 100;
  703. }
  704. elsif ( $isLocked != 1 )
  705. {
  706. out("$entry $already $state.\n");
  707. exit 102;
  708. }
  709. else
  710. {
  711. # not locked using our schema, but nsaccountlock is probably present
  712. out("$entry inactivated (probably directly).\n");
  713. exit 103;
  714. }
  715. }
  716. elsif ( $operation ne "activate" )
  717. {
  718. out("$entry inactivated.\n");
  719. exit 103;
  720. }
  721. # else Locked directly, juste unlock it!
  722. debug("$entry locked individually\n");
  723. }
  724. #
  725. # Inactivate/activate the entry
  726. #
  727. $action="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c >> {{DEV-NULL}} 2>&1";
  728. if ( $single == 1 )
  729. {
  730. @record=(
  731. "dn: $entry\n",
  732. "changetype: modify\n",
  733. "$modrole: nsRoleDN\n",
  734. "nsRoleDN: cn=nsManagedDisabledRole,@suffixN\n\n" );
  735. }
  736. else
  737. {
  738. @record=(
  739. "dn: cn=nsDisabledRole,@suffixN\n",
  740. "changetype: modify\n",
  741. "$modrole: nsRoleDN\n",
  742. "nsRoleDN: $entry\n\n" );
  743. }
  744. open(FD,"| $action ");
  745. print FD @record;
  746. close(FD);
  747. if ( $? != 0 )
  748. {
  749. debug("$modrole, $entry\n");
  750. $retCode=$?>>8;
  751. exit $retCode;
  752. }
  753. out("$entry $state.\n");
  754. exit 0;