Back to index

courier  0.68.2
Classes | Functions | Variables
pop3login.c File Reference
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include "waitlib/waitlib.h"
#include "proxy.h"
#include <courierauth.h>
#include <courierauthdebug.h>
#include <courierauthsasl.h>
#include "tcpd/spipe.h"
#include "numlib/numlib.h"
#include "tcpd/tlsclient.h"

Go to the source code of this file.

Classes

struct  pop3proxyinfo

Functions

void pop3dcapa ()
int have_starttls ()
int tls_required ()
const char * pop3_externalauth ()
static int starttls ()
static char * authresp (const char *s, void *dummy)
static int login_pop3 (int, const char *, void *)
static int login_callback (struct authinfo *ainfo, void *dummy)
int main (int argc, char **argv)

Variables

static const char * pop3d
static const char * defaultmaildir

Class Documentation

struct pop3proxyinfo

Definition at line 121 of file pop3login.c.

Class Members
const char * pwd
const char * uid

Function Documentation

static char* authresp ( const char *  s,
void *  dummy 
) [static]

Definition at line 99 of file pop3login.c.

{
char   *p;
char   buf[BUFSIZ];

       printf("+ %s\r\n", s);
       fflush(stdout);

       if (fgets(buf, sizeof(buf), stdin) == 0)  return (0);
       if ((p=strchr(buf, '\n')) == 0)    return (0);
       if (p > buf && p[-1] == '\r')      --p;
       *p=0;

       p=strdup(buf);
       if (!p)
       {
              perror("malloc");
              return (0);
       }
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int have_starttls ( )

Definition at line 29 of file capability.c.

{
const char *p;

       if ((p=getenv("IMAP_STARTTLS")) == 0)     return (0);
       if (*p != 'y' && *p != 'Y')        return (0);

       p=getenv("COURIERTLS");
       if (!p || !*p)       return (0);
       if (access(p, X_OK)) return (0);
       return (1);
}

Here is the caller graph for this function:

static int login_callback ( struct authinfo *  ainfo,
void *  dummy 
) [static]

Definition at line 128 of file pop3login.c.

{
       int rc;
       char *p;

       p=getenv("POP3_PROXY");

       if (p && atoi(p))
       {
              if (ainfo->options == NULL ||
                  (p=auth_getoption(ainfo->options,
                                  "mailhost")) == NULL)
              {
                     fprintf(stderr,"WARN: proxy enabled, but no proxy"
                             " host defined for %s\n",
                             ainfo->address);

                     /* Fallthru to account login */

              }
              else if (ainfo->clearpasswd == NULL)
              {
                     free(p);
                     fprintf(stderr, "WARN: proxy enabled, but no password"
                             " for %s\n", ainfo->address);
                     return -1;
              }
              else
              {
                     struct proxyinfo pi;
                     struct pop3proxyinfo ppi;
                     struct servent *se;
                     int fd;

                     se=getservbyname("pop3", NULL);

                     pi.host=p;
                     pi.port=se ? ntohs(se->s_port):110;

                     ppi.uid=ainfo->address;
                     ppi.pwd=ainfo->clearpasswd;

                     pi.connected_func=login_pop3;
                     pi.void_arg=&ppi;

                     if ((fd=connect_proxy(&pi)) < 0)
                     {
                            free(p);
                            return -1;
                     }
                     free(p);
                     if (fd > 0)
                     {
                            alarm(0);
                            proxyloop(fd);
                            exit(0);
                     }

                     /* FALLTHRU */
              }
       }

       rc=auth_callback_default(ainfo);

       if (rc == 0)
       {
              char *p=malloc(sizeof("OPTIONS=") + strlen(ainfo->options ?
                                                    ainfo->options:""));

              if (p)
              {
                     strcat(strcpy(p, "OPTIONS="),
                            ainfo->options ? ainfo->options:"");
                     putenv(p);

                     p=malloc(sizeof("AUTHENTICATED=")+
                             strlen(ainfo->address));
                     if (p)
                     {
                            strcat(strcpy(p, "AUTHENTICATED="),
                                   ainfo->address);
                            putenv(p);

                            alarm(0);
                            execl(pop3d, pop3d,
                                  ainfo->maildir ?
                                  ainfo->maildir:defaultmaildir,
                                  NULL);
                            fprintf(stderr, "ERR: exec(%s) failed!!\n",
                                                  pop3d);
                     }
              }
       }

       return (rc);
}

Here is the call graph for this function:

static int login_pop3 ( int  fd,
const char *  hostname,
void *  void_arg 
) [static]

Definition at line 446 of file pop3login.c.

{
       struct pop3proxyinfo *ppi=(struct pop3proxyinfo *)void_arg;
       struct proxybuf pb;
       char linebuf[256];
       char *cmd;

       DPRINTF("Proxy connected to %s", hostname);

       memset(&pb, 0, sizeof(pb));

       if (proxy_readline(fd, &pb, linebuf, sizeof(linebuf), 1) < 0)
              return -1;

       DPRINTF("%s: %s", hostname, linebuf);

       if (linebuf[0] != '+')
       {
              fprintf(stderr, "WARN: Did not receive greeting from %s\n",
                     hostname);
              return -1;
       }

       cmd=malloc(strlen(ppi->uid) + strlen(ppi->pwd)+100);
       /* Should be enough */

       if (!cmd)
              return -1;

       sprintf(cmd, "USER %s\r\n", ppi->uid);

       if (proxy_write(fd, hostname, cmd, strlen(cmd)))
       {
              free(cmd);
              return -1;
       }

       if (proxy_readline(fd, &pb, linebuf, sizeof(linebuf), 1) < 0)
       {
              free(cmd);
              return -1;
       }

       DPRINTF("%s: %s", hostname, linebuf);

       if (linebuf[0] != '+')
       {
              free(cmd);
              fprintf(stderr, "WARN: Login userid rejected by %s\n",
                     hostname);
              return -1;
       }

       sprintf(cmd, "PASS %s\r\n", ppi->pwd);

       if (proxy_write(fd, hostname, cmd, strlen(cmd)))
       {
              free(cmd);
              return -1;
       }

       if (proxy_readline(fd, &pb, linebuf, sizeof(linebuf), 1) < 0)
       {
              free(cmd);
              return -1;
       }

       DPRINTF("%s: %s", hostname, linebuf);

       if (linebuf[0] != '+')
       {
              free(cmd);
              fprintf(stderr, "WARN: Login password rejected by %s\n",
                     hostname);
              return -1;
       }

       free(cmd);
       if (fcntl(1, F_SETFL, 0) < 0 ||
           (printf("+OK Connected to proxy server.\r\n"), fflush(stdout)) < 0)
              return -1;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 225 of file pop3login.c.

{
char   *user=0;
char   *p;
char   buf[BUFSIZ];
int    c;
const  char *ip=getenv("TCPREMOTEIP");
char authservice[40];
char *q ;

#ifdef HAVE_SETVBUF_IOLBF
       setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
#endif

       if (!ip || !*ip)
       {
              ip="127.0.0.1";
       }

       if (argc != 3)
       {
              printf("-ERR pop3login requires exactly two arguments.\r\n");
              fflush(stdout);
              exit(1);
       }

       pop3d=argv[1];
       defaultmaildir=argv[2];

       courier_authdebug_login_init();

       fprintf(stderr, "DEBUG: Connection, ip=[%s]\n", ip);
       printf("+OK Hello there.\r\n");

       fflush(stdout);
       fflush(stderr);
       alarm(60);
       while (fgets(buf, sizeof(buf), stdin))
       {
              c=1;
              for (p=buf; *p; p++)
              {
                     if (*p == '\n')
                            break;

                     if (*p == ' ' || *p == '\t')       c=0;
                     if (c)
                            *p=toupper((int)(unsigned char)*p);
              }

              if (*p)
                     *p=0;
              else while ((c=getchar()) != EOF && c != '\n')
                     ;
              p=strtok(buf, " \t\r");
              if (p)
              {
                     courier_authdebug_login( 1, "command=%s", p );

                     if ( strcmp(p, "QUIT") == 0)
                     {
                            fprintf(stderr, "INFO: LOGOUT, ip=[%s]\n",
                                   ip);
                            fflush(stderr);
                            printf("+OK Better luck next time.\r\n");
                            fflush(stdout);
                            break;
                     }

                     if ( strcmp(p, "USER") == 0)
                     {
                            if (tls_required())
                            {
                                   printf("-ERR TLS required to log in.\r\n");
                                   fflush(stdout);
                                   continue;
                            }

                            p=strtok(0, "\r\n");
                            if (p)
                            {
                                   if (user)     free(user);
                                   if ((user=malloc(strlen(p)+1)) == 0)
                                   {
                                          printf("-ERR Server out of memory, aborting connection.\r\n");
                                          fflush(stdout);
                                          perror("malloc");
                                          exit(1);
                                   }
                                   strcpy(user, p);
                                   printf("+OK Password required.\r\n");
                                   fflush(stdout);
                                   continue;
                            }
                     } else if (strcmp(p, "CAPA") == 0)
                     {
                            pop3dcapa();
                            continue;
                     } else if (strcmp(p, "STLS") == 0)
                     {
                            if (!have_starttls())
                            {
                                   printf("-ERR TLS support not available.\r\n");
                                   fflush(stdout);
                                   continue;
                            }
                            starttls();
                            fflush(stdout);
                            continue;
                     } else if (strcmp(p, "AUTH") == 0)
                     {
                            char *authtype, *authdata;
                            char   *method=strtok(0, " \t\r");

                            if (tls_required())
                            {
                                   printf("-ERR TLS required to log in.\r\n");
                                   fflush(stdout);
                                   continue;
                            }

                            if (method)
                            {
                                   char *initreply=strtok(0, " \t\r");
                                   int    rc;
                                   char *p;

                                   for (p=method; *p; p++)
                                          *p=toupper(*p);

                                   if (initreply &&
                                       strcmp(initreply, "=") == 0)
                                          initreply="";

                                   rc=auth_sasl_ex(method, initreply,
                                                 pop3_externalauth(),
                                                 authresp,
                                                 NULL,
                                                 &authtype,
                                                 &authdata);

                                   if (rc == 0)
                                   {
                                          strcat(strcpy(authservice, "AUTHSERVICE"),getenv("TCPLOCALPORT"));
                                          q=getenv(authservice);
                                          if (!q || !*q)
                                                 q="pop3";

                                          rc=auth_generic(q,
                                                      authtype,
                                                      authdata,
                                                      login_callback,
                                                      NULL);
                                          free(authtype);
                                          free(authdata);
                                   }

                                   courier_safe_printf("INFO: LOGIN "
                                          "FAILED, method=%s, ip=[%s]",
                                          method, ip);
                                   if (rc == AUTHSASL_ABORTED)
                                       printf("-ERR Authentication aborted.\r\n");
                                   else if (rc > 0)
                                   {
                                       perror("ERR: authentication error");
                                       printf("-ERR Temporary problem, please try again later\r\n");
                                       fflush(stdout);
                                       exit(1);
                                   }                                  
                                   else
                                   {
                                       sleep(5);
                                       printf("-ERR Authentication failed.\r\n");
                                   }

                                   fflush(stdout);
                                   continue;
                            }
                     } else if (strcmp(p, "PASS") == 0)
                     {
                            int rc;

                            p=strtok(0, "\r\n");

                            if (!user || p == 0)
                            {
                                   printf("-ERR USER/PASS required.\r\n");
                                   fflush(stdout);
                                   continue;
                            }

                            strcat(strcpy(authservice, "AUTHSERVICE"),getenv("TCPLOCALPORT"));
                            q=getenv(authservice);
                            if (!q || !*q)
                                   q="pop3";

                            rc=auth_login(q, user, p, login_callback, NULL);
                            courier_safe_printf("INFO: LOGIN "
                                   "FAILED, user=%s, ip=[%s]",
                                   user, ip);
                            if (rc > 0)
                            {
                                   perror("ERR: authentication error");
                                   printf("-ERR Temporary problem, please try again later\r\n");
                                   fflush(stdout);
                                   exit(1);
                            }
                            sleep(5);
                            printf("-ERR Login failed.\r\n");
                            fflush(stdout);
                            continue;
                     }
              }
              printf("-ERR Invalid command.\r\n");
              fflush(stdout);
       }
       fprintf(stderr, "DEBUG: Disconnected, ip=[%s]\n", ip);
       exit(0);
       return (0);
}

Here is the call graph for this function:

const char* pop3_externalauth ( )

Definition at line 46 of file pop3dcapa.c.

{
       const char *external=NULL;
       const char *p;

       if ((p=getenv("POP3_TLS")) != 0 && atoi(p))
              external=externalauth();

       return external;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void pop3dcapa ( )

Definition at line 57 of file pop3dcapa.c.

{
       const char *p;
       const char *external=pop3_externalauth();

       printf("+OK Here's what I can do:\r\n");

       if ((p=getenv("POP3_TLS")) != 0 && atoi(p) &&
           (p=getenv("POP3AUTH_TLS")) != 0 && *p)
              ;
       else
              p=getenv("POP3AUTH");

       if ((p && *p) || external)
       {
              if (!p)
                     p="";

              if (!external)
                     external="";

              printf("SASL %s%s%s\r\n", p, *p && *external ? " ":"",
                     *external ? "EXTERNAL":"");
       }
              
       if (have_starttls())
              printf("STLS\r\n");

       printf("TOP\r\nUSER\r\nLOGIN-DELAY 10\r\nPIPELINING\r\nUIDL\r\nIMPLEMENTATION Courier Mail Server\r\n.\r\n");
       fflush(stdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int starttls ( ) [static]

Definition at line 41 of file pop3login.c.

{
       char *argvec[4];

       char localfd_buf[NUMBUFSIZE+40];
       char buf2[NUMBUFSIZE];
       struct couriertls_info cinfo;
       int pipefd[2];

       if (libmail_streampipe(pipefd))
       {
              printf("-ERR libmail_streampipe() failed.\r\n");
              return (-1);
       }

       couriertls_init(&cinfo);
       fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);

       strcat(strcpy(localfd_buf, "-localfd="),
              libmail_str_size_t(pipefd[1], buf2));

       argvec[0]=localfd_buf;
       argvec[1]="-tcpd";
       argvec[2]="-server";
       argvec[3]=NULL;

       printf("+OK Begin SSL/TLS negotiation now.\r\n");
       fflush(stdout);

       if (couriertls_start(argvec, &cinfo))
       {
              close(pipefd[0]);
              close(pipefd[1]);
              printf("-ERR STARTTLS failed: %s\r\n",
                     cinfo.errmsg);
              couriertls_destroy(&cinfo);
              return (-1);
       }

       couriertls_export_subject_environment(&cinfo);
       couriertls_destroy(&cinfo);

       close(pipefd[1]);
       close(0);
       close(1);
       if (dup(pipefd[0]) != 0 || dup(pipefd[0]) != 1)
       {
              perror("dup");
              exit(1);
       }
       close(pipefd[0]);

       putenv("POP3_STARTTLS=NO");
       putenv("POP3_TLS_REQUIRED=0");
       putenv("POP3_TLS=1");
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tls_required ( )

Definition at line 38 of file pop3dcapa.c.

{
       const char *p=getenv("POP3_TLS_REQUIRED");

        if (p && atoi(p))       return (1);
        return (0);
}

Here is the caller graph for this function:


Variable Documentation

const char* defaultmaildir [static]

Definition at line 39 of file pop3login.c.

const char* pop3d [static]

Definition at line 38 of file pop3login.c.