X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=client_common.c;h=eea7510fd0589e86fb4058dd7f4361f3c79901aa;hp=6652cc35477234a9dd4a9f0621be953c5cc9ba00;hb=6ee9f6e477fd968491be395bedfbf660e0ebea5c;hpb=017aa6503f639c7d0bb7b7be200da5fde4f2f4bd diff --git a/client_common.c b/client_common.c index 6652cc35..eea7510f 100644 --- a/client_common.c +++ b/client_common.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-2013 Andre Noll + * Copyright (C) 1997 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -32,44 +32,17 @@ /** The size of the receiving buffer. */ #define CLIENT_BUFSIZE 4000 -/** - * Close the connection to para_server and deallocate per-command resources. - * - * \param ct The client task. - * - * This frees all resources of the current command but keeps the configuration - * in \p ct->conf. - * - * \sa \ref client_close(). - */ -void client_disconnect(struct client_task *ct) -{ - if (!ct) - return; - if (ct->scc.fd >= 0) - close(ct->scc.fd); - free_argv(ct->features); - ct->features = NULL; - sc_free(ct->scc.recv); - ct->scc.recv = NULL; - sc_free(ct->scc.send); - ct->scc.send = NULL; - btr_remove_node(&ct->btrn[0]); - btr_remove_node(&ct->btrn[1]); -} - /** * Close the connection to para_server and free all resources. * * \param ct Pointer to the client data. * - * \sa \ref client_open(), \ref client_disconnect(). + * \sa \ref client_open(). */ void client_close(struct client_task *ct) { if (!ct) return; - client_disconnect(ct); free(ct->user); free(ct->config_file); free(ct->key_file); @@ -80,24 +53,19 @@ void client_close(struct client_task *ct) free(ct); } -/** +/* * The preselect hook for server commands. * - * \param s Pointer to the scheduler. - * \param t Pointer to the task struct for this command. - * * 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 \a s accordingly. - * - * \sa register_task() client_open(), struct sched, struct task. + * of the connection to the read or write fd set of s accordingly. */ -static void client_pre_select(struct sched *s, struct task *t) +static void client_pre_select(struct sched *s, void *context) { int ret; - struct client_task *ct = container_of(t, struct client_task, task); + struct client_task *ct = context; if (ct->scc.fd < 0) return; @@ -191,7 +159,10 @@ again: } if (n == 0) return 0; - if (!sb_received(ct->sbc[0], n, result)) + ret = sb_received(ct->sbc[0], n, result); + if (ret < 0) + return ret; + if (ret == 0) goto again; ct->sbc[0] = NULL; return 1; @@ -295,27 +266,22 @@ static int send_sb_command(struct client_task *ct) return send_sb(ct, 0, command, len, SBD_COMMAND, false); } -/** +/* * The post select hook for client commands. * - * \param s Pointer to the scheduler. - * \param t Pointer to the task struct for this command. - * * Depending on the current state of the connection and the status of the read - * and write fd sets of \a s, this function performs the necessary steps to - * authenticate the connection, to send the command given by \a t->private_data + * 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. - * - * \sa struct sched, struct task. */ -static int client_post_select(struct sched *s, struct task *t) +static int client_post_select(struct sched *s, void *context) { - struct client_task *ct = container_of(t, struct client_task, task); + struct client_task *ct = context; int ret = 0; size_t n; char buf[CLIENT_BUFSIZE]; - ret = task_get_notification(t); + ret = task_get_notification(ct->task); if (ret < 0) goto out; if (ct->scc.fd < 0) @@ -326,17 +292,13 @@ static int client_post_select(struct sched *s, struct task *t) if (ret < 0 || n == 0) goto out; ct->features = parse_features(buf); - if (!has_feature("sideband", ct)) { - PARA_ERROR_LOG("server has no sideband support\n"); - ret = -E_INCOMPAT_FEAT; - goto out; - } ct->status = CL_RECEIVED_WELCOME; return 0; case CL_RECEIVED_WELCOME: /* send auth command */ if (!FD_ISSET(ct->scc.fd, &s->wfds)) return 0; - sprintf(buf, AUTH_REQUEST_MSG "%s sideband", ct->user); + sprintf(buf, AUTH_REQUEST_MSG "%s sideband%s", ct->user, + has_feature("aes_ctr128", ct)? ",aes_ctr128" : ""); PARA_INFO_LOG("--> %s\n", buf); ret = write_buffer(ct->scc.fd, buf); if (ret < 0) @@ -352,6 +314,7 @@ static int client_post_select(struct sched *s, struct task *t) /* decrypted challenge/session key buffer */ unsigned char crypt_buf[1024]; struct sb_buffer sbb; + bool use_aes; ret = recv_sb(ct, &s->rfds, &sbb); if (ret <= 0) @@ -370,9 +333,10 @@ static int client_post_select(struct sched *s, struct task *t) 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); + use_aes = has_feature("aes_ctr128", ct); + ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN, use_aes); ct->scc.recv = sc_new(crypt_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, - SESSION_KEY_LEN); + SESSION_KEY_LEN, use_aes); hash_to_asc(ct->challenge_hash, buf); PARA_INFO_LOG("--> %s\n", buf); ct->status = CL_RECEIVED_CHALLENGE; @@ -434,7 +398,7 @@ static int client_post_select(struct sched *s, struct task *t) btr_consume(ct->btrn[1], sz); } } - /* fall though */ + /* fall through */ case CL_EXECUTING: if (ct->btrn[0]) { ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT); @@ -473,6 +437,16 @@ out: 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)); + if (ct->scc.fd >= 0) { + close(ct->scc.fd); + ct->scc.fd = -1; + } + free_argv(ct->features); + ct->features = NULL; + sc_free(ct->scc.recv); + ct->scc.recv = NULL; + sc_free(ct->scc.send); + ct->scc.send = NULL; return ret; } @@ -510,11 +484,13 @@ int client_connect(struct client_task *ct, struct sched *s, EMBRACE(.name = "client recv", .parent = NULL, .child = child)); ct->btrn[1] = btr_new_node(&(struct btr_node_description) EMBRACE(.name = "client send", .parent = parent, .child = NULL)); - ct->task.pre_select = client_pre_select; - ct->task.post_select = client_post_select; - ct->task.error = 0; - sprintf(ct->task.status, "client"); - register_task(s, &ct->task); + + ct->task = task_register(&(struct task_info) { + .name = "client", + .pre_select = client_pre_select, + .post_select = client_post_select, + .context = ct, + }, s); return 1; err_out: close(ct->scc.fd);