--- /dev/null
+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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */