~ubuntu-branches/ubuntu/hoary/postfix/hoary-security

« back to all changes in this revision

Viewing changes to src/local/file.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-10-06 11:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20041006115033-ooo6yfg6kmoteu04
Tags: upstream-2.1.3
ImportĀ upstreamĀ versionĀ 2.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      file 3
 
4
/* SUMMARY
 
5
/*      mail delivery to arbitrary file
 
6
/* SYNOPSIS
 
7
/*      #include "local.h"
 
8
/*
 
9
/*      int     deliver_file(state, usr_attr, path)
 
10
/*      LOCAL_STATE state;
 
11
/*      USER_ATTR usr_attr;
 
12
/*      char    *path;
 
13
/* DESCRIPTION
 
14
/*      deliver_file() appends a message to a file, UNIX mailbox format,
 
15
/*      or qmail maildir format,
 
16
/*      with duplicate suppression. It will deliver only to non-executable
 
17
/*      regular files.
 
18
/*
 
19
/*      Arguments:
 
20
/* .IP state
 
21
/*      The attributes that specify the message, recipient and more.
 
22
/*      Attributes describing alias, include or forward expansion.
 
23
/*      A table with the results from expanding aliases or lists.
 
24
/* .IP usr_attr
 
25
/*      Attributes describing user rights and environment information.
 
26
/* .IP path
 
27
/*      The file to deliver to. If the name ends in '/', delivery is done
 
28
/*      in qmail maildir format, otherwise delivery is done in UNIX mailbox
 
29
/*      format.
 
30
/* DIAGNOSTICS
 
31
/*      deliver_file() returns non-zero when delivery should be tried again.
 
32
/* SEE ALSO
 
33
/*      defer(3)
 
34
/*      bounce(3)
 
35
/* LICENSE
 
36
/* .ad
 
37
/* .fi
 
38
/*      The Secure Mailer license must be distributed with this software.
 
39
/* AUTHOR(S)
 
40
/*      Wietse Venema
 
41
/*      IBM T.J. Watson Research
 
42
/*      P.O. Box 704
 
43
/*      Yorktown Heights, NY 10598, USA
 
44
/*--*/
 
45
 
 
46
/* System library. */
 
47
 
 
48
#include <sys_defs.h>
 
49
#include <sys/stat.h>
 
50
#include <unistd.h>
 
51
#include <fcntl.h>
 
52
#include <errno.h>
 
53
#include <string.h>
 
54
 
 
55
/* Utility library. */
 
56
 
 
57
#include <msg.h>
 
58
#include <htable.h>
 
59
#include <vstring.h>
 
60
#include <vstream.h>
 
61
#include <deliver_flock.h>
 
62
#include <set_eugid.h>
 
63
 
 
64
/* Global library. */
 
65
 
 
66
#include <mail_copy.h>
 
67
#include <bounce.h>
 
68
#include <defer.h>
 
69
#include <sent.h>
 
70
#include <been_here.h>
 
71
#include <mail_params.h>
 
72
#include <mbox_conf.h>
 
73
#include <mbox_open.h>
 
74
 
 
75
/* Application-specific. */
 
76
 
 
77
#include "local.h"
 
78
 
 
79
#define STR     vstring_str
 
80
 
 
81
/* deliver_file - deliver to file */
 
82
 
 
83
int     deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
 
84
{
 
85
    char   *myname = "deliver_file";
 
86
    struct stat st;
 
87
    MBOX   *mp;
 
88
    VSTRING *why;
 
89
    int     mail_copy_status = MAIL_COPY_STAT_WRITE;
 
90
    int     deliver_status;
 
91
    int     copy_flags;
 
92
 
 
93
    /*
 
94
     * Make verbose logging easier to understand.
 
95
     */
 
96
    state.level++;
 
97
    if (msg_verbose)
 
98
        MSG_LOG_STATE(myname, state);
 
99
 
 
100
    /*
 
101
     * DUPLICATE ELIMINATION
 
102
     * 
 
103
     * Skip this file if it was already delivered to as this user.
 
104
     */
 
105
    if (been_here(state.dup_filter, "file %ld %s", (long) usr_attr.uid, path))
 
106
        return (0);
 
107
 
 
108
    /*
 
109
     * DELIVERY POLICY
 
110
     * 
 
111
     * Do we allow delivery to files?
 
112
     */
 
113
    if ((local_file_deliver_mask & state.msg_attr.exp_type) == 0)
 
114
        return (bounce_append(BOUNCE_FLAGS(state.request),
 
115
                              BOUNCE_ATTR(state.msg_attr),
 
116
                              "mail to file is restricted"));
 
117
 
 
118
    /*
 
119
     * Don't deliver trace-only requests.
 
120
     */
 
121
    if (DEL_REQ_TRACE_ONLY(state.request->flags))
 
122
        return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr),
 
123
                     "delivers to file: %s", path));
 
124
 
 
125
    /*
 
126
     * DELIVERY RIGHTS
 
127
     * 
 
128
     * Use a default uid/gid when none are given.
 
129
     */
 
130
    if (usr_attr.uid == 0 && (usr_attr.uid = var_default_uid) == 0)
 
131
        msg_panic("privileged default user id");
 
132
    if (usr_attr.gid == 0 && (usr_attr.gid = var_default_gid) == 0)
 
133
        msg_panic("privileged default group id");
 
134
 
 
135
    /*
 
136
     * If the name ends in /, use maildir-style delivery instead.
 
137
     */
 
138
    if (path[strlen(path) - 1] == '/')
 
139
        return (deliver_maildir(state, usr_attr, path));
 
140
 
 
141
    /*
 
142
     * Deliver. From here on, no early returns or we have a memory leak.
 
143
     */
 
144
    if (msg_verbose)
 
145
        msg_info("deliver_file (%ld,%ld): %s",
 
146
                 (long) usr_attr.uid, (long) usr_attr.gid, path);
 
147
    if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
 
148
        msg_fatal("seek queue file %s: %m", state.msg_attr.queue_id);
 
149
    why = vstring_alloc(100);
 
150
 
 
151
    /*
 
152
     * As the specified user, open or create the file, lock it, and append
 
153
     * the message.
 
154
     */
 
155
    copy_flags = MAIL_COPY_MBOX;
 
156
    if ((local_deliver_hdr_mask & DELIVER_HDR_FILE) == 0)
 
157
        copy_flags &= ~MAIL_COPY_DELIVERED;
 
158
 
 
159
    set_eugid(usr_attr.uid, usr_attr.gid);
 
160
    mp = mbox_open(path, O_APPEND | O_CREAT | O_WRONLY,
 
161
                   S_IRUSR | S_IWUSR, &st, -1, -1,
 
162
                   local_mbox_lock_mask | MBOX_DOT_LOCK_MAY_FAIL, why);
 
163
    if (mp != 0) {
 
164
        if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
 
165
            vstream_fclose(mp->fp);
 
166
            vstring_sprintf(why, "destination file is executable");
 
167
            errno = 0;
 
168
        } else {
 
169
            mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
 
170
                                         S_ISREG(st.st_mode) ? copy_flags :
 
171
                                         (copy_flags & ~MAIL_COPY_TOFILE),
 
172
                                         "\n", why);
 
173
        }
 
174
        mbox_release(mp);
 
175
    }
 
176
    set_eugid(var_owner_uid, var_owner_gid);
 
177
 
 
178
    /*
 
179
     * As the mail system, bounce, defer delivery, or report success.
 
180
     */
 
181
    if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
 
182
        deliver_status = DEL_STAT_DEFER;
 
183
    } else if (mail_copy_status != 0) {
 
184
        deliver_status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ?
 
185
                          defer_append : bounce_append)
 
186
            (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr),
 
187
             "cannot append message to destination file %s: %s",
 
188
             path, STR(why));
 
189
    } else {
 
190
        deliver_status = sent(BOUNCE_FLAGS(state.request),
 
191
                              SENT_ATTR(state.msg_attr),
 
192
                              "delivered to file: %s", path);
 
193
    }
 
194
 
 
195
    /*
 
196
     * Clean up.
 
197
     */
 
198
    vstring_free(why);
 
199
    return (deliver_status);
 
200
}