diff -ru portage-2.1.1-orig/bin/misc-functions.sh portage-2.1.1/bin/misc-functions.sh --- portage-2.1.1-orig/bin/misc-functions.sh 2006-10-18 05:25:29.000000000 +0200 +++ portage-2.1.1/bin/misc-functions.sh 2006-10-18 05:25:51.000000000 +0200 @@ -287,35 +287,156 @@ eerror "${FUNCNAME}: IMAGE is unset" return 1 fi - # total suid control. - if hasq suidctl $FEATURES; then - sfconf=/etc/portage/suidctl.conf - vecho ">>> Performing suid scan in ${IMAGE}" - for i in $(find ${IMAGE}/ -type f \( -perm -4000 -o -perm -2000 \) ); do - if [ -s "${sfconf}" ]; then - suid="$(grep ^${i/${IMAGE}/}$ ${sfconf})" - if [ "${suid}" = "${i/${IMAGE}/}" ]; then - vecho "- ${i/${IMAGE}/} is an approved suid file" + + ### + ### Controls permissions of files with SetId permissions. + ### + ### Todo: + ### - Add a bit of flexibility to the file format (comments everywhere, + ### decorating spaces, and maybe allow space characters + ### as field separators... -the file is grealty easier to read + ### with tabulations, though the line length greatly increase...). + ### - Maybe support empty fields (they would match any value...), though it + ### greatly diminishes the usefulness of the setid-control feature. + ### - Maybe support more flexible file permissions (like "ugo-s", + ### for the last field -well, for now, it works out of the box, + ### but we might try some checks on this field, so we me think a bit + ### about it). + ### - Maybe support to configure the user and group to set, + ### for full customization... + ### - Maybe add a check to inform the user when an entry is outdated and + ### might be removed (like the original file + ### does not have SetId permissions set anymore). + ### + + ### Defines miscellaneous needed variables. + local SetId_control_feature_name="setid-control" + local SetId_control_configuration_file_path="/etc/portage/setid-control.conf" + local SetId_permissions_to_set_field_index="6" + + ### Checks that the SetId control feature is activated. + if hasq "${SetId_control_feature_name}" "${FEATURES}" + then + vecho ">>> Performing SetId scan in \"${IMAGE}\"..." + + ### Loop on files with SetId permissions. + for File_virtual_path in $(find "${IMAGE}/" -type f -perm -4000 -o -perm -2000) + do + ### Defines variables for needed informations about the package and file. + local Package_category_and_name="${CATEGORY}/${PN}" + local File_absolute_path="${File_virtual_path#${IMAGE}}" + local File_user=$(find "${File_virtual_path}" -printf "%u") ### "%u" means the file owner name or id + local File_group=$(find "${File_virtual_path}" -printf "%g") ### "%g" means the file group name or id + local File_permissions=$(find "${File_virtual_path}" -printf "%04m") ### "%04m" means the file permissions (with leading zeros) + + ### Tries to match the file with existing entries + ### from the configuration file. Notes we do not care if + ### the configuration file does not exist, as it is handled later. + ### ("-m" means "--max-count"; "-E" means "--extended-regexp") + ### @todo Maybe check the fields individually, for customized + ### warning messages (well, probably overkill). + ### @todo For the regex ending, if there are spaces (though illegal + ### as per configuration file format specifications), + ### accept the line... as we do not use the + ### file permission field elsewhere, for now, this is ok, + ### but if we later parse the entry to get + ### the value of this field, the spaces will have + ### to be removed. + Needed_entry_regex="${Package_category_and_name}:${File_virtual_path}:${File_user}:${File_group}:${File_permissions}([[:space:]]*|:.*)$" + Authorization_entry=$(grep -m 1 -E "^${Needed_entry_regex}" "${SetId_control_configuration_file_path}") + + ### Checks if the file matched an existing entry + ### from the configuration file. + if [ -n "${Authorization_entry}" ] + then + ### Gets the file permissions to set, from + ### the authorization entry, if present. + ### ("-d" means "--delimiter"; "-f" means "--fields") + File_permissions_to_set=$(echo "${Authorization_entry}" | cut -d ":" -f "${SetId_permissions_to_set_field_index}") + + ### Keeps the file permissions as is, if + ### the file permission to set field is not present, or empty, + ### or identical to the file original permissions. + if [ -z "${File_permissions_to_set}" ] || [ "${File_permissions_to_set}" = "${File_permissions}" ] + then + vecho ">>> File \"${File_absolute_path}\" requested SetId permissions, and has been authorized to keep them, as per configuration." + + ### Continues to the next file with SetId permissions. + continue else - vecho ">>> Removing sbit on non registered ${i/${IMAGE}/}" - for x in 5 4 3 2 1 0; do echo -ne "\a"; sleep 0.25 ; done - vecho -ne "\a" - ls_ret=$(ls -ldh "${i}") - chmod ugo-s "${i}" - grep ^#${i/${IMAGE}/}$ ${sfconf} > /dev/null || { - # sandbox prevents us from writing directly - # to files outside of the sandbox, but this - # can easly be bypassed using the addwrite() function - addwrite "${sfconf}" - vecho ">>> Appending commented out entry to ${sfconf} for ${PF}" - echo "## ${ls_ret%${IMAGE}*}${ls_ret#*${IMAGE}}" >> ${sfconf} - echo "#${i/${IMAGE}/}" >> ${sfconf} - # no delwrite() eh? - # delwrite ${sconf} - } + vecho ">>> File \"${File_absolute_path}\" requested SetId permissions, and is registered, so we will apply the configuration..." + + ### Sets the file permission, as per configuration. + ### @todo Sanity checks on file permissions to set? + chmod "${File_permissions_to_set}" "${File_virtual_path}" + + File_set_permissions=$(find "${File_virtual_path}" -printf "%04m") ### "%04m" means the file permissions (with leading zeros) + + vecho ">>> File \"${File_absolute_path}\" now has permissions: \"${File_set_permissions}\" (previously: \"${File_permissions}\")." + + ### Continues to the next file with SetId permissions. + continue fi + + #Checks that the file owner, group and permissions, match. else - vecho "suidctl feature set but you are lacking a ${sfconf}" + vecho ">>> File \"${File_absolute_path}\" requested SetId permissions, but is unregistered, so we will strip them..." + + ### Removes the SetId permissions from the file. + chmod ugo-s "${File_virtual_path}" + + ### Defines the secure SetId permissions (ie., no SetId permissions). + Secure_SetId_permissions=$(find "${File_virtual_path}" -printf "%04m") ### "%04m" means the file permissions (with leading zeros) + + ### Constructs a configuration file default (secure) entry for the current file. + Default_entry="${Package_category_and_name}:${File_absolute_path}:${File_user}:${File_group}:${File_permissions}:${Secure_SetId_permissions}" + + ### Creates the configuration file parent directory, if needed. + if [ ! -d $(dirname "${SetId_control_configuration_file_path}") ] + then + addwrite "/" ### Sandbox bypassing + mkdir -p $(dirname "${SetId_control_configuration_file_path}") + export SANDBOX_WRITE="${SANDBOX_WRITE%:/}" ### Sandbox restoring + fi + + ### Creates a base configuration files, if not present (for the comments on the file format). + if [ ! -f "${SetId_control_configuration_file_path}" ] + then + SetId_control_default_configuration_file_path="/usr/share/portage/setid-control.conf.default" ### !!! Place it elsewhere? (directly in "/etc/portage"? -without the ".default" suffix-, in which case this block should be removed) + addwrite "${SetId_control_configuration_file_path}" ### Sandbox bypassing + cp "${SetId_control_default_configuration_file_path}" "${SetId_control_configuration_file_path}" + export SANDBOX_WRITE="${SANDBOX_WRITE%:${SetId_control_configuration_file_path}}" ### Sandbox restoring + fi + + ### Adds the default entry to the configuration file. + addwrite "${SetId_control_configuration_file_path}" ### Sandbox bypassing + echo "${Default_entry}" >> "${SetId_control_configuration_file_path}" + export SANDBOX_WRITE="${SANDBOX_WRITE%:${SetId_control_configuration_file_path}}" ### Sandbox restoring + + ### Displays a warning. + ebeep 3 && epause 5 + ewarn + ewarn "You have the \"${SetId_control_feature_name}\" feature set in your \"/etc/make.conf\" file," + ewarn "and the current package requests SetId permissions for the file:" + ewarn "\"${File_absolute_path}\"," + ewarn "which cannot be found in the SetId control configuration file." + ewarn + ewarn "If you already have an entry, for the same package and file path," + ewarn "it probably means that the file user, group, or original permissions," + ewarn "have changed. In this case, check the default entry which was added" + ewarn "to the configuration file, and adapt your configuration as needed." + ewarn + ewarn "The following default (secure) entry was added to the configuration file" + ewarn "(${SetId_control_configuration_file_path}):" + ewarn "${Default_entry}" + ewarn + ewarn "The file has been stripped from its SetId permissions. If know what" + ewarn "you are doing, and want \`emerge\` to keep these permissions, follow" + ewarn "the instructions from the SetId control configuration file." + ewarn + + ### Continues to the next file with SetId permissions. + continue fi done fi