On Mon, Jun 21, 2021 at 10:44:42AM +0200, Nicolas Schier wrote:
A recursive symlink (here: Inbox -> ".") might be considered bad
practise. But perhaps a recursion detection is more user-friendly?
it's unreasonable to implement an actual recursion detection to cover
such a corner case. an arbitrary nesting depth limitation of 10 would be
easy to do, though.
>From 9b8fc616f3986c3bcdc8195f5ec221c38043e8d6 Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <o...@users.sf.net>
Date: Mon, 21 Jun 2021 11:35:24 +0200
Subject: [PATCH] limit maildir nesting depth
this is a cheap way to catch symlink loops. 10 seems like a reasonable
limit, as it's unlikely that anyone would be able to actually work with
such a deeply nested mailbox tree.
fixes debian bug #990117.
---
src/drv_maildir.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 5ba83f7..cd8e849 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -395,7 +395,7 @@ static int maildir_list_inbox( maildir_store_t *ctx, int flags, const char *base
static int maildir_list_path( maildir_store_t *ctx, int flags, const char *inbox );
static int
-maildir_list_recurse( maildir_store_t *ctx, int isBox, int flags,
+maildir_list_recurse( maildir_store_t *ctx, int isBox, int flags, int depth,
const char *inbox, uint inboxLen, const char *basePath, uint basePathLen,
char *path, int pathLen, char *name, int nameLen )
{
@@ -417,6 +417,12 @@ maildir_list_recurse( maildir_store_t *ctx, int isBox, int flags,
closedir( dir );
return -1;
}
+ if (++depth > 10) {
+ // We do the other checks first to avoid confusing error messages for files.
+ error( "Maildir error: path nesting level exceeds 10 for %s\n", path );
+ closedir( dir );
+ return -1;
+ }
while ((de = readdir( dir ))) {
const char *ent = de->d_name;
if (ent[0] == '.' && (!ent[1] || (ent[1] == '.' && !ent[2])))
@@ -464,7 +470,7 @@ maildir_list_recurse( maildir_store_t *ctx, int isBox, int flags,
add_string_list( &ctx->boxes, name );
path[pl] = 0;
name[nl++] = '/';
- if (maildir_list_recurse( ctx, isBox + 1, flags, inbox, inboxLen, basePath, basePathLen, path, pl, name, nl ) < 0) {
+ if (maildir_list_recurse( ctx, isBox + 1, flags, depth, inbox, inboxLen, basePath, basePathLen, path, pl, name, nl ) < 0) {
closedir( dir );
return -1;
}
@@ -485,7 +491,7 @@ maildir_list_inbox( maildir_store_t *ctx, int flags, const char *basePath )
add_string_list( &ctx->boxes, "INBOX" );
return maildir_list_recurse(
- ctx, 1, flags, NULL, 0, basePath, basePath ? strlen( basePath ) - 1 : 0,
+ ctx, 1, flags, 0, NULL, 0, basePath, basePath ? strlen( basePath ) - 1 : 0,
path, nfsnprintf( path, _POSIX_PATH_MAX, "%s/", ctx->conf->inbox ),
name, nfsnprintf( name, _POSIX_PATH_MAX, "INBOX/" ) );
}
@@ -502,7 +508,7 @@ maildir_list_path( maildir_store_t *ctx, int flags, const char *inbox )
if (maildir_ensure_path( ctx->conf ) < 0)
return -1;
return maildir_list_recurse(
- ctx, 0, flags, inbox, inbox ? strlen( inbox ) : 0, NULL, 0,
+ ctx, 0, flags, 0, inbox, inbox ? strlen( inbox ) : 0, NULL, 0,
path, nfsnprintf( path, _POSIX_PATH_MAX, "%s", ctx->conf->path ),
name, 0 );
}
--
2.31.1.2.g8c0bdb8a70