Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 257410
Collapse All | Expand All

(-)cyrus-imapd-2.3.13/README.autocreate (+211 lines)
Line 0 Link Here
1
Cyrus IMAP autocreate Inbox patch
2
----------------------------------
3
4
NOTE : This patch has been created at the University of Athens. For more info, as well 
5
as more patches on Cyrus IMAPD server, please visit http://email.uoa.gr/ 
6
7
The design of Cyrus IMAP server does not predict the automatic creation of users'
8
INBOX folders. The creation of a user's INBOX is considered to be an external task,
9
that has to be completed as part of the user email account creation procedure. 
10
Hence, to create a new email account the site administrator has to:
11
12
  a) Include the new account in the user database for the authentication procedure
13
     (e.g. sasldb, shadow, mysql, ldap).
14
  b) Create the corresponding INBOX folder. 
15
16
Alternatively, the user, if succesfully authenticated, may create his own INBOX folder,
17
as long as the configuration of the site allows it (see "autocreatequota" in imapd.conf).
18
Unlike what not careful readers may think, enabling the "autocreatequota" option, doesn't 
19
lead to the automatic INBOX folder creation by Cyrus IMAP server.
20
In fact, "autocreate" means that the IMAP clients are allowed to automatically create 
21
the user INBOX. 
22
23
This patch adds the functionality of automatic creation of the users' INBOX folders into
24
the Cyrus IMAP server. It is implemented as two features, namely the  "create on login"
25
and "create on post".
26
 
27
28
29
Create on login
30
===============
31
This feauture provides automatic creation of a user's INBOX folder when all of the 
32
following requirements are met:
33
34
i)  The user has succesfully passed the authentication procedure.
35
36
ii) The user's authorisation ID (typically the same as the user's
37
authentication ID)  doesn't belong to the imap_admins or admins
38
accounts (see imapd.conf).
39
40
iii) The "autocreatequota" option in the imap configuration file 
41
has been set to a non zero value. 
42
43
iv) The corresponding to the user's authorisation ID INBOX folder
44
does not exist.
45
46
The user's first login is the most typical case when all four requirements are met. 
47
Note that if the authenticated ID is allowed to proxy to another account for which 
48
all of the above requirements are met, the corresponding INBOX folder for that account 
49
will be created.
50
51
52
53
Create on post
54
==============
55
This feauture provides automatic creation of a user's INBOX folder when all of the 
56
following requirements are met. 
57
58
i) An email message addressed to the user has been received.  
59
60
ii) The recipient is not any of the imap_admins or admins accounts. 
61
Note that passing emails to admins or imap_admins accounts from 
62
the MTA to LMTP should be avoided in any case.
63
64
iii) The recipient's INBOX does not exist.
65
66
iv) The "autocreatequota" option in the imap configuration file 
67
has been set to a non zero value. 
68
69
v) The "createonpost" option in the imap configuration file 
70
has been switched on. 
71
72
73
Besides the automatic creation of INBOX folder, additional functionalities are
74
provided:
75
76
  (A) Automatic creation of INBOX subfolders controlled by "autocreateinboxfolders"
77
configuration option. eg 
78
79
autocreateinboxfolders: sent|drafts|spam|templates
80
81
  (B) Automatic subscription of INBOX subfolders controlled by "autosubscribeinboxfolders"
82
configuration option. eg
83
84
autosubscribeinboxfolders: sent|spam
85
86
Obviously, only subscription to subfolders included in the "autocreateinboxfolder"
87
list is meaningful. 
88
89
  (C) Automatic subscription to shared folders (bulletin boards). The user gets
90
automatically subscribed to the shared folders declared in the "autosubscribesharedfolders"
91
configuration option in imapd.conf.
92
eg autosubscribesharedfolders: public_folder | public_folder.subfolder
93
94
In order the above action to succeed, the shared folder has to pre-exist the INBOX creation
95
and the user must have the appropriate permissions in order to be able to subscribe to the
96
shared folder.
97
98
* A new config option has been added. 'autosubscribe_all_sharedfolders' is a yes/no
99
option. When set to yes, the user is automatically subscribed to all shared folders one 
100
has permission to subscribe to. Please, note that when this option is set to yes, then
101
'autosubscribesharedfolders' option is overriden.
102
103
  (D) Automatic creation of a predefined default sieve script.
104
105
This is very useful when a default sieve script is used for every user. Usually, a
106
default anti-spam script may me be written in a file and copied to each user
107
sieve scripts upon the INBOX creation. The imapd.conf options that have been added
108
are 'autocreate_sieve_script', 'autocreate_sieve_compiledscript' and 
109
'generate_compiled_sieve_script'. 
110
111
autocreate_sieve_script configuration option refers to the full path of the file 
112
that contains the sieve script. The default value is null and if no file is defined,
113
then no default script is created upon INBOX creation. (The feature is disabled)
114
eg autocreate_sieve_script: /etc/default_sieve_script
115
116
autocreate_sieve_compiledscript configuration option refers to the full path of the
117
file that contains the bytecode compiled sieve script. If this filename is defined
118
in imapd.conf and the file exists, then it is automatically copied in the user's sieve
119
directory. If it is not defined, then a bytecode sieve script gets on the fly compiled
120
by the daemon. 
121
eg autocreate_sieve_compiledscript: /etc/default_sieve_script.bc
122
123
generate_compiled_sieve_script is a boolean option that triggers the compilation of the 
124
source sieve script to bytecode sieve script. The file that the bytecode script will
125
be saved is pointed by autocreate_sieve_compiledscript.
126
127
Ways of compiling a sieve script : 
128
1. Compile a sieve script using the standard sievec utility, distributed by CMU
129
2. Compile a sieve script using the compile_sieve utility, released by UoA. This 
130
   tool is almost identical to the sievec utility, with the difference that it 
131
   reads the input and output file from autocreate_sieve_script and 
132
   autocreate_sieve_compiledscript options in imapd.conf
133
3. Let cyrus create a compiled sieve script using a source script. Cyrus can be
134
   instructed to save the compiled script any time a compiled script does not exist.
135
136
NOTES : 
137
1. In order this functionality to work, the following requirements must have been met:
138
   - 'sieveusehomedir' option must be 'no' in the configuration (default).
139
   - 'sievedir' option must have a valid value.
140
2. Currently, this patch checks the validity of the source script while generating a 
141
   bytecode compiled script, but not the validity of the bytecode sieve script file.
142
   The administrator should make sure that the provided files contain a valid sieve
143
   script as well as the compiled script is updated every time the source script changes.
144
145
146
  (E) The administrator may control for which users and/or groups may the INBOXes 
147
automatically be created. The autocreate_users option restricts the groups
148
for which the patch will create the mailboxes. 
149
150
The default value of autocreate_users is anyone. So, if not set at all, the patch will 
151
work for all users. However, one may set:
152
153
autocreate_users: user1 user2 group:group1 group:group2
154
155
In that case, the INBOX will be created only for user1, user2 and the users that belong 
156
to group1 and group2. 
157
158
More refined control per service is provided by the options imap_autocreate_users,
159
pop3_autocreate_users and lmtp_autocreate_users. These options override the 
160
autocreate_users option and offer per service control.
161
162
Example: 
163
One may want to restrict the create on post functionality only for a specific group
164
of users. To achieve this, the following lines must be added in the imapd.conf file:
165
166
createonpost: yes
167
lmtp_autocreate_users: group:groupname
168
169
170
171
Issues to be considered 
172
=======================
173
174
I) In order to use the create on post feauture one should be absolutely sure that: 
175
a) The MTA checks the validity of the email recipient before sending the email to
176
LMTP. This is an RFC821 requirement. This usually expands to "the mta should be 
177
able to use the account database as user mailbox database". 
178
b) Only authorised accounts/services can talk to LMTP.
179
180
II) Especially in the case of imap logins, the current patch implementation checks
181
for the INBOX folder existence upon login, causing an extra mailbox lookup in most 
182
of the cases. 
183
A better approach would be to chase the "IMAP_MAILBOX_NONEXISTENT" error code and
184
check if the error is associated with an INBOX folder. However, this would mess up
185
Cyrus code. The way it was implemented may not have been the most performance
186
optimised, but it produces a much cleaner and simple patch.
187
188
189
190
Virtual Domains Support
191
=======================
192
193
Virtual domains are supported by all versions of the patch for cyrus-imapd-2.2.1-BETA and 
194
later. However, it is not possible to declare different INBOX subfolders to be created or 
195
shared folders to be subscribed to for every domain.
196
197
198
199
Things to be done
200
=================
201
202
1. Support MUPDATE
203
204
It is within the developers' intentions to support the mupdate protocol, but serious 
205
design issues on future cyrus releases have to resolved first.
206
207
2. Select different attributes (quota, partition, sieve filter, etc) depending on the group
208
a user belongs to. 
209
210
For more information and updates please visit http://email.uoa.gr/projects/cyrus/autocreate
211
(-)cyrus-imapd-2.3.13/imap/Makefile.in (-74 / +78 lines)
Lines 101-107 Link Here
101
	convert_code.o duplicate.o saslclient.o saslserver.o signals.o \
101
	convert_code.o duplicate.o saslclient.o saslserver.o signals.o \
102
	annotate.o search_engines.o squat.o squat_internal.o mbdump.o \
102
	annotate.o search_engines.o squat.o squat_internal.o mbdump.o \
103
	imapparse.o telemetry.o user.o notify.o idle.o quota_db.o \
103
	imapparse.o telemetry.o user.o notify.o idle.o quota_db.o \
104
	sync_log.o $(SEEN) mboxkey.o backend.o tls.o message_guid.o \
104
	sync_log.o autosieve.o $(SEEN) mboxkey.o backend.o tls.o message_guid.o \
105
	statuscache_db.o
105
	statuscache_db.o
106
106
107
IMAPDOBJS=pushstats.o imapd.o proxy.o imap_proxy.o index.o version.o
107
IMAPDOBJS=pushstats.o imapd.o proxy.o imap_proxy.o index.o version.o
Lines 118-124 Link Here
118
	fud smmapd reconstruct quota mbpath ipurge cyr_dbtool cyr_synclog \
118
	fud smmapd reconstruct quota mbpath ipurge cyr_dbtool cyr_synclog \
119
	cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \
119
	cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \
120
	ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \
120
	ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \
121
	unexpunge @IMAP_PROGS@
121
	unexpunge compile_sieve @IMAP_PROGS@
122
122
123
BUILTSOURCES = imap_err.c imap_err.h pushstats.c pushstats.h \
123
BUILTSOURCES = imap_err.c imap_err.h pushstats.c pushstats.h \
124
	lmtpstats.c lmtpstats.h xversion.h mupdate_err.c mupdate_err.h \
124
	lmtpstats.c lmtpstats.h xversion.h mupdate_err.c mupdate_err.h \
Lines 183-191 Link Here
183
mupdate_err.h: mupdate_err.c
183
mupdate_err.h: mupdate_err.c
184
184
185
### Services
185
### Services
186
idled: idled.o mutex_fake.o libimap.a $(DEPLIBS)
186
idled: idled.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS)
187
	$(CC) $(LDFLAGS) -o idled \
187
	$(CC) $(LDFLAGS) -o idled \
188
	 idled.o mutex_fake.o libimap.a $(DEPLIBS) $(LIBS)
188
	 idled.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
189
189
190
lmtpd: lmtpd.o proxy.o $(LMTPOBJS) $(SIEVE_OBJS) mutex_fake.o \
190
lmtpd: lmtpd.o proxy.o $(LMTPOBJS) $(SIEVE_OBJS) mutex_fake.o \
191
	 libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
191
	 libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
Lines 199-360 Link Here
199
	 $(SERVICE) lmtpd.o proxy.o $(LMTPOBJS) $(SIEVE_OBJS) \
199
	 $(SERVICE) lmtpd.o proxy.o $(LMTPOBJS) $(SIEVE_OBJS) \
200
	 mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
200
	 mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
201
201
202
imapd: $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE)
202
imapd: $(IMAPDOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
203
	$(CC) $(LDFLAGS) -o imapd \
203
	$(CC) $(LDFLAGS) -o imapd \
204
	 $(SERVICE) $(IMAPDOBJS) mutex_fake.o \
204
	 $(SERVICE) $(IMAPDOBJS) mutex_fake.o \
205
	libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP)
205
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
206
206
207
imapd.pure: $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE)
207
imapd.pure: $(IMAPDOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
208
	$(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o imapd.pure \
208
	$(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o imapd.pure \
209
	 $(SERVICE) $(IMAPDOBJS) mutex_fake.o libimap.a \
209
	 $(SERVICE) $(IMAPDOBJS) mutex_fake.o libimap.a \
210
	$(DEPLIBS) $(LIBS) $(LIB_WRAP)
210
	$(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
211
211
212
imapd.quant: $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE)
212
imapd.quant: $(IMAPDOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
213
	$(QUANTIFY) $(QUANTOPT) $(CC) $(LDFLAGS) -o imapd.quant \
213
	$(QUANTIFY) $(QUANTOPT) $(CC) $(LDFLAGS) -o imapd.quant \
214
	 $(SERVICE) $(IMAPDOBJS) mutex_fake.o libimap.a \
214
	 $(SERVICE) $(IMAPDOBJS) mutex_fake.o libimap.a \
215
	$(DEPLIBS) $(LIBS) $(LIB_WRAP)
215
	$(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
216
216
217
mupdate: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o tls.o \
217
mupdate: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o tls.o \
218
	libimap.a $(DEPLIBS)
218
	libimap.a $(SIEVE_LIBS) $(DEPLIBS)
219
	$(CC) $(LDFLAGS) -o mupdate \
219
	$(CC) $(LDFLAGS) -o mupdate \
220
	 $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \
220
	 $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \
221
	 mutex_pthread.o tls.o libimap.a \
221
	 mutex_pthread.o tls.o libimap.a \
222
	 $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread
222
	 $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread
223
223
224
mupdate.pure: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o \
224
mupdate.pure: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o \
225
	libimap.a $(DEPLIBS)
225
	libimap.a $(SIEVE_LIBS) $(DEPLIBS)
226
	$(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o mupdate.pure \
226
	$(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o mupdate.pure \
227
	 $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \
227
	 $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \
228
	 mutex_pthread.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread
228
	 mutex_pthread.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread
229
229
230
pop3d: pop3d.o proxy.o backend.o tls.o mutex_fake.o libimap.a \
230
pop3d: pop3d.o proxy.o backend.o tls.o mutex_fake.o libimap.a \
231
	$(DEPLIBS) $(SERVICE)
231
	$(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
232
	$(CC) $(LDFLAGS) -o pop3d pop3d.o proxy.o backend.o tls.o $(SERVICE) \
232
	$(CC) $(LDFLAGS) -o pop3d pop3d.o proxy.o backend.o tls.o $(SERVICE) \
233
	 mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP)
233
	 mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
234
234
235
nntpd: nntpd.o proxy.o backend.o index.o smtpclient.o spool.o tls.o \
235
nntpd: nntpd.o proxy.o backend.o index.o smtpclient.o spool.o tls.o \
236
	 mutex_fake.o nntp_err.o libimap.a $(DEPLIBS) $(SERVICE)
236
	 mutex_fake.o nntp_err.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
237
	$(CC) $(LDFLAGS) -o nntpd nntpd.o proxy.o backend.o index.o spool.o \
237
	$(CC) $(LDFLAGS) -o nntpd nntpd.o proxy.o backend.o index.o spool.o \
238
	 smtpclient.o tls.o $(SERVICE) mutex_fake.o nntp_err.o \
238
	 smtpclient.o tls.o $(SERVICE) mutex_fake.o nntp_err.o \
239
	 libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP)
239
	 libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
240
240
241
fud: fud.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE)
241
fud: fud.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
242
	$(CC) $(LDFLAGS) -o fud $(SERVICE) fud.o mutex_fake.o libimap.a \
242
	$(CC) $(LDFLAGS) -o fud $(SERVICE) fud.o mutex_fake.o libimap.a \
243
	$(DEPLIBS) $(LIBS) $(LIB_WRAP)
243
	$(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
244
244
245
smmapd: smmapd.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE)
245
smmapd: smmapd.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
246
	$(CC) $(LDFLAGS) -o smmapd $(SERVICE) smmapd.o mutex_fake.o libimap.a \
246
	$(CC) $(LDFLAGS) -o smmapd $(SERVICE) smmapd.o mutex_fake.o libimap.a \
247
	$(DEPLIBS) $(LIBS) $(LIB_WRAP)
247
	$(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
248
248
249
sync_server: sync_server.o sync_support.o sync_commit.o \
249
sync_server: sync_server.o sync_support.o sync_commit.o \
250
	imapparse.o tls.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE)
250
	imapparse.o tls.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE)
251
	$(CC) $(LDFLAGS) -o \
251
	$(CC) $(LDFLAGS) -o \
252
	sync_server sync_server.o sync_support.o sync_commit.o \
252
	sync_server sync_server.o sync_support.o sync_commit.o \
253
	imapparse.o tls.o $(SERVICE) libimap.a mutex_fake.o \
253
	imapparse.o tls.o $(SERVICE) libimap.a mutex_fake.o \
254
	$(DEPLIBS) $(LIBS) $(LIB_WRAP)
254
	$(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP)
255
255
256
### Command Line Utilities
256
### Command Line Utilities
257
arbitron: arbitron.o $(CLIOBJS) libimap.a $(DEPLIBS)
257
arbitron: arbitron.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
258
	$(CC) $(LDFLAGS) -o arbitron arbitron.o $(CLIOBJS) \
258
	$(CC) $(LDFLAGS) -o arbitron arbitron.o $(CLIOBJS) \
259
	libimap.a $(DEPLIBS) $(LIBS)
259
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
260
260
261
cyr_dbtool: cyr_dbtool.o mutex_fake.o libimap.a $(DEPLIBS)
261
cyr_dbtool: cyr_dbtool.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS)
262
	$(CC) $(LDFLAGS) -o cyr_dbtool cyr_dbtool.o $(CLIOBJS) \
262
	$(CC) $(LDFLAGS) -o cyr_dbtool cyr_dbtool.o $(CLIOBJS) \
263
	libimap.a $(DEPLIBS) $(LIBS)
263
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
264
264
265
cyr_synclog: cyr_synclog.o mutex_fake.o libimap.a $(DEPLIBS)
265
cyr_synclog: cyr_synclog.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS)
266
	$(CC) $(LDFLAGS) -o cyr_synclog cyr_synclog.o $(CLIOBJS) \
266
	$(CC) $(LDFLAGS) -o cyr_synclog cyr_synclog.o $(CLIOBJS) \
267
	libimap.a $(DEPLIBS) $(LIBS)
267
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
268
268
269
cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(DEPLIBS)
269
cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS)
270
	$(CC) $(LDFLAGS) -o cvt_cyrusdb cvt_cyrusdb.o $(CLIOBJS) \
270
	$(CC) $(LDFLAGS) -o cvt_cyrusdb cvt_cyrusdb.o $(CLIOBJS) \
271
	libimap.a $(DEPLIBS) $(LIBS)
271
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
272
272
273
chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(DEPLIBS)
273
chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS)
274
	$(CC) $(LDFLAGS) -o chk_cyrus chk_cyrus.o $(CLIOBJS) \
274
	$(CC) $(LDFLAGS) -o chk_cyrus chk_cyrus.o $(CLIOBJS) \
275
	libimap.a $(DEPLIBS) $(LIBS)
275
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
276
276
277
deliver: deliver.o $(LMTPOBJS) proxy.o mutex_fake.o libimap.a $(DEPLIBS)
277
deliver: deliver.o $(LMTPOBJS) proxy.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS)
278
	$(CC) $(LDFLAGS) -o deliver deliver.o $(LMTPOBJS) proxy.o \
278
	$(CC) $(LDFLAGS) -o deliver deliver.o $(LMTPOBJS) proxy.o \
279
	mutex_fake.o libimap.a $(DEPLIBS) $(LIBS)
279
	mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
280
280
281
ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS)
281
ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
282
	$(CC) $(LDFLAGS) -o \
282
	$(CC) $(LDFLAGS) -o \
283
	 $@ ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
283
	 $@ ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
284
284
285
ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(DEPLIBS)
285
ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
286
	$(CC) $(LDFLAGS) -o $@ ctl_mboxlist.o mupdate-client.o $(CLIOBJS) \
286
	$(CC) $(LDFLAGS) -o $@ ctl_mboxlist.o mupdate-client.o $(CLIOBJS) \
287
	libimap.a $(DEPLIBS) $(LIBS)
287
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
288
288
289
ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS)
289
ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
290
	$(CC) $(LDFLAGS) -o \
290
	$(CC) $(LDFLAGS) -o \
291
	 $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
291
	 $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
292
292
293
cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(DEPLIBS)
293
cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
294
	$(CC) $(LDFLAGS) -o $@ cyr_expire.o $(CLIOBJS) \
294
	$(CC) $(LDFLAGS) -o $@ cyr_expire.o $(CLIOBJS) \
295
	libimap.a $(DEPLIBS) $(LIBS)
295
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
296
296
297
fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS)
297
fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
298
	$(CC) $(LDFLAGS) -o \
298
	$(CC) $(LDFLAGS) -o \
299
	 $@ fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
299
	 $@ fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
300
300
301
squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(DEPLIBS)
301
squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
302
	$(CC) $(LDFLAGS) -o squatter squatter.o index.o squat_build.o \
302
	$(CC) $(LDFLAGS) -o squatter squatter.o index.o squat_build.o \
303
	$(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
303
	$(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
304
304
305
mbpath: mbpath.o $(CLIOBJS) libimap.a $(DEPLIBS)
305
mbpath: mbpath.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
306
	$(CC) $(LDFLAGS) -o mbpath mbpath.o $(CLIOBJS) libimap.a \
306
	$(CC) $(LDFLAGS) -o mbpath mbpath.o $(CLIOBJS) libimap.a \
307
	$(DEPLIBS) $(LIBS)
307
	$(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
308
308
309
ipurge: ipurge.o $(CLIOBJS) libimap.a $(DEPLIBS)
309
ipurge: ipurge.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
310
	$(CC) $(LDFLAGS) -o ipurge ipurge.o $(CLIOBJS) \
310
	$(CC) $(LDFLAGS) -o ipurge ipurge.o $(CLIOBJS) \
311
	libimap.a $(DEPLIBS) $(LIBS)
311
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
312
312
313
cyr_virusscan: cyr_virusscan.o index.o $(CLIOBJS) libimap.a $(DEPLIBS)
313
cyr_virusscan: cyr_virusscan.o index.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
314
	$(CC) $(LDFLAGS) -o cyr_virusscan cyr_virusscan.o index.o $(CLIOBJS) \
314
	$(CC) $(LDFLAGS) -o cyr_virusscan cyr_virusscan.o index.o $(CLIOBJS) \
315
	libimap.a $(DEPLIBS) $(LIBS) -lclamav
315
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) -lclamav
316
316
317
cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(DEPLIBS)
317
cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
318
	$(CC) $(LDFLAGS) -o cyrdump cyrdump.o index.o $(CLIOBJS) \
318
	$(CC) $(LDFLAGS) -o cyrdump cyrdump.o index.o $(CLIOBJS) \
319
	libimap.a $(DEPLIBS) $(LIBS)
319
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
320
320
321
mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS)
321
mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
322
	$(CC) $(LDFLAGS) -o \
322
	$(CC) $(LDFLAGS) -o \
323
	 mbexamine mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
323
	 mbexamine mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
324
324
325
reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS)
325
reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
326
	$(CC) $(LDFLAGS) -o \
326
	$(CC) $(LDFLAGS) -o \
327
	 reconstruct reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
327
	 reconstruct reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
328
328
329
quota: quota.o $(CLIOBJS) libimap.a $(DEPLIBS)
329
quota: quota.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
330
	$(CC) $(LDFLAGS) -o quota quota.o $(CLIOBJS) \
330
	$(CC) $(LDFLAGS) -o quota quota.o $(CLIOBJS) \
331
	libimap.a $(DEPLIBS) $(LIBS)
331
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
332
332
333
tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS)
333
tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
334
	$(CC) $(LDFLAGS) -o \
334
	$(CC) $(LDFLAGS) -o \
335
	 $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS)
335
	 $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
336
336
337
unexpunge: unexpunge.o $(CLIOBJS) libimap.a $(DEPLIBS)
337
unexpunge: unexpunge.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS)
338
	$(CC) $(LDFLAGS) -o $@ unexpunge.o $(CLIOBJS) \
338
	$(CC) $(LDFLAGS) -o $@ unexpunge.o $(CLIOBJS) \
339
	libimap.a $(DEPLIBS) $(LIBS)
339
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
340
340
341
make_md5: make_md5.o libimap.a mutex_fake.o $(DEPLIBS)
341
make_md5: make_md5.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS)
342
	$(CC) $(LDFLAGS) -o make_md5 make_md5.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS)
342
	$(CC) $(LDFLAGS) -o make_md5 make_md5.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
343
343
344
make_sha1: make_sha1.o libimap.a mutex_fake.o $(DEPLIBS)
344
make_sha1: make_sha1.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS)
345
	$(CC) $(LDFLAGS) -o make_sha1 make_sha1.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS)
345
	$(CC) $(LDFLAGS) -o make_sha1 make_sha1.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
346
346
347
sync_client: sync_client.o sync_support.o \
347
sync_client: sync_client.o sync_support.o \
348
	backend.o tls.o imapparse.o libimap.a mutex_fake.o $(DEPLIBS)
348
	backend.o tls.o imapparse.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS)
349
	$(CC) $(LDFLAGS) -o \
349
	$(CC) $(LDFLAGS) -o \
350
	sync_client sync_client.o sync_support.o \
350
	sync_client sync_client.o sync_support.o \
351
	backend.o tls.o imapparse.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS)
351
	backend.o tls.o imapparse.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
352
352
353
sync_reset: sync_reset.o sync_support.o sync_commit.o \
353
sync_reset: sync_reset.o sync_support.o sync_commit.o \
354
	libimap.a mutex_fake.o $(DEPLIBS)
354
	libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS)
355
	$(CC) $(LDFLAGS) -o \
355
	$(CC) $(LDFLAGS) -o \
356
	sync_reset sync_reset.o sync_support.o sync_commit.o \
356
	sync_reset sync_reset.o sync_support.o sync_commit.o \
357
	libimap.a mutex_fake.o $(DEPLIBS) $(LIBS)
357
	libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
358
359
compile_sieve: compile_sieve.o libimap.a $(DEPLIBS) $(SIEVE_LIBS)
360
	$(CC) $(LDFLAGS) -o compile_sieve compile_sieve.o $(CLIOBJS) \
361
	libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS)
358
362
359
### Other Misc Targets
363
### Other Misc Targets
360
364
(-)cyrus-imapd-2.3.13/imap/autosieve.c (+590 lines)
Line 0 Link Here
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
#ifdef HAVE_UNISTD_H
6
#include <unistd.h>
7
#endif
8
9
#include <errno.h>
10
#include <sys/types.h>
11
#include <sys/stat.h>
12
#include <sys/uio.h>
13
#include <fcntl.h>
14
#include <ctype.h>
15
#include <time.h>
16
#include <syslog.h>
17
#include <com_err.h>
18
#include <config.h>
19
20
#include "global.h"
21
#include "util.h"
22
#include "xmalloc.h"
23
#include "xstrlcpy.h"
24
#include "xstrlcat.h"
25
#include "mailbox.h"
26
#include "imap_err.h"
27
#include "sieve_interface.h"
28
#include "script.h"
29
30
#define TIMSIEVE_FAIL 	-1
31
#define TIMSIEVE_OK 	0
32
#define MAX_FILENAME	1024
33
34
static int get_script_name(char *sievename, size_t buflen, const char *filename);
35
static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir);
36
int autoadd_sieve(char *userid, const char *source_script);
37
38
//static void fatal(const char *s, int code);
39
static void foo(void);
40
static int sieve_notify(void *ac __attribute__((unused)),
41
                        void *interp_context __attribute__((unused)),
42
                        void *script_context __attribute__((unused)),
43
                        void *message_context __attribute__((unused)),
44
                        const char **errmsg __attribute__((unused)));
45
static int mysieve_error(int lineno, const char *msg,
46
                  void *i __attribute__((unused)), void *s);
47
static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret);
48
49
50
sieve_vacation_t vacation2 = {
51
    0,                          /* min response */
52
    0,                          /* max response */
53
    (sieve_callback *) &foo,    /* autorespond() */
54
    (sieve_callback *) &foo     /* send_response() */
55
};
56
57
58
/*
59
 * Find the name of the sieve script
60
 * given the source script and compiled script names
61
 */
62
static int get_script_name(char *sievename, size_t buflen, const char *filename)
63
{
64
  char *p;
65
  int r;
66
67
  p = strrchr(filename, '/');
68
  if (p == NULL)
69
      p = (char *) filename;
70
  else
71
      p++;
72
73
  r = strlcpy(sievename, p, buflen) - buflen;
74
  return (r >= 0 || r == -buflen ? 1 : 0);
75
}
76
77
78
/*
79
 * Find the directory where the sieve scripts of the user
80
 * reside
81
 */
82
static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir)
83
{
84
    char *user = NULL, *domain = NULL;
85
86
    /* Setup the user and the domain */
87
    if(config_virtdomains && (domain = strchr(userid, '@'))) {
88
        user = (char *) xmalloc((domain - userid +1) * sizeof(char));
89
        strlcpy(user, userid, domain - userid + 1);
90
        domain++;
91
    } else
92
        user = userid;
93
94
    /*  Find the dir path where the sieve scripts of the user will reside */   
95
    if (config_virtdomains && domain) {
96
         if(snprintf(sieve_script_dir, buflen, "%s%s%c/%s/%c/%s/",
97
              sieve_dir, FNAME_DOMAINDIR, dir_hash_c(domain, config_fulldirhash), domain, dir_hash_c(user,config_fulldirhash), user) >= buflen) {
98
                 free(user);
99
                 return 1;
100
 	 }
101
    } else {
102
         if(snprintf(sieve_script_dir, buflen, "%s/%c/%s/", 
103
     	      sieve_dir, dir_hash_c(user,config_fulldirhash), user) >= buflen) 
104
                 return 1;
105
    }
106
107
    /* Free the xmalloced user memory, reserved above */
108
    if(user != userid)
109
        free(user);
110
111
    return 0;
112
}
113
114
int autoadd_sieve(char *userid, const char *source_script)
115
{   
116
    sieve_script_t *s = NULL;
117
    bytecode_info_t *bc = NULL;
118
    char *err = NULL;
119
    FILE *in_stream, *out_fp;
120
    int out_fd, in_fd, r, k;
121
    int do_compile = 0;
122
    const char *sieve_dir = NULL;
123
    const char *compiled_source_script = NULL;
124
    char sievename[MAX_FILENAME];
125
    char sieve_script_name[MAX_FILENAME];
126
    char sieve_script_dir[MAX_FILENAME];
127
    char sieve_bcscript_name[MAX_FILENAME];
128
    char sieve_default[MAX_FILENAME];
129
    char sieve_tmpname[MAX_FILENAME];
130
    char sieve_bctmpname[MAX_FILENAME];
131
    char sieve_bclink_name[MAX_FILENAME];
132
    char buf[4096];
133
    mode_t oldmask;
134
    struct stat statbuf;
135
136
    /* We don't support using the homedirectory, like timsieved */
137
    if (config_getswitch(IMAPOPT_SIEVEUSEHOMEDIR)) {
138
        syslog(LOG_WARNING,"autocreate_sieve: autocreate_sieve does not work with sieveusehomedir option in imapd.conf");
139
        return 1;
140
    }
141
142
    /* Check if sievedir is defined in imapd.conf */
143
    if(!(sieve_dir = config_getstring(IMAPOPT_SIEVEDIR))) { 
144
        syslog(LOG_WARNING, "autocreate_sieve: sievedir option is not defined. Check imapd.conf");
145
        return 1;
146
    }
147
148
    /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */
149
    if(!(compiled_source_script  = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) {
150
        syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it");
151
        do_compile = 1;
152
    }
153
154
    if(get_script_dir(sieve_script_dir, sizeof(sieve_script_dir), userid, sieve_dir)) {
155
        syslog(LOG_WARNING, "autocreate_sieve: Cannot find sieve scripts directory");
156
        return 1;
157
    }
158
159
    if (get_script_name(sievename, sizeof(sievename), source_script)) {
160
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve script %s", source_script);
161
        return 1;
162
    }
163
164
    if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s%s.script.NEW",sieve_script_dir, sievename) >= sizeof(sieve_tmpname)) {
165
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid);
166
        return 1;
167
    }
168
    if(snprintf(sieve_bctmpname, sizeof(sieve_bctmpname), "%s%s.bc.NEW",sieve_script_dir, sievename) >= sizeof(sieve_bctmpname)) {
169
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid);
170
        return 1;
171
    }    
172
    if(snprintf(sieve_script_name, sizeof(sieve_script_name), "%s%s.script",sieve_script_dir, sievename) >= sizeof(sieve_script_name)) {
173
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid);
174
        return 1;
175
    }
176
    if(snprintf(sieve_bcscript_name, sizeof(sieve_bcscript_name), "%s%s.bc",sieve_script_dir, sievename) >= sizeof(sieve_bcscript_name)) {
177
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid);
178
        return 1;
179
    }
180
    if(snprintf(sieve_default, sizeof(sieve_default), "%s%s",sieve_script_dir,"defaultbc") >= sizeof(sieve_default)) {
181
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid);
182
        return 1;
183
    }
184
    if(snprintf(sieve_bclink_name, sizeof(sieve_bclink_name), "%s.bc", sievename) >= sizeof(sieve_bclink_name))  {
185
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid);
186
        return 1;
187
    }
188
189
    /* Check if a default sieve filter alrady exists */
190
    if(!stat(sieve_default,&statbuf)) {
191
        syslog(LOG_WARNING,"autocreate_sieve: Default sieve script already exists");
192
        fclose(in_stream);
193
        return 1;
194
    }
195
196
    /* Open the source script. if there is a problem with that exit */
197
    in_stream = fopen(source_script, "r");
198
    if(!in_stream) {
199
        syslog(LOG_WARNING,"autocreate_sieve: Unable to open sieve script %s. Check permissions",source_script);
200
        return 1;
201
    }
202
    
203
    
204
    /* 
205
     * At this point we start the modifications of the filesystem 
206
     */
207
208
    /* Create the directory where the sieve scripts will reside */
209
    r = cyrus_mkdir(sieve_script_dir, 0755);
210
    if(r == -1) {
211
        /* If this fails we just leave */
212
        syslog(LOG_WARNING,"autocreate_sieve: Unable to create directory %s. Check permissions",sieve_script_name);
213
        return 1;
214
    }
215
216
    /*
217
     * We open the file that will be used as the bc file. If this file exists, overwrite it 
218
     * since something bad has happened. We open the file here so that this error checking is
219
     * done before we try to open the rest of the files to start copying etc. 
220
     */
221
    out_fd = open(sieve_bctmpname, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
222
    if(out_fd < 0) {
223
        if(errno == EEXIST) {
224
            syslog(LOG_WARNING,"autocreate_sieve: File %s already exists. Probaly left over. Ignoring",sieve_bctmpname);
225
        } else if (errno == EACCES) {
226
            syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_bctmpname);
227
            fclose(in_stream);
228
            return 1;
229
        } else {
230
            syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s. Unknown error",sieve_bctmpname);
231
            fclose(in_stream);
232
            return 1;
233
        }
234
    }
235
236
    if(!do_compile && compiled_source_script && (in_fd = open(compiled_source_script, O_RDONLY)) != -1) {
237
        while((r = read(in_fd, buf, sizeof(buf))) > 0) {
238
            if((k=write(out_fd, buf,r)) < 0) {
239
                syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_bctmpname, errno);
240
                close(out_fd);
241
                close(in_fd);
242
                fclose(in_stream);
243
                unlink(sieve_bctmpname);
244
                return 1;
245
           }
246
        } 
247
248
        if(r == 0) { /* EOF */
249
            close(out_fd);
250
            close(in_fd);
251
        } else if (r < 0) {
252
            syslog(LOG_WARNING, "autocreate_sieve: Error reading compiled script file: %s. Will try to compile it", 
253
                           compiled_source_script);
254
            close(in_fd);
255
            do_compile = 1;
256
            if(lseek(out_fd, 0, SEEK_SET)) {
257
                syslog(LOG_WARNING, "autocreate_sieve: Major IO problem. Aborting");
258
                return 1;
259
            }
260
        }
261
        close(in_fd);
262
    } else {
263
        if(compiled_source_script)
264
              syslog(LOG_WARNING,"autocreate_sieve: Problem opening compiled script file: %s. Compiling it", compiled_source_script);
265
        do_compile = 1;
266
    }
267
268
269
    /* Because we failed to open a precompiled bc sieve script, we compile one */
270
    if(do_compile) {
271
       if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) {
272
            if(err && *err) {
273
               syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script %s.",err);
274
               free(err);
275
            } else
276
                syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script");
277
    
278
            unlink(sieve_bctmpname);
279
            fclose(in_stream);
280
            close(out_fd);
281
            return 1;
282
        }
283
284
        /* generate the bytecode */
285
        if(sieve_generate_bytecode(&bc, s) == TIMSIEVE_FAIL) {
286
            syslog(LOG_WARNING,"autocreate_sieve: problem compiling sieve script");
287
            /* removing the copied script and cleaning up memory */
288
            unlink(sieve_bctmpname);
289
            sieve_script_free(&s);
290
            fclose(in_stream);
291
            close(out_fd);
292
            return 1;
293
        }
294
295
        if(sieve_emit_bytecode(out_fd, bc) == TIMSIEVE_FAIL) {
296
            syslog(LOG_WARNING,"autocreate_sieve: problem emiting sieve script");
297
            /* removing the copied script and cleaning up memory */
298
            unlink(sieve_bctmpname);
299
            sieve_free_bytecode(&bc);
300
            sieve_script_free(&s);
301
            fclose(in_stream);
302
            close(out_fd);
303
            return 1;
304
        }
305
306
        /* clean up the memory */
307
        sieve_free_bytecode(&bc);
308
        sieve_script_free(&s);
309
    }
310
311
    close(out_fd);
312
    rewind(in_stream);
313
314
    /* Copy the initial script */
315
    oldmask = umask(077);
316
    if((out_fp = fopen(sieve_tmpname, "w")) == NULL) {
317
        syslog(LOG_WARNING,"autocreate_sieve: Unable to open %s destination sieve script", sieve_tmpname);
318
        unlink(sieve_bctmpname);
319
        umask(oldmask);
320
        fclose(in_stream);
321
        return 1;
322
    }
323
    umask(oldmask);
324
325
    while((r = fread(buf,sizeof(char), sizeof(buf), in_stream))) {
326
        if( fwrite(buf,sizeof(char), r, out_fp) != r) {
327
            syslog(LOG_WARNING,"autocreate_sieve: Problem writing to sieve script file: %s",sieve_tmpname);
328
            fclose(out_fp);
329
            unlink(sieve_tmpname);
330
            unlink(sieve_bctmpname);
331
            fclose(in_stream);
332
            return 1;
333
        }
334
    }
335
    
336
    if(feof(in_stream)) {
337
        fclose(out_fp);
338
    } else { /* ferror */
339
        fclose(out_fp);
340
        unlink(sieve_tmpname);
341
        unlink(sieve_bctmpname);
342
        fclose(in_stream);
343
        return 1;
344
    }
345
346
    /* Renaming the necessary stuff */
347
    if(rename(sieve_tmpname, sieve_script_name)) {
348
        unlink(sieve_tmpname);
349
        unlink(sieve_bctmpname);
350
        return 1;
351
    }
352
353
    if(rename(sieve_bctmpname, sieve_bcscript_name)) {
354
        unlink(sieve_bctmpname);
355
        unlink(sieve_bcscript_name);
356
        return 1;
357
    }
358
359
    /* end now with the symlink */
360
    if(symlink(sieve_bclink_name, sieve_default)) {
361
        if(errno != EEXIST) {
362
            syslog(LOG_WARNING, "autocreate_sieve: problem making the default link.");
363
            /* Lets delete the files */
364
            unlink(sieve_script_name);
365
            unlink(sieve_bcscript_name);
366
        }
367
    }
368
369
    /* 
370
     * If everything has succeeded AND we have compiled the script AND we have requested
371
     * to generate the global script so that it is not compiled each time then we create it.
372
     */
373
    if(do_compile && 
374
          config_getswitch(IMAPOPT_GENERATE_COMPILED_SIEVE_SCRIPT)) {
375
376
        if(!compiled_source_script) {
377
            syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf");
378
            return 0;
379
        }
380
381
        if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script) >= sizeof(sieve_tmpname))
382
            return 0;
383
384
        /*
385
         * Copy everything from the newly created bc sieve sieve script.
386
         */
387
        if((in_fd = open(sieve_bcscript_name, O_RDONLY))<0) {
388
            return 0;
389
        }
390
391
        if((out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
392
            if(errno == EEXIST) {
393
               /* Someone is already doing this so just bail out. */
394
               syslog(LOG_WARNING, "autocreate_sieve: %s already exists. Some other instance processing it, or it is left over", sieve_tmpname);
395
                close(in_fd);
396
                return 0; 
397
            } else if (errno == EACCES) {
398
                syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_tmpname);
399
                close(in_fd);
400
                return 0;
401
            } else {
402
                syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s",sieve_tmpname);
403
                close(in_fd);
404
                return 0;
405
            }
406
        }
407
408
        while((r = read(in_fd, buf, sizeof(buf))) > 0) {
409
            if((k = write(out_fd,buf,r)) < 0) {
410
                syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno);
411
                close(out_fd);
412
                close(in_fd);
413
                unlink(sieve_tmpname);
414
                return 0;
415
           }
416
        }
417
418
        if(r == 0 ) { /*EOF */
419
            close(out_fd);
420
            close(in_fd);
421
        } else if (r < 0) {
422
                syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno);
423
                close(out_fd);
424
                close(in_fd);
425
                unlink(sieve_tmpname);
426
                return 0;
427
        }
428
429
        /* Rename the temporary created sieve script to its final name. */
430
        if(rename(sieve_tmpname, compiled_source_script)) {
431
            if(errno != EEXIST) {
432
               unlink(sieve_tmpname);
433
               unlink(compiled_source_script);
434
        }
435
            return 0;
436
        }
437
438
        syslog(LOG_NOTICE, "autocreate_sieve: Compiled sieve script was successfully saved in %s", compiled_source_script);
439
    }
440
441
    return 0;
442
}
443
444
/*static void fatal(const char *s, int code)
445
{   
446
    printf("Fatal error: %s (%d)\r\n", s, code);
447
    exit(1);
448
}*/
449
450
/* to make larry's stupid functions happy :) */
451
static void foo(void)
452
{
453
    fatal("stub function called", 0);
454
}
455
456
static int sieve_notify(void *ac __attribute__((unused)),
457
                        void *interp_context __attribute__((unused)),
458
                        void *script_context __attribute__((unused)),
459
                        void *message_context __attribute__((unused)),
460
                        const char **errmsg __attribute__((unused)))
461
{
462
    fatal("stub function called", 0);
463
    return SIEVE_FAIL;
464
}
465
466
static int mysieve_error(int lineno, const char *msg,
467
                  void *i __attribute__((unused)), void *s)
468
{
469
    char buf[1024];
470
    char **errstr = (char **) s;
471
472
    snprintf(buf, 80, "line %d: %s\r\n", lineno, msg);
473
    *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30);
474
    syslog(LOG_DEBUG, "%s", buf);
475
    strcat(*errstr, buf);
476
477
    return SIEVE_OK;
478
}
479
480
/* end the boilerplate */
481
482
/* returns TRUE or FALSE */
483
int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret)
484
{
485
    sieve_interp_t *i;
486
    sieve_script_t *s;
487
    int res;
488
489
    res = sieve_interp_alloc(&i, NULL);
490
    if (res != SIEVE_OK) {
491
        syslog(LOG_WARNING, "sieve_interp_alloc() returns %d\n", res);
492
        return TIMSIEVE_FAIL;
493
    }
494
495
    res = sieve_register_redirect(i, (sieve_callback *) &foo);
496
    if (res != SIEVE_OK) {
497
        syslog(LOG_WARNING, "sieve_register_redirect() returns %d\n", res);
498
        return TIMSIEVE_FAIL;
499
    }
500
    res = sieve_register_discard(i, (sieve_callback *) &foo);
501
    if (res != SIEVE_OK) {
502
        syslog(LOG_WARNING, "sieve_register_discard() returns %d\n", res);
503
        return TIMSIEVE_FAIL;
504
    }
505
    res = sieve_register_reject(i, (sieve_callback *) &foo);
506
    if (res != SIEVE_OK) {
507
        syslog(LOG_WARNING, "sieve_register_reject() returns %d\n", res);
508
        return TIMSIEVE_FAIL;
509
    }
510
    res = sieve_register_fileinto(i, (sieve_callback *) &foo);
511
    if (res != SIEVE_OK) {
512
        syslog(LOG_WARNING, "sieve_register_fileinto() returns %d\n", res);
513
        return TIMSIEVE_FAIL;
514
    }
515
    res = sieve_register_keep(i, (sieve_callback *) &foo);
516
    if (res != SIEVE_OK) {
517
        syslog(LOG_WARNING, "sieve_register_keep() returns %d\n", res);
518
        return TIMSIEVE_FAIL;
519
    }
520
521
    res = sieve_register_imapflags(i, NULL);
522
    if (res != SIEVE_OK) {
523
        syslog(LOG_WARNING, "sieve_register_imapflags() returns %d\n", res);
524
        return TIMSIEVE_FAIL;
525
    }
526
527
    res = sieve_register_size(i, (sieve_get_size *) &foo);
528
    if (res != SIEVE_OK) {
529
        syslog(LOG_WARNING, "sieve_register_size() returns %d\n", res);
530
        return TIMSIEVE_FAIL;
531
    }
532
533
    res = sieve_register_header(i, (sieve_get_header *) &foo);
534
    if (res != SIEVE_OK) {
535
        syslog(LOG_WARNING, "sieve_register_header() returns %d\n", res);
536
        return TIMSIEVE_FAIL;
537
    }
538
539
    res = sieve_register_envelope(i, (sieve_get_envelope *) &foo);
540
    if (res != SIEVE_OK) {
541
        syslog(LOG_WARNING, "sieve_register_envelope() returns %d\n", res);
542
        return TIMSIEVE_FAIL;
543
    }
544
545
    res = sieve_register_vacation(i, &vacation2);
546
    if (res != SIEVE_OK) {
547
        syslog(LOG_WARNING, "sieve_register_vacation() returns %d\n", res);
548
        return TIMSIEVE_FAIL;
549
    }
550
551
    res = sieve_register_notify(i, &sieve_notify);
552
    if (res != SIEVE_OK) {
553
        syslog(LOG_WARNING, "sieve_register_notify() returns %d\n", res);
554
        return TIMSIEVE_FAIL;
555
    }
556
557
    res = sieve_register_parse_error(i, &mysieve_error);
558
    if (res != SIEVE_OK) {
559
        syslog(LOG_WARNING, "sieve_register_parse_error() returns %d\n", res);
560
        return TIMSIEVE_FAIL;
561
    }
562
563
    rewind(stream);
564
565
    *errstr = (char *) xmalloc(20 * sizeof(char));
566
    strcpy(*errstr, "script errors:\r\n");
567
568
    res = sieve_script_parse(i, stream, errstr, &s);
569
570
    if (res == SIEVE_OK) {
571
        if(ret) {
572
            *ret = s;
573
        } else {
574
            sieve_script_free(&s);
575
        }
576
        free(*errstr);
577
        *errstr = NULL;
578
    }
579
580
    /* free interpreter */
581
    sieve_interp_free(&i);
582
583
    return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL;
584
}
585
586
/*
587
 * Btw the initial date of this patch is Sep, 02 2004 which is the birthday of
588
 * Pavlos. Author of cyrusmaster. So consider this patch as his birthday present
589
 */
590
(-)cyrus-imapd-2.3.13/imap/compile_sieve.c (+365 lines)
Line 0 Link Here
1
/* This tool compiles the sieve script from a command
2
line so that it can be used wby the autoadd patch */
3
#include <stdio.h>
4
#include <stdlib.h>
5
6
#include <config.h>
7
#include <string.h>
8
#ifdef HAVE_UNISTD_H
9
#include <unistd.h>
10
#endif
11
#include <errno.h>
12
#include <sys/types.h>
13
#include <sys/stat.h>
14
#include <sys/uio.h>
15
#include <fcntl.h>
16
#include <ctype.h>
17
#include <time.h>
18
#include <com_err.h>
19
20
#include "global.h"
21
22
#include "util.h"
23
#include "xmalloc.h"
24
#include "xstrlcpy.h"
25
#include "xstrlcat.h"
26
#include "mailbox.h"
27
#include "imap_err.h"
28
#include "sieve_interface.h"
29
#include "script.h"
30
31
#include <pwd.h>
32
33
#define TIMSIEVE_FAIL 		-1
34
#define TIMSIEVE_OK 		0
35
#define MAX_FILENAME_SIZE	100
36
37
/* Needed by libconfig */
38
const int config_need_data = 0;
39
40
static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret);
41
42
/*static void fatal(const char *s, int code)
43
{   
44
    printf("Fatal error: %s (%d)\r\n", s, code);
45
46
    exit(1);
47
}*/
48
49
void usage(void)
50
{
51
    fprintf(stderr,
52
            "Usage:\n\tcompile_sieve [-C <altconfig>] [-i <infile> -o <outfile>]\n");
53
    exit(-1);
54
}
55
56
57
int main (int argc, char **argv)
58
{   
59
60
    sieve_script_t *s = NULL;
61
    bytecode_info_t *bc = NULL;
62
    char *err = NULL;
63
    FILE *in_stream;
64
    int  out_fd, opt;
65
    char *source_script = NULL;
66
    char *compiled_source_script = NULL;
67
    char *alt_config = NULL;
68
    extern char *optarg;
69
    char sieve_tmpname[MAX_MAILBOX_NAME+1];
70
71
    if (geteuid() == 0) fatal("must run as the Cyrus user", EC_USAGE);
72
73
    while((opt = getopt(argc, argv, "C:i:o:")) != EOF) {
74
        switch (opt) {
75
            case 'C': /* alt config file */
76
	        alt_config =  optarg;
77
	        break;
78
	    case 'i': /* input script file */
79
		source_script = optarg;
80
		break;
81
	    case 'o': /* output script file */
82
		compiled_source_script = optarg;
83
		break;
84
	    default:
85
	        usage();
86
		break;
87
	}
88
    }
89
90
    if(source_script && !compiled_source_script) {
91
	    fprintf(stderr, "No output file was defined\n");
92
	    usage();
93
    } else if (!source_script && compiled_source_script) {
94
	    fprintf(stderr, "No input file was defined\n");
95
	    usage();
96
    }	
97
98
    /*
99
     * If no <infile> has been defined, then read them from
100
     * the configuration file.
101
     */
102
    if (!source_script && !compiled_source_script) { 
103
	    cyrus_init(alt_config, "compile_sieve", 0);
104
105
	    /* Initially check if we want to have the sieve script created */
106
	    if(!(source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT))) {
107
        	fprintf(stderr,"autocreate_sieve_script option not defined. Check imapd.conf\n");
108
	        return 1;
109
	    }
110
111
	    /* Check if we have an already compiled sieve script*/
112
	    if(!(compiled_source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) {
113
	        fprintf(stderr, "autocreate_sieve_compiledscript option not defined. Check imapd.conf\n");
114
		return 1;
115
	    }
116
117
	    if(!strrchr(source_script,'/') || !strrchr(compiled_source_script,'/')) {
118
       		/* 
119
		 * At this point the only think that is inconsistent is the directory 
120
		 * that was created. But if the user will have any sieve scripts then 
121
		 * they will eventually go there, so no big deal 
122
		 */
123
	        fprintf(stderr, 
124
			"In imapd.conf the full path of the filenames must be defined\n");
125
	       	return 1;
126
	    }
127
    }
128
129
    printf("input file : %s, output file : %s\n", source_script, compiled_source_script);
130
131
132
    if(strlen(compiled_source_script) + sizeof(".NEW") + 1 > sizeof(sieve_tmpname)) {
133
	    fprintf(stderr, "Filename %s is too big\n", compiled_source_script);
134
	    return 1;
135
    }
136
    	
137
    snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script);
138
139
    in_stream = fopen(source_script,"r");
140
141
    if(!in_stream) {
142
        fprintf(stderr,"Unable to open %s source sieve script\n",source_script);
143
        return 1; 
144
    }
145
146
    /* 
147
     * We open the file that will be used as the bc file. If this file exists, overwrite it 
148
     * since something bad has happened. We open the file here so that this error checking is
149
     * done before we try to open the rest of the files to start copying etc. 
150
     */
151
    out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
152
    if(out_fd < 0) {
153
        if(errno == EEXIST) {
154
            fprintf(stderr, "File %s already exists\n", sieve_tmpname);
155
        } else if (errno == EACCES) {
156
            fprintf(stderr,"No access to create file %s. Please check that you have the correct permissions\n",
157
			    sieve_tmpname);
158
        } else {
159
            fprintf(stderr,"Unable to create %s. Please check that you have the correct permissions\n", 
160
			    sieve_tmpname);
161
        }
162
	
163
	fclose(in_stream);
164
	return 1;
165
    }
166
167
    if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) {
168
        if(err && *err) {
169
           fprintf(stderr, "Error while parsing script %s\n",err);
170
           free(err);
171
        }
172
        else
173
            fprintf(stderr,"Error while parsing script\n");
174
            unlink(sieve_tmpname);
175
	    fclose(in_stream);
176
	    close(out_fd);
177
        return 1;
178
   }
179
180
181
    /* generate the bytecode */
182
    if(sieve_generate_bytecode(&bc,s) == TIMSIEVE_FAIL) {
183
        fprintf(stderr,"Error occured while compiling sieve script\n");
184
        /* removing the copied script and cleaning up memory */
185
        unlink(sieve_tmpname);
186
        sieve_script_free(&s);
187
        fclose(in_stream);
188
        close(out_fd);
189
        return 1;
190
    }
191
    if(sieve_emit_bytecode(out_fd,bc) == TIMSIEVE_FAIL) {
192
        fprintf(stderr, "Error occured while emitting sieve script\n");
193
        unlink(sieve_tmpname);
194
        sieve_free_bytecode(&bc);
195
        sieve_script_free(&s);
196
        fclose(in_stream);
197
        close(out_fd);
198
        return 1;
199
    }
200
201
    /* clean up the memory */
202
    sieve_free_bytecode(&bc);
203
    sieve_script_free(&s);
204
205
    close(out_fd);
206
207
    if(rename(sieve_tmpname, compiled_source_script)) {
208
        if(errno != EEXIST) {
209
            unlink(sieve_tmpname);
210
            unlink(compiled_source_script);
211
            return 1;
212
        }
213
    }
214
    return 0;
215
}
216
217
218
/* to make larry's stupid functions happy :) */
219
static void foo(void)
220
{
221
    fatal("stub function called", 0);
222
}
223
224
extern sieve_vacation_t vacation2;/* = {
225
    0,                          / min response /
226
    0,                          / max response /
227
    (sieve_callback *) &foo,    / autorespond() /
228
    (sieve_callback *) &foo     / send_response() /
229
}; */
230
231
static int sieve_notify(void *ac __attribute__((unused)),
232
                        void *interp_context __attribute__((unused)),
233
                        void *script_context __attribute__((unused)),
234
                        void *message_context __attribute__((unused)),
235
                        const char **errmsg __attribute__((unused)))
236
{
237
    fatal("stub function called", 0);
238
    return SIEVE_FAIL;
239
}
240
241
static int mysieve_error(int lineno, const char *msg,
242
                  void *i __attribute__((unused)), void *s)
243
{
244
    char buf[1024];
245
    char **errstr = (char **) s;
246
247
    snprintf(buf, 80, "line %d: %s\r\n", lineno, msg);
248
    *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30);
249
    fprintf(stderr, "%s\n", buf);
250
    strcat(*errstr, buf);
251
252
    return SIEVE_OK;
253
}
254
255
/* end the boilerplate */
256
257
/* returns TRUE or FALSE */
258
int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret)
259
{
260
    sieve_interp_t *i;
261
    sieve_script_t *s;
262
    int res;
263
264
    res = sieve_interp_alloc(&i, NULL);
265
    if (res != SIEVE_OK) {
266
        fprintf(stderr, "sieve_interp_alloc() returns %d\n", res);
267
        return TIMSIEVE_FAIL;
268
    }
269
270
    res = sieve_register_redirect(i, (sieve_callback *) &foo);
271
    if (res != SIEVE_OK) {
272
        fprintf(stderr, "sieve_register_redirect() returns %d\n", res);
273
        return TIMSIEVE_FAIL;
274
    }
275
    res = sieve_register_discard(i, (sieve_callback *) &foo);
276
    if (res != SIEVE_OK) {
277
        fprintf(stderr, "sieve_register_discard() returns %d\n", res);
278
        return TIMSIEVE_FAIL;
279
    }
280
    res = sieve_register_reject(i, (sieve_callback *) &foo);
281
    if (res != SIEVE_OK) {
282
        fprintf(stderr, "sieve_register_reject() returns %d\n", res);
283
        return TIMSIEVE_FAIL;
284
    }
285
    res = sieve_register_fileinto(i, (sieve_callback *) &foo);
286
    if (res != SIEVE_OK) {
287
        fprintf(stderr, "sieve_register_fileinto() returns %d\n", res);
288
        return TIMSIEVE_FAIL;
289
    }
290
    res = sieve_register_keep(i, (sieve_callback *) &foo);
291
    if (res != SIEVE_OK) {
292
        fprintf(stderr, "sieve_register_keep() returns %d\n", res);
293
        return TIMSIEVE_FAIL;
294
    }
295
296
    res = sieve_register_imapflags(i, NULL);
297
    if (res != SIEVE_OK) {
298
        fprintf(stderr, "sieve_register_imapflags() returns %d\n", res);
299
        return TIMSIEVE_FAIL;
300
    }
301
302
    res = sieve_register_size(i, (sieve_get_size *) &foo);
303
    if (res != SIEVE_OK) {
304
        fprintf(stderr, "sieve_register_size() returns %d\n", res);
305
        return TIMSIEVE_FAIL;
306
    }
307
308
    res = sieve_register_header(i, (sieve_get_header *) &foo);
309
    if (res != SIEVE_OK) {
310
        fprintf(stderr, "sieve_register_header() returns %d\n", res);
311
        return TIMSIEVE_FAIL;
312
    }
313
314
    res = sieve_register_envelope(i, (sieve_get_envelope *) &foo);
315
    if (res != SIEVE_OK) {
316
        fprintf(stderr, "sieve_register_envelope() returns %d\n", res);
317
        return TIMSIEVE_FAIL;
318
    }
319
320
    res = sieve_register_vacation(i, &vacation2);
321
    if (res != SIEVE_OK) {
322
        fprintf(stderr, "sieve_register_vacation() returns %d\n", res);
323
        return TIMSIEVE_FAIL;
324
    }
325
326
    res = sieve_register_notify(i, &sieve_notify);
327
    if (res != SIEVE_OK) {
328
        fprintf(stderr, "sieve_register_notify() returns %d\n", res);
329
        return TIMSIEVE_FAIL;
330
    }
331
332
    res = sieve_register_parse_error(i, &mysieve_error);
333
    if (res != SIEVE_OK) {
334
        fprintf(stderr, "sieve_register_parse_error() returns %d\n", res);
335
        return TIMSIEVE_FAIL;
336
    }
337
338
    rewind(stream);
339
340
    *errstr = (char *) xmalloc(20 * sizeof(char));
341
    strcpy(*errstr, "script errors:\r\n");
342
343
    res = sieve_script_parse(i, stream, errstr, &s);
344
345
    if (res == SIEVE_OK) {
346
        if(ret) {
347
            *ret = s;
348
        } else {
349
            sieve_script_free(&s);
350
        }
351
        free(*errstr);
352
        *errstr = NULL;
353
    }
354
355
    /* free interpreter */
356
    sieve_interp_free(&i);
357
358
    return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL;
359
}
360
361
362
363
364
365
(-)cyrus-imapd-2.3.13/imap/imapd.c (+43 lines)
Lines 209-214 Link Here
209
void motd_file(int fd);
209
void motd_file(int fd);
210
void shut_down(int code);
210
void shut_down(int code);
211
void fatal(const char *s, int code);
211
void fatal(const char *s, int code);
212
void autocreate_inbox(void);
212
213
213
void cmdloop(void);
214
void cmdloop(void);
214
void cmd_login(char *tag, char *user);
215
void cmd_login(char *tag, char *user);
Lines 1975-1980 Link Here
1975
}
1976
}
1976
1977
1977
/*
1978
/*
1979
 * Autocreate Inbox and subfolders upon login
1980
 */
1981
void autocreate_inbox()
1982
{
1983
    char inboxname[MAX_MAILBOX_NAME+1];
1984
    int autocreatequota;
1985
    int r;
1986
 
1987
    /*
1988
     * Exlude admin's accounts
1989
     */
1990
    if (imapd_userisadmin || imapd_userisproxyadmin)
1991
        return;
1992
 
1993
    /*
1994
     * Exclude anonymous
1995
     */
1996
    if (!strcmp(imapd_userid, "anonymous"))
1997
        return;
1998
 
1999
    if ((autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) {
2000
        /* This is actyally not required
2001
           as long as the lenght of userid is ok */
2002
           r = (*imapd_namespace.mboxname_tointernal) (&imapd_namespace,
2003
                                      "INBOX", imapd_userid, inboxname);
2004
           if (!r)
2005
               r = mboxlist_lookup(inboxname, NULL, NULL);
2006
 
2007
           if (r == IMAP_MAILBOX_NONEXISTENT) {
2008
                mboxlist_autocreateinbox(&imapd_namespace, imapd_userid,
2009
                         imapd_authstate, inboxname, autocreatequota);
2010
	   }
2011
     }
2012
}
2013
2014
2015
/*
1978
 * Perform a LOGIN command
2016
 * Perform a LOGIN command
1979
 */
2017
 */
1980
void cmd_login(char *tag, char *user)
2018
void cmd_login(char *tag, char *user)
Lines 2151-2156 Link Here
2151
				strcspn(imapd_userid, "@") : 0);
2189
				strcspn(imapd_userid, "@") : 0);
2152
2190
2153
    freebuf(&passwdbuf);
2191
    freebuf(&passwdbuf);
2192
2193
    autocreate_inbox();
2194
2154
    return;
2195
    return;
2155
}
2196
}
2156
2197
Lines 2308-2313 Link Here
2308
				config_virtdomains ?
2349
				config_virtdomains ?
2309
				strcspn(imapd_userid, "@") : 0);
2350
				strcspn(imapd_userid, "@") : 0);
2310
2351
2352
    autocreate_inbox();
2353
2311
    return;
2354
    return;
2312
}
2355
}
2313
2356
(-)cyrus-imapd-2.3.13/imap/lmtpd.c (+92 lines)
Lines 117-122 Link Here
117
static FILE *spoolfile(message_data_t *msgdata);
117
static FILE *spoolfile(message_data_t *msgdata);
118
static void removespool(message_data_t *msgdata);
118
static void removespool(message_data_t *msgdata);
119
119
120
static int autocreate_inbox(const char *user, const char *domain);
121
120
/* current namespace */
122
/* current namespace */
121
static struct namespace lmtpd_namespace;
123
static struct namespace lmtpd_namespace;
122
124
Lines 976-981 Link Here
976
    exit(code);
978
    exit(code);
977
}
979
}
978
980
981
982
/*
983
 * Autocreate Inbox and subfolders upon login
984
 */
985
int autocreate_inbox(const char *user, const char *domain)
986
{
987
    struct auth_state *auth_state;
988
    char inboxname[MAX_MAILBOX_NAME+1];
989
    char *rcpt_userid = NULL;
990
    int autocreatequota;
991
    int r = 0;
992
993
    if (user == NULL)
994
          return IMAP_MAILBOX_NONEXISTENT;
995
996
    if (domain != NULL) {
997
	int k;
998
	
999
	rcpt_userid = (char *) xmalloc((strlen(user) + strlen(domain) + 2) * sizeof(char));
1000
	k = strlcpy(rcpt_userid, user, strlen(user) + 1);
1001
  	*(rcpt_userid + k) = '@';
1002
       strlcpy(rcpt_userid + k + 1, domain, strlen(domain) + 1);
1003
    } else {
1004
	rcpt_userid = (char *) user;
1005
    }
1006
1007
1008
    /*
1009
     * Exclude anonymous
1010
     */
1011
    if (!strcmp(rcpt_userid, "anonymous")) {
1012
	if (rcpt_userid != user) {
1013
	    free(rcpt_userid);
1014
	}
1015
1016
        return IMAP_MAILBOX_NONEXISTENT;
1017
    }
1018
    
1019
    /*
1020
     * Check for autocreatequota and createonpost
1021
     */
1022
    if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)) ||
1023
        !(config_getswitch(IMAPOPT_CREATEONPOST))) {
1024
	    
1025
	if (rcpt_userid != user) {
1026
	    free(rcpt_userid);
1027
	}
1028
	
1029
        return IMAP_MAILBOX_NONEXISTENT;
1030
     }
1031
1032
1033
    /*
1034
     * Exclude admin's accounts
1035
     */
1036
     auth_state = auth_newstate(rcpt_userid);
1037
     
1038
     if (global_authisa(auth_state, IMAPOPT_ADMINS)) {
1039
	if (rcpt_userid != user) {
1040
	    free(rcpt_userid);
1041
	}
1042
1043
        return IMAP_MAILBOX_NONEXISTENT;
1044
     }
1045
     
1046
     r = (*lmtpd_namespace.mboxname_tointernal) (&lmtpd_namespace,
1047
                                "INBOX", rcpt_userid, inboxname);
1048
     
1049
     if (!r)
1050
 	r = mboxlist_autocreateinbox(&lmtpd_namespace, rcpt_userid,
1051
                         auth_state, inboxname, autocreatequota);
1052
     
1053
     if (rcpt_userid != user) {
1054
	free(rcpt_userid);
1055
     }
1056
       
1057
     return r;
1058
}
1059
1060
979
static int verify_user(const char *user, const char *domain, char *mailbox,
1061
static int verify_user(const char *user, const char *domain, char *mailbox,
980
		       long quotacheck, struct auth_state *authstate)
1062
		       long quotacheck, struct auth_state *authstate)
981
{
1063
{
Lines 1019-1024 Link Here
1019
	 */
1101
	 */
1020
	r = mlookup(namebuf, &server, &acl, NULL);
1102
	r = mlookup(namebuf, &server, &acl, NULL);
1021
1103
1104
	/* If user mailbox does not exist, then invoke autocreate inbox function */
1105
	if (r == IMAP_MAILBOX_NONEXISTENT) {
1106
	    r = autocreate_inbox(user, domain);
1107
1108
	    /* Try to locate the mailbox again */
1109
	    if (!r)
1110
		r = mlookup(namebuf, &server, &acl, NULL);
1111
	}
1112
1022
	if (r == IMAP_MAILBOX_NONEXISTENT && !user &&
1113
	if (r == IMAP_MAILBOX_NONEXISTENT && !user &&
1023
	    config_getswitch(IMAPOPT_LMTP_FUZZY_MAILBOX_MATCH) &&
1114
	    config_getswitch(IMAPOPT_LMTP_FUZZY_MAILBOX_MATCH) &&
1024
	    /* see if we have a mailbox whose name is close */
1115
	    /* see if we have a mailbox whose name is close */
Lines 1045-1050 Link Here
1045
			     aclcheck, (quotacheck < 0)
1136
			     aclcheck, (quotacheck < 0)
1046
			     || config_getswitch(IMAPOPT_LMTP_STRICT_QUOTA) ?
1137
			     || config_getswitch(IMAPOPT_LMTP_STRICT_QUOTA) ?
1047
			     quotacheck : 0);
1138
			     quotacheck : 0);
1139
1048
	}
1140
	}
1049
    }
1141
    }
1050
1142
(-)cyrus-imapd-2.3.13/imap/mboxlist.c (+370 lines)
Lines 83-88 Link Here
83
#include "quota.h"
83
#include "quota.h"
84
#include "sync_log.h"
84
#include "sync_log.h"
85
85
86
#ifdef USE_SIEVE
87
extern int autoadd_sieve(char *userid, 
88
		const char *source_script);
89
#endif
90
91
86
#define DB config_mboxlist_db
92
#define DB config_mboxlist_db
87
#define SUBDB config_subscription_db
93
#define SUBDB config_subscription_db
88
94
Lines 100-110 Link Here
100
static int mboxlist_changequota(const char *name, int matchlen, int maycreate,
106
static int mboxlist_changequota(const char *name, int matchlen, int maycreate,
101
				void *rock);
107
				void *rock);
102
108
109
static int mboxlist_autochangesub(char *name, int matchlen, int maycreate,
110
			      void *rock);
111
112
static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace,
113
                        char *userid, char *auth_userid,
114
                        struct auth_state *auth_state);
115
103
struct change_rock {
116
struct change_rock {
104
    struct quota *quota;
117
    struct quota *quota;
105
    struct txn **tid;
118
    struct txn **tid;
106
};
119
};
107
120
121
/*
122
 * Struct needed to be passed as void *rock to
123
 * mboxlist_autochangesub();
124
 */
125
struct changesub_rock_st {
126
        char *userid;
127
        char *auth_userid;
128
        struct auth_state *auth_state;
129
};
130
131
108
#define FNAME_SUBSSUFFIX ".sub"
132
#define FNAME_SUBSSUFFIX ".sub"
109
133
110
/*
134
/*
Lines 3383-3385 Link Here
3383
3407
3384
    return(config_delete_mode == IMAP_ENUM_DELETE_MODE_DELAYED);
3408
    return(config_delete_mode == IMAP_ENUM_DELETE_MODE_DELAYED);
3385
}
3409
}
3410
3411
/*
3412
 * Automatically subscribe user to *ALL* shared folders,
3413
 * one has permissions to be subscribed to.
3414
 * INBOX subfolders are excluded.
3415
 */
3416
static int mboxlist_autochangesub(char *name, int matchlen, int maycreate,
3417
                        void *rock) {
3418
3419
  struct changesub_rock_st *changesub_rock = (struct changesub_rock_st *) rock;
3420
  char *userid = changesub_rock->userid;
3421
  char *auth_userid = changesub_rock->auth_userid;
3422
  struct auth_state *auth_state = changesub_rock->auth_state;
3423
  int r;
3424
3425
3426
  if((strlen(name) == 5 && !strncmp(name, "INBOX", 5)) || /* Exclude INBOX */
3427
     (strlen(name) > 5  && !strncmp(name, "INBOX.",6)) || /* Exclude INBOX subfolders */
3428
     (strlen(name) > 4  && !strncmp(name, "user.", 5)))   /* Exclude other users' folders */
3429
	  return 0;
3430
3431
     
3432
  r = mboxlist_changesub(name, userid, auth_state, 1, 0);
3433
3434
  if (r) {
3435
      syslog(LOG_WARNING,
3436
             "autosubscribe: User %s to folder %s, subscription failed: %s",
3437
             auth_userid, name, error_message(r));
3438
  } else {
3439
      syslog(LOG_NOTICE,
3440
             "autosubscribe: User %s to folder %s, subscription succeeded",
3441
             auth_userid, name);
3442
  }
3443
3444
  return 0;
3445
}
3446
3447
#define SEP '|'
3448
3449
/*
3450
 * Automatically subscribe user to a shared folder.
3451
 * Subscription is done successfully, if the shared
3452
 * folder exists and the user has the necessary 
3453
 * permissions.
3454
 */
3455
static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace,
3456
                        char *userid, char *auth_userid,
3457
                        struct auth_state *auth_state) {
3458
        
3459
    const char *sub ;
3460
    char *p, *q, *next_sub;
3461
    char folder[MAX_MAILBOX_NAME+1], name[MAX_MAILBOX_NAME+1], mailboxname[MAX_MAILBOX_NAME+1];
3462
    int len;
3463
    int r = 0;
3464
    int subscribe_all_sharedfolders = 0;
3465
3466
    subscribe_all_sharedfolders = config_getswitch(IMAPOPT_AUTOSUBSCRIBE_ALL_SHAREDFOLDERS);
3467
3468
    /*
3469
     * If subscribeallsharedfolders is set to yes in imapd.conf, then
3470
     * subscribe user to every shared folder one has the apropriate 
3471
     * permissions.
3472
     */
3473
    if(subscribe_all_sharedfolders) {
3474
       char pattern[MAX_MAILBOX_PATH+1];
3475
       struct changesub_rock_st changesub_rock;
3476
3477
       strcpy(pattern, "*");
3478
       changesub_rock.userid = userid;
3479
       changesub_rock.auth_userid = auth_userid;
3480
       changesub_rock.auth_state = auth_state;
3481
3482
       r = mboxlist_findall(namespace, pattern, 0, userid,
3483
                            auth_state, mboxlist_autochangesub, &changesub_rock);
3484
3485
       return r;
3486
    }
3487
3488
    if ((sub=config_getstring(IMAPOPT_AUTOSUBSCRIBESHAREDFOLDERS)) == NULL)
3489
       return r;
3490
3491
    next_sub = (char *) sub;
3492
    while (*next_sub) {
3493
        for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++);
3494
        for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++);
3495
        for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--);
3496
        if (!*p ) continue;
3497
3498
        len = q - p + 1;
3499
        /* Check for folder length */
3500
        if (len  > sizeof(folder)-1)
3501
                continue;
3502
3503
        if (!r) {
3504
                strncpy(folder, p, len);
3505
                folder[len] = '\0';
3506
3507
               strlcpy(name, namespace->prefix[NAMESPACE_SHARED], sizeof(name));
3508
               len = strlcat(name, folder, sizeof(name));
3509
3510
               r = (namespace->mboxname_tointernal) (namespace, name, userid,
3511
                                                                  mailboxname);
3512
       }
3513
                                                                  
3514
        if (!r)
3515
               r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 0);
3516
3517
        if (!r) {
3518
                syslog(LOG_NOTICE, "autosubscribe: User %s to %s succeeded", 
3519
                       userid, folder);
3520
        } else {
3521
                syslog(LOG_WARNING, "autosubscribe: User %s to %s failed: %s", 
3522
                       userid, folder, error_message(r));
3523
                r = 0;
3524
        }
3525
    }
3526
3527
    return r;
3528
}
3529
3530
3531
3532
int mboxlist_autocreateinbox(struct namespace *namespace,
3533
                        char *userid,
3534
                        struct auth_state *auth_state,
3535
                        char *mailboxname, int autocreatequota) {
3536
    char name [MAX_MAILBOX_NAME+1];
3537
    char folder [MAX_MAILBOX_NAME+1];
3538
    char *auth_userid = NULL;
3539
    char *partition = NULL;
3540
    const char *crt;
3541
    const char *sub;
3542
    char *p, *q, *next_crt, *next_sub;
3543
    int len;
3544
    int r = 0;
3545
    int numcrt = 0;
3546
    int numsub = 0;
3547
#ifdef USE_SIEVE
3548
    const char *source_script;
3549
#endif
3550
3551
3552
3553
    auth_userid = auth_canonuser(auth_state);
3554
    if (auth_userid == NULL) {
3555
         /*
3556
          * Couldn't get cannon userid
3557
          */
3558
          syslog(LOG_ERR,
3559
                 "autocreateinbox: Could not get canonified userid for user %s", userid);
3560
          return IMAP_PARTITION_UNKNOWN;
3561
    }
3562
3563
    /* Added this for debug information. */
3564
    syslog(LOG_DEBUG, "autocreateinbox: autocreate inbox for user %s was called", auth_userid);
3565
3566
   /*
3567
    * While this is not needed for admins
3568
    * and imap_admins accounts, it would be
3569
    * better to separate *all* admins and
3570
    * proxyservers from normal accounts
3571
    * (accounts that have mailboxes).
3572
    * UOA Specific note(1): Even if we do not
3573
    * exclude these servers-classes here,
3574
    * UOA specific code, will neither return
3575
    * role, nor create INBOX, because none of these
3576
    * administrative accounts belong to  the
3577
    * mailRecipient objectclass, or have imapPartition.
3578
    * UOA Specific note(2): Another good reason for doing
3579
    * this, is to prevent the code, from getting into
3580
    * cyrus_ldap.c because of the continues MSA logins to LMTPd.
3581
    */
3582
3583
   /*
3584
    * admins and the coresponding imap
3585
    * service, had already been excluded.
3586
    */
3587
3588
   /*
3589
    * Do we really need group membership
3590
    * for admins or service_admins?
3591
    */
3592
    if (global_authisa(auth_state, IMAPOPT_ADMINS)) return 0;
3593
3594
   /*
3595
    * Do we really need group membership
3596
    * for proxyservers?
3597
    */
3598
    if (global_authisa(auth_state, IMAPOPT_PROXYSERVERS)) return 0;
3599
3600
    /* 
3601
     * Check if user belongs to the autocreate_users group. This option
3602
     * controls for whom the mailbox may be automatically created. Default
3603
     * value for this option is 'anyone'. So, if not declared, all mailboxes
3604
     * will be created.
3605
     */
3606
    if (!global_authisa(auth_state, IMAPOPT_AUTOCREATE_USERS)) {
3607
	    syslog(LOG_DEBUG, "autocreateinbox: User %s does not belong to the autocreate_users. No mailbox is created",
3608
			    auth_userid);
3609
	    return IMAP_MAILBOX_NONEXISTENT;
3610
    }
3611
3612
#if 0
3613
        /*
3614
         * Get Partition info or return.
3615
         * (Here you should propably use
3616
         * you own "get_partition(char *userid)"
3617
         * function. Otherwise all new INBOXes will be
3618
         * created into whatever partition has been declared
3619
         * as default in your imapd.conf)
3620
         */
3621
3622
        partition = get_partition(userid);
3623
        if (partition == NULL) {
3624
            /*
3625
             * Couldn't get partition info
3626
             */
3627
            syslog(LOG_ERR,
3628
                   "Could not get imapPartition info for user %s", userid);
3629
            return IMAP_PARTITION_UNKNOWN;
3630
        }
3631
#endif
3632
3633
    r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL,
3634
                                      1, userid, auth_state, 0, 0, 0);
3635
3636
    if (!r && autocreatequota > 0)
3637
        r = mboxlist_setquota(mailboxname, autocreatequota, 0);
3638
3639
    if (!r)
3640
        r = mboxlist_changesub(mailboxname, userid,
3641
                              auth_state, 1, 1);
3642
3643
    if (!r) {
3644
       syslog(LOG_NOTICE, "autocreateinbox: User %s, INBOX was successfully created in partition %s", 
3645
               auth_userid, partition == NULL ? "default" : partition);
3646
    } else {
3647
       syslog(LOG_ERR, "autocreateinbox: User %s, INBOX failed. %s", 
3648
               auth_userid, error_message(r));
3649
    }
3650
3651
#if 0
3652
    /* Allocated from get_partition, and not needed any more */
3653
    free_partition(partition);
3654
#endif
3655
3656
    if (r) return r;
3657
3658
    /* INBOX's subfolders */
3659
    if ((crt=config_getstring(IMAPOPT_AUTOCREATEINBOXFOLDERS)))
3660
        sub=config_getstring(IMAPOPT_AUTOSUBSCRIBEINBOXFOLDERS);
3661
3662
    /* Roll through crt */
3663
    next_crt = (char *) crt;
3664
    while (next_crt!=NULL && *next_crt) {
3665
          for (p = next_crt ; isspace((int) *p) || *p == SEP ; p++);
3666
          for (next_crt = p ; *next_crt && *next_crt != SEP ; next_crt++);
3667
          for (q = next_crt ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--);
3668
3669
          if (!*p) continue;
3670
3671
          len = q - p + 1;
3672
3673
          /* First time we check for length */
3674
          if (len > sizeof(folder) - 5)
3675
              r = IMAP_MAILBOX_BADNAME;
3676
3677
          if (!r) {
3678
                  strncpy(folder, p, len);
3679
                  folder[len] = '\0';
3680
3681
                  strlcpy(name, namespace->prefix[NAMESPACE_INBOX], sizeof(name));
3682
                  len = strlcat(name, folder, sizeof(name));
3683
          }
3684
3685
          if (!r)
3686
            r = (namespace->mboxname_tointernal) (namespace, name, userid,
3687
                                                 mailboxname);
3688
          if (!r)
3689
             r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL,
3690
                                            1, userid, auth_state, 0, 0, 0);
3691
3692
          if (!r) {
3693
            numcrt++;
3694
            syslog(LOG_NOTICE, "autocreateinbox: User %s, subfolder %s creation succeeded.", 
3695
               auth_userid, name);
3696
         } else {
3697
             syslog(LOG_WARNING, "autocreateinbox: User %s, subfolder %s creation failed. %s", 
3698
               auth_userid, name, error_message(r));
3699
             r=0;
3700
             continue;
3701
          }
3702
3703
          /* Roll through sub */
3704
          next_sub = (char *) sub;
3705
          while (next_sub!=NULL && *next_sub) {
3706
                for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++);
3707
                for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++);
3708
                for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--);
3709
                if (!*p ) continue;
3710
3711
                len = q - p + 1;
3712
3713
                if (len != strlen(folder) || strncmp(folder, p, len))
3714
                    continue;
3715
3716
                r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 1);
3717
3718
               if (!r) {
3719
                   numsub++;
3720
                   syslog(LOG_NOTICE,"autocreateinbox: User %s, subscription to %s succeeded",
3721
                       auth_userid, name);
3722
               } else
3723
                    syslog(LOG_WARNING, "autocreateinbox: User %s, subscription to  %s failed. %s",
3724
                       auth_userid, name, error_message(r));
3725
3726
                break;
3727
         }
3728
    }
3729
3730
    if (crt!=NULL && *crt)
3731
       syslog(LOG_INFO, "User %s, Inbox subfolders, created %d, subscribed %d", 
3732
               auth_userid, numcrt, numsub);
3733
3734
    /*
3735
     * Check if shared folders are available for subscription.
3736
     */
3737
    mboxlist_autosubscribe_sharedfolders(namespace, userid, auth_userid, auth_state);
3738
3739
#ifdef USE_SIEVE
3740
    /*
3741
     * Here the autocreate sieve script feature is iniated from.
3742
     */
3743
    source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT);
3744
 
3745
    if (source_script) {
3746
        if (!autoadd_sieve(userid, source_script))
3747
            syslog(LOG_NOTICE, "autocreate_sieve: User %s, default sieve script creation succeeded", auth_userid);
3748
        else
3749
            syslog(LOG_WARNING, "autocreate_sieve: User %s, default sieve script creation failed", auth_userid);
3750
    }
3751
#endif
3752
3753
    return r;
3754
}
3755
(-)cyrus-imapd-2.3.13/imap/mboxlist.h (+4 lines)
Lines 212-215 Link Here
212
int mboxlist_abort(struct txn *tid);
212
int mboxlist_abort(struct txn *tid);
213
213
214
int mboxlist_delayed_delete_isenabled(void);
214
int mboxlist_delayed_delete_isenabled(void);
215
int mboxlist_autocreateinbox(struct namespace *namespace,char *userid,
216
                       struct auth_state *auth_state, char *mailboxname, 
217
                       int autocreatequota);
218
215
#endif
219
#endif
(-)cyrus-imapd-2.3.13/imap/pop3d.c (+46 lines)
Lines 172-177 Link Here
172
static char popd_apop_chal[45 + MAXHOSTNAMELEN + 1]; /* <rand.time@hostname> */
172
static char popd_apop_chal[45 + MAXHOSTNAMELEN + 1]; /* <rand.time@hostname> */
173
static void cmd_apop(char *response);
173
static void cmd_apop(char *response);
174
174
175
static int autocreate_inbox(char *inboxname, char *userid);
176
175
static void cmd_auth(char *arg);
177
static void cmd_auth(char *arg);
176
static void cmd_capa(void);
178
static void cmd_capa(void);
177
static void cmd_pass(char *pass);
179
static void cmd_pass(char *pass);
Lines 1245-1250 Link Here
1245
	popd_userid = xstrdup(userbuf);
1247
	popd_userid = xstrdup(userbuf);
1246
	prot_printf(popd_out, "+OK Name is a valid mailbox\r\n");
1248
	prot_printf(popd_out, "+OK Name is a valid mailbox\r\n");
1247
    }
1249
    }
1250
1248
}
1251
}
1249
1252
1250
void cmd_pass(char *pass)
1253
void cmd_pass(char *pass)
Lines 1548-1553 Link Here
1548
}
1551
}
1549
1552
1550
/*
1553
/*
1554
 * Autocreate Inbox and subfolders upon login
1555
 */
1556
int autocreate_inbox(char *inboxname, char *auth_userid)
1557
{
1558
    struct auth_state *auth_state;
1559
    int autocreatequota;
1560
    int r;
1561
1562
    if (inboxname == NULL || auth_userid == NULL)
1563
	    return IMAP_MAILBOX_NONEXISTENT;
1564
    
1565
    /*
1566
     * Exclude anonymous
1567
     */
1568
    if (!strcmp(popd_userid, "anonymous"))
1569
        return IMAP_MAILBOX_NONEXISTENT;
1570
1571
    /*
1572
     * Check for autocreatequota
1573
     */
1574
    if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)))
1575
        return IMAP_MAILBOX_NONEXISTENT;
1576
1577
    /*
1578
     * Exclude admin's accounts
1579
     */
1580
     auth_state = auth_newstate(popd_userid);
1581
     if (global_authisa(auth_state, IMAPOPT_ADMINS))
1582
          return IMAP_MAILBOX_NONEXISTENT;
1583
1584
     r = mboxlist_autocreateinbox(&popd_namespace, auth_userid,
1585
                         auth_state, inboxname, autocreatequota);
1586
     return r;
1587
}
1588
1589
1590
/*
1551
 * Complete the login process by opening and locking the user's inbox
1591
 * Complete the login process by opening and locking the user's inbox
1552
 */
1592
 */
1553
int openinbox(void)
1593
int openinbox(void)
Lines 1576-1581 Link Here
1576
1616
1577
    if (!r) r = mboxlist_detail(inboxname, &type, NULL, NULL,
1617
    if (!r) r = mboxlist_detail(inboxname, &type, NULL, NULL,
1578
				&server, &acl, NULL);
1618
				&server, &acl, NULL);
1619
1620
    /* Try once again after autocreate_inbox */
1621
    if (r == IMAP_MAILBOX_NONEXISTENT && !(r = autocreate_inbox(inboxname, userid)))
1622
	r = mboxlist_detail(inboxname, &type, NULL, NULL,
1623
				&server, &acl, NULL);
1624
1579
    if (!r && (config_popuseacl = config_getswitch(IMAPOPT_POPUSEACL)) &&
1625
    if (!r && (config_popuseacl = config_getswitch(IMAPOPT_POPUSEACL)) &&
1580
	(!acl ||
1626
	(!acl ||
1581
	 !((myrights = cyrus_acl_myrights(popd_authstate, acl)) & ACL_READ))) {
1627
	 !((myrights = cyrus_acl_myrights(popd_authstate, acl)) & ACL_READ))) {
(-)cyrus-imapd-2.3.13/lib/auth.c (+8 lines)
Lines 118-120 Link Here
118
118
119
    auth->freestate(auth_state);
119
    auth->freestate(auth_state);
120
}
120
}
121
122
char *auth_canonuser(struct auth_state *auth_state)
123
{
124
    struct auth_mech *auth = auth_fromname();
125
126
    return auth->auth_canonuser(auth_state);
127
}
128
(-)cyrus-imapd-2.3.13/lib/auth.h (+2 lines)
Lines 55-60 Link Here
55
             const char *identifier);
55
             const char *identifier);
56
    struct auth_state *(*newstate)(const char *identifier);
56
    struct auth_state *(*newstate)(const char *identifier);
57
    void (*freestate)(struct auth_state *auth_state);
57
    void (*freestate)(struct auth_state *auth_state);
58
    char *(*auth_canonuser)(struct auth_state *auth_state);
58
};
59
};
59
60
60
extern struct auth_mech *auth_mechs[];
61
extern struct auth_mech *auth_mechs[];
Lines 77-81 Link Here
77
 	 const char *identifier);
78
 	 const char *identifier);
78
struct auth_state *auth_newstate(const char *identifier);
79
struct auth_state *auth_newstate(const char *identifier);
79
void auth_freestate(struct auth_state *auth_state);
80
void auth_freestate(struct auth_state *auth_state);
81
char *auth_canonuser(struct auth_state *auth_state);
80
82
81
#endif /* INCLUDED_AUTH_H */
83
#endif /* INCLUDED_AUTH_H */
(-)cyrus-imapd-2.3.13/lib/auth_krb.c (+17 lines)
Lines 340-345 Link Here
340
    free((char *)auth_state);
340
    free((char *)auth_state);
341
}
341
}
342
342
343
static char *mycanonuser(struct auth_state *auth_state)
344
{
345
    if (auth_state)
346
       return auth_state->userid;
347
348
    return NULL;
349
}
350
351
343
#else /* HAVE_KRB */
352
#else /* HAVE_KRB */
344
353
345
static int mymemberof(
354
static int mymemberof(
Lines 371-376 Link Here
371
	fatal("Authentication mechanism (krb) not compiled in", EC_CONFIG);
380
	fatal("Authentication mechanism (krb) not compiled in", EC_CONFIG);
372
}
381
}
373
382
383
static char *mycanonuser(
384
    struct auth_state *auth_state __attribute__((unused)))
385
{
386
        fatal("Authentication mechanism (krb) not compiled in", EC_CONFIG);
387
}
388
389
374
#endif
390
#endif
375
391
376
struct auth_mech auth_krb = 
392
struct auth_mech auth_krb = 
Lines 381-384 Link Here
381
    &mymemberof,
397
    &mymemberof,
382
    &mynewstate,
398
    &mynewstate,
383
    &myfreestate,
399
    &myfreestate,
400
    &mycanonuser,
384
};
401
};
(-)cyrus-imapd-2.3.13/lib/auth_krb5.c (+15 lines)
Lines 199-204 Link Here
199
    free(auth_state);
199
    free(auth_state);
200
}
200
}
201
201
202
static char *mycanonuser(struct auth_state *auth_state)
203
{
204
    if (auth_state)
205
       return auth_state->userid;
206
207
    return NULL;
208
}
209
202
#else /* HAVE_GSSAPI_H */
210
#else /* HAVE_GSSAPI_H */
203
211
204
static int mymemberof(
212
static int mymemberof(
Lines 230-235 Link Here
230
	fatal("Authentication mechanism (krb5) not compiled in", EC_CONFIG);
238
	fatal("Authentication mechanism (krb5) not compiled in", EC_CONFIG);
231
}
239
}
232
240
241
static char *mycanonuser(
242
    struct auth_state *auth_state __attribute__((unused)))
243
{
244
        fatal("Authentication mechanism (krb5) not compiled in", EC_CONFIG);
245
}
246
233
#endif
247
#endif
234
248
235
struct auth_mech auth_krb5 = 
249
struct auth_mech auth_krb5 = 
Lines 240-243 Link Here
240
    &mymemberof,
254
    &mymemberof,
241
    &mynewstate,
255
    &mynewstate,
242
    &myfreestate,
256
    &myfreestate,
257
    &mycanonuser,
243
};
258
};
(-)cyrus-imapd-2.3.13/lib/auth_pts.c (+9 lines)
Lines 512-517 Link Here
512
    free(auth_state);
512
    free(auth_state);
513
}
513
}
514
514
515
static char *mycanonuser(struct auth_state *auth_state)
516
{
517
    if (auth_state)
518
       return auth_state->userid.id;
519
520
    return NULL;
521
}
522
515
struct auth_mech auth_pts = 
523
struct auth_mech auth_pts = 
516
{
524
{
517
    "pts",		/* name */
525
    "pts",		/* name */
Lines 520-523 Link Here
520
    &mymemberof,
528
    &mymemberof,
521
    &mynewstate,
529
    &mynewstate,
522
    &myfreestate,
530
    &myfreestate,
531
    &mycanonuser,
523
};
532
};
(-)cyrus-imapd-2.3.13/lib/auth_unix.c (+11 lines)
Lines 314-319 Link Here
314
    free((char *)auth_state);
314
    free((char *)auth_state);
315
}
315
}
316
316
317
static char *mycanonuser(auth_state)
318
    struct auth_state *auth_state;
319
{
320
    if (auth_state)
321
         return auth_state->userid;
322
323
    return NULL;
324
}
325
326
317
327
318
struct auth_mech auth_unix = 
328
struct auth_mech auth_unix = 
319
{
329
{
Lines 323-326 Link Here
323
    &mymemberof,
333
    &mymemberof,
324
    &mynewstate,
334
    &mynewstate,
325
    &myfreestate,
335
    &myfreestate,
336
    &mycanonuser,
326
};
337
};
(-)cyrus-imapd-2.3.13/lib/imapoptions (+49 lines)
Lines 198-203 Link Here
198
/* Number of seconds to wait before returning a timeout failure when
198
/* Number of seconds to wait before returning a timeout failure when
199
   performing a client connection (e.g., in a murder environment) */
199
   performing a client connection (e.g., in a murder environment) */
200
200
201
{ "createonpost", 0, SWITCH }
202
/* If yes, when lmtpd receives an incoming mail for an INBOX that does not exist,
203
   then the INBOX is automatically created by lmtpd. */
204
205
{ "autocreateinboxfolders", NULL, STRING }
206
/* If a user does not have an INBOX created then the INBOX as well as some INBOX 
207
   subfolders are created under two conditions.
208
     1. The user logins via the IMAP or the POP3 protocol. (autocreatequota option must have a nonzero value)
209
     2. A message arrives for the user through the LMTPD protocol.(createonpost option must be yes)
210
   autocreateinboxfolders is a list of INBOX's subfolders separated by a "|", that 
211
   are automatically created by the server under the previous two situations. */
212
213
{ "autosubscribeinboxfolders", NULL, STRING }
214
/* A list of folder names, separated by "|", that the users get automatically subscribed to, 
215
   when their INBOX is created. These folder names must have been included in the 
216
   autocreateinboxfolders option of the imapd.conf. */
217
218
{ "autosubscribesharedfolders", NULL, STRING }
219
/* A list of shared folders (bulletin boards), separated by "|", that the users get
220
   automatically subscribed to, after their INBOX is created. The shared folder must 
221
   have been created and the user must have the required permissions to get subscribed 
222
   to it. Otherwise, subscribing to the shared folder fails. */
223
224
{ "autosubscribe_all_sharedfolders", 0, SWITCH }
225
/* If set to yes, the user is automatically subscribed to all shared folders, one has permission
226
   to subscribe to. */
227
228
{ "autocreate_sieve_script", NULL, STRING }
229
/* The full path of a file that contains a sieve script. This script automatically becomes a
230
   user's initial default sieve filter script. When this option is not defined, no default 
231
   sieve filter is created. The file must be readable by the cyrus daemon. */
232
233
{ "autocreate_sieve_compiledscript", NULL, STRING }
234
/* The full path of a file that contains a compiled in bytecode sieve script. This script 
235
   automatically becomes a user's initial default sieve filter script.  If this option is 
236
   not specified, or the filename doesn't exist then the script defined by 
237
   autocreate_sieve_script is compiled on the fly and installed as the user's default
238
   sieve script */
239
240
{ "generate_compiled_sieve_script", 0, SWITCH }
241
/* If set to yes and no compiled sieve script file exists, the sieve script which is 
242
   compiled on the fly will be saved in the file name that autocreate_sieve_compiledscript 
243
   option points to. In order a compiled script to be generated, autocreate_sieve_script and 
244
   autocreate_sieve_compiledscript must have valid values */
245
246
{ "autocreate_users", "anyone", STRING }
247
/* A space separated list of users and/or groups that are allowed their INBOX to be
248
   automatically created. */
249
201
{ "configdirectory", NULL, STRING }
250
{ "configdirectory", NULL, STRING }
202
/* The pathname of the IMAP configuration directory.  This field is
251
/* The pathname of the IMAP configuration directory.  This field is
203
   required. */
252
   required. */
(-)cyrus-imapd-2.3.13/notifyd/Makefile.in (-1 / +2 lines)
Lines 71-80 Link Here
71
SERVICE=../master/service.o
71
SERVICE=../master/service.o
72
72
73
IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@
73
IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@
74
SIEVE_LIBS = @SIEVE_LIBS@
74
IMAP_COM_ERR_LIBS = @IMAP_COM_ERR_LIBS@
75
IMAP_COM_ERR_LIBS = @IMAP_COM_ERR_LIBS@
75
LIB_WRAP = @LIB_WRAP@
76
LIB_WRAP = @LIB_WRAP@
76
LIBS = @ZEPHYR_LIBS@ @LIBS@ $(IMAP_COM_ERR_LIBS)
77
LIBS = @ZEPHYR_LIBS@ @LIBS@ $(IMAP_COM_ERR_LIBS)
77
DEPLIBS=../imap/mutex_fake.o ../imap/libimap.a ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@
78
DEPLIBS=../imap/mutex_fake.o ../imap/libimap.a $(SIEVE_LIBS) ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@
78
79
79
PURIFY=/usr/local/bin/purify
80
PURIFY=/usr/local/bin/purify
80
PUREOPT=-best-effort
81
PUREOPT=-best-effort
(-)cyrus-imapd-2.3.13/notifyd/notifyd.c (-1 / +1 lines)
Lines 96-102 Link Here
96
96
97
#define NOTIFY_MAXSIZE 8192
97
#define NOTIFY_MAXSIZE 8192
98
98
99
int do_notify()
99
static int do_notify()
100
{
100
{
101
    struct sockaddr_un sun_data;
101
    struct sockaddr_un sun_data;
102
    socklen_t sunlen = sizeof(sun_data);
102
    socklen_t sunlen = sizeof(sun_data);
(-)cyrus-imapd-2.3.13/ptclient/Makefile.in (-1 / +2 lines)
Lines 57-66 Link Here
57
AFS_LDFLAGS = @AFS_LDFLAGS@ @COM_ERR_LDFLAGS@
57
AFS_LDFLAGS = @AFS_LDFLAGS@ @COM_ERR_LDFLAGS@
58
AFS_LIBS = @AFS_LIBS@
58
AFS_LIBS = @AFS_LIBS@
59
IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@
59
IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@
60
SIEVE_LIBS = @SIEVE_LIBS@
60
LIBS = $(IMAP_LIBS) @COM_ERR_LIBS@
61
LIBS = $(IMAP_LIBS) @COM_ERR_LIBS@
61
LIB_SASL = @LIB_SASL@
62
LIB_SASL = @LIB_SASL@
62
LIB_WRAP = @LIB_WRAP@
63
LIB_WRAP = @LIB_WRAP@
63
DEPLIBS = ../imap/libimap.a ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@
64
DEPLIBS = ../imap/libimap.a $(SIEVE_LIBS) ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ 
64
UTIL_LIBS = ../imap/mutex_fake.o ../imap/cli_fatal.o
65
UTIL_LIBS = ../imap/mutex_fake.o ../imap/cli_fatal.o
65
66
66
LDAP_LIBS=@LDAP_LIBS@
67
LDAP_LIBS=@LDAP_LIBS@

Return to bug 257410