Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UID SEARCH broken on >= 3.6 #5047

Open
dhke opened this issue Sep 19, 2024 · 0 comments
Open

UID SEARCH broken on >= 3.6 #5047

dhke opened this issue Sep 19, 2024 · 0 comments

Comments

@dhke
Copy link

dhke commented Sep 19, 2024

Affects: cyrus-imapd > 3.4 when running in proxy-backend configuration.

The issue appeared when I tried to upgrade our test systems to cyrus-imapd 3.6 from Ubuntu 24.04. The installation almost immediately breaks access e.g. via Thunderbird, which does an UID SEARCH RECENT when accessing some mailbox folders. The client gets a

Unrecognized UID subcommand

response from the IMAP server.

I first assumed a packaging or distribution patch problem, but that does not seem to be the case.

If using cyrus-imapd >= 3.6 in proxy mode, the proxy receives

<76 uid SEARCH UNDELETED SUBJECT "foo"

but sends to the backend:

<76 Uid UNDELETED SUBJECT "foo"

Note the absence of the actual SEARCH command on the backend request.

It looks like #4321 (with commit 2e67202) broke "UID SEARCH" when using a frontend-backend configuration with imapd acting as proxy. The commit drops usinguid from the parameters of cmd_search() and does not seem to handle that case before passing the command to the backend:

    if (backend_current) {
        /* remote mailbox */
        prot_printf(backend_current->out, "%s %s ", tag, cmd);
        if (!pipe_command(backend_current, 65536)) {
            pipe_including_tag(backend_current, tag, 0);
        }
        return;
    }

Since cmdloop() consumes the next word after Uid using c = getword(imapd_in, &arg1);, the actual SEARCH command never reaches the backend, which responds with

BAD Unrecognized UID subcommand

The fix might be easy, but it needs to be backported to cyrus 3.6 and 3.8.

Update: Remove suggested patch that breaks esearch.

+++ b/imap/imapd.c
@@ -532,7 +532,7 @@ static int parse_fetch_args(const char *tag, const char *cmd,
 static void fetchargs_fini (struct fetchargs *fa);
 static void cmd_fetch(char *tag, char *sequence, int usinguid);
 static void cmd_store(char *tag, char *sequence, int usinguid);
-static void cmd_search(char *tag, char *cmd);
+static void cmd_search(char *tag, char *cmd, int usinguid);
 static void cmd_sort(char *tag, int usinguid);
 static void cmd_thread(char *tag, int usinguid);
 static void cmd_copy(char *tag, char *sequence, char *name, int usinguid, int ismove);
@@ -1811,7 +1811,7 @@ static void cmdloop(void)
             else if (!strcmp(cmd.s, "Esearch")) {
                 if (c != ' ') goto missingargs;
 
-                cmd_search(tag.s, cmd.s);
+                cmd_search(tag.s, cmd.s, 1);
 
                 prometheus_increment(CYRUS_IMAP_ESEARCH_TOTAL);
             }
@@ -2336,8 +2336,7 @@ static void cmdloop(void)
                 if (client_capa & CAPA_UIDONLY) goto uidonly;
                 if (c != ' ') goto missingargs;
             search:
-
-                cmd_search(tag.s, cmd.s);
+                cmd_search(tag.s, cmd.s, usinguid);
 
                 prometheus_increment(CYRUS_IMAP_SEARCH_TOTAL);
             }
@@ -6113,7 +6112,7 @@ static int multisearch_cb(const mbentry_t *mbentry, void *rock)
     return 0;
 }
 
-static void cmd_search(char *tag, char *cmd)
+static void cmd_search(char *tag, char *cmd, int usinguid)
 {
     int c;
     struct searchargs *searchargs;
@@ -6124,23 +6123,24 @@ static void cmd_search(char *tag, char *cmd)
 
     if (backend_current) {
         /* remote mailbox */
-        prot_printf(backend_current->out, "%s %s ", tag, cmd);
+
+        if (usinguid) {
+            /* command was "Uid Search", and "Search" is already consumed */
+            prot_printf(backend_current->out, "%s %s Search ", tag, cmd);
+        } else {
+            prot_printf(backend_current->out, "%s %s ", tag, cmd);
+        }
         if (!pipe_command(backend_current, 65536)) {
             pipe_including_tag(backend_current, tag, 0);
         }
         return;
     }
 
-    switch (cmd[0]) {
-    case 'E':  // Esearch (multisearch)
+    if (cmd[0] == 'E') {
+        // Esearch (multisearch)
         client_behavior.did_multisearch = 1;
         state |= GETSEARCH_SOURCE;
-
-        GCC_FALLTHROUGH
-
-    case 'U':  // Uid Search
-        usinguid = 1;
-        break;
+        // usinguid = 1;
     }
 
     /* RFC 9855, Section 3: MUST reject SEARCH with a charset specification */ 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant