This is a discussion on [courier-users] Fun with authpipe within the Courier-Imap forums, part of the Mail Servers and Related category; This is a multi-part message in MIME format. --------------080504060907030008000209 Content-Type: text/plain; charset=ISO-8859-1; format=flowed ...
|
|||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
This is a multi-part message in MIME format.
--------------080504060907030008000209 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit I just wanted to share a use for authpipe that others might find useful. I wanted to use a virtual shared folder setup in Courier-IMAP so that I could use IMAP folder ACLs. However, I needed to do username/password checks against a Windows Active Directory controller. I wanted to set up Courier-IMAP in such a way that I didn't touch the LDAP schema of the AD controller, so I decided to use userdb to store the account information. However, because I wanted to check usernames/passwords against the AD controller, I couldn't store the passwords in the userdb files. I decided that rather than write my own module, I would stack a "filter" module of sorts on top of the others. This is possible only because of the way that authdaemond uses the modules -- if for any request a module returns "FAIL", then authdaemond makes the same request from the next module in its list. I wrote a shell script, suitable for use with the authpipe module, and a tiny C program that checks username/password pairs via PAM (and I used pam_winbind, though you could use any PAM module). The shell script "authProg" speaks the "authpipe" protocol outlined in: http://www.courier-mta.org/authlib/README_authlib.html The script takes an "AUTH" request, checks the username/password using the "chkpw_pam" program, then makes a separate connection to authdaemond to make a "PRE" request to return the account data. Since authProg simply sends "FAIL" for a "PRE" request, the request falls through to the authuserdb module. This simple idea works and required almost no programming, but I'd like to know if there's a nicer way to do this. Cheers, -- Johnny Lam <jlam@pkgsrc.org> --------------080504060907030008000209 Content-Type: text/plain; name="authProg" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="authProg" #!/bin/sh auth() { chkpwprog=/etc/pkg/authlib/chkpw_pam hoseprog=/usr/pkg/bin/hose socketfile=/var/authdaemon/socket [ -x $chkpwprog ] || { fail; return; } [ -x $hoseprog ] || { fail; return; } [ -S $socketfile ] || { fail; return; } # Read the AUTH data from stdin. read service junk read authtype junk; [ "$authtype" = "login" ] || { fail; return; } read username junk read password # Authenticate the user/password combination. CHKPW_PASSWD="$password"; export CHKPW_PASSWD $chkpwprog $service $username || { fail; return; } # Make a PRE request to authdaemond so that the next module's # results will return. Filter out PASSWD* lines since they # won't apply, given that the correct passwords are stored in # the service checked by $chkpwprog. # echo "PRE . $service $username" | $hoseprog localhost $socketfile --unix --slave | while read line; do case $line in PASSWD=*|PASSWD2=*) ;; .) echo "."; break ;; *) echo "$line" ;; esac done } # Set the other actions to fail so that authdaemond will fall through and # try the next module on the authmodulelist. # pre() { fail; } passwd() { fail; } enumerate() { echo "."; } fail() { echo "FAIL"; } # Read the first line of standard input to figure out which action should # be taken. # read stdin echo " Read: $stdin" case $stdin in "AUTH "*) auth ;; "PRE . "*) pre ;; "PASSWD "*) passwd ;; "ENUMERATE") enumerate ;; *) fail ;; esac exit 0 --------------080504060907030008000209 Content-Type: text/plain; name="chkpw_pam.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="chkpw_pam.c" #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <security/pam_appl.h> static int pam_nullconv(int n, const struct pam_message **msg, struct pam_response **resp, void *data) { return PAM_CONV_ERR; } static struct pam_conv pamc = { pam_nullconv, NULL }; int main(int argc, char *argv[]) { pam_handle_t *pamh = NULL; int pam_err = PAM_ABORT; const char *service; const char *user; const char *pass; if (argc != 3) goto cleanup; service = argv[1]; user = argv[2]; /* * Grab the password for the user from the CHKPW_PASSWD environment * variable. */ if ((pass = getenv("CHKPW_PASSWD")) == NULL) goto cleanup; if ((pam_err = pam_start(service, user, &pamc, &pamh)) != PAM_SUCCESS) goto cleanup; if ((pam_err = pam_set_item(pamh, PAM_AUTHTOK, pass)) != PAM_SUCCESS) goto cleanup; if ((pam_err = pam_authenticate(pamh, PAM_SILENT)) != PAM_SUCCESS) goto cleanup; cleanup: if (pamh != NULL) { pam_end(pamh, pam_err); } /* Return 0 for a success, and 1 for everything else. */ return (pam_err == PAM_SUCCESS ? 0 : 1); } --------------080504060907030008000209-- ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click _______________________________________________ courier-users mailing list courier-users@lists.sourceforge.net Unsubscribe: https://lists.sourceforge.net/lists/.../courier-users |
![]() |
| Thread Tools | |
| Display Modes | |
|
|