2016-10-25 34 views
3

的CentOS-6.8的Perl,v5.10.1(*)爲x86_64的Linux的線程多怎樣才能提供IPC ::通過用戶輸入設置的參數包含嵌入的運行空白

這個問題從內置下降這一個Where is the shell command called which invokes OpenSSL commands?。簡而言之,我正在竊聽用於維護內部私有PKI的非常古老的Perl腳本,以便默認簽名哈希和密鑰大小滿足當前瀏覽器的要求。

我有這些代碼段:

. . .  
$args->{keypass} = $self->getPassword("Private key password",1) 
    unless $args->{keypass};  
$self->warn("# Password argument: $args->{keypass}\n") if $ENV{CSPDEBUG}; 
my $cmd = "-out $args->{keyfile} $args->{keysize}"; 
$cmd = "-des3 -passout pass:$args->{keypass} ".$cmd if defined($args->{keypass}); 
$self->{openssl}->cmd('genrsa',$cmd,$args); 
. . . 
$self->{openssl}->cmd('req',"-x509 $common_args -new -out $cacert",$args); 
. . . 
use IPC::Run qw(start pump finish timeout new_appender new_chunker); 
. . . 
sub cmd 
    { 
    my $self = shift; 
    my $cmd = shift; 
    my $cmdline = shift; 
    my $args = shift; 
    my $conf; 
    my $cfgcmd; 
. . . 
    $self->{_handle}->pump while length ${$self->{_in}}; 
. . . 

如果密碼參數值,所述用戶提供不包含空白然後根據需要此代碼執行。如果它包含嵌入式的空白空間,那麼代碼會自動失敗。如果傳遞給keypass的參數與開始和結束單引號連接,那麼代碼同樣會失敗。在兩種失敗案例中,腳本都報告成功。

爲什麼?

無論用戶輸入是否包含空格,該代碼是否有效需要進行哪些更改?

+0

讓我只是得到正確的問題,你試圖消除密碼字段中的任何空格,以確保它的工作?或者特別是爲了使其工作,即使密碼中有空格? –

+0

@ user2082599來自上一個問題和這裏的描述,我相信密碼可能包含空格。如果是這樣,程序將失敗,因爲命令行參數中的空白字符會丟失。引用它不起作用。 – simbabque

+0

@詹姆斯,請你突出顯示哪些參數是密碼?我不清楚這一點。 – simbabque

回答

1

要回答你的文字問題,讓我quote the IPC::Run manual

run()start()harness()可以拿線束規格爲輸入線束規格可以是一個單一字符串傳遞到系統'shell […]或要執行的命令,io操作和/或定時器/超時列表。「

爲了防止命令參數被shell解析(當參數包含空格時會導致事件中斷),您不應該將它們作爲單個字符串傳遞,而應該作爲對包含每個單獨的參數作爲一個字符串,像這樣:

my @cmd = ("-out", $args->{keyfile}, $args->{keysize}); 
unshift @cmd, ("-des3", "-passout", "pass:$args->{keypass}") if defined $args->{keypass}; 
# ... 
my $h = start ["openssl", "genrsa", @cmd], \$in, \$out; # or something equivalent 

(你已經發布的代碼似乎是使用IPC ::通過一些自定義的界面層運行,因爲你還沒有我們究竟出什麼層看起來像,我已經用IPC :: Run :: start的簡單調用來代替它。)


在任何情況下,請注意在命令行上傳遞密碼通常被認爲是不安全的:如果任何不受信任的用戶可以在同一臺服務器上運行代碼(即使在非特權帳戶下),只需運行ps ax即可看到密碼。 openssl manual注意到這一點,並警告pass:password「只能用於安全性不重要的地方。」

一個更安全的選擇是send the password over a separate file descriptor。方便地,IPC :: Run使這非常容易:

my @cmd = ("-out", $args->{keyfile}, $args->{keysize}); 
unshift @cmd, ("-des3", "-passout", "fd:3") if defined $args->{keypass}; 
# ... 
my $h = start ["openssl", "genrsa", @cmd], '<', \$in, '>', \$out, '3<', \$args->{keypass}; 

這裏,密碼通過文件描述符編號3傳遞;如果您需要傳入多個密碼,則可以使用文件描述符4,5等。 (描述符0,1和2是stdin,stdout和stderr。)

聲明:這顯然是所有未經測試的代碼。我不是IPC :: Run的專家,所以我可能犯了一些愚蠢的命令語法錯誤或其他錯誤。使用前請仔細測試!

+0

我的困難是對我來說都很陌生。我正在剽竊一種以我只有粗略知識的語言寫成的非常古老的第三方劇本;並且原作者已經移動並放棄了它。我需要通過對密鑰大小的默認值進行一些小的更改並改變簽名哈希算法來滿足當前的期望值。不幸的是,我偶然偶然發現了這個問題,因爲我希望得到一個合適的解決方案。簡單的解決方法就是不要使用帶空格的密碼短語。但這似乎是錯誤的。 –

+0

@ JamesB.Byrne:不幸的是,你需要修改的部分代碼是用'替換的代碼。 。在你的問題中。具體來說,大概有一個IPC :: Run'start()'調用在那裏,您需要修改以獲取數組引用而不是字符串。這可能需要至少基本熟悉Perl。如果你沒有這些,你的選擇基本上是1)拿一本好的介紹性的Perl書籍並學習,2)找到比你更懂Perl的其他人,或者3)放棄,記錄錯誤並繼續前進。 –

+0

首先,我需要建立我們的替代PKI。目前看來,這似乎不會成爲問題,因爲我似乎已經超越或避開了我遇到的障礙。重新編寫代碼以將整個程序從字符串切換到數組參數是不可能的,直到我找到時間,哪個資源的供應量很小。我可以直接使用openssl來更改密鑰上的密碼短語,從而獲得所需的結果,並避免重新編程腳本 - 這一過程無疑會揭示其他疣。 –

相關問題