Initial revision
authorJohn Kohl <jtkohl@mit.edu>
Wed, 20 Mar 1991 15:25:30 +0000 (15:25 +0000)
committerJohn Kohl <jtkohl@mit.edu>
Wed, 20 Mar 1991 15:25:30 +0000 (15:25 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@1923 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/popper/orig-makefiles/Makefile [new file with mode: 0644]
src/appl/popper/pop_init.c [new file with mode: 0644]
src/appl/popper/pop_pass.c [new file with mode: 0644]

diff --git a/src/appl/popper/orig-makefiles/Makefile b/src/appl/popper/orig-makefiles/Makefile
new file mode 100644 (file)
index 0000000..346e4aa
--- /dev/null
@@ -0,0 +1,108 @@
+CSRCS          =       pop_dele.c pop_dropcopy.c pop_dropinfo.c \
+                       pop_get_command.c pop_get_subcommand.c pop_init.c \
+                       pop_last.c pop_list.c pop_log.c pop_lower.c \
+                       pop_msg.c pop_parse.c pop_pass.c pop_quit.c \
+                       pop_rset.c pop_send.c pop_stat.c pop_updt.c \
+                       pop_user.c pop_xtnd.c pop_xmit.c popper.c
+
+OBJS           =       pop_dele.o pop_dropcopy.o pop_dropinfo.o \
+                       pop_get_command.o pop_get_subcommand.o pop_init.o \
+                       pop_last.o pop_list.o pop_log.o pop_lower.o \
+                       pop_msg.o pop_parse.o pop_pass.o pop_quit.o \
+                       pop_rset.o pop_send.o pop_stat.o pop_updt.o \
+                       pop_user.o pop_xtnd.o pop_xmit.o popper.o
+
+SP_SRCS                =       pop_enter.c 
+SP_OBJS                =       pop_enter.o 
+
+DOCS           =       README pop3.rfc1081 pop3e.rfc1082 popper.8
+
+INCLUDES       =       popper.h version.h
+
+SRCS           =       ${CSRCS} ${INCLUDES}
+
+SCCS           =       /usr/ucb/sccs
+
+REL            =
+
+MAKEFILE       =       Makefile
+
+#               Options are:
+#               BIND43          -      If you are using BSD 4.3 domain 
+#                                      name service.
+#              DEBUG           -       Include the debugging code.  Note:  You
+#                                      still have to use the -d or -t flag to
+#                                      enable debugging.
+#               HAVE_VSPRINTF   -      If the vsprintf functions are available 
+#                                      on your system.
+#               SYSLOG42        -      For BSD 4.2 syslog (default is BSD 4.3 
+#                                      syslog).
+#               STRNCASECMP     -      If you do not have strncasecmp()
+#              KERBEROS        -       If you want authentication vis Kerberos
+#                                                                      (tom)
+#              KERBEROS_PASSWD_HSCK -  Use popper as passwd server
+
+CFLAGS         =       -O -DBIND43 -DKERBEROS -DNOSTATUS
+
+TARGET         =       popper
+
+TAR            =       ${TARGET}.tar
+
+INSTALLDIR     =       /usr/etc
+
+MANPAGE                =       popper.8
+
+CATPAGE                =       popper.0
+
+MANDIR         =       /usr/local/man/cat8
+
+LIBS           =       -lkrb -ldes
+
+all: ${TARGET} 
+
+spop:  ${SP_OBJS}
+       cc  ${SP_OBJS} -o spop ${LIBS}
+
+${TARGET}: ${OBJS}
+       cc  ${OBJS} -o ${TARGET} ${LIBS}
+
+tar: ${SRCS} ${DOCS} ${MAKEFILE}
+       rm -f ${TAR} *.Z*
+       tar -cvf ${TAR} ${SRCS} ${DOCS} ${MAKEFILE}
+       compress ${TAR}
+       uuencode ${TAR}.Z ${TAR}.Z > ${TAR}.Z.uuencoded
+       split -300 ${TAR}.Z.uuencoded
+       mv xaa ${TAR}.Z.uuencoded.xaa
+       mv xab ${TAR}.Z.uuencoded.xab
+       mv xac ${TAR}.Z.uuencoded.xac
+       mv xad ${TAR}.Z.uuencoded.xad
+       mv xae ${TAR}.Z.uuencoded.xae
+
+clean:
+       rm -f core *~ *.o *.Z*
+#      ${SCCS} clean
+
+install: ${TARGET}
+       install -c -m 700 -o root -g staff ${TARGET} ${INSTALLDIR}
+
+installman:
+       rm -f ${CATPAGE}
+       nroff -man ${MANPAGE} > ${CATPAGE}
+       install -c -m 644 -o root -g staff ${CATPAGE} ${MANDIR}
+
+edit:
+       ${SCCS} edit ${REL} ${SRCS}
+
+admin:
+       ${SCCS} admin -ft"Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n" ${SRCS}
+
+sources: ${SRCS}
+
+${SRCS}:
+       ${SCCS} get ${REL} $@ -p | expand -4 > $@
+
+${DOCS}:
+       ${SCCS} get README -p | expand -4 > README
+       ${SCCS} get popper.8 -p | expand -4 > popper.8
+       
+${OBJS}:    popper.h version.h
diff --git a/src/appl/popper/pop_init.c b/src/appl/popper/pop_init.c
new file mode 100644 (file)
index 0000000..8b91109
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * added kerberos authentication (tom coppeto, 1/15/91)
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_init.c  1.12    8/16/90";
+#endif not lint
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "popper.h"
+
+#ifdef KERBEROS
+#include <krb.h>
+    
+AUTH_DAT kdata;
+#endif /* KERBEROS */
+
+extern int      errno;
+
+/* 
+ *  init:   Start a Post Office Protocol session
+ */
+
+pop_init(p,argcount,argmessage)
+POP     *       p;
+int             argcount;
+char    **      argmessage;
+{
+
+    struct sockaddr_in      cs;                 /*  Communication parameters */
+    struct hostent      *   ch;                 /*  Client host information */
+    int                     errflag = 0;
+    int                     c;
+    int                     len;
+    extern char         *   optarg;
+    int                     options = 0;
+    int                     sp = 0;             /*  Socket pointer */
+    char                *   trace_file_name;
+
+    /*  Initialize the POP parameter block */
+    bzero ((char *)p,(int)sizeof(POP));
+
+    /*  Save my name in a global variable */
+    p->myname = argmessage[0];
+
+    /*  Get the name of our host */
+    (void)gethostname(p->myhost,MAXHOSTNAMELEN);
+
+    /*  Open the log file */
+#ifdef SYSLOG42
+    (void)openlog(p->myname,0);
+#else
+    (void)openlog(p->myname,POP_LOGOPTS,POP_FACILITY);
+#endif
+
+    /*  Process command line arguments */
+    while ((c = getopt(argcount,argmessage,"dt:")) != EOF)
+        switch (c) {
+
+            /*  Debugging requested */
+            case 'd':
+                p->debug++;
+                options |= SO_DEBUG;
+                break;
+
+            /*  Debugging trace file specified */
+            case 't':
+                p->debug++;
+                if ((p->trace = fopen(optarg,"a+")) == NULL) {
+                    pop_log(p,POP_ERROR,
+                        "Unable to open trace file \"%s\", err = %d",
+                            optarg,errno);
+                    exit(-1);
+                }
+                trace_file_name = optarg;
+                break;
+
+            /*  Unknown option received */
+            default:
+                errflag++;
+        }
+
+    /*  Exit if bad options specified */
+    if (errflag) {
+        (void)fprintf(stderr,"Usage: %s [-d]\n",argmessage[0]);
+        exit(-1);
+    }
+
+    /*  Get the address and socket of the client to whom I am speaking */
+    len = sizeof(cs);
+    if (getpeername(sp,(struct sockaddr *)&cs,&len) < 0){
+        pop_log(p,POP_ERROR,
+            "Unable to obtain socket and address of client, err = %d",errno);
+        exit(-1);
+    }
+
+    /*  Save the dotted decimal form of the client's IP address 
+        in the POP parameter block */
+    p->ipaddr = inet_ntoa(cs.sin_addr);
+
+    /*  Save the client's port */
+    p->ipport = ntohs(cs.sin_port);
+
+    /*  Get the canonical name of the host to whom I am speaking */
+    ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), AF_INET);
+    if (ch == NULL){
+        pop_log(p,POP_PRIORITY,
+            "%s: unable to get canonical name of client, err = %d", 
+               p->ipaddr, errno);
+        p->client = p->ipaddr;
+    }
+    /*  Save the cannonical name of the client host in 
+        the POP parameter block */
+    else {
+
+#ifndef BIND43
+        p->client = ch->h_name;
+#else
+#       include <arpa/nameser.h>
+#       include <resolv.h>
+
+        /*  Distrust distant nameservers */
+        extern struct state     _res;
+        struct hostent      *   ch_again;
+        char            *   *   addrp;
+
+        /*  We already have a fully-qualified name */
+        _res.options &= ~RES_DEFNAMES;
+
+        /*  See if the name obtained for the client's IP 
+            address returns an address */
+        if ((ch_again = gethostbyname(ch->h_name)) == NULL) {
+         pop_log(p,POP_PRIORITY,
+                "%s: resolves to an unknown host name \"%s\".",
+                    p->ipaddr,ch->h_name);
+            p->client = p->ipaddr;
+        }
+        else {
+            /*  Save the host name (the previous value was 
+                destroyed by gethostbyname) */
+            p->client = ch_again->h_name;
+
+            /*  Look for the client's IP address in the list returned 
+                for its name */
+            for (addrp=ch_again->h_addr_list; *addrp; ++addrp)
+                if (bcmp(*addrp,&(cs.sin_addr),sizeof(cs.sin_addr)) == 0) break;
+
+            if (!*addrp) {
+                pop_log (p,POP_PRIORITY,
+                        "%s: not listed for its host name \"%s\".",
+                        p->ipaddr,ch->h_name);
+                p->client = p->ipaddr;
+            }
+        }
+#endif BIND43
+    }
+
+    /*  Create input file stream for TCP/IP communication */
+    if ((p->input = fdopen(sp,"r")) == NULL){
+        pop_log(p,POP_ERROR,
+            "%s: unable to open communication stream for input, err = %d",
+               p->client, errno);
+        exit (-1);
+    }
+
+    /*  Create output file stream for TCP/IP communication */
+    if ((p->output = fdopen(sp,"w")) == NULL){
+      pop_log(p,POP_ERROR,
+             "%s: unable to open communication stream for output, err = %d",
+             p->client, errno);
+        exit (-1);
+    }
+
+    pop_log(p,POP_INFO,
+        "%s: (v%s) Servicing request at %s\n", p->client, VERSION, p->ipaddr);
+
+#ifdef DEBUG
+    if (p->trace)
+        pop_log(p,POP_PRIORITY,
+            "Tracing session and debugging information in file \"%s\"",
+                trace_file_name);
+    else if (p->debug)
+        pop_log(p,POP_PRIORITY,"Debugging turned on");
+#endif DEBUG
+    
+    return(authenticate(p, &cs));
+}
+
+
+authenticate(p, addr)
+     POP     *p;
+     struct sockaddr_in *addr;
+{
+#ifdef KERBEROS
+    Key_schedule schedule;
+    KTEXT_ST ticket;
+    char instance[INST_SZ];  
+    char version[9];
+    int auth;
+  
+    strcpy(instance, "*");
+    auth = krb_recvauth(0L, 0, &ticket, "pop", instance,
+                       addr, (struct sockaddr_in *) NULL,
+                       &kdata, "", schedule, version);
+    
+    if (auth != KSUCCESS) {
+        pop_msg(p, POP_FAILURE, "Kerberos authentication failure: %s", 
+               krb_err_txt[auth]);
+       pop_log(p, POP_WARNING, "%s: (%s.%s@%s) %s", p->client, 
+               kdata.pname, kdata.pinst, kdata.prealm, krb_err_txt[auth]);
+        exit(-1);
+    }
+
+#ifdef DEBUG
+    pop_log(p, POP_DEBUG, "%s.%s@%s (%s): ok", kdata.pname, 
+           kdata.pinst, kdata.prealm, inet_ntoa(addr->sin_addr));
+#endif /* DEBUG */
+
+#endif /* KERBEROS */
+
+    return(POP_SUCCESS);
+}
diff --git a/src/appl/popper/pop_pass.c b/src/appl/popper/pop_pass.c
new file mode 100644 (file)
index 0000000..127dfb6
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* 
+ * authorization rules for use with kerberos (tom)
+ * password server using kerberos (jon)
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_pass.c  1.7 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <pwd.h>
+#include "popper.h"
+
+#ifdef KERBEROS
+#include <krb.h>
+extern AUTH_DAT kdata;
+#endif /* KERBEROS */
+
+#ifndef KERBEROS_PASSWD_HACK
+
+/* 
+ *  pass:   Obtain the user password from a POP client
+ */
+
+int pop_pass (p)
+POP     *   p;
+{
+#ifdef KERBEROS
+    char lrealm[REALM_SZ];
+    int status; 
+#else
+    register struct passwd  *   pw;
+    char *crypt();
+#endif /* KERBEROS */
+
+
+#ifdef KERBEROS
+    if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) {
+        pop_log(p, POP_WARNING, "%s: (%s.%s@%s) %s", p->client, kdata.pname, 
+               kdata.pinst, kdata.prealm, krb_err_txt[status]);
+        return(pop_msg(p,POP_FAILURE,
+            "Kerberos error:  \"%s\".", krb_err_txt[status]));
+    }
+
+    if (strcmp(kdata.prealm,lrealm))  {
+         pop_log(p, POP_WARNING, "%s: (%s.%s@%s) realm not accepted.", 
+                p->client, kdata.pname, kdata.pinst, kdata.prealm);
+        return(pop_msg(p,POP_FAILURE,
+                    "Kerberos realm \"%s\" not accepted.", kdata.prealm));
+    }
+
+    if (strcmp(kdata.pinst,"")) {
+        pop_log(p, POP_WARNING, "%s: (%s.%s@%s) instance not accepted.", 
+                p->client, kdata.pname, kdata.pinst, kdata.prealm);
+        return(pop_msg(p,POP_FAILURE,
+             "Must use null Kerberos(tm) instance -  \"%s.%s\" not accepted.",
+             kdata.pname, kdata.pinst));
+    }
+
+    /*
+     * be careful! we are assuming that the instance and realm have been
+     * checked already! I used to simply copy the pname into p->user
+     * but this causes too much confusion and assumes p->user will never
+     * change. This makes me feel more comfortable.
+     */
+    if(strcmp(p->user, kdata.pname))
+      {
+       pop_log(p, POP_WARNING, "%s: auth failed: %s.%s@%s vs %s", 
+                p->client, kdata.pname, kdata.pinst, kdata.prealm, p->user);
+        return(pop_msg(p,POP_FAILURE,
+             "Wrong username supplied (%s vs. %s).\n", kdata.pname, 
+                      p->user));
+      }
+
+    /*  Build the name of the user's maildrop */
+    (void)sprintf(p->drop_name,"%s/%s",POP_MAILDIR,p->user);
+    
+    /*  Make a temporary copy of the user's maildrop */
+    if (pop_dropcopy(p) != POP_SUCCESS) return (POP_FAILURE);
+
+#else /* KERBEROS */
+
+    /*  Look for the user in the password file */
+    if ((pw = getpwnam(p->user)) == NULL)
+        return (pop_msg(p,POP_FAILURE,
+            "Password supplied for \"%s\" is incorrect.",p->user));
+        
+    /*  We don't accept connections from users with null passwords */
+    if (pw->pw_passwd == NULL)
+        return (pop_msg(p,POP_FAILURE,
+            "Password supplied for \"%s\" is incorrect.",p->user));
+      
+    /*  Compare the supplied password with the password file entry */
+    if (strcmp (crypt (p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) != 0)
+        return (pop_msg(p,POP_FAILURE,
+            "Password supplied for \"%s\" is incorrect.",p->user));
+
+    /*  Build the name of the user's maildrop */
+    (void)sprintf(p->drop_name,"%s/%s",POP_MAILDIR,p->user);
+
+    /*  Make a temporary copy of the user's maildrop */
+    if (pop_dropcopy(p) != POP_SUCCESS) return (POP_FAILURE);
+
+    /*  Set the group and user id */
+    (void)setgid(pw->pw_gid);
+    (void)setuid(pw->pw_uid);
+
+#ifdef DEBUG
+    if(p->debug)pop_log(p,POP_DEBUG,"uid = %d, gid = %d",getuid(),getgid());
+#endif DEBUG
+
+#endif /* KERBEROS */
+
+    /*  Get information about the maildrop */
+    if (pop_dropinfo(p) != POP_SUCCESS) {
+      pop_log(p, POP_PRIORITY, "dropinfo failure");
+      return(POP_FAILURE);
+    }
+
+    /*  Initialize the last-message-accessed number */
+    p->last_msg = 0;
+
+    /*  Authorization completed successfully */
+    return (pop_msg (p,POP_SUCCESS,
+        "%s has %d message(s) (%d octets).",
+            p->user,p->msg_count,p->drop_size));
+}
+
+
+
+
+
+#else /* KERBEROS_PASSWD_HACK */
+
+
+
+
+/*
+ * Check to see if the user is in the passwd file, if not get a kerberos
+ * ticket with the password
+ */
+
+
+
+#include <sys/file.h>
+#include <netdb.h>
+#include <krb.h>
+
+int pop_pass (p)
+POP     *   p;
+{
+    register struct passwd  *   pw;
+    char *crypt();
+    
+    setpwfile(POP_PASSFILE);
+
+    /*  Look for the user in the password file */
+    pw = getpwnam(p->user);
+
+    /*  Compare the supplied password with the password file entry */
+    if (pw && pw->pw_passwd) {
+      if (strcmp (crypt (p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) != 0)
+        return (pop_msg(p,POP_FAILURE,
+            "Password supplied for \"%s\" is incorrect.",p->user));
+    }
+    else {
+      if(verify_passwd_hack_hack_hack(p) != POP_SUCCESS)
+       return(POP_FAILURE);
+
+      pop_log(p, POP_WARNING, "hack successful");
+    }
+
+    /*  Build the name of the user's maildrop */
+    (void)sprintf(p->drop_name,"%s/%s",POP_MAILDIR,p->user);
+    
+    /*  Make a temporary copy of the user's maildrop */
+    if (pop_dropcopy(p) != POP_SUCCESS) return (POP_FAILURE);
+
+    /*  Set the group and user id */
+    (void)setgid(pw->pw_gid);
+    (void)setuid(pw->pw_uid);
+
+#ifdef DEBUG
+    if(p->debug)pop_log(p,POP_DEBUG,"uid = %d, gid = %d",getuid(),getgid());
+#endif DEBUG
+
+    /*  Get information about the maildrop */
+    if (pop_dropinfo(p) != POP_SUCCESS) {
+      pop_log(p, POP_PRIORITY, "dropinfo failure");
+      return(POP_FAILURE);
+    }
+    pop_log(p, POP_WARNING, "DRP successful");
+    /*  Initialize the last-message-accessed number */
+    p->last_msg = 0;
+
+    /*  Authorization completed successfully */
+    return (pop_msg (p,POP_SUCCESS,
+        "%s has %d message(s) (%d octets).",
+            p->user,p->msg_count,p->drop_size));
+}
+
+
+/* for Ultrix and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+
+int verify_passwd_hack_hack_hack(p)
+     POP *p;
+{
+    char lrealm[REALM_SZ];
+    int status, fd; 
+    KTEXT_ST ticket;
+    AUTH_DAT kdata;
+    char savehost[MAXHOSTNAMELEN];
+    char tkt_file_name[MAXPATHLEN];
+    unsigned long faddr;
+    struct hostent *hp;
+    extern int errno;
+
+    /* Be sure ticket file is correct and exists */
+
+    sprintf(tkt_file_name, "/tmp/tkt_pop.%s.%d", p->user, getpid());
+    if (setenv("KRBTKFILE", tkt_file_name, 1 /* overwrite = yes */))
+      return(pop_msg(p,POP_FAILURE, "Could not set ticket file name."));
+
+    if ((fd = open(tkt_file_name, O_RDWR|O_CREAT, 0600)) == -1) {
+      close(fd);
+      return(pop_msg(p,POP_FAILURE, "Could not create ticket file, \"%s\": %s",
+                    tkt_file_name, sys_errlist[errno]));
+    }
+    close(fd);
+
+    /* 
+     * Get an initial ticket using the given name/password and then use it.
+     * This hack will allow us to stop maintaining a separate pop passwd 
+     * on eagle. We can cut over to real Kerberos POP clients at any point. 
+     */
+
+    if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) 
+        return(pop_msg(p,POP_FAILURE, "Kerberos error:  \"%s\".", 
+                      krb_err_txt[status]));
+    status = krb_get_pw_in_tkt(p->user, "", lrealm, "krbtgt", lrealm,
+                               2 /* 10 minute lifetime */, p->pop_parm[1]);
+
+    if (status != KSUCCESS) 
+      return(pop_msg(p,POP_FAILURE,
+                    "Kerberos error:  \"%s\".", krb_err_txt[status]));
+    
+    /*
+     * Now use the ticket for something useful, to make sure
+     * it is valid.
+     */
+
+    if ((hp = gethostbyname(p->myhost)) == (struct hostent *) NULL) {
+          dest_tkt();
+          return(pop_msg(p, POP_FAILURE,
+                         "Unable to get address of \"%s\": %s",
+                         p->myhost, sys_errlist[errno]));
+    }
+    bcopy((char *)hp->h_addr, (char *) &faddr, sizeof(faddr));
+
+    (void) strncpy(savehost, krb_get_phost(p->myhost), sizeof(savehost));
+    savehost[sizeof(savehost)-1] = 0;
+
+    status = krb_mk_req(&ticket, "pop", savehost, lrealm, 0);
+    if (status == KDC_PR_UNKNOWN) {
+          return(pop_msg(p,POP_FAILURE,
+                    "POP Server configuration error:  \"%s\".", 
+                    krb_err_txt[status]));
+    } 
+      
+    if (status != KSUCCESS) {
+         dest_tkt();
+         return(pop_msg(p,POP_FAILURE,
+                        "Kerberos error (getting mk_req): \"%s\".",
+                        krb_err_txt[status]));
+    }  
+
+    if ((status = krb_rd_req(&ticket, "pop", savehost, faddr, &kdata, ""))
+       != KSUCCESS) {
+         dest_tkt();
+        return(pop_msg(p,POP_FAILURE,
+                       "Could not use ticket.  Bad password? \"%s\".", 
+                       krb_err_txt[status]));
+    }
+    dest_tkt();
+    return(POP_SUCCESS);
+}
+
+#endif /* KERBEROS_PASSWD_HACK */