[tpop3d-discuss] tpop3d, auth-other, php auth script and heavy load

Ivan Matveyev hobot at zebratelecom.ru
Tue, 11 Mar 2003 09:00:27 +0300 (MSK)


On Tue, 4 Mar 2003, Chris Lightfoot wrote:

> Don't do that. tpop3d will hold off restarting the
> authentication child to avoid an out-of-control script
> consuming system resources. That's probably why you're
> seeing poor performance under heavier load.
Chris, I have new version. ;-) It works fine on a busy server with more
than 300k accounts.

#!/usr/local/bin/php -q
<?
/*
For example, for domain1 and domain2 we want web auth, for any other domain
we try regarding file in /etc/teapop.
/etc/teapop/$domain file format is:
"login:password:mailbox"

Web auth returns "YES" if the user is allowed, and "NO" in other case.

Also, I had to modify auth_other_send_request function in auth_other.c
to make it work properly with the php auth module.

int auth_other_send_request(const int nvars, ...) {
    va_list ap;
    int i, ret = 0;
    char buffer[MAX_DATA_SIZE] = {0};
    char *p;
    size_t nn;

    if (!authchild_pid) return 0;

    va_start(ap, nvars);

    for (i = 0, p = buffer, nn = 0; i < nvars; ++i) {
        const char *key, *val;
        key = va_arg(ap, const char *);
        nn += strlen(key) + 1;
        if (nn > sizeof(buffer)) goto fail;
        memcpy(p, key, strlen(key));
        p += strlen(key);
        memcpy(p,"=",1);
        p++;

        val = va_arg(ap, const char *);
        nn += strlen(val) + 1;
        if (nn > sizeof(buffer)) goto fail;
        memcpy(p, val, strlen(val));
        p += strlen(val);
        memcpy(p," ",1);
        p++;
        }
    memcpy(p,"\n",1);
    p++;
    nn++;

    if (nn > sizeof(buffer)) {
        log_print(LOG_ERR, _("auth_other_send_request: total size of request would exceed %d bytes"), sizeof(buffer));
        goto fail;
    }
    /* Since write operations are atomic, this will either succeed entirely or
     * fail. In the latter case, it may be with EAGAIN because the child
     * process is blocking; we interpret this as a protocol error. */
    if (try_write(authchild_wr, buffer, nn)) ret = 1;
    else {
        if (errno == EAGAIN)
            log_print(LOG_ERR, _("auth_other_send_request: write: write on pipe blocked; killing child"));
        else
            log_print(LOG_ERR, _("auth_other_send_request: write: %m; killing child"));
        auth_other_kill_child();
    }

fail:
    va_end(ap);

    return ret;
}

If you have any questions, mail hobot@moecho.org
*/

error_reporting(0);
set_time_limit(0);

function array_get($what,$array)
        {
        foreach($array as $val)
                {
                if(ereg("^".$what,$val))
                        {
                        list($none,$value)=split("=",$val);
                        return $value;
                        }
                }
        }

function array_get_pw($what,$array)
        {
        foreach($array as $val)
                {
                if(ereg("^".$what,$val))
                        {
                        list($none,$value,$none)=split(":",$val);
                        return $value;
                        }
                }
        }

function logs($in)
        {
	$what=date("D M j G:i:s T Y ").$in."\n";
	$fp = fopen ("pop-auth.log","a");
	fwrite ($fp,$what);
	fclose($fp);
	}

function stdout($what)
    {
    $stdout=fopen("php://stdout","w");
    fwrite($stdout,$what);
    fclose($stdout);
    }


$stdin=fopen("php://stdin","r");
$term=fscanf($stdin,"%s %s %s %s %s %s %s %s %s %s %s\n");
while($term)
{
//foreach($term as $val) logs($val);
$username=array_get("user",$term);
$password=array_get("pass",$term);
$ip=array_get("clienthost",$term);
$answer="NO";
$mailbox="";

	list($local_part,$domain)=explode("@",$username);
	if($domain==""||$domain=="domain1"||$domain=="domain2")
	    {
	    $string="http://some.url?user_name=$local_part&password=$password";
	    $tmp=file($string);
	    $answer=str_replace("\n","",$tmp[0]);
	    }
	    else
		{
		$em_pw_db=file("/etc/teapop/$domain");
		if($password==array_get_pw($local_part,$em_pw_db)) $answer="YES";
		    else $answer="NO";
		$mailbox="mailbox\0/var/mail/$domain/$local_part\0";
		}
	if($answer=="YES")
	    {
	    stdout("result\0YES\0uid\0mail\0gid\0mail\0$mailbox\0");
	    }
	    if($answer=="NO")
		{
		stdout("result\0NO\0\0");
		}
//logs("$username $password ($local_part $domain) $answer");
$term=fscanf($stdin,"%s %s %s %s %s %s %s %s %s %s %s\n");
//$term=fgets($stdin,399);
}
fclose($stdin);
?>

-- 
Ivan Matveyev, Zebra Telecom
Tech Dept, +7(095)741-0001