Re: [Exim] Crazy expansion

Top Page
Delete this message
Reply to this message
Author: Vadim Vygonets
Date:  
To: exim-users
Subject: Re: [Exim] Crazy expansion
Quoth Dave C. on Fri, May 05, 2000:
> 1. The username-part of the auth data contains an "@"
>
> (if $1 contains "@" then () else pam () ) ?


Yup.

> 2. A directory exists, /path/to/<DOMAINPART>, where <DOMAINPART> is the
>    portion of the username-part after the "@"


No, I don't think it's needed. You can only test the thingie
below. I mean, if /a/b/c/d exists, /a/b/c surely exists, no?

> 3. There exists in that directory a file /path/to/<DOMAINPART>/passwd,
>    which contains a standard username/password pair, and the username
>    in the file matches the portion of the username-part of auth data
>    which is before the "@"

>
> (exists : /path/to/(substr(everything_after(@)($1)))/passwd ) ?


Yup.

> 4. The password for that username in the file matches (with crypt) the
>    password-part of the auth data.


WARNING: If you don't REALLY want to know the answer AND want to
retain your sanity, DON'T look below. THERE BE DRAGONS.

Some explanation, first. Remember that expansion operator
"match" changes values of $1, $2, $3, etc. But it changes them
only in the innermost enclosing ${if ...} block. This leads us
to two design decisions:

1. Because I still want to access the original $2 and $3 (or
   whatever), I couldn't write:
    ${if match{$2}{@}\
        {check with passwd file}\
        {check with pam}}
  I needed to add another level of indirection:
    ${if eq{${if match{$2}{@}{yes}{no}}}{yes}\
        {check with passwd file}\
        {check with pam}}


2. To ease quick access to local part of $2, domain of $2, and
   password ($3) in the passwd checking part, I used match to put
   them into $1, $2, and $3:
    match{$2@$3}{(^[^@]+)@([^@]+)@(.+)?\\$}}
  This match has yet another function: it guards against empty
  passwords, so we don't have to handle this in the lookup.
  Without it, we would need yet another level of nesting or two
  in the lookup.


Dragons, remember? Code follows.

fixed_login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_condition = "${if eq {${if match{$1}{@}{yes}{no}}}{yes}\
    {${if and{\
        {match{$1@$2}{(^[^@]+)@([^@]+)@(.+)\\$}}\
        {exists{/path/to/$2/passwd}}\
        {crypteq {${lookup{$1}lsearch{/tmp/$2/passwd}{$value}}}\
            {$3}}}\
        {yes}{no}}}\
    {${if pam{$1:$2}{yes}{no}}}}"
  server_set_id = $1


fixed_plain:
  driver = plaintext
  public_name = PLAIN
  server_condition = "${if eq {${if match{$2}{@}{yes}{no}}}{yes}\
    {${if and{\
        {match{$2@$3}{(^[^@]+)@([^@]+)@(.+)\\$}}\
        {exists{/path/to/$2/passwd}}\
        {crypteq {${lookup{$1}lsearch{/tmp/$2/passwd}{$value}}}\
            {$3}}}\
        {yes}{no}}}\
    {${if pam{$2:$3}{yes}{no}}}}"
  server_set_id = $2


Tested on Exim 3.14 without PAM (my OS doesn't have it) and
without crypteq (because I'm lazy, that's why).

Seems about right. Only 8 levels of nested braces. I'm ashamed.

Vadik.

--
Avoid reality at all costs.