1 /*
2 * cleanup.c
3 * (C)1997-2011 by Marc Huber <Marc.Huber@web.de>
4 * All rights reserved.
5 *
6 * $Id: cleanup.c,v 1.18 2015/03/14 06:11:24 marc Exp marc $
7 *
8 */
9
10 #include "headers.h"
11
12 static const char rcsid[] __attribute__ ((used)) = "$Id: cleanup.c,v 1.18 2015/03/14 06:11:24 marc Exp marc $";
13
14 static void cleanup_context(struct context *, int);
15
cleanup_control_finish(struct context * ctx,int cur)16 static void cleanup_control_finish(struct context *ctx, int cur)
17 {
18 Debug((DEBUG_PROC, "cleanup_control_finish\n"));
19 io_close(ctx->io, cur);
20 ctx->cfn = -1;
21
22 if (ctx->sctp_fn > -1) {
23 close(ctx->sctp_fn);
24 ctx->sctp_fn = -1;
25 }
26
27 cleanup_context(ctx, -1);
28 }
29
cleanup_control_ssl_error(struct context * ctx,int cur)30 void cleanup_control_ssl_error(struct context *ctx, int cur)
31 {
32 #ifdef WITH_SSL
33 if (ctx->ssl_c) {
34 SSL_free(ctx->ssl_c);
35 ctx->ssl_c = NULL;
36 }
37 #endif
38 cleanup_control(ctx, cur);
39 }
40
cleanup_data_ssl_error(struct context * ctx,int cur)41 void cleanup_data_ssl_error(struct context *ctx, int cur)
42 {
43 #ifdef WITH_SSL
44 if (ctx->ssl_d) {
45 SSL_free(ctx->ssl_d);
46 ctx->ssl_d = NULL;
47 }
48 #endif
49 cleanup_data(ctx, cur);
50 }
51
cleanup_data_finish(struct context * ctx,int cur)52 static void cleanup_data_finish(struct context *ctx, int cur __attribute__ ((unused)))
53 {
54 DebugIn(DEBUG_PROC | DEBUG_NET);
55 if (ctx->dfn > -1) {
56 io_close(ctx->io, ctx->dfn);
57 ctx->dfn = -1;
58 ctx->buffer_filled = 0;
59 ctx->ascii_in_buffer = 0;
60 ctx->conversion = CONV_NONE;
61 cleanup_context(ctx, -1);
62 }
63 DebugOut(DEBUG_PROC | DEBUG_NET);
64 }
65
66 #ifdef WITH_SSL
ssl_cleanup_control(struct context * ctx,int cur)67 static void ssl_cleanup_control(struct context *ctx, int cur __attribute__ ((unused)))
68 {
69 Debug((DEBUG_PROC, "ssl_cleanup_control\n"));
70
71 if (io_SSL_shutdown(ctx->ssl_c, ctx->io, ctx->cfn, (void *) ssl_cleanup_control) < 0 && errno == EAGAIN)
72 return;
73
74 SSL_free(ctx->ssl_c);
75 ctx->ssl_c = NULL;
76 cleanup_control_finish(ctx, ctx->cfn);
77 }
78
ssl_cleanup_data(struct context * ctx,int cur)79 static void ssl_cleanup_data(struct context *ctx, int cur __attribute__ ((unused)))
80 {
81 Debug((DEBUG_PROC, "ssl_cleanup_data\n"));
82
83 if (io_SSL_shutdown(ctx->ssl_d, ctx->io, ctx->dfn, (void *) ssl_cleanup_data) < 0 && errno == EAGAIN)
84 return;
85
86 SSL_free(ctx->ssl_d);
87 ctx->ssl_d = NULL;
88 cleanup_data_finish(ctx, ctx->dfn);
89 }
90 #endif /* WITH_SSL */
91
cleanup_ident(struct context * ctx,int cur)92 void cleanup_ident(struct context *ctx, int cur __attribute__ ((unused)))
93 {
94 DebugIn(DEBUG_PROC);
95
96 if (ctx->ifn > -1) {
97 io_clr_i(ctx->io, ctx->ifn);
98 io_clr_o(ctx->io, ctx->ifn);
99
100 io_close(ctx->io, ctx->ifn);
101 Xfree(&ctx->ident_buf);
102 ctx->ifn = -1;
103 }
104
105 DebugOut(DEBUG_PROC);
106 }
107
cleanup_control(struct context * ctx,int cur)108 void cleanup_control(struct context *ctx, int cur __attribute__ ((unused)))
109 {
110 DebugIn(DEBUG_PROC);
111
112 if (ctx->cfn > -1) {
113 #ifdef WITH_SSL
114 if (io_get_cb_i(ctx->io, ctx->cfn) == (void *) ssl_cleanup_control) {
115 Debug((DEBUG_PROC, "- %s #C\n", __func__));
116 return;
117 }
118 #endif
119
120 ftp_log(ctx, LOG_EVENT, ctx->login_logged ? "logout" : "reject");
121
122 if (ctx->ffn < 0 && ctx->dbuf)
123 cleanup_data(ctx, ctx->dfn);
124
125 #ifdef WITH_SSL
126 if (ctx->ssl_c) {
127 io_clr_i(ctx->io, ctx->cfn);
128 io_clr_o(ctx->io, ctx->cfn);
129 ssl_cleanup_control(ctx, ctx->cfn);
130 } else
131 #endif /* WITH_SSL */
132 cleanup_control_finish(ctx, ctx->cfn);
133 }
134 DebugOut(DEBUG_PROC);
135 }
136
cleanup_data_reuse(struct context * ctx,int cur)137 void cleanup_data_reuse(struct context *ctx, int cur __attribute__ ((unused)))
138 {
139 if (ctx->dfn > -1) {
140 ctx->outgoing_data = 0;
141 io_clr_o(ctx->io, ctx->dfn);
142 io_clr_i(ctx->io, ctx->dfn);
143
144 if (io_get_cb_o(ctx->io, ctx->dfn) == (void *) buffer2socket)
145 io_set_cb_i(ctx->io, ctx->dfn, (void *) socket2buffer);
146 else if (io_get_cb_i(ctx->io, ctx->dfn) == (void *) socket2buffer)
147 io_set_cb_o(ctx->io, ctx->dfn, (void *) buffer2socket);
148 }
149 ctx->estp = 0;
150 ctx->estp_valid = 0;
151 ctx->passive_transfer = 0;
152 ctx->transfer_in_progress = 0;
153 }
154
cleanup_data(struct context * ctx,int cur)155 void cleanup_data(struct context *ctx, int cur __attribute__ ((unused)))
156 {
157 int ffn = ctx->ffn;
158 int outgoing_data = ctx->outgoing_data;
159
160 DebugIn(DEBUG_PROC | DEBUG_NET);
161
162 ctx->estp = 0;
163 ctx->estp_valid = 0;
164 ctx->passive_transfer = 0;
165 ctx->transfer_in_progress = 0;
166
167 if (ctx->dfn > -1) {
168 ctx->iomode = IOMODE_dunno, ctx->iomode_fixed = 0;
169 #ifdef WITH_SSL
170 if (io_get_cb_i(ctx->io, ctx->dfn) == (void *) ssl_cleanup_data) {
171 Debug((DEBUG_PROC, "- %s #C\n", __func__));
172 return;
173 }
174 #endif
175
176 if (io_sched_del(ctx->io, ctx, (void *) cleanup_data)) {
177 if (io_get_cb_i(ctx->io, ctx->dfn) == (void *) connect_data)
178 reply(ctx, MSG_431_Opening_datacon_failed);
179 ctx->dbufi = buffer_free_all(ctx->dbufi);
180 if (ctx->ffn < 0 || io_get_cb_i(ctx->io, ctx->dfn) != (void *) socket2buffer) {
181 ctx->dbuf = buffer_free_all(ctx->dbuf);
182 if (ctx->ffn > -1)
183 cleanup_file(ctx, ctx->ffn);
184 }
185 }
186
187 Debug((DEBUG_PROC | DEBUG_NET, " ctx->dfn: %d\n", ctx->dfn));
188
189 io_clr_cb_i(ctx->io, ctx->dfn);
190 io_clr_cb_o(ctx->io, ctx->dfn);
191
192 if (ctx->ffn < 0 || outgoing_data) {
193 ctx->dbuf = buffer_free_all(ctx->dbuf);
194 ctx->dbufi = buffer_free_all(ctx->dbufi);
195 }
196
197 /* reset remote data CEP to defaults */
198 ctx->sa_d_remote = ctx->sa_c_remote;
199
200 #ifdef WITH_SSL
201 if (ctx->ssl_d) {
202 io_clr_i(ctx->io, ctx->dfn);
203 io_clr_o(ctx->io, ctx->dfn);
204 ssl_cleanup_data(ctx, ctx->dfn);
205 } else
206 #endif /* WITH_SSL */
207 cleanup_data_finish(ctx, ctx->dfn);
208 }
209 if (ffn > -1) {
210 if (outgoing_data)
211 cleanup_file(ctx, ffn);
212 else
213 buffer2file(ctx, ffn);
214 }
215
216 DebugOut(DEBUG_PROC | DEBUG_NET);
217 }
218
cleanup_file(struct context * ctx,int cur)219 int cleanup_file(struct context *ctx, int cur __attribute__ ((unused)))
220 {
221 int result = 0;
222
223 DebugIn(DEBUG_PROC);
224
225 if (ctx->ffn > -1) {
226 Debug((DEBUG_PROC, " ctx->ffn: %d\n", ctx->ffn));
227
228 ctx->io_offset = 0;
229 ctx->io_offset_start = 0;
230 ctx->io_offset_end = -1;
231
232 if (ctx->quota_path && ctx->quota_update_on_close) {
233 struct stat st;
234 fstat(ctx->ffn, &st);
235 quota_add(ctx, st.st_size - ctx->quota_filesize_before_stor);
236 }
237
238 result = close(ctx->ffn);
239
240 ctx->ffn = -1;
241 cleanup_context(ctx, -1);
242 }
243
244 DebugOut(DEBUG_PROC);
245
246 return result;
247 }
248
cleanup_context(struct context * ctx,int cur)249 static void cleanup_context(struct context *ctx, int cur __attribute__ ((unused)))
250 {
251 DebugIn(DEBUG_PROC);
252
253 if (ctx->ffn > -1 || ctx->dfn > -1 || ctx->cfn > -1) {
254 Debug((DEBUG_PROC, "- %s (not yet)\n", __func__));
255 return;
256 }
257
258 if (ctx->is_client) {
259 struct scm_data sd;
260 sd.type = SCM_DONE;
261 if (common_data.scm_send_msg(0, &sd, -1))
262 die_when_idle = -1;
263
264 common_data.users_cur--;
265 if (common_data.users_cur == 0 && die_when_idle) {
266 Debug((DEBUG_PROC, "exiting -- process out of use\n"));
267 mavis_drop(mcx);
268 logmsg("Terminating, no longer needed.");
269 exit(EX_OK);
270 }
271 }
272
273 if (ctx->ifn > -1)
274 cleanup_ident(ctx, ctx->ifn);
275
276 #ifdef WITH_LWRES
277 if (ctx->reverse)
278 Xfree(&ctx->reverse);
279 else
280 io_dns_cancel(idc, ctx);
281 #endif /* WITH_LWRES */
282
283 #ifdef WITH_SSL
284 Xfree(&ctx->certsubj);
285 Xfree(&ctx->certsubjaltname);
286 #endif
287
288 ctx->pst_valid = 0;
289
290 Xfree(&ctx->ident_buf);
291 Xfree(&ctx->ident_user);
292 Xfree(&ctx->user);
293 Xfree(&ctx->email);
294 Xfree(&ctx->vhost);
295 Xfree(&ctx->visited_dirs);
296 if (ctx->auth_in_progress)
297 mavis_cancel(mcx, ctx);
298
299 #ifdef WITH_ZLIB
300 if (ctx->zstream) {
301 deflateEnd(ctx->zstream);
302 Xfree(&ctx->zstream);
303 }
304 #endif
305
306 RB_tree_delete(ctx->filelist);
307
308 while (io_sched_pop(ctx->io, ctx));
309
310 if (ctx->dirfn > -1)
311 close(ctx->dirfn);
312
313 if (ctx->incoming) {
314 regfree(ctx->incoming);
315 free(ctx->incoming);
316 }
317
318 Xfree(&ctx->quota_path);
319
320 buffer_free_all(ctx->cbufi);
321 buffer_free_all(ctx->cbufo);
322 buffer_free_all(ctx->dbuf);
323 buffer_free_all(ctx->dbufi);
324 free(ctx);
325
326 set_proctitle(die_when_idle ? ACCEPT_NEVER : ACCEPT_YES);
327
328 DebugOut(DEBUG_PROC);
329 }
330
cleanup(struct context * ctx,int cur)331 void cleanup(struct context *ctx, int cur __attribute__ ((unused)))
332 {
333 struct io_context *io = ctx->io;
334 int cfn = ctx->cfn;
335 int dfn = ctx->dfn;
336 int ffn = ctx->ffn;
337
338 Debug((DEBUG_PROC, "+ %s(%d)\n", __func__, cur));
339
340 while (io_sched_pop(ctx->io, ctx));
341
342 if (dfn > -1 && io_get_ctx(io, dfn))
343 cleanup_data(ctx, dfn);
344 if (ffn > -1 && io_get_ctx(io, ffn))
345 cleanup_file(ctx, ffn);
346 if (cfn > -1 && io_get_ctx(io, cfn))
347 cleanup_control(ctx, cfn);
348
349 DebugOut(DEBUG_PROC);
350 }
351
cleanup_spawnd(struct context * ctx,int cur)352 void cleanup_spawnd(struct context *ctx __attribute__ ((unused)), int cur __attribute__ ((unused)))
353 {
354 if (common_data.users_cur == 0) {
355 Debug((DEBUG_PROC, "exiting -- process out of use\n"));
356 mavis_drop(mcx);
357 logmsg("Terminating, no longer needed.");
358 exit(EX_OK);
359 }
360 die_when_idle = -1;
361 set_proctitle(ACCEPT_NEVER);
362 }
363