2016-06-26 56 views
3

我需要获取用户主文件夹。目前我使用这个无评估的Tilde扩展

home=$(eval echo ~$user) 

$user内容是由主叫方提供的,因此不被信任值。这里使用的危险是eval?如果是(可能),如何解决它没有它?

+0

类似'$(cd〜; pwd)'也许吧? – n0rd

+1

@ n0rd - 我认为OP意味着他们需要获得给定用户名的主文件夹,这是从不可信任来源指定的用户名。 –

+1

对于未经验证的*输入,'eval'是危险的;你可以确保'$ user'只包含一个有效的用户名,例如'[[$ user =〜[a-zA-Z] [a-zA-Z0-9_]]] && home = $(eval echo 〜$用户)'。 (我不记得具体是什么构成了一个有效的用户名,但它就像一个有效的标识符。) – chepner

回答

4

在拥有它的系统,你可以使用getent(1)

$ getent passwd "$username" | cut -d: -f 6 
/path/to/user/home 

确保虽然检查结果为空。

+0

很酷,我会与此一起去,谢谢。在我的Linux机器上工作。尽管如此,仍然看它是否也适用于cygwin。 – Paladin

1

Tilde扩展在解析过程中很早就发生,并且没有任何方法可以在没有多次评估的情况下实现您想要的功能。因此eval的一个解决方案。达到你想要什么,最安全的方式是:

eval "$(printf "home=~%q" "$user")" 

多亏了%q修改,扩展$user将全面引用,所以这里没有危险(不修改行虽然,你一定会介绍一些安全漏洞)。

自身,则不应使用这样的:这条线之后,你必须检查你得到一个有效的目录,例如,

if [[ ! -d $home ]]; then 
    echo >&2 "Couldn't find home dir for user $user" 
    exit 1 
fi 

而且考虑当user是空的:在这种情况下, home将是运行脚本的用户的主目录。你是否想要这种行为取决于你。

还有一点需要考虑:当user包含斜杠:是否需要此功能取决于您。

现在,这取决于你想拥有什么功能,它可能会更好,以验证扩展$user对一些预定义的模式一劳永逸,例如,

if [[ $user != [a-z]*([-a-z0-9_]) ]]; then 
    echo >&2 'Provided user doesn't match valid pattern' 
    exit 1 
fi 

而且事实证明,用此验证,您的解决方案很安全。


例子:

的情况一切正常:

$ user=gniourf 
$ eval "$(printf "home=~%q" "$user")" 
$ declare -p home 
declare -- home="/home/gniourf" 

,这将是你的代码的危险的情况(与您的代码,ls将被执行,而不是在这里) :

$ user='; ls >&2' 
$ eval "$(printf "home=~%q" "$user")" 
$ declare -p home 
declare -- home="~; ls >&2"