X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=client_common.c;h=f8ee80c9d7a01956769284eaa117f1606c59cd76;hb=d440a71683940a58747de6dc32643db452d9cf54;hp=094b93be85addc7882a1bfc8d65110ce128ec215;hpb=8919784065fdfd210dc25e4ab31c6fa92f9e3219;p=paraslash.git diff --git a/client_common.c b/client_common.c index 094b93be..f8ee80c9 100644 --- a/client_common.c +++ b/client_common.c @@ -50,13 +50,12 @@ void client_close(struct client_task *ct) } /* - * The preselect hook for server commands. + * This function asks the scheduler to monitor a file descriptor which + * corresponds to an active connection. The descriptor is monitored for either + * reading or writing, depending on the state of the connection. * - * The task pointer must contain a pointer to the initialized client data - * structure as it is returned by client_open(). - * - * This function checks the state of the connection and adds the file descriptor - * of the connection to the read or write fd set of s accordingly. + * The context pointer is assumed to refer to a client task structure that was + * initialized earlier by client_open(). */ static void client_pre_select(struct sched *s, void *context) { @@ -86,7 +85,7 @@ static void client_pre_select(struct sched *s, void *context) else if (ret > 0) para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno); } - /* fallthrough */ + __attribute__ ((fallthrough)); case CL_EXECUTING: if (ct->btrn[0]) { ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT); @@ -259,13 +258,21 @@ static int send_sb_command(struct client_task *ct) return send_sb(ct, 0, command, len, SBD_COMMAND, false); } +static bool has_feature(const char *feature, struct client_task *ct) +{ + return find_arg(feature, ct->features) >= 0? true : false; +} + /* - * The post select hook for client commands. + * This function reads or writes to the socket file descriptor which + * corresponds to an established connection between the client and the server. + * It depends on the current state of the connection and on the readiness of + * the socket file descriptor which type of I/O is going to be performed. + * Besides the initial handshake and authentication, the function sends the + * server command and receives the output from the server, if any. * - * Depending on the current state of the connection and the status of the read - * and write fd sets of s, this function performs the necessary steps to - * authenticate the connection, to send the command given by t->private_data - * and to receive para_server's output, if any. + * The context pointer refers to a client task structure that was initialized + * earlier by client_open(). */ static int client_post_select(struct sched *s, void *context) { @@ -288,16 +295,25 @@ static int client_post_select(struct sched *s, void *context) ct->status = CL_RECEIVED_WELCOME; return 0; case CL_RECEIVED_WELCOME: /* send auth command */ + { + /* + * Use sha256 iff the server announced the feature. After 0.7.0 + * we may request and use the feature unconditionally. After + * 0.8.0 we no longer need to request the feature. + */ + bool has_sha256; if (!FD_ISSET(ct->scc.fd, &s->wfds)) return 0; - sprintf(buf, AUTH_REQUEST_MSG "%s sideband,aes_ctr128", - ct->user); + has_sha256 = has_feature("sha256", ct); + sprintf(buf, AUTH_REQUEST_MSG "%s%s", ct->user, has_sha256? + " sha256" : ""); PARA_INFO_LOG("--> %s\n", buf); ret = write_buffer(ct->scc.fd, buf); if (ret < 0) goto out; ct->status = CL_SENT_AUTH; return 0; + } case CL_SENT_AUTH: /* * Receive challenge and session keys, decrypt the challenge and @@ -318,24 +334,34 @@ static int client_post_select(struct sched *s, void *context) } n = sbb.iov.iov_len; PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n); - ret = priv_decrypt(ct->key_file, crypt_buf, + ret = apc_priv_decrypt(ct->key_file, crypt_buf, sbb.iov.iov_base, n); free(sbb.iov.iov_base); if (ret < 0) goto out; - 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, + ct->challenge_hash = para_malloc(HASH2_SIZE); + + if (has_feature("sha256", ct)) { + hash2_function((char *)crypt_buf, APC_CHALLENGE_SIZE, ct->challenge_hash); + hash2_to_asc(ct->challenge_hash, buf); + } else { + hash_function((char *)crypt_buf, APC_CHALLENGE_SIZE, ct->challenge_hash); + hash_to_asc(ct->challenge_hash, buf); + } + ct->scc.send = sc_new(crypt_buf + APC_CHALLENGE_SIZE, SESSION_KEY_LEN); + ct->scc.recv = sc_new(crypt_buf + APC_CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN); - hash_to_asc(ct->challenge_hash, buf); PARA_INFO_LOG("--> %s\n", buf); ct->status = CL_RECEIVED_CHALLENGE; return 0; } case CL_RECEIVED_CHALLENGE: - ret = send_sb(ct, 0, ct->challenge_hash, HASH_SIZE, - SBD_CHALLENGE_RESPONSE, false); + if (has_feature("sha256", ct)) + ret = send_sb(ct, 0, ct->challenge_hash, HASH2_SIZE, + SBD_CHALLENGE_RESPONSE, false); + else + ret = send_sb(ct, 0, ct->challenge_hash, HASH_SIZE, + SBD_CHALLENGE_RESPONSE, false); if (ret != 0) ct->challenge_hash = NULL; if (ret <= 0) @@ -389,7 +415,7 @@ static int client_post_select(struct sched *s, void *context) btr_consume(ct->btrn[1], sz); } } - /* fall through */ + __attribute__ ((fallthrough)); case CL_EXECUTING: if (ct->btrn[0]) { ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT); @@ -426,8 +452,7 @@ out: return 0; btr_remove_node(&ct->btrn[0]); btr_remove_node(&ct->btrn[1]); - if (ret != -E_SERVER_CMD_SUCCESS && ret != -E_SERVER_CMD_FAILURE) - PARA_ERROR_LOG("%s\n", para_strerror(-ret)); + PARA_NOTICE_LOG("closing connection (%s)\n", para_strerror(-ret)); if (ct->scc.fd >= 0) { close(ct->scc.fd); ct->scc.fd = -1;