Created
April 18, 2009 00:59
-
-
Save wmw/97372 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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