chiark / gitweb /
protocol gen 2 support for eclient.c
[disorder] / lib / eclient.c
index d93412aeefd6ce2f851f655bff68b31871c1c342..012db987d9a1599b97de73100c88925667b65fda 100644 (file)
@@ -236,10 +236,6 @@ disorder_eclient *disorder_eclient_new(const disorder_eclient_callbacks *cb,
   vector_init(&c->vec);
   dynstr_init(&c->input);
   dynstr_init(&c->output);
-  if(!config->password) {
-    error(0, "no password set");
-    return 0;
-  }
   return c;
 }
 
@@ -340,6 +336,11 @@ void disorder_eclient_polled(disorder_eclient *c, unsigned mode) {
 
   if(c->state == state_disconnected) {
     D(("state_disconnected"));
+    /* If there is no password yet then we cannot connect */
+    if(!config->password) {
+      comms_error(c, "no password is configured");
+      return;
+    }
     with_sockaddr(c, start_connect);
     /* might now be state_disconnected (on error), state_connecting (slow
      * connect) or state_connected (fast connect).  If state_disconnected then
@@ -535,7 +536,7 @@ static void authbanner_opcallback(disorder_eclient *c,
   const char *res;
   char **rvec;
   int nrvec;
-  const char *algo = "SHA1";
+  const char *protocol, *algorithm, *challenge;
   
   D(("authbanner_opcallback"));
   if(c->rc / 100 != 2
@@ -546,15 +547,22 @@ static void authbanner_opcallback(disorder_eclient *c,
     disorder_eclient_close(c);
     return;
   }
-  if(nrvec > 1) {
-    algo = *rvec++;
-    --nrvec;
+  if(nrvec != 3) {
+    protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
+    disorder_eclient_close(c);
   }
-  nonce = unhex(rvec[0], &nonce_len);
-  res = authhash(nonce, nonce_len, config->password, algo);
+  protocol = *rvec++;
+  algorithm = *rvec++;
+  challenge = *rvec++;
+  if(strcmp(protocol, "2")) {
+    protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
+    disorder_eclient_close(c);
+  }
+  nonce = unhex(challenge, &nonce_len);
+  res = authhash(nonce, nonce_len, config->password, algorithm);
   if(!res) {
     protocol_error(c, op, c->rc, "%s: unknown authentication algorithm '%s'",
-                   c->ident, algo);
+                   c->ident, algorithm);
     disorder_eclient_close(c);
     return;
   }
@@ -818,13 +826,19 @@ static void stash_command(disorder_eclient *c,
 
 /* Command support ***********************************************************/
 
-/* for commands with a simple string response */ 
+/* for commands with a quoted string response */ 
 static void string_response_opcallback(disorder_eclient *c,
                                        struct operation *op) {
   D(("string_response_callback"));
   if(c->rc / 100 == 2) {
-    if(op->completed)
-      ((disorder_eclient_string_response *)op->completed)(op->v, c->line + 4);
+    if(op->completed) {
+      char **rr = split(c->line + 4, 0, SPLIT_QUOTES, 0, 0);
+
+      if(rr && *rr)
+        ((disorder_eclient_string_response *)op->completed)(op->v, *rr);
+      else
+        protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
+    }
   } else
     protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
 }