Differences between current version and predecessor to the previous major change of vpopmail_check_user.c.

Other diffs: Previous Revision, Previous Author

Newer page: version 6 Last edited on Sunday, 21 March 2010 15:18:34 by CyberLeo
Older page: version 5 Last edited on Sunday, 19 April 2009 13:40:36 by CyberLeo Revert
@@ -1,6 +1,5 @@
-<?plugin RawHtml  
-<pre class ="brush: c; ">  
+<code brush ="c" 
 #include <string.h> 
 #include <stdlib.h> 
 #include <stdio.h> 
 #include <sys/types.h> 
@@ -158,6 +157,5 @@
  // Delivery will probably fail. Dump out. 
  printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n"); 
  exit(1); 
 
-</pre>  
-?
+</code

current version

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

const int vpopuid = 98;
const int vpopgid = 98;

int errno = 0;

const char *VDOMINFO = "/home/vpopmail/bin/vdominfo";
const char *VUSERINFO = "/home/vpopmail/bin/vuserinfo";
const char *VALIAS = "/home/vpopmail/bin/valias";
const char *DOMAINS = "/home/vpopmail/domains";
char *email = NULL;
char *user = NULL;
char *domain = NULL;
char *homedir = NULL;

int relayable = 0;

struct stat s_stat;

int main(int argc, char **argv){
        char *stmp;
        char *stmp2;
        char *command;
        FILE *fp;
        int result;

        if(getenv("RELAYCLIENT"))
                relayable = 1;

        // Pull in email address for checking
        if(argc > 1){
                email = (char *) malloc( strlen( argv[1] ) + 1 );
                strcpy(email, argv[1]);
        }else{
                if( getenv("SMTPRCPTTO") != NULL ){
                        email = (char *) malloc( strlen( getenv("SMTPRCPTTO") ) + 1 );
                        strcpy(email, getenv("SMTPRCPTTO"));
                }
        }
        if(email == NULL){
                fprintf(stderr, "qmail-spp: vpopmail_check_recipient; No email address specified from %s\n", getenv("TCPREMOTEIP"));
                printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n");
                exit(1);
        }

        // Quick validation test: only accept A-Za-z0-9-_@.[]
        stmp = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_@.[]";
        result = strspn(email, stmp);
        if(result != strlen(email)){
                fprintf(stderr, "qmail-spp: vpopmail_check_recipient: Illegal characters in email address from %s\n", getenv("TCPREMOTEIP"));
                printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n");
                exit(1);
        }

        // extract user portion of email address
        stmp = strtok(email, "@");
        if(stmp == NULL){
                fprintf(stderr, "qmail-spp: vpopmail_check_recipient: No @ sign in email address from %s\n", getenv("TCPREMOTEIP"));
                printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n");
                exit(1);
        }
        user = (char *) malloc( strlen( stmp ) + 1 );
        strcpy(user, stmp);

        // Extract domain portion of email address
        stmp = strtok(NULL, "@");
        if(stmp == NULL){
                fprintf(stderr, "qmail-spp: vpopmail_check_recipient: No domain in email address from %s\n", getenv("TCPREMOTEIP"));
                printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n");
                exit(1);
        }
        domain = (char *) malloc( strlen( stmp ) + 1 );
        strcpy(domain, stmp);

        // Any more @ signs? If so, trash it.
        if(strtok(NULL, "@") != NULL){
                fprintf(stderr, "qmail-spp: vpopmail_check_recipient: Too many @ signs in email address from %s\n", getenv("TCPREMOTEIP"));
                printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n");
                exit(1);
        }

        // Discard email and reform it. strtok isn't nice.
        free(email);
        email = (char *) malloc( strlen( user ) + strlen( domain ) + 2);
        sprintf(email, "%s@%s", user, domain);

        // Check if the domain exists
        command = (char *) malloc(strlen(domain) + strlen(VDOMINFO) + 19);
        sprintf(command, "%s %s |grep -e '^dir:'", VDOMINFO, domain);
        fp = popen(command, "r");
        stmp2 = (char *) malloc(512);
        stmp = (char *) malloc(1);
        while(!feof(fp)){
                result = fread(stmp2, 1, 512, fp);
                stmp = realloc(stmp, sizeof(stmp) + result);
                strcat(stmp, stmp2);
        }
        free(stmp2);
        result = pclose(fp);
        free(command);
        if(result != 0){
                if(!relayable){
                        fprintf(stderr, "qmail-spp: vpopmail_check_recipient: Relaying denied to: %s from %s\n", email, getenv("TCPREMOTEIP"));
                        printf("E551 Relaying denied (#5.5.1)\n");
                        exit(1);
                }else{
                        fprintf(stderr, "qmail-spp: vpopmail_check_recipient: Authorizing relay to: %s from %s\n", email, getenv("TCPREMOTEIP"));
                        exit(0);
                }
        }

        // parse the output to grab the homedir, for later
        stmp2 = strrchr(stmp, ' '); // find last space. Start of homedir
        homedir = (char *) malloc(strlen(stmp2));
        strncpy(homedir, stmp2 + 1, (strlen(stmp2) - 1)); // Read between the whitespace
        homedir[strlen(stmp2) - 2] = '\0'; // Null-terminate
        free(stmp);

        // Check .qmail-default to see if a catchall is defined.
        command = (char *) malloc( strlen(homedir) + 55);
        sprintf(command, "cat %s/.qmail-default |grep 'bounce-no-mailbox' >/dev/null", homedir);
        result = system(command);
        if(0 != result){
                // Catchall defined. Any mail delivery will succeed
                exit(0);
        }

        // Check if the user has a mailbox in the domain
        command = (char *) malloc(strlen(email) + strlen(VUSERINFO) + 14);
        sprintf(command, "%s %s > /dev/null", VUSERINFO, email);
        result = system(command);
        free(command);
        if(0 == result){
                // Has mailbox
                exit(0);
        }

        // We want a .qmail file in homedir
        command = (char *) malloc( strlen(homedir) + 7 + strlen(user) + 1);
        sprintf(command, "%s/.qmail-%s", homedir, user);
//      fprintf(stderr, "qmail-spp: vpopmail_check_recipient: Checking for file %s\n", command);
        result = stat(command, &s_stat);
//      fprintf(stderr, "qmail-spp: vpopmail_check_recipient: stat() returned %d %d\n", result, errno);

        free(command);
        if(0 == result){
                // Has .qmail file
                exit(0);
        }

        // Delivery will probably fail. Dump out.
        printf("E550 Sorry, no mailbox here by that name (#5.5.0)\n");
        exit(1);
}