获取由于遍历的目录不可执行而导致权限被拒绝的原因

Get reason for permission denied due to traversed directory not executable

我有一个文件 /a/b 可供用户 A 读取。但是/a没有给A提供可执行权限,所以路径/a/b无法遍历/a。对于任意长的路径,我如何确定由于用户无法访问中间路径而无法访问给定路径的原因?

事情是这样的:

#!/bin/bash
PAR=
PAR=${PAR:="."}
if ! [[ "${PAR:0:1}" == / || "${PAR:0:2}" == ~[/a-z] ]]
then
  TMP=`pwd`
  PAR=$(dirname ${TMP}/${PAR})
fi

cd $PAR 2> /dev/null
if [ $? -eq 1 ]; then
  while [ ! -z "$PAR" ]; do
    PREV=$(readlink -f ${PAR})
    TMP=$(echo ${PAR}|awk -F\/ '{$NF=""}'1|tr ' ' \/)
    PAR=${TMP%/}
    cd ${PAR} 2>/dev/null
    if [ $? -eq 0 ]; then
      if [ -e ${PREV} ]; then
        ls -ld ${PREV}
      fi
      exit
    fi
  done
fi

丑陋,但它会完成工作..

所以这个想法基本上是采用参数 $1,如果它不是绝对目录,将其扩展到这样,然后删除路径的最后一个元素并尝试 cd 进入它,如果失败,则 rince 并重复。 . 如果有效,PREV 将保留用户无法进入的最后一个目录,所以将其打印出来..

手动解析树并将错误精确定位到单行的替代答案是使用 namei 工具。

namei -mo a/b/c/d
f: a/b/c/d
 drwxrw-rw- rasjani rasjani a
 drw-rwxr-x rasjani rasjani b
                        c - No such file or directory

这显示了整个树结构和权限,直到权限被拒绝的条目。

这是我拼凑的。在写这篇文章之前,我实际上并没有看 rasjani 的回答,但它使用了相同的概念,你可以在其中获取命令的退出状态。基本上它会遍历所有目录(从链的最下方开始)并尝试 ls 它们。如果退出状态为 0,则 ls 成功,并打印出它无法 ls 的最后一个目录(我不确定在某些边缘情况下会发生什么,例如 where您无法访问 任何内容):

LAST=/a/b
while [ ! -z "$LAST" ] ; do
    NEXT=`echo "$LAST" | sed 's/[^\/]*$//' | sed 's/\/$//'`
    ls "$NEXT" 2> /dev/null > /dev/null
    if [ $? -eq 0 ] ; then 
        echo "Can't access: $LAST"
        break
    fi
    LAST="$NEXT"
done

我喜欢把这样的东西放在一行中只是为了好玩:

LAST=/a/b; while [ ! -z "$LAST" ] ; do NEXT=`echo "$LAST" | sed 's/[^\/]*$//' | sed 's/\/$//'`; ls "$NEXT" 2> /dev/null > /dev/null; if [ $? -eq 0 ] ; then echo "Can't access: $LAST"; break; fi; LAST="$NEXT"; done

我有下面的 C 程序供您执行此操作。以下是步骤

  1. 将程序复制并保存为 file.c。
  2. 用gcc编译程序file.c -o file
  3. 作为./file PATH
  4. 执行

假设您的路径为 /a/b/c/d 而您没有 'c' 的权限,那么输出将为

  Given Path = /a/b/c/d

  No permission on = /a/b/c

为了获得许可,我依赖 "EACCES" 错误。假设路径长度为 1024。

如果您有任何问题,请分享。

  #include <stdio.h>
  #include <string.h>
  #include <errno.h>

  #define MAX_LEN 1024

  int main(int argc, char *argv[])
  {
    char path[MAX_LEN] = "/home/sudhansu/Test";
    int i = 0;
    char parse[MAX_LEN] = "";

    if(argc == 2)
    {
      strcpy(path, argv[1]);
      printf("\n\t\t Given Path = %s\n", path);
    }
    else
    {
      printf("\n\t\t Usage : ./file PATH\n\n");
      return 0;
    }

    if(path[strlen(path)-1] != '/')
      strcat(path, "/");

    path[strlen(path)] = '[=11=]';

    while(path[i])
    {
      if(path[i] == '/')
      {
        strncpy(parse, path, i+1);
        if(chdir(parse) < 0)
        {
          if(errno == EACCES)
          {
            printf("\t\t No permission on = [%s]\n", parse);
            break;
          }
        }
      }

      parse[i] = path[i];
      i++;
    }

    printf("\n");
    return 0;
  }

此致, 苏丹苏