#! /bin/sh
#
#This is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation.
#
# script to migrate existing NS to LDAP
# Useage: ldapmigrate [-y]
# $Id: ldapmigrate.sh,v 1.1.2.1 1999/01/18 04:33:47 greg Exp $

ETCDIR=/etc
# Magic to set host-specific options.
if [ `uname` = "Linux" ];then
DOMAINNAME=`hostname -d`
else if [ `uname` = "SunOS" ]; then
DOMAINNAME=`cat /etc/defaultdomain`
else echo "Unsupported platform,trying anyway.."
fi;fi
SUFFIX=`echo $DOMAINNAME |/bin/sed -e 's/\(.*\)\(\.\)/dc=\1,dc=/'`
PREFIX=`echo $DOMAINNAME |/bin/sed -e 's/\(.*\)\(\..*\)/\1/'`
VERSION=0
LDIFFILE=/tmp/migrate.ldif
BACKFILE=/tmp/migrate.bak

# Functions
userdiag () {
  echo -n "Name Service             : "
  if [ $YP = y ];then echo "NIS";else echo "Files";fi
  echo -n "Online/Offline Migration : "
  if [ $SLAP = y ];then echo "Online";else echo "Offline";fi
  echo    "Suffix                   : "$SUFFIX
  if [ $SLAP = y ]; then
    echo -n "Backup LDAP server       : "
    if [ $BACKUP = y ];then echo "Yes";else echo "No";fi
    echo    "LDAP Server name         : "$LDAPHOST
    echo    "Bind DN                  : "$BINDDN
    echo    "Bind Password            : "$BINDPW
  fi
  echo -n "Correct? [Y/N] "
  read YN
  if [ $YN = "Y"i ] || [ $YN = "y" ]; then return;fi 
  echo -n "Name Service [n]is or [f]iles: "
  read YP;if [ $YP = Y ];then YP=y;fi
  echo -n "Online Migration        [y/n]: "
  read SLAP;if [ $SLAP = Y ];then SLAP=y;fi
  echo -n "Suffix                       : "
  read SUFFIX
  if [ $SLAP = y ]; then
    echo -n "Backup LDAP server      [y/n]: "
    read BACKUP;if [ $BACKUP = Y ];then BACKUP=y;fi
    echo -n "LDAP Server name             : "
    read LDAPHOST
    echo -n "Bind DN                      : "
    read BINDDN
    echo -n "Bind Password                : "
    read BINDPW
  else
    LDAPHOST=""
    BINDDN=""
    BINDPW=""
  fi

  userdiag
}

#notes: must figure out if we're nis,files, or something else (dns?)
# handle shadow/nonshadow inteligently

#(if `ypwhich >/dev/null 2>&1`;then \
#  ypcat passwd;else cat $ETCDIR/passwd;fi)
echo "LDAP Nameservice migration tool"

if `ypwhich >/dev/null 2>&1`;then YP=y;else YP=f; fi
if [ `ps aux|grep -v grep|grep -c slapd` -gt "0" ];then
  SLAP=y
  BACKUP=y
  LDAPHOST=localhost
  BINDDN="cn=root,"$SUFFIX
  echo -n "Bind Password              : "
  read BINDPW
else
  SLAP=n
  BACKUP=n
fi
if [ "$1" != "-y" ];then userdiag;fi
if [ $SLAP = y ];then
  LOADCMD="/usr/bin/ldapadd -cr -D"$BINDDN" -w"$BINDPW" -h"$LDAPHOST" -f"
else
  LOADCMD="/usr/sbin/ldif2ldbm -j 5 -f $ETCDIR/ldap/slapd.conf -i"
fi

if [ $BACKUP = y ];then
  echo "Backing up server to "$BACKFILE
  ldapsearch -L -b"$SUFFIX" -D"$BINDDN" -w"$BINDPW" \
  -h"$LDAPHOST" "objectclass=*" >$BACKFILE
fi
 
echo "LDIF File will be saved in "$LDIFFILE
cp /dev/null $LDIFFILE
cat <<EOF >>$LDIFFILE
dn: $SUFFIX
dc: $PREFIX
objectclass: top
objectclass: domain

EOF
# Migrate passwords
echo "passwords..."
if [ $YP = y ];then
  PW_CAT=`ypcat passwd.byname`
else
  if [ -f $ETCDIR/shadow ];then
    PW_CAT=`/bin/awk 'BEGIN { FS=":"; OFS=":";
      while ( getline < "'$ETCDIR'/shadow" > 0) 
      shadow[$1] = $2 } /^[a-zA-Z0-9_]/ { $2 = shadow[$1];
      print $0 }' $ETCDIR/passwd`
  else
    PW_CAT=`cat $ETCDIR/passwd`
  fi
fi
echo "$PW_CAT" |/bin/awk 'BEGIN { FS=":" }
  /^[a-zA-Z0-9_]/ {
    print "dn: uid="$1",'$SUFFIX'"
    print "uid: "$1
    if ( $5 ) { split($5,a,","); print "cn: "a[1] }
    print "objectclass: top"
    print "objectclass: posixAccount"
    print "objectclass: account"
    if ( $7 ) { print "loginshell: "$7 }
    print "uidnumber: "$3
    print "gidnumber: "$4
    if ( $6 ) { print "homedirectory: "$6 }
    if ( $5 ) { print "gecos: "$5 }
    print "userpassword: {crypt}"$2
    print ""
 }' >>$LDIFFILE

# Migrate Services
echo "services..."
if [ $YP = y ];then
  SRV_CAT=`ypcat services.byname`
else
  SRV_CAT=`cat $ETCDIR/services`
fi
echo "$SRV_CAT" |/bin/awk 'BEGIN{ FS="[\t/ ]+" }
   /^[a-zA-Z0-9_]/ {
      print "dn: cn="$1"+ipServiceProtocol="$3",'$SUFFIX'"
      print "objectclass: ipService"
      print "objectclass: top"
      print "ipserviceport: "$2
      print "ipserviceprotocol: "$3
      print "cn: "$1
      for ( x = 4; !($x ~ /#/) && x <= NF;x++ ) { print "cn: "$x }
      print ""
}' >>$LDIFFILE

# Protocols
echo "protocols..."
if [ $YP = y ];then
  PROTO_CAT=`ypcat protocols.byname`
else
  PROTO_CAT=`cat $ETCDIR/protocols`
fi
echo "$PROTO_CAT" |/bin/awk '
  /^[a-zA-Z0-9_]/ {
    print "dn: cn="$1",'$SUFFIX'"
    print "objectclass: ipProtocol"
    print "objectclass: top"
    print "ipprotocolnumber: "$2
    print "cn: "$1
    for ( x = 3; !($x ~ /#/) && x <= NF;x++ ) { print "cn: "$x }
    print ""
}' >>$LDIFFILE

# Hosts
echo "hosts..."
if [ $YP = y ];then
  HOSTS_CAT=`ypcat hosts.byname`
else
  HOSTS_CAT=`cat $ETCDIR/hosts`
fi
echo "$HOSTS_CAT" |/bin/awk '
  /^[a-zA-Z0-9_]/ {
    split($2,sn,".")
    print "dn: cn="sn[1]",'$SUFFIX'"
    print "objectclass: top"
    print "objectclass: ipHost"
    print "objectclass: device"
    print "iphostnumber: "$1
    print "cn: "sn[1]
    for ( x = 3; !($x ~ /#/) && x <= NF;x++ ) { print "cn: "$x }
    print ""
}' >>$LDIFFILE

# Groups
echo "groups..."
if [ $YP = y ];then
  GROUP_CAT=`ypcat group.byname`
else
  GROUP_CAT=`cat $ETCDIR/group`
fi
echo "$GROUP_CAT" |/bin/awk 'BEGIN { FS="[:,]" }
  /^[a-zA-Z0-9_]/ {
    print "dn: cn="$1",'$SUFFIX'"
    print "objectclass: posixGroup"
    print "objectclass: top"
    print "cn: "$1
    print "gidnumber: "$3
    for ( x = 4; !($x ~ /#/) && x <= NF;x++ ) {
      if ($x ) { print "memberuid: "$x }
    }
    print ""
}' >>$LDIFFILE

# RPC
echo "rpc..."
if [ $YP = y ];then
  RPC_CAT=`ypcat rpc.bynumber`
else
  RPC_CAT=`cat $ETCDIR/rpc`
fi
echo "$RPC_CAT" |/bin/awk '
  /^[a-zA-Z0-9_]/ {
    print "dn: cn="$1",'$SUFFIX'"
    print "objectclass: oncRpc"
    print "objectclass: top"
    print "oncrpcnumber: "$2
    print "cn: "$1
    for ( x = 3; !($x ~ /#/) && x <= NF;x++ ) { print "cn: "$x }
    print ""
}' >>$LDIFFILE
echo Loading database with command:
echo $LOADCMD $LDIFFILE
if [ $SLAP = n ];then
($LOADCMD $LDIFFILE;rm $LDIFFILE) &
  while [ -f $LDIFFILE ];do
    for i in '/' '-' '\\' '|' '/' '-' '\\' '|';do
      sleep 1
      echo -ne $i"\b"
    done
  done
else
  $LOADCMD $LDIFFILE;rm $LDIFFILE
fi
echo "Migration Completed"
