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

Reply via email to