From 3ee6e108c0fd5c4e7ed0e7d352aae59887672777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Groenvall?= Date: Tue, 5 May 1992 22:35:44 +0000 Subject: [PATCH] Initial revision git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@3 ec53bebd-3082-4978-b11e-865c3cabbd6b --- appl/popper/pop_dropcopy.c | 161 +++++++++++++++++++++++++++++++ appl/popper/pop_init.c | 188 +++++++++++++++++++++++++++++++++++++ appl/popper/pop_user.c | 29 ++++++ 3 files changed, 378 insertions(+) create mode 100644 appl/popper/pop_dropcopy.c create mode 100644 appl/popper/pop_init.c create mode 100644 appl/popper/pop_user.c diff --git a/appl/popper/pop_dropcopy.c b/appl/popper/pop_dropcopy.c new file mode 100644 index 000000000..d848962b7 --- /dev/null +++ b/appl/popper/pop_dropcopy.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef lint +static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n"; +static char SccsId[] = "@(#)@(#)pop_dropcopy.c 2.6 2.6 4/3/91"; +#endif not lint + +#include +#include +#include +#include +#include +#include +#include +#include "popper.h" + +extern int errno; +extern int sys_nerr; +extern char *sys_errlist[]; + +/* + * dropcopy: Make a temporary copy of the user's mail drop and + * save a stream pointer for it. + */ + +pop_dropcopy(p,pwp) +POP * p; +struct passwd * pwp; +{ + int mfd; /* File descriptor for + the user's maildrop */ + int dfd; /* File descriptor for + the SERVER maildrop */ + FILE *tf; /* The temp file */ + char template[POP_TMPSIZE]; /* Temp name holder */ + char buffer[BUFSIZ]; /* Read buffer */ + long offset; /* Old/New boundary */ + int nchar; /* Bytes written/read */ + struct stat mybuf; /* For lstat() */ + + /* Create a temporary maildrop into which to copy the updated maildrop */ + (void)sprintf(p->temp_drop,POP_DROP,p->user); + +#ifdef DEBUG + if(p->debug) + pop_log(p,POP_DEBUG,"Creating temporary maildrop '%s'", + p->temp_drop); +#endif DEBUG + + /* Here we work to make sure the user doesn't cause us to remove or + * write over existing files by limiting how much work we do while + * running as root. + */ + + /* First create a unique file. Would prefer mkstemp, but Ultrix...*/ + strcpy(template,POP_TMPDROP); + (void) mktemp(template); + if ( (tf=fopen(template,"w+")) == NULL ) { /* failure, bail out */ + pop_log(p,POP_PRIORITY, + "Unable to create temporary temporary maildrop '%s': %s",template, + (errno < sys_nerr) ? sys_errlist[errno] : "") ; + return pop_msg(p,POP_FAILURE, + "System error, can't create temporary file."); + } + + /* Now give this file to the user */ + (void) chown(template,pwp->pw_uid, pwp->pw_gid); + (void) chmod(template,0600); + + /* Now link this file to the temporary maildrop. If this fails it + * is probably because the temporary maildrop already exists. If so, + * this is ok. We can just go on our way, because by the time we try + * to write into the file we will be running as the user. + */ + (void) link(template,p->temp_drop); + (void) fclose(tf); + (void) unlink(template); + + /* Now we run as the user. */ + (void) setuid(pwp->pw_uid); + (void) setgid(pwp->pw_gid); + +#ifdef DEBUG + if(p->debug)pop_log(p,POP_DEBUG,"uid = %d, gid = %d",getuid(),getgid()); +#endif DEBUG + + /* Open for append, this solves the crash recovery problem */ + if ((dfd = open(p->temp_drop,O_RDWR|O_APPEND|O_CREAT,0600)) == -1){ + pop_log(p,POP_PRIORITY, + "Unable to open temporary maildrop '%s': %s",p->temp_drop, + (errno < sys_nerr) ? sys_errlist[errno] : "") ; + return pop_msg(p,POP_FAILURE, + "System error, can't open temporary file, do you own it?"); + } + + /* Lock the temporary maildrop */ + if ( flock (dfd, LOCK_EX|LOCK_NB) == -1 ) + switch(errno) { + case EWOULDBLOCK: + return pop_msg(p,POP_FAILURE, + "Maildrop lock busy! Is another session active?"); + /* NOTREACHED */ + default: + return pop_msg(p,POP_FAILURE,"flock: '%s': %s", p->temp_drop, + (errno < sys_nerr) ? sys_errlist[errno] : ""); + /* NOTREACHED */ + } + + /* May have grown or shrunk between open and lock! */ + offset = lseek(dfd,0,L_XTND); + + /* Open the user's maildrop, If this fails, no harm in assuming empty */ + if ((mfd = open(p->drop_name,O_RDWR)) > 0) { + + /* Lock the maildrop */ + if (flock (mfd,LOCK_EX) == -1) { + (void)close(mfd) ; + return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop, + (errno < sys_nerr) ? sys_errlist[errno] : ""); + } + + /* Copy the actual mail drop into the temporary mail drop */ + while ( (nchar=read(mfd,buffer,BUFSIZ)) > 0 ) + if ( nchar != write(dfd,buffer,nchar) ) { + nchar = -1 ; + break ; + } + + if ( nchar != 0 ) { + /* Error adding new mail. Truncate to original size, + and leave the maildrop as is. The user will not + see the new mail until the error goes away. + Should let them process the current backlog, in case + the error is a quota problem requiring deletions! */ + (void)ftruncate(dfd,(int)offset) ; + } else { + /* Mail transferred! Zero the mail drop NOW, that we + do not have to do gymnastics to figure out what's new + and what is old later */ + (void)ftruncate(mfd,0) ; + } + + /* Close the actual mail drop */ + (void)close (mfd); + } + + /* Acquire a stream pointer for the temporary maildrop */ + if ( (p->drop = fdopen(dfd,"a+")) == NULL ) { + (void)close(dfd) ; + return pop_msg(p,POP_FAILURE,"Cannot assign stream for %s", + p->temp_drop); + } + + rewind (p->drop); + + return(POP_SUCCESS); +} diff --git a/appl/popper/pop_init.c b/appl/popper/pop_init.c new file mode 100644 index 000000000..fa14be06c --- /dev/null +++ b/appl/popper/pop_init.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef lint +static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n"; +static char SccsId[] = "@(#)@(#)pop_init.c 2.1 2.1 3/18/91"; +#endif not lint + +#include +#include +#include +#include +#include +#include +#include +#include "popper.h" + +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_PRIORITY, + "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_PRIORITY, + "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, + "Unable to get canonical name of client, err = %d",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 +# include + + /* 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, + "Client at \"%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, + "Client address \"%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_PRIORITY, + "Unable to open communication stream for input, err = %d",errno); + exit (-1); + } + + /* Create output file stream for TCP/IP communication */ + if ((p->output = fdopen(sp,"w")) == NULL){ + pop_log(p,POP_PRIORITY, + "Unable to open communication stream for output, err = %d",errno); + exit (-1); + } + + pop_log(p,POP_PRIORITY, + "(v%s) Servicing request from \"%s\" at %s\n", + VERSION,p->client,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(POP_SUCCESS); +} diff --git a/appl/popper/pop_user.c b/appl/popper/pop_user.c new file mode 100644 index 000000000..7fca0b656 --- /dev/null +++ b/appl/popper/pop_user.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef lint +static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n"; +static char SccsId[] = "@(#)@(#)pop_user.c 2.1 2.1 3/18/91"; +#endif not lint + +#include +#include +#include +#include "popper.h" + +/* + * user: Prompt for the user name at the start of a POP session + */ + +int pop_user (p) +POP * p; +{ + /* Save the user name */ + (void)strcpy(p->user, p->pop_parm[1]); + + /* Tell the user that the password is required */ + return (pop_msg(p,POP_SUCCESS,"Password required for %s.",p->user)); +}