From: Andre Noll Date: Wed, 4 Jan 2012 20:47:55 +0000 (+0100) Subject: Use sideband also for challenge response. X-Git-Tag: v0.4.11~14^2~8 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=4744d937c4160898d1fe151257606430750e580c;hp=fa9e0ecb219000e07eaf694f50679a8edfb5dc9e Use sideband also for challenge response. This changes server and client to exchange the challenge response as a sideband packet if both ends support sideband connections. The SBD_CHALLENGE_RESPONSE designator is used for this purpose. On the client side the changes are less intrusive due to an additional cleanup of the state handling. During connection setup the client's idea of the state of the connection is monitored in the ->status variable of struct client_task. If the client is in the CL_SENT_AUTH state, it receives the challenge and sends the hash of the decrypted challenge back to the server. Either operation may fail, and it seems cleaner to separate the two. So this patch adds the new state CL_RECEIVED_CHALLENGE. The clients enters this state once it decrypted the received challenge. --- diff --git a/client.h b/client.h index a4234062..b841b7e1 100644 --- a/client.h +++ b/client.h @@ -14,6 +14,8 @@ enum { CL_RECEIVED_WELCOME, /** Client sends the authentification request. */ CL_SENT_AUTH, + /** Server sends encrypted challenge. */ + CL_RECEIVED_CHALLENGE, /** Client solves the challenge and sends the result. */ CL_SENT_CH_RESPONSE, /** Server accepts this authentication. */ @@ -36,6 +38,8 @@ struct client_task { bool use_sideband; /** The sideband context, ignored if \a use_sideband is false. */ struct sb_context *sbc; + /** The hash value of the decrypted challenge. */ + unsigned char *challenge_hash; /** The configuration (including the command). */ struct client_args_info conf; /** The config file for client options. */ diff --git a/client_common.c b/client_common.c index f3cea05d..eea14fa8 100644 --- a/client_common.c +++ b/client_common.c @@ -68,6 +68,8 @@ void client_close(struct client_task *ct) free(ct->config_file); free(ct->key_file); client_cmdline_parser_free(&ct->conf); + free(ct->challenge_hash); + sb_free(ct->sbc); free(ct); } @@ -103,6 +105,7 @@ static void client_pre_select(struct sched *s, struct task *t) case CL_RECEIVED_WELCOME: case CL_RECEIVED_PROCEED: + case CL_RECEIVED_CHALLENGE: para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno); return; @@ -297,7 +300,6 @@ static void client_post_select(struct sched *s, struct task *t) /* decrypted challenge/session key buffer */ unsigned char crypt_buf[1024]; /* the SHA1 of the decrypted challenge */ - unsigned char challenge_hash[HASH_SIZE]; if (ct->use_sideband) { struct sb_buffer sbb; @@ -326,18 +328,31 @@ static void client_post_select(struct sched *s, struct task *t) if (ret < 0) goto out; } - hash_function((char *)crypt_buf, CHALLENGE_SIZE, challenge_hash); + ct->challenge_hash = para_malloc(HASH_SIZE); + hash_function((char *)crypt_buf, CHALLENGE_SIZE, ct->challenge_hash); ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN); ct->scc.recv = sc_new(crypt_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN); - hash_to_asc(challenge_hash, buf); + hash_to_asc(ct->challenge_hash, buf); PARA_INFO_LOG("--> %s\n", buf); - ret = write_all(ct->scc.fd, (char *)challenge_hash, HASH_SIZE); - if (ret < 0) - goto out; - ct->status = CL_SENT_CH_RESPONSE; + ct->status = CL_RECEIVED_CHALLENGE; return; } + case CL_RECEIVED_CHALLENGE: + if (ct->use_sideband) { + ret = send_sb(ct, ct->challenge_hash, HASH_SIZE, + SBD_CHALLENGE_RESPONSE, false); + if (ret != 0) + ct->challenge_hash = NULL; + if (ret <= 0) + goto out; + } else { + ret = write_all(ct->scc.fd, (char *)ct->challenge_hash, HASH_SIZE); + if (ret < 0) + goto out; + } + ct->status = CL_SENT_CH_RESPONSE; + goto out; case CL_SENT_CH_RESPONSE: /* read server response */ { ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n); diff --git a/command.c b/command.c index 5790f11d..5e13df66 100644 --- a/command.c +++ b/command.c @@ -934,22 +934,28 @@ __noreturn void handle_connect(int fd, const char *peername) PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n", CHALLENGE_SIZE, numbytes); if (cc->use_sideband) { + struct iovec iov; ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false); buf = NULL; if (ret < 0) goto net_err; - buf = para_malloc(HANDSHAKE_BUFSIZE); + ret = recv_sb(&cc->scc, SBD_CHALLENGE_RESPONSE, + HANDSHAKE_BUFSIZE, &iov); + if (ret < 0) + goto net_err; + buf = iov.iov_base; + numbytes = iov.iov_len; } else { ret = write_all(fd, buf, numbytes); if (ret < 0) goto net_err; + /* recv challenge response */ + ret = recv_bin_buffer(fd, buf, HASH_SIZE); + if (ret < 0) + goto net_err; + numbytes = ret; } - /* recv challenge response */ - ret = recv_bin_buffer(fd, buf, HASH_SIZE); - if (ret < 0) - goto net_err; - numbytes = ret; - PARA_DEBUG_LOG("received %d bytes challenge response\n", ret); + PARA_DEBUG_LOG("received %zu bytes challenge response\n", numbytes); ret = -E_BAD_USER; if (!cc->u) goto net_err;