#!/usr/bin/perl  -w
##
## Convert an LDIF file containing sambaAccount entries
## to the new sambaSamAccount objectclass
##
## Copyright Gerald (Jerry) Carter	2003
##
## Usage: convertSambaAccount <Domain SID> <input ldif> <output ldif>
##


use strict;
use Net::LDAP::LDIF;

my ( $domain, $domsid );
my ( $ldif, $ldif2 );
my ( $entry, @objclasses, $obj );
my ( $is_samba_account, $is_samba_group );
my ( %attr_map, %group_attr_map, $key );
my ( @dels, $deletion, @adds, $addition );

if ( $#ARGV != 2 ) {
	print "Usage: convertSambaAccount domain_sid input_ldif output_ldif\n";
	exit 1;
}

%attr_map = ( 
	lmPassword	=> 'sambaLMPassword',
	ntPassword	=> 'sambaNTPassword',
	pwdLastSet	=> 'sambaPwdLastSet',
	pwdMustChange	=> 'sambaPwdMustChange',
	pwdCanChange	=> 'sambaPwdCanChange',
	homeDrive	=> 'sambaHomeDrive',
	smbHome		=> 'sambaHomePath',
	scriptPath	=> 'sambaLogonScript',
	profilePath	=> 'sambaProfilePath',
	kickoffTime	=> 'sambaKickoffTime',
	logonTime	=> 'sambaLogonTime',
	logoffTime	=> 'sambaLogoffTime',
	userWorkstations	=> 'sambaUserWorkstations',
	domain		=> 'sambaDomainName',
	acctFlags	=> 'sambaAcctFlags',
);

%group_attr_map = (
	ntSid		=> 'sambaSID',
	ntGroupType	=> 'sambaGroupType',
);

$domsid = $ARGV[0];

$ldif = Net::LDAP::LDIF->new ($ARGV[1], "r")
	or die $!;
$ldif2 = Net::LDAP::LDIF->new ($ARGV[2], "w")
	or die $!;

while ( !$ldif->eof ) {
	undef ( $entry );
	$entry = $ldif->read_entry();

	## skip entry if we find an error
	if ( $ldif->error() ) {
		print "Error msg: ",$ldif->error(),"\n";
		print "Error lines:\n",$ldif->error_lines(),"\n";
		next;
	}

	##
	## check to see if we have anything to do on this
	## entry.  If not just write it out
	##
	@objclasses = $entry->get_value( "objectClass" );
	undef ( $is_samba_account );
	undef ( $is_samba_group );
	@adds = ();
	@dels = ();
	foreach $obj ( @objclasses ) {
		if ( "$obj" eq "sambaAccount" ) {
			$is_samba_account = 1;
		} elsif ( "$obj" eq "sambaGroupMapping" ) {
			$is_samba_group = 1;
		}
	}

	if ( defined ( $is_samba_account ) ) {
		##
		## start editing the sambaAccount
		##

		@dels = ( 'objectclass: sambaAccount', 'rid' );
		@adds = ('objectclass: sambaSamAccount', "sambaSID: " .  ${domsid} . "-" . ${entry}->get_value( 'rid' ) );
		$entry->delete( 'objectclass' => [ 'sambaAccount' ] );
		$entry->add( 'objectclass' => 'sambaSamAccount' );

		$entry->add( 'sambaSID' => $domsid."-".$entry->get_value( "rid" ) );
		$entry->delete( 'rid' );
	
		if ( $entry->get_value( "primaryGroupID" ) ) {
			push @adds, "sambaPrimaryGroupSID: " . $domsid."-".$entry->get_value( "primaryGroupID" );
			push @dels, "primaryGroupID";
			$entry->add( 'sambaPrimaryGroupSID' => $domsid."-".$entry->get_value( "primaryGroupID" ) );
			$entry->delete( 'primaryGroupID' );
		}
	

		foreach $key ( keys %attr_map ) {
			if ( defined($entry->get_value($key)) ) {
				push @adds, "$attr_map{$key}: " . $entry->get_value($key);
				push @dels, "$key";
				$entry->add( $attr_map{$key} => $entry->get_value($key) );
				$entry->delete( $key );
			}
		}
	} elsif ( defined ( $is_samba_group ) ) {
		foreach $key ( keys %group_attr_map ) {
			if ( defined($entry->get_value($key)) ) {
				push @adds, "$group_attr_map{$key}: " . $entry->get_value($key);
				push @dels, "$key";
				$entry->add( $group_attr_map{$key} => $entry->get_value($key) );
				$entry->delete( $key );
			}
		}
	}
	
	$ldif2->write_entry( $entry );
	if ( defined ( $is_samba_account ) || defined ( $is_samba_group ) ){
		if ( @adds + @dels > 0 ) {
			print "dn: " . $entry->dn . "\n";
			foreach $addition (@adds) {
				$addition =~ /(^\w+):/;
				print "add: " . $1  . "\n";
				print "$addition\n-\n";
			}
			foreach $deletion (@dels) {
				if ( $deletion =~ /^(\w+):\s(.*)/ ) {
					print "delete: $1\n$1: $2\n-\n";
				} else {
					print "delete: $deletion\n-\n"
				}
			}
			print "\n"
		}
	}
}


