]> diplodocus.org Git - nmh/commitdiff
A little closer to being somewhat useful.
authorKen Hornstein <kenh@pobox.com>
Wed, 25 Oct 2017 20:00:09 +0000 (16:00 -0400)
committerKen Hornstein <kenh@pobox.com>
Wed, 25 Oct 2017 20:00:09 +0000 (16:00 -0400)
uip/imaptest.c

index 63ff4e6..549431d 100644 (file)
@@ -56,9 +56,13 @@ static int imap_sasl_callback(enum sasl_message_type, unsigned const char *,
 
 static void parse_capability(const char *, unsigned int len);
 static int capability_set(const char *);
 
 static void parse_capability(const char *, unsigned int len);
 static int capability_set(const char *);
-static int send_imap_command(netsec_context *, char **errstr,
-                            const char *, ...);
-static int get_imap_response(netsec_context *, const char *, char **, char **);
+static void clear_capability(void);
+static int have_capability(void);
+static int send_imap_command(netsec_context *, int noflush, char **errstr,
+                            const char *fmt, ...);
+static int get_imap_response(netsec_context *, const char *token,
+                            char **tokenresp, char **status, int failerr,
+                            char **errstr);
 
 int
 main (int argc, char **argv)
 
 int
 main (int argc, char **argv)
@@ -219,12 +223,13 @@ main (int argc, char **argv)
     } else {
         char *capstring;
 
     } else {
         char *capstring;
 
-       if (send_imap_command(nsc, &errstr, "CAPABILITY") != OK) {
+       if (send_imap_command(nsc, 0, &errstr, "CAPABILITY") != OK) {
            fprintf(stderr, "Unable to send CAPABILITY command: %s\n", errstr);
            goto finish;
        }
 
            fprintf(stderr, "Unable to send CAPABILITY command: %s\n", errstr);
            goto finish;
        }
 
-       if (get_imap_response(nsc, "CAPABILITY", &capstring, &errstr) != OK) {
+       if (get_imap_response(nsc, "CAPABILITY", &capstring, NULL, 1,
+                             &errstr) != OK) {
            fprintf(stderr, "Cannot get CAPABILITY response: %s\n", errstr);
            goto finish;
        }
            fprintf(stderr, "Cannot get CAPABILITY response: %s\n", errstr);
            goto finish;
        }
@@ -244,12 +249,12 @@ main (int argc, char **argv)
                    "has no support for STARTTLS\n");
            goto finish;
        }
                    "has no support for STARTTLS\n");
            goto finish;
        }
-       if (send_imap_command(nsc, &errstr, "STARTTLS") != OK) {
+       if (send_imap_command(nsc, 0, &errstr, "STARTTLS") != OK) {
            fprintf(stderr, "Unable to issue STARTTLS: %s\n", errstr);
            goto finish;
        }
 
            fprintf(stderr, "Unable to issue STARTTLS: %s\n", errstr);
            goto finish;
        }
 
-       if (get_imap_response(nsc, NULL, NULL, &errstr) != OK) {
+       if (get_imap_response(nsc, NULL, NULL, NULL, 1, &errstr) != OK) {
            fprintf(stderr, "STARTTLS failed: %s\n", errstr);
            goto finish;
        }
            fprintf(stderr, "STARTTLS failed: %s\n", errstr);
            goto finish;
        }
@@ -263,10 +268,16 @@ main (int argc, char **argv)
            fprintf(stderr, "SASL negotiation failed: %s\n", errstr);
            goto finish;
        }
            fprintf(stderr, "SASL negotiation failed: %s\n", errstr);
            goto finish;
        }
+    } else {
+       if (capability_set("LOGINDISABLED")) {
+           fprintf(stderr, "User did not request SASL, but LOGIN "
+                   "is disabled\n");
+           goto finish;
+       }
     }
 
     }
 
-    send_imap_command(nsc, NULL, "LOGOUT");
-    get_imap_response(nsc, NULL, NULL, NULL);
+    send_imap_command(nsc, 0, NULL, "LOGOUT");
+    get_imap_response(nsc, NULL, NULL, NULL, 0, NULL);
 
 finish:
     netsec_shutdown(nsc);
 
 finish:
     netsec_shutdown(nsc);
@@ -330,6 +341,23 @@ capability_set(const char *capability)
     return svector_find(imap_capabilities, capability) != NULL;
 }
 
     return svector_find(imap_capabilities, capability) != NULL;
 }
 
+/*
+ * Clear the CAPABILITY list (used after we call STARTTLS, for example)
+ */
+
+static void
+capability_clear(void)
+{
+    svector_free(imap_capabilities);
+    imap_capabilities = NULL;
+}
+
+static int
+have_capability(void)
+{
+    return imap_capabilities != NULL;
+}
+
 /*
  * Our SASL callback, which handles the SASL authentication dialog
  */
 /*
  * Our SASL callback, which handles the SASL authentication dialog
  */
@@ -341,7 +369,7 @@ imap_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 {
     int rc, snoopoffset;
     char *mech, *line;
 {
     int rc, snoopoffset;
     char *mech, *line;
-    size_t len, b64len;
+    size_t len;
     netsec_context *nsc = (netsec_context *) context;
 
     switch (mtype) {
     netsec_context *nsc = (netsec_context *) context;
 
     switch (mtype) {
@@ -369,14 +397,14 @@ imap_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
                 * of the next tag.
                 */
                snoopoffset = 17 + strlen(mech);
                 * of the next tag.
                 */
                snoopoffset = 17 + strlen(mech);
-               rc = send_imap_command(nsc, errstr, "AUTHENTICATE %s %s",
+               rc = send_imap_command(nsc, 0, errstr, "AUTHENTICATE %s %s",
                                       mech, b64data);
                free(b64data);
                netsec_set_snoop_callback(nsc, NULL, NULL);
                if (rc)
                    return NOTOK;
            } else {
                                       mech, b64data);
                free(b64data);
                netsec_set_snoop_callback(nsc, NULL, NULL);
                if (rc)
                    return NOTOK;
            } else {
-               rc = send_imap_command(nsc, errstr, "AUTHENTICATE %s", mech);
+               rc = send_imap_command(nsc, 0, errstr, "AUTHENTICATE %s", mech);
                line = netsec_readline(nsc, &len, errstr);
                if (! line)
                    return NOTOK;
                line = netsec_readline(nsc, &len, errstr);
                if (! line)
                    return NOTOK;
@@ -399,15 +427,16 @@ imap_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
                    return NOTOK;
            }
        } else {
                    return NOTOK;
            }
        } else {
-           if (send_imap_command(nsc, errstr, "AUTHENTICATE %s", mech) != OK)
+           if (send_imap_command(nsc, 0, errstr, "AUTHENTICATE %s",
+                                 mech) != OK)
                return NOTOK;
        }
 
        break;
 
                return NOTOK;
        }
 
        break;
 
-       /*
-        * Get a response, decode it and process it.
-        */
+    /*
+     * Get a response, decode it and process it.
+     */
 
     case NETSEC_SASL_READ:
        netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset);
 
     case NETSEC_SASL_READ:
        netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset);
@@ -436,9 +465,9 @@ imap_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
        }
        break;
 
        }
        break;
 
-       /*
-        * Simple request encoding
-        */
+    /*
+     * Simple request encoding
+     */
 
     case NETSEC_SASL_WRITE:
        if (indatalen > 0) {
 
     case NETSEC_SASL_WRITE:
        if (indatalen > 0) {
@@ -466,7 +495,32 @@ imap_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
      */
 
     case NETSEC_SASL_FINISH:
      */
 
     case NETSEC_SASL_FINISH:
-       if (get_imap_response(nsc, NULL, NULL, errstr) != OK)
+       if (get_imap_response(nsc, NULL, NULL, &line, 1, errstr) != OK)
+           return NOTOK;
+       /*
+        * We MIGHT get a capability response here.  If so, be sure we
+        * parse it.
+        */
+
+       if (has_prefix(line, "OK [CAPABILITY ")) {
+           char *p = line + 15, *q;
+           q = strchr(p, ']');
+
+           if (q)
+               parse_capability(p, q - p);
+       }
+
+       break;
+
+    /*
+     * Cancel an authentication dialog
+     */
+
+    case NETSEC_SASL_CANCEL:
+       rc = netsec_printf(nsc, errstr, "*\r\n");
+       if (rc == OK)
+           rc = netsec_flush(nsc, errstr);
+       if (rc != OK)
            return NOTOK;
        break;
     }
            return NOTOK;
        break;
     }
@@ -478,7 +532,8 @@ imap_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
  */
 
 static int
  */
 
 static int
-send_imap_command(netsec_context *nsc, char **errstr, const char *fmt, ...)
+send_imap_command(netsec_context *nsc, int noflush, char **errstr,
+                 const char *fmt, ...)
 {
     static unsigned int seq = 0;       /* Tag sequence number */
     va_list ap;
 {
     static unsigned int seq = 0;       /* Tag sequence number */
     va_list ap;
@@ -506,7 +561,7 @@ send_imap_command(netsec_context *nsc, char **errstr, const char *fmt, ...)
        return NOTOK;
     }
 
        return NOTOK;
     }
 
-    if (netsec_flush(nsc, errstr) != OK) {
+    if (!noflush && netsec_flush(nsc, errstr) != OK) {
        free(cmd);
        return NOTOK;
     }
        free(cmd);
        return NOTOK;
     }
@@ -524,10 +579,11 @@ send_imap_command(netsec_context *nsc, char **errstr, const char *fmt, ...)
 
 static int
 get_imap_response(netsec_context *nsc, const char *token, char **tokenresponse,
 
 static int
 get_imap_response(netsec_context *nsc, const char *token, char **tokenresponse,
-                 char **errstr)
+                 char **status, int failerr, char **errstr)
 {
     char *line;
     struct imap_cmd *cmd;
 {
     char *line;
     struct imap_cmd *cmd;
+    int numerrs = 0;
 
     if (tokenresponse)
        *tokenresponse = NULL;
 
     if (tokenresponse)
        *tokenresponse = NULL;
@@ -553,7 +609,14 @@ getline:
                    if (has_prefix(line, cmd->next->tag)) {
                        struct imap_cmd *cmd2 = cmd->next;
                        cmd->next = cmd->next->next;
                    if (has_prefix(line, cmd->next->tag)) {
                        struct imap_cmd *cmd2 = cmd->next;
                        cmd->next = cmd->next->next;
+                       if (failerr && strncmp(line + strlen(cmd2->tag),
+                                                       "OK ", 3) != 0) {
+                           numerrs++;
+                           netsec_err(errstr, "%s", line + strlen(cmd2->tag));
+                       }
                        free(cmd2);
                        free(cmd2);
+                       if (status)
+                           *status = getcpy(line);
                        goto getline;
                    }
                    netsec_err(errstr, "Non-matching response line: %s\n",
                        goto getline;
                    }
                    netsec_err(errstr, "Non-matching response line: %s\n",
@@ -564,5 +627,5 @@ getline:
        }
     }
 
        }
     }
 
-    return OK;
+    return numerrs == 0 ? OK : NOTOK;
 }
 }