#!/usr/bin/perl
#Copyright (c) 2006, Midwest Connections Inc.
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without 
#modification, are permitted provided that the following conditions are met:
#
#    * Redistributions of source code must retain the above copyright notice,
#		this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright notice,
#		this list of conditions and the following disclaimer in the documentation
#		and/or other materials provided with the distribution.
#    * Neither the name of the Midwest Connections Inc. nor the names of its
#		contributors may be used to endorse or promote products derived from
#		this software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
#FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#written by Zane C. Bowers <zanecb@midwest-connections.com>

use strict;
use warnings;
use Getopt::Std;

my %opts=();
getopts('o:G:U:p:s:g:', \%opts);
#o=out prepend
#G=group base
#U=user base
#p=passwd file
#s=shadow file
#g=group file

my %config=();

if(!defined($opts{o})){
	$config{prepend}="";
};

if (!defined($opts{G}) ||
	!defined($opts{U}) ||
	!defined($opts{p}) ||
	!defined($opts{s}) ||
	!defined($opts{g})){
	
	print "-G, -U, -p, -s, or -g is not given\n\n".
		"-G = group base DN\n".
		"-U = user base DN\n".
		"-p = passwd file\n".
		"-s = shadow file\n".
		"-g = group file\n";

	exit 1;
};

$config{groupDN}=$opts{G};
$config{userDN}=$opts{U};
$config{passwd}=$opts{p};
$config{shadow}=$opts{s};
$config{group}=$opts{g};

if (!-f $config{passwd}){
	print $config{passwd}." is not a file\n";
	exit 1;
};

if (!-f $config{shadow}){
	print $config{shadow}." is not a file\n";
	exit 1;
};

if (!-f $config{group}){
	print $config{group}." is not a file\n";
	exit 1;
};


open(GROUP,"<", $config{group});
my @group_array=grep(!/^#/,<GROUP>);
close(GROUP);

open(GROUP_WRITE,">", $config{prepend}."group.ldif");

my $count=0;
while(defined($group_array[$count])){
	chomp($group_array[$count]);
	my ($gname, $gpass, $gid, $gmembers)=split(/:/, $group_array[$count]);
	
	if (defined($gname) && defined($gid)){
		print GROUP_WRITE "dn: cn=".$gname.",".$config{groupDN}."\n".
			"cn: ".$gname."\n".
			"gidNumber: ".$gid."\n";

		if (defined($gmembers)){
			my @gmembers_array=split(/,/, $gmembers);
			my $gmember_count=0;
			while (defined($gmembers_array[$gmember_count])){
				if ($gmembers_array[$gmember_count] ne ""){
					print GROUP_WRITE "memberUid: ".$gmembers_array[$gmember_count]."\n";
				};
				$gmember_count++;
			};
		};
		
		print GROUP_WRITE "\n";
		
	};

	$count++;
};

close(GROUP_WRITE);

open(SHADOW,"<", $config{shadow});
my @shadow_array=grep(!/^#/,<SHADOW>);
close(SHADOW);

my %shadow=();
$count=0;
while(defined($shadow_array[$count])){
	chomp($shadow_array[$count]);
	my ($uname, $pass)=split(/:/, $shadow_array[$count]);
	
	$shadow{$uname}={pass => $pass};
	
	$count++;
};

open(PASSWD,"<", $config{passwd});
my @passwd_array=grep(!/^#/,<PASSWD>);
close(PASSWD);

open(USER_WRITE,">", $config{prepend}."user.ldif");

$count=0;
while(defined($passwd_array[$count])){
	chomp($passwd_array[$count]);
	my ($uname, $upass, $uid, $gid, $gecos, $home, $shell)=split(/:/, $passwd_array[$count]);
	
	if (defined($uname) && (defined($uid) && (defined($gid) && (defined($home) && defined($shell))))){
		print USER_WRITE "dn: uid=".$uname.",".$config{userDN}."\n".
			"cn: ".$uname."\n".
			"uid: ".$uname."\n".
			"uidNumber: ".$uid."\n".
			"gidNumber: ".$gid."\n".
			"homeDirectory: ".$home."\n".
			"loginShell: ".$shell."\n".
			"userPassword: {crypt}".$shadow{$uname}{pass}."\n";

	};
	print USER_WRITE "\n";
	$count++;
};

close(USER_WRITE);

exit 0;

#-----------------------------------------------------------
# POD documentation section
#-----------------------------------------------------------

=head1 NAME

californicus-linux - convert group, passwd, and shadow files into LDIFs

=head1 SYNOPSIS

coalifornicus-linux B<-G> group base DN B<-U> user base DN B<-p> passwd file
B<-g> group file B<-s> shadow file [B<-o> output file prepend]

=head1 DESCRIPTION

It takes the specified shadow, passwd, and group file and generates two LDIFs. The
prepend, specified using -o, is applied to both group.ldif and user.ldif.

=head1 SWITCHES

=item B<-G> group base DN

This is the switch for the base DN that will be used for when generating the group file.
It should be pointed to where the groups are stored in your LDAP directory.

=item B<-U> user base DN

This switch specifies the base DN that will be used for when generating the user file.
It should be pointed to where the users are stored in your LDAP directory.

=item B<-g> group file

This is the group file that will be used for generating group.ldif.

=item B<-p> passwd file

This is the passwd file to be used for generating the user.ldif.

=item B<-s> shadow file

This is the passwd file to be used for the source of password hashes for when
generating user.ldif.

=item B<-o> output prepend

This will prepended to user.ldig and group.ldif.

=head1 Example

=item californicus-linux -G ou=groups,dc=fu,dc=bar -U ou=users,dc=fu,dc=bar -g ./group -u ./passwd -s ./shadow -o fu.bar-

Will generate fu.bar-group.ldif and fu.bar-user.ldif from group, passwd, and shadow in the current directory.

=head1 AUTHOR

Copyright (c) 2006, Midwest Connections Inc.

All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
    * Neither the name of the Midwest Connections Inc. nor the names of its
     contributors may be used to endorse or promote products derived from
     this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

written by Zane C. Bowers <zanecb@midwest-connections.com>

=head1 SCRIPT CATEGORIES

Unix/System_administration

=head1 OSNAMES

any

=head1 README

californicus-linux is a tool for taking a passwd, group, and shadow file and generating a LDIF for them.

=head1 CHANGELOG

=head2 2006-10-24

=item version 1.0.0

I am now considering this done.

=cut

#-----------------------------------------------------------
# End of POD documentation
#-----------------------------------------------------------
