Linux で $HOME/.forward ファイルを書き換えるCGIを作りたいです。

私にはその為の難題が 2つあります。

1) 認証の方法が分かりません
/etc/{passwd,shadow} を使う!?
web で perl の getpwent関数を使ってるのを探したが、使い物にならなかった。

2) ファイルの書き換え方法が分かりません
CGIプロセスオーナーとファイル所有者の権限問題

言語は perl/ruby のいづれかで、具体的な回答が欲しいです。

回答の条件
  • 1人3回まで
  • 登録:2007/07/09 16:51:43
  • 終了:2007/07/16 16:55:03

回答(2件)

id:tombe No.1

tombe回答回数38ベストアンサー獲得回数72007/07/09 23:30:23

ポイント35pt

これはサーバーや開発環境の条件次第ですので、具体的なPGコードはとりあえず省略しますが、概略としては以下のような方法があります。


【方法1】Apache の SuExec 機能を使う

http://www.google.co.jp/search?hl=ja&q=apache+suexec&btn...

これは簡単に言うと、CGIプロセスを各ユーザー権限で動作させる仕組みです。

SuExecを使わない通常の設定の場合、CGIプロセスはApache権限(nobody とか www とか)で動作する為、$HOME/.forwardとかのファイルは書き込み出来きません。

SuExecを使えば、CGIプロセスがユーザー権限(仮にhoge)で動作するので、hogeオーナーのファイルを読み書きできます。

プログラム側の対処は特に必要ありません。認証手続きも必要ありません。単にファイルオープンして read、writeするだけです。

当然ながら自分でApacheの設定変更が出来るという条件が前提です。通常のレンタル・サーバー等ではまず無理かもしれませんが、たまにSuExec設定のサーバーもあります。

------------------

【方法2】sudoを使う

sudoの検索

http://www.google.co.jp/search?hl=ja&q=linux+sudo&btnG=%...

Perlのsudoモジュール

http://search.cpan.org/~landman/Sudo-0.32/lib/Sudo.pm

sudoは特定のユーザー権限でコマンドを実行するコマンドです。

ただし、これはパスワード入力に特徴があって、端末(Puttyとかのターミナルソフト)から直接sudoを起動する場合は手動でパスワードを入力すれば良いのですが、プログラムから、例えばPerlのsystem()関数を使ってsudoを起動するのは困難です。なぜならsudoは端末を持っていないプロセス(この場合CGIプロセス)からのパスワードを受け付けないからです。

これを容易にするのが上記のPerlモジュールです。

------------------

【方法3】ftpを使う

Perl Net::FTP

http://search.cpan.org/~gbarr/libnet-1.21/Net/FTP.pm

同じサーバー上でftpでファイル転送してしまう方法。

馬鹿らしいかもしれませんが、ftpログインさえできれば、サーバーの設定を変更する必要がありません。

id:fellowbx No.2

fellowbx回答回数17ベストアンサー獲得回数02007/07/10 22:25:24

ポイント35pt

ncftpクライアントを使えば、以下のスクリプトを改良して実現できるのでは?

$HOME/.forward を生成するわけではないので、ちゃんと最初にオーナーをユーザに、権限を0755など、サーバ管理上適切な値にしておく必要アリ。

/etc/profile に.forwardを事前作成しておくと、ID新規作成のときも楽かもね。

###.###.###.###はメールサーバを指定。Firewallの設定変更が必要かも。

あまり参考となるスクリプトはないかもね。以下のスクリプトは自作出典ナリ。ユーザIDとメールアドレス(@の前)が同一である条件で。

<h3>o- *********</h3>

HTML(必要部分のみ)権限(0644)

<h3>o- *********</h3>

forwarding

<form action="./forward.cgi" method="post">

account<input name="USERNAME">

password<input type="password" name="PASSWORD">

forwarding to...

<input name="EMAIL">

<input name="EMAIL2">

<input name="EMAIL3">

<input type="hidden" name="MODE" value="forward">

<input type="submit" value="set">

</form>

verify

<form action="./forward.cgi" method="post">

account<input name="USERNAME">

password<input type="password" name="PASSWORD">

<input type="hidden" name="MODE" value="verify">

<input type="submit" value="verify">

</form>

<form action="./forward.cgi" method="post">

account<input name="USERNAME">

password<input type="password" name="PASSWORD">

<input type="hidden" name="MODE" value="unset">

<input type="submit" value="unset">

</form>

<h3>o- *********</h3>

CGI権限(0755)

<h3>o- *********</h3>

#!/usr/bin/perl -w

$header = <<'_EOF_';

Content-type: text/html; charset=euc-jp

<html><head><title>CGI Title</title></head>

<body><h2>mail setting</h2>

_EOF_

$footer='</body></html>';

if($ENV{'REQUEST_METHOD'}eq"POST"){

read(STDIN,$query_string,$ENV{'CONTENT_LENGTH'});

@a=split(/&/,$query_string);

foreach $x(@a){

($name,$value)=split(/=/,$x);

$name=~tr/+/ /;

$name=~s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;

$value=~tr/+/ /;

$value=~s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg;

$value=~s/[\r\n]+/\n/g;

if($FORM{$name}eq""){

$FORM{$name}=$value;

$FORM[$cnt++]=$name;

}else{

$FORM{$name}.=(" ".$value);

}}}

$UN=$FORM{'USERNAME'};

$PW=$FORM{'PASSWORD'};

if($FORM{'USERNAME'}eq''){

print "$header
Error$footer";

}elsif($FORM{'PASSWORD'}eq''){

print "$header
Error$footer";

}else {

if("$FORM{'MODE'}"eq"unset"){

open(OUT,"> /tmp/.forward");

close(OUT);

system("/usr/local/bin/ncftpput -u $UN -p $PW ###.###.###.### .\/ \/tmp\/.forward\n");

system("echo $? > /tmp/result");

$result=`/bin/cat /tmp/result`;

if($result!=0){

print "$header
Error$footer";

}else{

print "$header
unset forward$footer";

}}

if("$FORM{'MODE'}"eq"forward"){

$FORM{'EMAIL'}=~ /^[^@]+@[^.]+\..+/;

$FORM{'EMAIL2'} =~ /^[^@]+@[^.]+\..+/;

$FORM{'EMAIL3'} =~ /^[^@]+@[^.]+\..+/;

if($FORM{'EMAIL'}eq''){

$FORM{'EMAIL'}=$FORM{'EMAIL2'};

$FORM{'EMAIL2'}='';

}

if($FORM{'EMAIL2'}eq''){

$FORM{'EMAIL2'}=$FORM{'EMAIL3'};

$FORM{'EMAIL3'}='';

}

if( $FORM{'EMAIL'}eq''){

$FORM{'EMAIL'}=$FORM{'EMAIL2'};

$FORM{'EMAIL2'}='';

}

if("$FORM{'EMAIL'}$FORM{'EMAIL2'}$FORM{'EMAIL3'}"eq''){

print "$header
Error$footer";

}else{

open(OUT,"> /tmp/.forward");

if($FORM{'EMAIL'}ne''){

print OUT "$FORM{'EMAIL'}\n";

}

if($FORM{'EMAIL2'}ne''){

print OUT "$FORM{'EMAIL2'}\n";

}

if($FORM{'EMAIL3'}ne''){

print OUT "$FORM{'EMAIL3'}\n";

}

print OUT "$UN";

close(OUT);

system("/usr/local/bin/ncftpput -u $UN -p $PW ###.###.###.### .\/ \/tmp\/.forward\n");

system("echo $? > /tmp/result");

$result=`/bin/cat /tmp/result`;

if($result!=0){

print "$header
Error$footer";

}else{

print "$header
forwarding...";

print "$FORM{'EMAIL'}\n";

print ",$FORM{'EMAIL2'}\n" if($FORM{'EMAIL2'}ne'');

print ",$FORM{'EMAIL3'}\n" if($FORM{'EMAIL3'}ne'');

print "$footer";

}}}

if("$FORM{'MODE'}"eq"verify"){

system("rm -f /tmp/.forward");

system("/usr/local/bin/ncftpget -u $UN -p $PW ###.###.###.### \/tmp\/ .\/.forward\n");

system("echo $? > /tmp/result");

$result=`/bin/cat /tmp/result`;

if($result!=0){

open(OUT, "> /tmp/.forward");

close(OUT);

system("/usr/local/bin/ncftpput -u $UN -p $PW ###.###.###.### . \/tmp\/.forward\n");

system("echo $? > /tmp/result");

$result=`/bin/cat /tmp/result`;

if($result!=0){

print "$header
Error$footer";

}else{

system("rm -f /tmp/.forward");

system("/usr/local/bin/ncftpget -u $UN -p $PW ###.###.###.### \/tmp\/ .\/.forward\n");

system("echo $? > /tmp/result");

$result=`/bin/cat /tmp/result`;

if($result!=0){

print "$header
Error$footer";

}else{

print "$headerVerify
$UN forwarding to...";

$i=0;$j=0;

open(IN,"/tmp/.forward");

while(<IN>){

if($_ eq$UN){

$j=1;

} else {

print "
\n$_";

$i++;

}}

close(IN);

print "NotFound." if($i==0);

print "$footer";

}}

}else{

print "$header\n";

print "$headerVerify
$UN forwarding to...";

$i=0;$j=0;

open(IN,"/tmp/.forward");

while(<IN>){

if($_ eq$UN){

$j=1;

} else {

print "
\n$_";

$i++;

}}

close(IN);

print "NotFound." if($i==0);

print "$footer\n";

}}}

  • id:naopontan
    回答して下さった方々、ありがとうございます。
    初めてHatena::Question を使っての質問だったので、勝手が分からず、とまどってしまいました。

    結論から言えば満足度は90%といったところでしょうか。
    お二方の情報を元に、試行錯誤してみます。

    ありがとうございました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません