16
16
* You should have received a copy of the GNU General Public License
17
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
20
20
* As a special exemption, The ProFTPD Project team and other respective
21
21
* copyright holders give permission to link this program with OpenSSL, and
22
22
* distribute the resulting executable, without including the source code for
23
23
* OpenSSL in the source distribution.
25
* $Id: mod_site_misc.c,v 1.18 2011/03/03 21:38:54 castaglia Exp $
25
* $Id: mod_site_misc.c,v 1.20 2011/05/26 23:14:01 castaglia Exp $
30
#define MOD_SITE_MISC_VERSION "mod_site_misc/1.4"
30
#define MOD_SITE_MISC_VERSION "mod_site_misc/1.5"
32
extern pr_response_t *resp_list, *resp_err_list;
32
34
static unsigned int site_misc_engine = TRUE;
98
110
while (tmp_path &&
102
117
pr_signals_handle();
104
119
curr_dir = strsep(&tmp_path, "/");
105
120
curr_path = pdircat(p, curr_path, curr_dir, NULL);
107
if (site_misc_create_dir(curr_path) < 0) {
122
/* Dispatch the fake C_MKD command, e.g. for mod_quotatab. */
123
sub_pool = pr_pool_create_sz(p, 64);
124
cmd = pr_cmd_alloc(sub_pool, 2, pstrdup(sub_pool, C_MKD),
125
pstrdup(sub_pool, curr_path));
126
cmd->arg = pstrdup(cmd->pool, curr_path);
127
cmd->class = CL_DIRS|CL_WRITE;
129
res = pr_cmd_dispatch_phase(cmd, PRE_CMD, 0);
133
pr_log_debug(DEBUG3, MOD_SITE_MISC_VERSION
134
": creating directory '%s' blocked by MKD handler: %s", curr_path,
137
pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
138
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
139
pr_response_clear(&resp_err_list);
141
destroy_pool(sub_pool);
149
res = site_misc_create_dir(curr_path);
153
pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
154
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
155
pr_response_clear(&resp_err_list);
157
destroy_pool(sub_pool);
165
pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
166
pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
167
pr_response_clear(&resp_list);
169
destroy_pool(sub_pool);
138
203
if (S_ISDIR(st.st_mode)) {
139
if (site_misc_delete_dir(p, file) < 0) {
142
pr_fsio_closedir(dirh);
148
} else if (pr_fsio_unlink(file) < 0) {
151
pr_fsio_closedir(dirh);
204
res = site_misc_delete_dir(p, file);
208
pr_fsio_closedir(dirh);
216
/* Dispatch fake C_DELE command, e.g. for mod_quotatab */
217
sub_pool = pr_pool_create_sz(p, 64);
218
cmd = pr_cmd_alloc(sub_pool, 2, pstrdup(sub_pool, C_DELE),
219
pstrdup(sub_pool, file));
220
cmd->arg = pstrdup(cmd->pool, file);
221
cmd->class = CL_WRITE;
223
res = pr_cmd_dispatch_phase(cmd, PRE_CMD, 0);
227
pr_log_debug(DEBUG3, MOD_SITE_MISC_VERSION
228
": deleting file '%s' blocked by DELE handler: %s", file,
231
pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
232
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
233
pr_response_clear(&resp_err_list);
235
destroy_pool(sub_pool);
236
pr_fsio_closedir(dirh);
242
res = pr_fsio_unlink(file);
246
pr_fsio_closedir(dirh);
248
pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
249
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
250
pr_response_clear(&resp_err_list);
252
destroy_pool(sub_pool);
253
pr_fsio_closedir(dirh);
259
pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
260
pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
261
pr_response_clear(&resp_list);
262
destroy_pool(sub_pool);
158
266
pr_fsio_closedir(dirh);
160
if (pr_fsio_rmdir(dir) < 0)
268
/* Dispatch fake C_RMD command, e.g. for mod_quotatab */
269
sub_pool = pr_pool_create_sz(p, 64);
270
cmd = pr_cmd_alloc(sub_pool, 2, pstrdup(sub_pool, C_RMD),
271
pstrdup(sub_pool, dir));
272
cmd->arg = pstrdup(cmd->pool, dir);
273
cmd->class = CL_DIRS|CL_WRITE;
275
res = pr_cmd_dispatch_phase(cmd, PRE_CMD, 0);
279
pr_log_debug(DEBUG3, MOD_SITE_MISC_VERSION
280
": removing directory '%s' blocked by RMD handler: %s", dir,
283
pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
284
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
285
pr_response_clear(&resp_err_list);
287
destroy_pool(sub_pool);
293
res = pr_fsio_rmdir(dir);
297
pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
298
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
299
pr_response_clear(&resp_err_list);
301
destroy_pool(sub_pool);
306
pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
307
pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
308
pr_response_clear(&resp_list);
309
destroy_pool(sub_pool);
307
457
path = pr_fs_decode_path(cmd->tmp_pool, path);
309
459
if (site_misc_check_filters(cmd, path) < 0) {
310
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EPERM));
462
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
311
465
return PR_ERROR(cmd);
314
468
path = dir_canonical_path(cmd->tmp_pool, path);
315
469
if (path == NULL) {
316
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL));
472
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
317
475
return PR_ERROR(cmd);
320
478
cmd_name = cmd->argv[0];
321
479
cmd->argv[0] = "SITE_MKDIR";
322
480
if (!dir_check_canon(cmd->tmp_pool, cmd, G_WRITE, path, NULL)) {
323
483
cmd->argv[0] = cmd_name;
325
485
pr_log_debug(DEBUG4, MOD_SITE_MISC_VERSION
326
486
": %s command denied by <Limit>", cmd->argv[0]);
327
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EPERM));
487
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
328
490
return PR_ERROR(cmd);
330
492
cmd->argv[0] = cmd_name;
332
494
if (site_misc_create_path(cmd->tmp_pool, path) < 0) {
333
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno));
497
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
334
500
return PR_ERROR(cmd);
378
547
path = dir_canonical_path(cmd->tmp_pool, path);
379
548
if (path == NULL) {
380
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL));
551
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
381
554
return PR_ERROR(cmd);
384
557
cmd_name = cmd->argv[0];
385
558
cmd->argv[0] = "SITE_RMDIR";
386
559
if (!dir_check_canon(cmd->tmp_pool, cmd, G_WRITE, path, NULL)) {
387
562
cmd->argv[0] = cmd_name;
389
564
pr_log_debug(DEBUG4, MOD_SITE_MISC_VERSION
390
565
": %s command denied by <Limit>", cmd->argv[0]);
391
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EPERM));
566
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
392
569
return PR_ERROR(cmd);
394
571
cmd->argv[0] = cmd_name;
396
573
if (site_misc_delete_path(cmd->tmp_pool, path) < 0) {
397
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno));
576
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
398
579
return PR_ERROR(cmd);
431
613
authenticated = get_param_ptr(cmd->server->conf, "authenticated", FALSE);
433
if (!authenticated || *authenticated == FALSE) {
615
if (!authenticated ||
616
*authenticated == FALSE) {
434
617
pr_response_add_err(R_530, _("Please login with USER and PASS"));
435
619
return PR_ERROR(cmd);
438
622
src = pr_fs_decode_path(cmd->tmp_pool, cmd->argv[2]);
439
623
src = dir_canonical_path(cmd->tmp_pool, src);
440
624
if (src == NULL) {
441
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL));
627
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
442
630
return PR_ERROR(cmd);
445
633
cmd_name = cmd->argv[0];
446
634
cmd->argv[0] = "SITE_SYMLINK";
447
635
if (!dir_check_canon(cmd->tmp_pool, cmd, G_READ, src, NULL)) {
448
638
cmd->argv[0] = cmd_name;
450
640
pr_log_debug(DEBUG4, MOD_SITE_MISC_VERSION
451
641
": %s command denied by <Limit>", cmd->argv[0]);
452
pr_response_add_err(R_550, "%s: %s", cmd->argv[2], strerror(EPERM));
642
pr_response_add_err(R_550, "%s: %s", cmd->argv[2], strerror(xerrno));
453
645
return PR_ERROR(cmd);
456
648
dst = pr_fs_decode_path(cmd->tmp_pool, cmd->argv[3]);
457
649
dst = dir_canonical_path(cmd->tmp_pool, dst);
458
650
if (dst == NULL) {
459
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL));
653
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
460
656
return PR_ERROR(cmd);
463
659
if (!dir_check_canon(cmd->tmp_pool, cmd, G_WRITE, dst, NULL)) {
464
662
cmd->argv[0] = cmd_name;
466
664
pr_log_debug(DEBUG4, MOD_SITE_MISC_VERSION
467
665
": %s command denied by <Limit>", cmd->argv[0]);
468
pr_response_add_err(R_550, "%s: %s", cmd->argv[3], strerror(EPERM));
666
pr_response_add_err(R_550, "%s: %s", cmd->argv[3], strerror(xerrno));
469
669
return PR_ERROR(cmd);
471
671
cmd->argv[0] = cmd_name;
473
673
if (site_misc_check_filters(cmd, dst) < 0) {
474
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EPERM));
676
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
475
679
return PR_ERROR(cmd);
484
688
pr_fs_clear_cache();
485
689
res = pr_fsio_stat(src, &st);
487
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno));
693
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
488
696
return PR_ERROR(cmd);
491
699
if (pr_fsio_symlink(src, dst) < 0) {
492
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno));
702
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
493
705
return PR_ERROR(cmd);
530
743
if (!authenticated ||
531
744
*authenticated == FALSE) {
532
745
pr_response_add_err(R_530, _("Please login with USER and PASS"));
533
747
return PR_ERROR(cmd);
536
750
/* Accept both 'YYYYMMDDhhmm' and 'YYYYMMDDhhmmss' formats. */
537
751
if (strlen(cmd->argv[2]) != 12 &&
538
752
strlen(cmd->argv[2]) != 14) {
539
755
pr_log_debug(DEBUG7, MOD_SITE_MISC_VERSION
540
756
": wrong number of digits in timestamp argument '%s' (%lu)",
541
757
cmd->argv[2], (unsigned long) strlen(cmd->argv[2]));
542
pr_response_add_err(R_500, "%s: %s", cmd->arg, strerror(EINVAL));
758
pr_response_add_err(R_500, "%s: %s", cmd->arg, strerror(xerrno));
543
761
return PR_ERROR(cmd);
555
773
path = dir_canonical_path(cmd->tmp_pool, path);
556
774
if (path == NULL) {
557
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL));
777
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
558
780
return PR_ERROR(cmd);
561
783
cmd_name = cmd->argv[0];
562
784
cmd->argv[0] = "SITE_UTIME";
563
785
if (!dir_check_canon(cmd->tmp_pool, cmd, G_WRITE, path, NULL)) {
564
788
cmd->argv[0] = cmd_name;
566
790
pr_log_debug(DEBUG4, MOD_SITE_MISC_VERSION
567
791
": %s command denied by <Limit>", cmd->argv[0]);
568
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EPERM));
792
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
569
795
return PR_ERROR(cmd);
571
797
cmd->argv[0] = cmd_name;
573
799
if (site_misc_check_filters(cmd, path) < 0) {
574
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EPERM));
802
pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
575
805
return PR_ERROR(cmd);