[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Clavier en qwerty dans luks



Bonjour,

Le vendredi 23 octobre 09 à 16:41, Christophe Mehay a écrit :
| J'ai reconfiguré les paquets (consolekit console-terminus console-setup
|     et console-tools avec dpkg-reconfigure) et exécuté "update-initramfs
| -u", mais luks est toujours en qwerty après reboot...

Je suis dans une configuration similaire (partition racine chiffrée avec
LUKS) et j'ai deux scripts qui manipulent le clavier.

En revanche, je ne sais pas du tout d'où ils viennent. Ils ne sont pas
issus directement d'un paquet, cryptsetup fournit des scripts qui
s'appellent pareil dans /usr/share, mais ils sont différents de ceux dans
/etc.

Je n'ai pas le temps d'investiguer plus, je les mets en pièce-jointe au
cas-où ça pourrait aider...

Seb
#!/bin/sh

PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case $1 in
prereqs)
	prereqs
	exit 0
	;;
esac

. /usr/share/initramfs-tools/hook-functions

get_root_device() {
	local device mount type options dump pass

	if [ ! -r /etc/fstab ]; then
		return 1
	fi

	grep '^[^#]' /etc/fstab | \
	while read device mount type options dump pass; do
		if [ "$mount" = "/" ]; then
			echo "$device"
			return
		fi
	done
}

get_resume_devices() {
	local device opt count dupe candidates devices
	candidates=""

	# First, get a list of potential resume devices

	# uswsusp
	if [ -e /etc/uswsusp.conf ]; then
		device=$(sed -rn 's/^resume device[[:space:]]+[:=][[:space:]]+// p' /etc/uswsusp.conf)
		if [ -n "$device" ]; then
			candidates="$candidates $device"
		fi
	fi

	# uswsusp - again...
	if [ -e /etc/suspend.conf ]; then
		device=$(sed -rn 's/^resume device[[:space:]]+[:=][[:space:]]+// p' /etc/suspend.conf)
		if [ -n "$device" ]; then
			candidates="$candidates $device"
		fi
	fi

	# regular swsusp
	for opt in $(cat /proc/cmdline); do
		case $opt in
		resume=*)
			device="${opt#resume=}"
			candidates="$candidates $device"
			;;
		esac
	done

	# initramfs-tools
	if [ -e /etc/initramfs-tools/conf.d/resume ]; then
		device=$(sed -rn 's/^RESUME[[:space:]]+=[[:space:]]+// p' /etc/initramfs-tools/conf.d/resume)
		if [ -n "$device" ]; then
			candidates="$candidates $device"
		fi
	fi

	# Now check the sanity of all candidates
	devices=""
	count=0
	for device in $candidates; do
		# Weed out clever defaults
		if [ "$device" = "<path_to_resume_device_file>" ]; then
			continue
		fi

		# Weed out duplicates
		dupe=0
		for opt in $devices; do
			if [ "$device" = "$opt" ]; then
				dupe=1
			fi
		done
		if [ $dupe -eq 1 ]; then
			continue
		fi

		# This device seems ok
		devices="$devices $device"
		count=$(( $count + 1 ))
	done

	if [ $count -gt 1 ]; then
		echo "cryptsetup: WARNING: found more than one resume device candidate:" >&2
		for device in $devices; do
			echo "                     $device" >&2
		done
	fi

	if [ $count -gt 0 ]; then
		echo $devices
	fi

	return 0
}

node_is_in_crypttab() {
	local node
	node="$1"

	grep -q ^$node /etc/crypttab
	return $?
}

get_lvm_deps() {
	local node deps maj min depnode
	node="$1"

	if [ -z $node ]; then
		echo "cryptsetup: WARNING: get_lvm_deps - invalid arguments" >&2
		return 1
	fi

	if ! deps=$(dmsetup deps "$node" 2> /dev/null | sed 's/[^:]*: *//;s/[ (]//g;s/)/ /g'); then
		echo "cryptsetup: WARNING: failed to find deps for $node" >&2
		return 1
	fi

	# We should now have a list of major,minor pairs, e.g. "3,2 3,3"
	for dep in $deps; do
		maj=${dep%,*}
		min=${dep#*,}
		depnode=$(dmsetup ls | sed -n "s/\\([^ ]*\\) *($maj, $min)/\\1/p")
		if [ -z "$depnode" ]; then
			continue
		fi
		if [ "$(dmsetup table $depnode 2> /dev/null | cut -d' ' -f3)" != "crypt" ]; then
			continue
		fi
		echo "$depnode"
	done

	return 0
}

get_device_opts() {
	local target source link extraopts rootopts opt
	target="$1"
	extraopts="$2"
	KEYSCRIPT=""
	OPTIONS=""

	if [ -z "$target" ]; then
		echo "cryptsetup: WARNING: get_device_opts - invalid arguments" >&2
		return 1
	fi

	opt=$( grep ^$target /etc/crypttab | head -1 | sed 's/[[:space:]]\+/ /g' )
	source=$( echo $opt | cut -d " " -f2 )
	key=$( echo $opt | cut -d " " -f3 )
	rootopts=$( echo $opt | cut -d " " -f4- )

	if [ -z "$opt" ] || [ -z "$source" ] || [ -z "$key" ] || [ -z "$rootopts" ]; then
		echo "cryptsetup: WARNING: invalid line in /etc/crypttab - $opt" >&2
		return 1
	fi

	# Sanity checks for $source
	if [ -h "$source" ]; then
		link=$(readlink -nqe "$source")
		if [ -z "$link" ]; then
			echo "cryptsetup: WARNING: $source is a dangling symlink" >&2
			return 1
		fi

		if [ "$link" != "${link#/dev/mapper/}" ]; then
			echo "cryptsetup: NOTE: using $link instead of $source for $target" >&2
			source="$link"
		fi
	fi

	# Sanity checks for $key
	if [ "$key" = "/dev/random" ] || [ "$key" = "/dev/urandom" ]; then
		echo "cryptsetup: WARNING: target $target has a random key, skipped" >&2
		return 1
	fi

	if [ -n "$extraopts" ]; then
		rootopts="$extraopts,$rootopts"
	fi

	# We have all the basic options, let's go trough them
	OPTIONS="target=$target,source=$source,key=$key"
	local IFS=", "
	for opt in $rootopts; do
		case $opt in
			cipher=*)
				OPTIONS="$OPTIONS,$opt"
				;;
			hash=*)
				OPTIONS="$OPTIONS,$opt"
				;;
			size=*)
				OPTIONS="$OPTIONS,$opt"
				;;
			lvm=*)
				OPTIONS="$OPTIONS,$opt"
				;;
			keyscript=*)
				opt=${opt#keyscript=}
				if [ ! -x "$opt" ]; then
					echo "cryptsetup: WARNING: target $target has an invalid keyscript, skipped" >&2
					return 1
				fi
				KEYSCRIPT="$opt"
				opt=$(basename "$opt")
				OPTIONS="$OPTIONS,keyscript=/keyscripts/$opt"
				;;
			*)
				# Presumably a non-supported option
				;;
		esac
	done

	# If keyscript is set, the "key" is just an argument to the script
	if [ "$key" != "none" ] && [ -z "$KEYSCRIPT" ]; then
		echo "cryptsetup: WARNING: target $target uses a key file, skipped" >&2
		return 1
	fi
}

get_device_modules() {
	local node value cipher blockcipher ivhash
	node="$1"

	# Check the ciphers used by the active root mapping
	value=$(dmsetup table "$node" | cut -d " " -f4)
	cipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f1)
	blockcipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f2)
	ivhash=$(echo "$value" | cut -d ":" -s -f2)

	if [ -n "$cipher" ]; then
		echo "$cipher"
	else
		return 1
	fi

	if [ -n "$blockcipher" ] && [ "$blockcipher" != "plain" ]; then
		echo "$blockcipher"
	fi

	if [ -n "$ivhash" ] && [ "$ivhash" != "plain" ]; then
		echo "$ivhash"
	fi
	return 0
}

prepare_keymap() {
	local env charmap

	# Allow the correct keymap to be loaded if possible
	if [ ! -x /bin/loadkeys ] || [ ! -r /etc/console/boottime.kmap.gz ]; then
		return 1
	fi

	copy_exec /bin/loadkeys /bin/
	cp /etc/console/boottime.kmap.gz $DESTDIR/etc/

	# Check for UTF8 console
	if [ ! -x /usr/bin/kbd_mode ]; then
		return 0
	fi

	if [ -r /etc/environment ]; then
		env="/etc/environment"
	elif [ -r /etc/default/locale ]; then
		env="/etc/default/locale"
	else
		return 0
	fi

	for var in LANG LC_ALL LC_CTYPE; do
		value=$(egrep "^[^#]*${var}=" $env | tail -n1 | cut -d= -f2)
		eval $var=$value
	done

	charmap=$(LANG=$LANG LC_ALL=$LC_ALL LC_CTYPE=$LC_CTYPE locale charmap)
	if [ "$charmap" = "UTF-8" ]; then
		copy_exec /usr/bin/kbd_mode /bin/
	fi
	return 0
}

add_device() {
	local node nodes opts lastopts i count
	nodes="$1"
	opts=""     # Applied to all nodes
	lastopts="" # Applied to last node

	if [ -z "$nodes" ]; then
		return 0
	fi

	# Check that it is a node under /dev/mapper/
	nodes="${nodes#/dev/mapper/}"
	if [ "$nodes" = "$1" ]; then
		return 0
	fi

	# Can we find this node in crypttab
	if ! node_is_in_crypttab "$nodes"; then
		# dm node but not in crypttab, is it a lvm device backed by dm-crypt nodes?
		lvmnodes=$(get_lvm_deps "$nodes") || return 1

		# not backed by any dm-crypt nodes; stop here
		if [ -z "$lvmnodes" ]; then
		    return 0
		fi

		# It is a lvm device!
		lastopts="lvm=$nodes"
		nodes="$lvmnodes"
	fi

	# Prepare to setup each node
	count=$(echo "$nodes" | wc -w)
	i=1
	for node in $nodes; do
		# Prepare the additional options
		if [ $i -eq $count ]; then
			if [ -z "$opts" ]; then
				opts="$lastopts"
			else
				opts="$opts,$lastopts"
			fi
		fi

		# Get crypttab root options
		if ! get_device_opts $node $opts; then
			continue
		fi
		echo "$OPTIONS" >> "$DESTDIR/conf/conf.d/cryptroot"

		# If we have a keyscript, make sure it is included
		if [ -n "$KEYSCRIPT" ]; then
			if [ ! -d "$DESTDIR/keyscripts" ]; then
				mkdir "$DESTDIR/keyscripts"
			fi
			copy_exec "$KEYSCRIPT" /keyscripts
		fi

		# Calculate needed modules
		modules=$(get_device_modules $node | sort | uniq)
		if [ -z "$modules" ]; then
			echo "cryptsetup: WARNING: failed to determine cipher modules to load for $node" >&2
			continue
		fi
		echo dm_mod
		echo dm_crypt
		echo "$modules"

		i=$(( $i + 1 ))
	done

	return 0
}


#
# Begin real processing
#

# Unless MODULES = "dep", we always add a basic subset of modules/tools
if [ "$MODULES" != "dep" ]; then
	for mod in dm_mod dm_crypt aes sha256 cbc; do
		manual_add_modules $mod
	done
	copy_exec /sbin/cryptsetup /sbin
	copy_exec /sbin/dmsetup /sbin
	prepare_keymap
fi

# We can't do anything without a config file
if [ ! -r /etc/crypttab ]; then
	exit 0
fi

# Find out which devices to add to the config file
rootdev=$(get_root_device)
if [ -z "$rootdev" ]; then
	echo "cryptsetup: WARNING: could not determine root device from /etc/fstab" >&2
fi
resumedevs=$(get_resume_devices)
if [ -z "$rootdev" ] && [ -z "$resumedevs" ]; then
	exit 0
fi

# Load the config opts and modules for each device
for dev in $rootdev $resumedevs; do
	if ! modules=$(add_device "$dev"); then
		echo "cryptsetup: FAILURE: could not determine configuration for $dev" >&2
		continue
	fi

	for mod in $modules; do
		manual_add_modules $mod
	done
done

# Prepare the initramfs
copy_exec /sbin/cryptsetup /sbin
copy_exec /sbin/dmsetup /sbin
prepare_keymap

# Done
exit 0
#!/bin/sh

#
# Standard initramfs preamble
#
prereqs()
{
	# Make sure that cryptroot is run last in local-top
	for req in /scripts/local-top/*; do
		script=$(basename $req)
		if [ $script != cryptroot ]; then
			echo $script
		fi
	done
}

case $1 in
prereqs)
	prereqs
	exit 0
	;;
esac


#
# Helper functions
#
parse_options()
{
	local cryptopts
	cryptopts="$1"

	if [ -z "$cryptopts" ]; then
		return 1
	fi

	# Defaults
	cryptcipher=aes-cbc-essiv:sha256
	cryptsize=256
	crypthash=sha256
	crypttarget=cryptroot
	cryptsource=""
	cryptlvm=""
	cryptkeyscript=""
	cryptkey="" # This is only used as an argument to an eventual keyscript

	local IFS=" ,"
	for x in $cryptopts; do
		case $x in
		hash=*)
			crypthash=${x#hash=}
			;;
		size=*)
			cryptsize=${x#size=}
			;;
		cipher=*)
			cryptcipher=${x#cipher=}
			;;
		target=*)
			crypttarget=${x#target=}
			;;
		source=*)
			cryptsource=${x#source=}
			;;
		lvm=*)
			cryptlvm=${x#lvm=}
			;;
		keyscript=*)
			cryptkeyscript=${x#keyscript=}
			;;
		key=*)
			if [ "${x#key=}" != "none" ]; then
				cryptkey=${x#key=}
			fi
			;;
		esac
	done

	if [ -z "$cryptsource" ]; then
		echo "cryptsetup: source parameter missing"
		return 1
	fi
	return 0
}

activate_vg()
{
	local vg
	vg="${1#/dev/mapper/}"

	# Sanity checks
	if [ ! -x /sbin/vgchange ] || [ "$vg" = "$1" ]; then
		return 1
	fi

	# Make sure that the device contains at least one dash
	if [ "${vg%%-*}" = "$vg" ]; then
		return 1
	fi

	# Split volume group from logical volume.
	vg=$(echo ${vg} | sed -e 's#\(.*\)\([^-]\)-[^-].*#\1\2#')

	# Reduce padded --'s to -'s
	vg=$(echo ${vg} | sed -e 's#--#-#g')

	vgchange -ay ${vg}
	return $?
}

activate_evms()
{
	local dev module
	dev="${1#/dev/evms/}"

	# Sanity checks
	if [ ! -x /sbin/evms_activate ] || [ "$dev" = "$1" ]; then
		return 1
	fi

	# Load modules used by evms
	for module in dm-mod linear raid0 raid1 raid10 raid5 raid6; do
		modprobe -q $module
	done

	# Activate it
	/sbin/evms_activate
	return $?
}

load_keymap()
{
	local opts
	opts="-q"

	# Should terminal be in UTF8 mode?
	if [ -x /bin/kbd_mode ]; then
		/bin/kbd_mode -u
		opts="$opts -u"
	fi

	# Load custom keymap
	if [ -x /bin/loadkeys -a -r /etc/boottime.kmap.gz ]; then
		loadkeys $opts /etc/boottime.kmap.gz
	fi
}

setup_mapping()
{
	local opts count cryptcreate cryptremove NEWROOT
	opts="$1"

	if [ -z "$opts" ]; then
		return 0
	fi

	parse_options "$opts" || return 1

	# The same target can be specified multiple times
	# e.g. root and resume lvs-on-lvm-on-crypto
	if [ -e "/dev/mapper/$crypttarget" ]; then
		return 0
	fi

	modprobe -q dm_crypt
	
	# Add delay
    	echo "Sleeping for 5 seconds to allow USB detection."
	sleep 5
	echo "Awake, attempting to mount encrypted partitions."

	echo "Setting up cryptographic volume $crypttarget (based on $cryptsource)"

	# Make sure the cryptsource device is available
	if [ ! -e $cryptsource ]; then
		activate_vg $cryptsource
		activate_evms $cryptsource
	fi

	if [ ! -e $cryptsource ]; then
		echo "cryptsetup: Source device $cryptsource not found"
		return 1
	fi

	# Prepare commands
	if /sbin/cryptsetup isLuks $cryptsource > /dev/null 2>&1; then
		cryptcreate="/sbin/cryptsetup luksOpen $cryptsource $crypttarget"
	else
		cryptcreate="/sbin/cryptsetup -c $cryptcipher -s $cryptsize -h $crypthash create $crypttarget $cryptsource"
	fi
	cryptremove="/sbin/cryptsetup remove $crypttarget"
	NEWROOT="/dev/mapper/$crypttarget"

	# Try to get a satisfactory password three times
	count=0
	while [ $count -lt 3 ]; do
		count=$(( $count + 1 ))

		if [ -n "$cryptkeyscript" ]; then
			if [ ! -x "$cryptkeyscript" ]; then
				echo "cryptsetup: error - $cryptkeyscript missing"
				return 1
			fi
			$cryptkeyscript $cryptkey < /dev/console | $cryptcreate --key-file=-
		else
			$cryptcreate < /dev/console
		fi

		if [ $? -ne 0 ]; then
			echo "cryptsetup: cryptsetup failed, bad password or options?"
			sleep 3
			continue
		elif [ ! -e "$NEWROOT" ]; then
			echo "cryptsetup: unknown error setting up device mapping"
			return 1
		fi

		FSTYPE=''
		eval $(fstype < "$NEWROOT")

		# See if we need to setup lvm on the crypto device
		if [ "$FSTYPE" = "lvm" ] || [ "$FSTYPE" = "lvm2" ]; then
			if [ -z "$cryptlvm" ]; then
				echo "cryptsetup: lvm fs found but no lvm configured"
				return 1
			elif ! activate_vg "/dev/mapper/$cryptlvm"; then
				echo "cryptsetup: failed to setup lvm device"
				return 1
			fi

			NEWROOT="/dev/mapper/$cryptlvm"
			eval $(fstype < "$NEWROOT")
		fi

		if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then
			echo "cryptsetup: unknown fstype, bad password or options?"
			$cryptremove
			sleep 3
			continue
		fi

		break
	done

	if [ $count -lt 3 ]; then
		return 0
	else
		echo "cryptsetup: maximum number of tries exceeded"
		return 1
	fi
}

#
# Begin real processing
#

# If possible, load the keymap so that the user can input non-en characters
load_keymap

# Do we have any kernel boot arguments?
found=''
for opt in $(cat /proc/cmdline); do
	case $opt in
	cryptopts=*)
		found=yes
		setup_mapping "${opt#cryptopts=}"
		;;
	esac
done

if [ -n "$found" ]; then
	exit 0
fi

# Do we have any settings from the /conf/conf.d/cryptroot file?
if [ -r /conf/conf.d/cryptroot ]; then
	while read mapping; do
		setup_mapping "$mapping"
	done < /conf/conf.d/cryptroot
fi

exit 0

Reply to: