Advertisement
Guest User

Untitled

a guest
May 9th, 2017
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 5.46 KB | None | 0 0
  1. #!/usr/bin/perl -w
  2. ##############################################################################
  3. #
  4. # Script to export a list of all email addresses from Active Directory
  5. # Brian Landers <brian@packetslave.com>
  6. # Modified by Ben Scott:
  7. # - Move Sendmail-specific comments out to other locations
  8. # - Read site-dependant configuration from an external file
  9. # - Include email addresses for AD "Contact" objects
  10. #
  11. # Specifiy config file as first and only argument.
  12. # Format of config file:
  13. # Line 1: LDAP user in DN form (example: cn=JSMITH,ou=Users,dc=example,dc=com)
  14. # Line 2: password for LDAP user
  15. # Line 3: base LDAP context (example: dc=example,dc=com)
  16. # Line 4: list of LDAP servers (Active Directory Domain Controllers), separated by spaces
  17. #
  18. ##############################################################################
  19.  
  20. use strict;
  21. use Fatal qw(open readline close);
  22.  
  23. $|++; # flush output channel after every output statement
  24.  
  25. use Net::LDAP;
  26. use Net::LDAP::Control::Paged;
  27. use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED );
  28.  
  29. # constants
  30. our $filter  = '(|' .
  31.     '(objectClass=publicFolder)' .
  32.     '(objectClass=contact)' .
  33.     '(&(sAMAccountName=*)(mail=*))' .
  34.     ')';
  35.  
  36. # globals
  37. our $ldapuser;
  38. our $passwd;
  39. our $base;
  40. our $servers;
  41. our @servers;
  42.  
  43. # arguments
  44. (@ARGV == 1) or die "wrong number of arguments";
  45. my $conffile = $ARGV[0];
  46.  
  47. # get configuration from file
  48. open CONFIG_FILE, '<', $conffile;
  49. $ldapuser = <CONFIG_FILE>;
  50. $passwd = <CONFIG_FILE>;
  51. $base = <CONFIG_FILE>;
  52. $servers = <CONFIG_FILE>;
  53. close CONFIG_FILE;
  54. chomp ($ldapuser, $passwd, $base, $servers);
  55. @servers = split ' ', $servers;
  56. (@servers > 0) or die "no servers specified in config file";
  57.  
  58. # We use this to keep track of addresses we've seen
  59. my %gSeen;
  60.  
  61. # Connect to the server, try each one until we succeed
  62. my $ldap = undef;
  63. foreach( @servers ) {
  64.   $ldap = Net::LDAP->new( $_ );
  65.   last if $ldap;
  66. }
  67.  
  68. die "Unable to connect to any LDAP servers!\n" if not defined $ldap;
  69.  
  70. # Create our paging control.  Exchange has a maximum recordset size of
  71. # 1000 records by default.  We have to use paging to get the full list.
  72.  
  73. my $page = Net::LDAP::Control::Paged->new( size => 100 );
  74.  
  75. # Try to bind (login) to the server now that we're connected
  76. my $msg = $ldap->bind( dn       => $ldapuser,
  77.                        password => $passwd
  78.                      );
  79.  
  80. # If we can't bind, we can't continue
  81. if( $msg->code() ) {
  82.   die( "error while binding:", $msg->error_text(), "\n" );
  83. }
  84.  
  85. # Build the args for the search
  86. my @args = ( base     => $base,
  87.              scope    => "subtree",
  88.              filter   => $filter,
  89.              attrs    => [ "proxyAddresses" ],
  90.              callback => \&handle_object,
  91.              control  => [ $page ],
  92.            );
  93.  
  94. # Now run the search in a loop until we run out of results.  This code
  95. # is taken pretty much directly from the example code in the perldoc
  96. # page for Net::LDAP::Control::Paged
  97.  
  98. my $cookie;
  99. while(1) {
  100.   # Perform search
  101.   my $mesg = $ldap->search( @args );
  102.  
  103.   # Only continue on LDAP_SUCCESS
  104.   $mesg->code and last;
  105.  
  106.   # Get cookie from paged control
  107.   my($resp)  = $mesg->control( LDAP_CONTROL_PAGED ) or last;
  108.   $cookie    = $resp->cookie or last;
  109.  
  110.   # Set cookie in paged control
  111.   $page->cookie($cookie);
  112. }
  113.  
  114. if( $cookie ) {
  115.   # We had an abnormal exit, so let the server know we do not want any more
  116.   $page->cookie($cookie);
  117.   $page->size(0);
  118.   $ldap->search( @args );
  119. }
  120.  
  121. # Finally, unbind from the server
  122. $ldap->unbind;
  123.  
  124. # ------------------------------------------------------------------------
  125. # Callback function that gets called for each record we get from the server
  126. # as we get it.  We look at the type of object and call the appropriate
  127. # handler function
  128. #
  129.  
  130. sub handle_object {
  131.  
  132.   my $msg  = shift;       # Net::LDAP::Message object
  133.   my $data = shift;       # May be Net::LDAP::Entry or Net::LDAP::Reference
  134.  
  135.   # Only process if we actually got data
  136.   return unless $data;
  137.  
  138.   return handle_entry( $msg, $data )     if $data->isa("Net::LDAP::Entry");
  139.   return handle_reference( $msg, $data ) if $data->isa("Net::LDAP::Reference");
  140.  
  141.   # If we get here, it was something we're not prepared to handle,
  142.   # so just return silently.
  143.  
  144.   return;
  145. }
  146.  
  147. # ------------------------------------------------------------------------
  148. # Handler for a Net::LDAP::Entry object.  This is an actual record.  We
  149. # extract all email addresses from the record and output only the SMTP
  150. # ones we haven't seen before.
  151.  
  152. sub handle_entry {
  153.  
  154.   my $msg  = shift;
  155.   my $data = shift;
  156.  
  157.   # Extract the email addressess, selecting only the SMTP ones, and
  158.   # filter them so that we only get unique addresses
  159.  
  160.   my @mails = grep { /^smtp:/i && !$gSeen{$_}++ }
  161.                    $data->get_value( "proxyAddresses" );
  162.  
  163.   # If we found any, strip off the SMTP: identifier and print them out
  164.   if( @mails ) {
  165.     print map { s/^smtp:(.+)$/\L$1\n/i; $_ } @mails;
  166.   }
  167. }
  168.  
  169. # ------------------------------------------------------------------------
  170. # Handler for a Net::LDAP::Reference object.  This is a 'redirect' to
  171. # another portion of the directory.  We simply extract the references
  172. # from the object and resubmit them to the handle_object function for
  173. # processing.
  174.  
  175. sub handle_reference {
  176.  
  177.   my $msg  = shift;
  178.   my $data = shift;
  179.  
  180.   foreach my $obj( $data->references() ) {
  181.  
  182.     # Oooh, recursion!  Might be a reference to another reference, after all
  183.     return handle_object( $msg, $obj );
  184.   }
  185. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement