Exemplo n.º 1
0
int
changeuser(POP *p, struct passwd *pwd)
{
    if(setgid(pwd->pw_gid) < 0) {
	pop_log (p, POP_PRIORITY,
		 "Unable to change to gid %u: %s",
		 (unsigned)pwd->pw_gid,
		 strerror(errno));
	return pop_msg (p, POP_FAILURE,
			"Unable to change gid");
    }
    if(setuid(pwd->pw_uid) < 0) {
	pop_log (p, POP_PRIORITY,
		 "Unable to change to uid %u: %s",
		 (unsigned)pwd->pw_uid,
		 strerror(errno));
	return pop_msg (p, POP_FAILURE,
			"Unable to change uid");
    }
#ifdef DEBUG
    if(p->debug)
	pop_log(p, POP_DEBUG,"uid = %u, gid = %u",
	       (unsigned)getuid(),
	       (unsigned)getgid());
#endif /* DEBUG */
    return POP_SUCCESS;
}
Exemplo n.º 2
0
int
login_user(POP *p)
{
    struct stat st;
    struct passwd *pw;

    /*  Look for the user in the password file */
    if ((pw = k_getpwnam(p->user)) == NULL) {
	pop_log(p, POP_PRIORITY, "user %s (from %s) not found",
		p->user, p->ipaddr);
	return pop_msg(p, POP_FAILURE, "Login incorrect.");
    }

    pop_log(p, POP_INFO, "login from %s as %s", p->ipaddr, p->user);

    /*  Build the name of the user's maildrop */
    snprintf(p->drop_name, sizeof(p->drop_name), "%s/%s", POP_MAILDIR, p->user);
    if(stat(p->drop_name, &st) < 0 || !S_ISDIR(st.st_mode)){
	/*  Make a temporary copy of the user's maildrop */
	/*    and set the group and user id */
	if (pop_dropcopy(p, pw) != POP_SUCCESS) return (POP_FAILURE);

	/*  Get information about the maildrop */
	if (pop_dropinfo(p) != POP_SUCCESS) return(POP_FAILURE);
    } else {
	if(changeuser(p, pw) != POP_SUCCESS) return POP_FAILURE;
	if(pop_maildir_info(p) != POP_SUCCESS) return POP_FAILURE;
    }
    /*  Initialize the last-message-accessed number */
    p->last_msg = 0;
    return POP_SUCCESS;
}
Exemplo n.º 3
0
int
add_missing_headers(POP *p, MsgInfoList *mp)
{
#if defined(UIDL) || defined(XOVER)
    if (mp->msg_id == NULL) {
	if (asprintf(&mp->msg_id, "no-message-id-%d", mp->number) == -1) {
	    fclose (p->drop);
	    p->msg_count = 0;
	    return pop_msg (p,POP_FAILURE,
			    "Can't build message list for '%s': Out of memory",
                            p->user);
	}
    }
#endif
#ifdef XOVER
    if (mp->subject == NULL)
	mp->subject = "<none>";
    if (mp->from == NULL)
	mp->from = "<unknown>";
    if (mp->date == NULL)
	mp->date = "<unknown>";
#endif
    return POP_SUCCESS;
}
Exemplo n.º 4
0
int
pop_updt (POP *p)
{
    FILE                *   md;                     /*  Stream pointer for
                                                        the user's maildrop */
    int                     mfd;                    /*  File descriptor for
                                                        above */
    char                    buffer[BUFSIZ];         /*  Read buffer */

    MsgInfoList         *   mp;                     /*  Pointer to message
                                                        info list */
    int		            msg_num;                /*  Current message
                                                        counter */
    int			    status_written;         /*  Status header field
                                                        written */
    int                     nchar;                  /* Bytes read/written */

    long                    offset;                 /* New mail offset */

    int			    blank_line;

#ifdef DEBUG
    if (p->debug) {
        pop_log(p,POP_DEBUG,"Performing maildrop update...");
        pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
    }
#endif /* DEBUG */

    if(IS_MAILDIR(p))
	return pop_maildir_update(p);

    if (p->msgs_deleted == p->msg_count) {
        /* Truncate before close, to avoid race condition,  DO NOT UNLINK!
           Another process may have opened,  and not yet tried to lock */
        ftruncate ((int)fileno(p->drop),0);
        fclose(p->drop) ;
        return (POP_SUCCESS);
    }

#ifdef DEBUG
    if (p->debug)
        pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name);
#endif /* DEBUG */

    /*  Open the user's real maildrop */
    if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0600)) == -1 ||
        (md = fdopen(mfd,"r+")) == NULL) {
        return pop_msg(p,POP_FAILURE,standard_error);
    }

    /*  Lock the user's real mail drop */
    if ( flock(mfd, LOCK_EX) == -1 ) {
        fclose(md) ;
        return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
		       strerror(errno));
    }

    /* Go to the right places */
    offset = lseek((int)fileno(p->drop),0,SEEK_END) ;

    /*  Append any messages that may have arrived during the session
        to the temporary maildrop */
    while ((nchar=read(mfd,buffer,BUFSIZ)) > 0)
        if ( nchar != write((int)fileno(p->drop),buffer,nchar) ) {
            nchar = -1;
            break ;
        }
    if ( nchar != 0 ) {
        fclose(md) ;
        ftruncate((int)fileno(p->drop),(int)offset) ;
        fclose(p->drop) ;
        return pop_msg(p,POP_FAILURE,standard_error);
    }

    rewind(md);
    lseek(mfd,0,SEEK_SET);
    ftruncate(mfd,0) ;

    /* Synch stdio and the kernel for the POP drop */
    rewind(p->drop);
    lseek((int)fileno(p->drop),0,SEEK_SET);

    /*  Transfer messages not flagged for deletion from the temporary
        maildrop to the new maildrop */
#ifdef DEBUG
    if (p->debug)
        pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"",
                p->drop_name,p->temp_drop);
#endif /* DEBUG */

    for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {

        int doing_body;

        /*  Get a pointer to the message information list */
        mp = &p->mlp[msg_num];

        if (mp->flags & DEL_FLAG) {
#ifdef DEBUG
            if(p->debug)
                pop_log(p,POP_DEBUG,
                    "Message %d flagged for deletion.",mp->number);
#endif /* DEBUG */
            continue;
        }

        fseek(p->drop,mp->offset,0);

#ifdef DEBUG
        if(p->debug)
            pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
#endif /* DEBUG */
	blank_line = 1;
        for(status_written = doing_body = 0 ;
            fgets(buffer,MAXMSGLINELEN,p->drop);) {

            if (doing_body == 0) { /* Header */

                /*  Update the message status */
                if (strncasecmp(buffer,"Status:",7) == 0) {
                    if (mp->flags & RETR_FLAG)
                        fputs("Status: RO\n",md);
                    else
                        fputs(buffer, md);
                    status_written++;
                    continue;
                }
                /*  A blank line signals the end of the header. */
                if (*buffer == '\n') {
                    doing_body = 1;
                    if (status_written == 0) {
                        if (mp->flags & RETR_FLAG)
                            fputs("Status: RO\n\n",md);
                        else
                            fputs("Status: U\n\n",md);
                    }
                    else fputs ("\n", md);
                    continue;
                }
                /*  Save another header line */
                fputs (buffer, md);
            }
            else { /* Body */
                if (blank_line && strncmp(buffer,"From ",5) == 0) break;
                fputs (buffer, md);
		blank_line = (*buffer == '\n');
            }
        }
    }

    /* flush and check for errors now!  The new mail will writen
       without stdio,  since we need not separate messages */

    fflush(md) ;
    if (ferror(md)) {
        ftruncate(mfd,0) ;
        fclose(md) ;
        fclose(p->drop) ;
        return pop_msg(p,POP_FAILURE,standard_error);
    }

    /* Go to start of new mail if any */
    lseek((int)fileno(p->drop),offset,SEEK_SET);

    while((nchar=read((int)fileno(p->drop),buffer,BUFSIZ)) > 0)
        if ( nchar != write(mfd,buffer,nchar) ) {
            nchar = -1;
            break ;
        }
    if ( nchar != 0 ) {
        ftruncate(mfd,0) ;
        fclose(md) ;
        fclose(p->drop) ;
        return pop_msg(p,POP_FAILURE,standard_error);
    }

    /*  Close the maildrop and empty temporary maildrop */
    fclose(md);
    ftruncate((int)fileno(p->drop),0);
    fclose(p->drop);

    return(pop_quit(p));
}
Exemplo n.º 5
0
int
pop_pass (POP *p)
{
    struct passwd  *pw;
    int i;
    int status;

    /* Make one string of all these parameters */

    for (i = 1; i < p->parm_count; ++i)
	p->pop_parm[i][strlen(p->pop_parm[i])] = ' ';

    /*  Look for the user in the password file */
    if ((pw = k_getpwnam(p->user)) == NULL)
	return (pop_msg(p,POP_FAILURE,
			"Password supplied for \"%s\" is incorrect.",
			p->user));

    if (p->kerberosp) {
#ifdef KRB5
	if (p->version == 5) {
	    char *name;

	    if (!krb5_kuserok (p->context, p->principal, p->user)) {
		pop_log (p, POP_PRIORITY,
			 "krb5 permission denied");
		return pop_msg(p, POP_FAILURE,
			       "Popping not authorized");
	    }
	    if(krb5_unparse_name (p->context, p->principal, &name) == 0) {
		pop_log(p, POP_INFO, "%s: %s -> %s",
			p->ipaddr, name, p->user);
		free (name);
	    }
	} else {
	    pop_log (p, POP_PRIORITY, "kerberos authentication failed");
	    return pop_msg (p, POP_FAILURE,
			    "kerberos authentication failed");
	}
#endif
	{ }
    } else {
	 /*  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));

#ifdef OTP
	 if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0)
	     /* pass OK */;
	 else
#endif
	 /*  Compare the supplied password with the password file entry */
	 if (p->auth_level != AUTH_NONE)
	     return pop_msg(p, POP_FAILURE,
			    "Password supplied for \"%s\" is incorrect.",
			    p->user);
	 else if (!strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))
	     /* pass OK */;
	 else {
	     int ret = -1;
#ifdef KRB5
	     if(ret)
		 ret = krb5_verify_password (p);
#endif
	     if(ret)
		 return pop_msg(p, POP_FAILURE,
				"Password incorrect");
	 }
    }
    status = login_user(p);
    if(status != POP_SUCCESS)
	return status;

    /*  Authorization completed successfully */
    return (pop_msg (p, POP_SUCCESS,
		     "%s has %d message(s) (%ld octets).",
		     p->user, p->msg_count, p->drop_size));
}
Exemplo n.º 6
0
/*
 *  popper: Handle a Post Office Protocol version 3 session
 */
int
main (int argc, char **argv)
{
    POP                 p;
    state_table     *   s;
    char                message[MAXLINELEN];

    signal(SIGHUP,  catchSIGHUP);
    signal(SIGPIPE, catchSIGHUP);

    /*  Start things rolling */
    pop_init(&p,argc,argv);

    /*  Tell the user that we are listenting */
    pop_msg(&p,POP_SUCCESS, "POP3 server ready");

    /*  State loop.  The POP server is always in a particular state in
        which a specific suite of commands can be executed.  The following
        loop reads a line from the client, gets the command, and processes
        it in the current context (if allowed) or rejects it.  This continues
        until the client quits or an error occurs. */

    for (p.CurrentState=auth1;p.CurrentState!=halt&&p.CurrentState!=error;) {
        if (hangup) {
            pop_msg(&p, POP_FAILURE, "POP hangup: %s", p.myhost);
            if (p.CurrentState > auth2 && !pop_updt(&p))
                pop_msg(&p, POP_FAILURE,
			"POP mailbox update failed: %s", p.myhost);
            p.CurrentState = error;
        } else if (tgets(message, MAXLINELEN, p.input, pop_timeout) == NULL) {
	    pop_msg(&p, POP_FAILURE, "POP timeout: %s", p.myhost);
	    if (p.CurrentState > auth2 && !pop_updt(&p))
                pop_msg(&p,POP_FAILURE,
			"POP mailbox update failed: %s", p.myhost);
            p.CurrentState = error;
        }
        else {
            /*  Search for the command in the command/state table */
            if ((s = pop_get_command(&p,message)) == NULL) continue;

            /*  Call the function associated with this command in
                the current state */
            if (s->function) p.CurrentState = s->result[(*s->function)(&p)];

            /*  Otherwise assume NOOP and send an OK message to the client */
            else {
                p.CurrentState = s->success_state;
                pop_msg(&p,POP_SUCCESS,"time passes");
            }
        }
    }

    /*  Say goodbye to the client */
    pop_msg(&p,POP_SUCCESS,"Pop server at %s signing off.",p.myhost);

    /*  Log the end of activity */
    pop_log(&p,POP_PRIORITY,
        "(v%s) Ending request from \"%s\" at %s\n",VERSION,p.client,p.ipaddr);

    /*  Stop logging */
    closelog();

    return(0);
}
Exemplo n.º 7
0
int
pop_dropinfo(POP *p)
{
    char                    buffer[BUFSIZ];         /*  Read buffer */
    MsgInfoList         *   mp;                     /*  Pointer to message
                                                        info list */
    int			    msg_num;                /*  Current message
                                                        counter */
    int                     nchar;                  /*  Bytes written/read */
    int blank_line = 1; /* previous line was blank */
    int in_header = 0; /* if we are in a header block */

    /*  Initialize maildrop status variables in the POP parameter block */
    p->msg_count = 0;
    p->msgs_deleted = 0;
    p->last_msg = 0;
    p->bytes_deleted = 0;
    p->drop_size = 0;

    /*  Allocate memory for message information structures */
    p->msg_count = ALLOC_MSGS;
    p->mlp = (MsgInfoList *)calloc((unsigned)p->msg_count,sizeof(MsgInfoList));
    if (p->mlp == NULL){
        fclose (p->drop);
        p->msg_count = 0;
        return pop_msg (p,POP_FAILURE,
            "Can't build message list for '%s': Out of memory", p->user);
    }

    rewind (p->drop);

    /*  Scan the file, loading the message information list with
        information about each message */

    for (msg_num = p->drop_size = 0, mp = p->mlp - 1;
             fgets(buffer,MAXMSGLINELEN,p->drop);) {

        nchar  = strlen(buffer);

        if (blank_line && strncmp(buffer,"From ",5) == 0) {
	    in_header = 1;
            if (++msg_num > p->msg_count) {
                p->mlp=(MsgInfoList *) realloc(p->mlp,
                    (p->msg_count+=ALLOC_MSGS)*sizeof(MsgInfoList));
                if (p->mlp == NULL){
                    fclose (p->drop);
                    p->msg_count = 0;
                    return pop_msg (p,POP_FAILURE,
                        "Can't build message list for '%s': Out of memory",
                            p->user);
                }
                mp = p->mlp + msg_num - 2;
            }
            ++mp;
            mp->number = msg_num;
            mp->length = 0;
            mp->lines = 0;
            mp->offset = ftell(p->drop) - nchar;
            mp->flags = 0;
#if defined(UIDL) || defined(XOVER)
	    mp->msg_id = 0;
#endif
#ifdef XOVER
	    mp->subject = 0;
	    mp->from = 0;
	    mp->date = 0;
#endif
#ifdef DEBUG
            if(p->debug)
                pop_log(p, POP_DEBUG,
			"Msg %d at offset %ld being added to list",
			mp->number, mp->offset);
#endif /* DEBUG */
        } else if(in_header)
	    parse_header(mp, buffer);
	blank_line = (strncmp(buffer, "\n", nchar) == 0);
	if(blank_line) {
	    int e;
	    in_header = 0;
	    e = add_missing_headers(p, mp);
	    if(e != POP_SUCCESS)
		return e;
	}
        mp->length += nchar;
        p->drop_size += nchar;
        mp->lines++;
    }
    p->msg_count = msg_num;

#ifdef DEBUG
    if(p->debug && msg_num > 0) {
        int i;
        for (i = 0, mp = p->mlp; i < p->msg_count; i++, mp++)
#ifdef UIDL
	    pop_log(p,POP_DEBUG,
		    "Msg %d at offset %ld is %ld octets long and has %u lines and id %s.",
                    mp->number,mp->offset,mp->length,mp->lines, mp->msg_id);
#else
            pop_log(p,POP_DEBUG,
                "Msg %d at offset %d is %d octets long and has %u lines.",
                    mp->number,mp->offset,mp->length,mp->lines);
#endif
    }
#endif /* DEBUG */

    return(POP_SUCCESS);
}