X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/bf5fdf14a659846700e62c5dcf2c8fceb56b2a8c..2bead8292800e9730448cc128a9f9e05f88b17a9:/lib/eclient.c diff --git a/lib/eclient.c b/lib/eclient.c index 2bf86e9..0037fb5 100644 --- a/lib/eclient.c +++ b/lib/eclient.c @@ -114,7 +114,7 @@ struct operation { /** @brief Client structure */ struct disorder_eclient { - const char *ident; + char *ident; int fd; /**< @brief connection to server */ enum client_state state; /**< @brief current state */ int authenticated; /**< @brief true when authenicated */ @@ -150,15 +150,8 @@ struct disorder_eclient { /* Forward declarations ******************************************************/ -static int start_connect(void *cc, - const struct sockaddr *sa, - socklen_t len, - const char *ident); +static int start_connect(disorder_eclient *c); static void process_line(disorder_eclient *c, char *line); -static int start_connect(void *cc, - const struct sockaddr *sa, - socklen_t len, - const char *ident); static void maybe_connected(disorder_eclient *c); static void authbanner_opcallback(disorder_eclient *c, struct operation *op); @@ -341,7 +334,7 @@ void disorder_eclient_polled(disorder_eclient *c, unsigned mode) { comms_error(c, "no password is configured"); return; } - with_sockaddr(c, start_connect); + start_connect(c); /* might now be state_disconnected (on error), state_connecting (slow * connect) or state_connected (fast connect). If state_disconnected then * we just rely on a periodic callback from the event loop sometime. */ @@ -467,14 +460,13 @@ void disorder_eclient_polled(disorder_eclient *c, unsigned mode) { } /** @brief Called to start connecting */ -static int start_connect(void *cc, - const struct sockaddr *sa, - socklen_t len, - const char *ident) { - disorder_eclient *c = cc; +static int start_connect(disorder_eclient *c) { + struct sockaddr *sa; + socklen_t len; D(("start_connect")); - c->ident = xstrdup(ident); + if((len = find_server(&sa, &c->ident)) == (socklen_t)-1) + return comms_error(c, "cannot look up server"); /* TODO better error */ if(c->fd != -1) { xclose(c->fd); c->fd = -1; @@ -494,7 +486,7 @@ static int start_connect(void *cc, return 0; default: /* Signal the error to the caller. */ - return comms_error(c, "connecting to %s: %s", ident, strerror(errno)); + return comms_error(c, "connecting to %s: %s", c->ident, strerror(errno)); } } else c->state = state_connected; @@ -536,7 +528,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 @@ -547,15 +539,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); + } + 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(rvec[0], &nonce_len); - res = authhash(nonce, nonce_len, config->password, algo); + 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; } @@ -819,13 +818,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); }