回精華區
作者Roger.bbs@no.bbs.che.nchu.edu.tw.spam (便當俠) 看板: plan
標題[功能]未認證成功使用者不能登入Coppermine Photo Gallery(標準.ACCT)
時間童化工坊 (2005/03/22 Tue 05:23:09) Updated: 2005/03/22
這篇文章是參考TroyLee和Titan前輩的文章
和自己對perl的了解修改而來
用了suidperl
對安全性作了加強
因為敝站的.ACCT未曾修改過
應該可以適用於大多數的站台

原理上是拷貝一個使用者的檔案到 /tmp/.ACCT
經過php解析來確定是不是合法的使用者
我是以tvalid認證時間來做判斷
判斷之後刪除 /tmp/.ACCT
www user不能複製或刪除bbs owner的檔案
所以需要suid的program


如果已經做過Titan前輩"[功能] bbs與Coppermine Photo Gallery帳號同步"
的使用者
修改login.php時請加入我修改的部分即可

首先請確定你的的作業系統有安裝suidperl
用通常是安裝在 /usr/bin/suidperl
FreeBSD系統在預設是沒有開啟suidperl功能的(你可以視之為"封印")
解除封印請輸入
# chmod u+s /usr/bin/suidperl

(http://www.freebsd.org/zh/FAQ/book.html#SUIDPERL)


接著是perl程式碼

: acct.pl 新增此程式

#!/usr/bin/suidperl -Tw

use Getopt::Long;
use File::Copy;
use strict;
my $copy;
my $remove;
my @id;
GetOptions  ( "c=s"  => \$copy,
              "r"    => \$remove );
my $user = $copy;

if ( $copy ) { @id = split //, $copy;
      copy("/home/bbs/usr/$id[0]/$copy/.ACCT" ,"/tmp/.ACCT") or die "$!";}
if ( $remove ) { unlink("/tmp/.ACCT") or die "$!";  }

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

修改後請確定 acct.pl 的權限為可執行


複製該檔案到你的網路相簿的目錄中,以cpg為例

cp acct.pl /usr/local/www/data/cpg/ 

將此acct.pl的owner改為bbs

chown bbs acct.pl

加上suid

chmod u+s acct.pl


在修改login.php之前
請先寫個php網頁放在自己的網站上

----------------------------
<?
$fp = fopen("/tmp/.ACCT", "r");
$binary = fread($fp, 224);
$acct = unpack("iuserno/a13userid/a14passwd/a20realname/a24username"
            ."/Iuserlevel/Iufo/Csignature/x"
            ."/cyear/cmonth/cday/csex/x3"
            ."/imoney/igold/inumlogins/inumposts/inumemails"
            ."/ifirstlogin/ilastlogin/itcheck/itvalid"
            ."/a30lasthost/a60email", $binary);
print_r($acct);

?>
--------------------------

隨便找個user的 .ACCT複製到 /tmp下做測試
然後讀取該php網頁
印出來的結果中
一定要確定每個欄位都是正確的才能繼續修改login.php
尤其是tvalid欄位
未認證的使用者  此欄位必須是0
如果貴站未改過.ACCT
印出來的結果應該是正常的


然後是php程式碼
改login.php

: login.php


在$cookie_warning = '';這句後面加上這段

- if (isset($HTTP_POST_VARS['submitted'])) {
-     $results = db_query("SELECT user_id, user_name, user_password FROM
-  {$CONFIG['TABLE_USERS']} WHERE user_name = '" . addslashes($HTTP_POST_VARS
- ['username']) . "' AND BINARY user_password = '" . addslashes($HTTP_POST_VARS
- ['password']) . "' AND user_active = 'YES'");

function is_ok($string)  //rocet提供
{
  $flag = trim(preg_replace("/(^[+-])((.+))/", "\\1", $string));
  if ($flag == "+")
    return true;
  else if ($flag == "-")
    return false;
}

$socket = 0;  // socket 開啟完成
$user = 0;    // user 檢查通過
$pass = 0;    // pass 檢查通過
$ok = 0;      // socket/user/pass 都正確

if (isset($HTTP_POST_VARS['submitted']))
{
  /* 以下是我做的修改  */

  $name = addslashes($HTTP_POST_VARS[username]);
  $cmd=sprintf("/usr/local/www/data/cpg/acct.pl --c=$name");
               /* 改成貴站相簿的目錄  */
  $fpa = popen($cmd,"w");
  pclose($fpa);
  if ( file_exists("/tmp/.ACCT"))
  {
  $fp = fopen("/tmp/.ACCT", "r");

  flock($fp,LOCK_EX);
  $binary = fread($fp, 224);
  $acct = unpack("iuserno/a13userid/a14passwd/a20realname/a24username"
            ."/Iuserlevel/Iufo/Csignature/x"
            ."/cyear/cmonth/cday/csex/x3"
            ."/imoney/igold/inumlogins/inumposts/inumemails"
            ."/ifirstlogin/ilastlogin/itcheck/itvalid"
            ."/a30lasthost/a60email", $binary);
       /*  此處為 .ACCT 結構  請確定列印結果正確才能使用  否則需要修改 */
  flock($fp,LOCK_UN);
  $cmd=sprintf("/usr/local/www/data/cpg/acct.pl --r");
                /* 改成貴站相簿的目錄  */
  $fpa = popen($cmd,"w");

  pclose($fpa);

  if ( $acct[tvalid] == 0 )
  {
        echo <<<EOT        /* 此處為認證失敗網頁,可自行修改 */
                  <P>
                  <P>
                  <CENTER><BR><BR>
                  <font size="4" color="red"><b>
                  抱歉,你在BBS的帳號尚未通過認證,
                  請到<A HREF="telnet://bbs.che.nchu.edu.tw">BBS註冊</A>
                  後才可使用相簿功能<b></font>
                  <P><A HREF="http://bbs.che.nchu.edu.tw/photo/">回首頁</A>

EOT;
   die;
  }

   /*  我修改的部分  結束   */

  $fp = fsockopen("localhost", 110, $errno, $errstr, 30);
  if (!$fp)
  {
    echo "$errstr ($errno)<br />\n";
  }
  else
  {
    if (is_ok(fgets($fp)))
      $socket = 1;
    else
      echo "socket can't open";

    fputs($fp, "user " . addslashes($HTTP_POST_VARS['username']) . "\r\n");
    if (is_ok(fgets($fp)))
      $user = 1;
    fputs($fp, "pass " . addslashes($HTTP_POST_VARS['password']) . "\r\n");
    if (is_ok(fgets($fp)))
      $pass = 1;
    fputs($fp, "quit\r\n");

    if ($socket && $user && $pass)
      $ok = 1;

    $checkdata = db_query("SELECT user_id FROM {$CONFIG['TABLE_USERS']}
      WHERE user_name = '" . addslashes($HTTP_POST_VARS['username']) . " '");

    if (!(mysql_num_rows($checkdata)) && $ok == "1")
    {
      $checkvalue = db_query("SELECT user_id FROM {$CONFIG['TABLE_USERS']}
        ORDER BY `user_id` DESC");
      $count = mysql_fetch_array($checkvalue);
      $newcount = $count[0] + 1;

      db_query("INSERT INTO {$CONFIG['TABLE_USERS']}
        (`user_id`, `user_group`, `user_active`, `user_name`,
         `user_password`, `user_lastvisit`, `user_regdate`,
         `user_group_list`, `user_email`, `user_website`, `user_location`,
         `user_interests`, `user_occupation`, `user_actkey`)
        VALUES ('$newcount', '2', 'YES', '" .
        addslashes($HTTP_POST_VARS['username']) . "', 'password',
        '0000-00-00 00:00:00', NOW() , '', '','', '', '', '', '');");
    }

    $result = db_query("SELECT user_password FROM {$CONFIG['TABLE_USERS']}
      WHERE user_name = '" . addslashes($HTTP_POST_VARS['username']) . "'
      AND user_active ='YES'");

    $value = mysql_fetch_array($result);

    $HTTP_POST_VARS['password'] = $value['user_password'];

    fclose($fp);
  }

  $results = db_query("SELECT user_id, user_name, user_password
    FROM {$CONFIG['TABLE_USERS']}
    WHERE user_name = '" . addslashes($HTTP_POST_VARS['username']) ."' AND
    BINARY user_password = '" . addslashes($HTTP_POST_VARS['password']) . "'
    AND user_active = 'YES'");

上面這段加完之後,改這個地方

- if (mysql_num_rows($results)) {
+ if (mysql_num_rows($results) && $ok == "1") {


: profile.php

既然帳號同步,那就不需要修改密碼的選項了

找到這一行,約240行左右

<input type="submit" name="change_pass"
          value="{$lang_register_php['change_pass']}" class="button">

直接刪除,或是註解起來,如:

<!-- <input type="submit" name="change_pass" value="{$lan
          value="{$lang_register_php['change_pass']}" class="button"> -->



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


以上在敝站測試正常
如果有更好的寫法或發現任何bug
歡迎提出 :)


--
       ╓───────────╖
◢◣  ╭─ Origin :童化工坊  bbs.che.nchu.edu.tw
◢◣◢   2005/03/22 Tue 05:23:09       ╙───────────╜
        Roger 從 e2029.dorm.nchu.edu.tw 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻