Skip to content

Instantly share code, notes, and snippets.

@wmw
Created April 18, 2009 00:59
Show Gist options
  • Save wmw/97372 to your computer and use it in GitHub Desktop.
Save wmw/97372 to your computer and use it in GitHub Desktop.
/*
* William Warnecke
* Backpack Software
*
* Courier Authpipe - Xmail Mailuserstab Authentication Program (CAXMAP)
*
* Version 1 - Release
*
* REFERENCES:
* - http://www.courier-mta.org/authlib/README_authlib.html
* - File Paths
* maildir: /xmail/MailRoot/domains/$domain/$user/Maildir/
* authlib bins: /usr/local/libexec/courier-authlib/
* authlib libs: /usr/local/lib/courier-authlib/
* authlib conf: /usr/local/etc/authlib/
* authProg: /usr/local/etc/authlib/authProg
* courier main: /usr/lib/courier-imap/
*
* BUGS:
* - Getting garbage in sAuthData
*
* TODO:
* - Change paths to be variables, or maybe ini file settings?
* - On the fly debugging levels? standardize logging
* - Configure script or ?
* - hashmap for fast checking
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *StrCrypt(char const * pszString, char *pszCourierCryptedPassword)
{
/*
* Xmail Crypt Function
*/
strcpy(pszCourierCryptedPassword, "");
for (int ii = 0; pszString[ii] != '\0'; ii++) {
signed int uChar = (unsigned int) pszString[ii];
char szByte[32] = "";
sprintf(szByte, "%02x", (uChar ^ 101) & 0xff);
strcat(pszCourierCryptedPassword, szByte);
}
return (pszCourierCryptedPassword);
}
char *StrDeCrypt(char const *pszString, char *pszDeCrypt)
{
/*
* Xmail Decrypt Function
* This is not currently used by this program
*/
int iStrLength = strlen(pszString);
int ii;
signed int uChar = 0;
char szByte[8] = "";
*pszDeCrypt = 0;
if ((iStrLength % 2) != 0) {
return (NULL);
}
for (ii = 0; ii < iStrLength; ii += 2) {
szByte[0] = pszString[ii];
szByte[1] = pszString[ii + 1];
szByte[2] = '\0';
if (sscanf(szByte, "%x", &uChar) != 1) {
return (NULL);
}
pszDeCrypt[ii >> 1] = (char) ((uChar ^ 101) & 0xff);
}
pszDeCrypt[ii >> 1] = '\0';
return (pszDeCrypt);
}
void main(int argc, char **argv)
{
/*
* file descriptors
*/
FILE *fdXmail;
FILE *fdLog;
/*
* stdin buffer
*/
char szStdinBuffer[1024] = "";
/*
* all used when reading/manipulating xmails user mailtab
*/
char szXmailDomain[128];
char szXmailUsername[128];
char szXmailPassword[128];
/*
* holding junk
*/
char *lpUnused1;
char *lpUnused2;
/*
* all used/populated by data that came from courier via stdin
* this stuff is user supplied, so it's dirty. may need to check
* buffers? dunno if the functions i used were vulnerable (don't think so :/)
*/
char *lpCourierFullUsername;
char *lpCourierUsername;
char szCourierQuotedUsername[128] = "";
char *lpCourierPassword;
char szCourierCryptedPassword[128] = "";
char szCourierQuotedPassword[128] = "";
char *lpCourierDomain;
char szCourierQuotedDomain[128] = "";
/*
* -- Main --
*/
fdLog = fopen("/usr/home/wwarnecke/log","a");
fprintf(fdLog,"started program\n");
fgets(szStdinBuffer, 1024, stdin);
fprintf(fdLog,"stdin: %s\n",szStdinBuffer);
/*
* after reading in stdin we should have either an AUTH, PRE, ENUMERATE,
* or PASSWD command. so far we've implmented AUTH and PRE
* under each section is a commant for the format in which we'll receieve
* stdin
*/
if(strstr(szStdinBuffer,"AUTH ")) {
/* AUTH len<newline>len-bytes */
int iAuthSize;
/*
* read stdin, and allocate buffer space
* then read in len-bytes of auth data
*/
sscanf(szStdinBuffer,"%*s%d",&iAuthSize);
fprintf(fdLog,"auth: '%d'\n",iAuthSize);
char sAuthData[iAuthSize-1];
fread(sAuthData,1,iAuthSize,stdin);
fprintf(fdLog,"stdin:\n%s\n--\n",sAuthData); /* XXX getting garbage here :( */
/*
* split apart username/domain, if domain is null populate it
* with a default (hardcoded at the momment)
* also encrypt password, additionally quote everything because
* it's all quoted in the xmail mailtab
*/
lpUnused1 = strtok(sAuthData,"\n"); /* unused 1 */
lpUnused2 = strtok(NULL,"\n"); /* unused 2 */
lpCourierFullUsername = strtok(NULL,"\n"); /* username@domain */
lpCourierPassword = strtok(NULL,"\n"); /* password */
lpCourierUsername = strtok(lpCourierFullUsername,"@"); /* username */
lpCourierDomain = strtok(NULL,"@"); /* domain */
if(lpCourierDomain == NULL) { lpCourierDomain = "winternet.com"; }
fprintf(fdLog,"u: %s , d: %s , p: %s\n",lpCourierUsername,lpCourierDomain,lpCourierPassword);
sprintf(szCourierQuotedUsername,"\"%s\"",lpCourierUsername); /* username - quoted */
sprintf(szCourierQuotedDomain,"\"%s\"",lpCourierDomain); /* domain - quoted */
StrCrypt(lpCourierPassword,szCourierCryptedPassword); /* password - encrypted */
sprintf(szCourierQuotedPassword,"\"%s\"",szCourierCryptedPassword); /* password - encrypted and quoted */
fdXmail = fopen("/xmail/MailRoot/mailusers.tab","rt");
/*
* read the file, loop on it. add a hashmap in here in the future.
* compared everything, if it matches return. if not, when we exit loop we fail
*/
while(fscanf(fdXmail, "%s %s %s %*d %*s %*s",szXmailDomain,szXmailUsername,szXmailPassword) != EOF) {
if((strcmp(szXmailUsername,szCourierQuotedUsername) == 0) &&
(strcmp(szXmailPassword,szCourierQuotedPassword) == 0) &&
(strcmp(szXmailDomain,szCourierQuotedDomain) == 0)) {
fprintf(stdout,"USERNAME=root\nUID=0\nGID=1\nHOME=/xmail/MailRoot/domains/%s/%s/\nADDRESS=%s\nNAME=%s\nMAILDIR=Maildir/\n.\n",lpCourierDomain,lpCourierUsername,lpCourierFullUsername,lpCourierFullUsername);
return 0;
}
}
fclose(fdXmail);
fprintf(stdout,"FAIL\n");
return 0;
} else if(strstr(szStdinBuffer,"PRE ")) {
/* PRE . authservice username <newline> */
/*
* almost the same thing here as above, except no password magic
* can read code comments above
*/
sscanf(szStdinBuffer,"%*s%*s%*s%s",lpCourierFullUsername);
lpCourierUsername = strtok(lpCourierFullUsername,"@"); /* username */
lpCourierDomain = strtok(NULL,"@"); /* domain */
if(lpCourierDomain == NULL) { lpCourierDomain = "winternet.com"; }
sprintf(szCourierQuotedUsername,"\"%s\"",lpCourierUsername); /* username - quoted */
sprintf(szCourierQuotedDomain,"\"%s\"",lpCourierDomain); /* domain - quoted */
fdXmail = fopen("/xmail/MailRoot/mailusers.tab","rt");
while(fscanf(fdXmail, "%s %s %s %*d %*s %*s",szXmailDomain,szXmailUsername,szXmailPassword) != EOF) {
if((strcmp(szXmailUsername,szCourierQuotedUsername) == 0) &&
(strcmp(szXmailDomain,lpCourierDomain) == 0)) {
fprintf(stdout,"USERNAME=root\nUID=0\nGID=1\nHOME=/xmail/MailRoot/domains/%s/%s/\nADDRESS=%s\nNAME=%s\nMAILDIR=Maildir/\n.\n",lpCourierDomain,lpCourierUsername,lpCourierFullUsername,lpCourierFullUsername);
return 0;
}
}
fclose(fdXmail);
fprintf(stdout,"FAIL\n");
return 0;
} else if(strstr(szStdinBuffer,"PASSWD ")) {
/* PASSWD service<tab> username<tab> oldpasswd<tab> newpasswd<tab> <newline> */
/* not yet implemented */
fprintf(stdout,"FAIL\n");
return 0;
} else if(strstr(szStdinBuffer,"ENUMERATE ")) {
/* ENUMERATE <newline> */
/* not yet implemented */
fprintf(stdout,".\n");
return 0;
} else {
/*
* if we didn't see anything we recognize from courier
* we'll just fail. program shouldn't be run from command line, etc
*/
fprintf(stdout,"FAIL\n");
return 0;
}
fflush(fdLog);
fclose(fdLog);
fprintf(stdout,"FAIL\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment