Browse Source

'AUTH' exchange. Now it's just a hand-shake to get starting prompt

Serj Kalichev 1 year ago
parent
commit
5aaaf94a82
4 changed files with 145 additions and 2 deletions
  1. 55 1
      bin/klish/interactive.c
  2. 57 1
      klish/ktp/ktp_session.c
  3. 31 0
      klish/ktp/ktpd_session.c
  4. 2 0
      klish/ktp_session.h

+ 55 - 1
bin/klish/interactive.c

@@ -23,11 +23,14 @@ typedef struct ctx_s {
 } ctx_t;
 
 
+bool_t auth_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
 bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
 bool_t completion_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
 bool_t help_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
 static bool_t stdin_cb(faux_eloop_t *eloop, faux_eloop_type_e type,
 	void *associated_data, void *user_data);
+static bool_t ktp_sync_auth(ktp_session_t *ktp, int *retcode,
+	faux_error_t *error);
 
 // Keys
 static bool_t tinyrl_key_enter(tinyrl_t *tinyrl, unsigned char key);
@@ -42,6 +45,7 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
 	tinyrl_t *tinyrl = NULL;
 	int stdin_flags = 0;
 	char *hist_path = NULL;
+	int auth_rc = -1;
 
 	assert(ktp);
 	if (!ktp)
@@ -60,22 +64,34 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
 	tinyrl_bind_key(tinyrl, '\r', tinyrl_key_enter);
 	tinyrl_bind_key(tinyrl, '\t', tinyrl_key_tab);
 	tinyrl_bind_key(tinyrl, '?', tinyrl_key_help);
-	tinyrl_redisplay(tinyrl);
 
 	ctx.ktp = ktp;
 	ctx.tinyrl = tinyrl;
 	ctx.opts = opts;
 
+	// Now AUTH command is used only for starting hand-shake and getting
+	// prompt from the server. Generally it must be necessary for
+	// non-interactive session too but for now is not implemented.
+	ktp_session_set_cb(ktp, KTP_SESSION_CB_AUTH_ACK, auth_ack_cb, &ctx);
+	if (!ktp_sync_auth(ktp, &auth_rc, ktp_session_error(ktp)))
+		goto cleanup;
+	if (auth_rc < 0)
+		goto cleanup;
+
 	// Don't stop interactive loop on each answer
 	ktp_session_set_stop_on_answer(ktp, BOOL_FALSE);
 
 	ktp_session_set_cb(ktp, KTP_SESSION_CB_CMD_ACK, cmd_ack_cb, &ctx);
 	ktp_session_set_cb(ktp, KTP_SESSION_CB_COMPLETION_ACK, completion_ack_cb, &ctx);
 	ktp_session_set_cb(ktp, KTP_SESSION_CB_HELP_ACK, help_ack_cb, &ctx);
+
+	tinyrl_redisplay(tinyrl);
+
 	eloop = ktp_session_eloop(ktp);
 	faux_eloop_add_fd(eloop, STDIN_FILENO, POLLIN, stdin_cb, &ctx);
 	faux_eloop_loop(eloop);
 
+cleanup:
 	// Cleanup
 	if (tinyrl_busy(tinyrl))
 		faux_error_free(ktp_session_error(ktp));
@@ -107,6 +123,32 @@ static bool_t process_prompt_param(tinyrl_t *tinyrl, const faux_msg_t *msg)
 }
 
 
+bool_t auth_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
+{
+	ctx_t *ctx = (ctx_t *)udata;
+	int rc = -1;
+	faux_error_t *error = NULL;
+
+	process_prompt_param(ctx->tinyrl, msg);
+
+	if (!ktp_session_retcode(ktp, &rc))
+		rc = -1;
+	error = ktp_session_error(ktp);
+	if ((rc < 0) && (faux_error_len(error) > 0)) {
+		faux_error_node_t *err_iter = faux_error_iter(error);
+		const char *err = NULL;
+		while ((err = faux_error_each(&err_iter)))
+			fprintf(stderr, "Error: %s\n", err);
+	}
+	faux_error_free(error);
+
+	// Happy compiler
+	msg = msg;
+
+	return BOOL_TRUE;
+}
+
+
 bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 {
 	ctx_t *ctx = (ctx_t *)udata;
@@ -401,3 +443,15 @@ bool_t help_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 
 	return BOOL_TRUE;
 }
+
+
+static bool_t ktp_sync_auth(ktp_session_t *ktp, int *retcode,
+	faux_error_t *error)
+{
+	if (!ktp_session_auth(ktp, error))
+		return BOOL_FALSE;
+
+	faux_eloop_loop(ktp_session_eloop(ktp));
+
+	return ktp_session_retcode(ktp, retcode);
+}

+ 57 - 1
klish/ktp/ktp_session.c

@@ -314,6 +314,44 @@ static bool_t ktp_session_process_stderr(ktp_session_t *ktp, const faux_msg_t *m
 }
 
 
+static bool_t ktp_session_process_auth_ack(ktp_session_t *ktp, const faux_msg_t *msg)
+{
+	uint8_t *retcode8bit = NULL;
+	ktp_status_e status = KTP_STATUS_NONE;
+	char *error_str = NULL;
+
+	assert(ktp);
+	assert(msg);
+
+	status = faux_msg_get_status(msg);
+
+	if (faux_msg_get_param_by_type(msg, KTP_PARAM_RETCODE,
+		(void **)&retcode8bit, NULL))
+		ktp->cmd_retcode = (int)(*retcode8bit);
+	error_str = faux_msg_get_str_param_by_type(msg, KTP_PARAM_ERROR);
+	if (error_str) {
+		faux_error_add(ktp->error, error_str);
+		faux_str_free(error_str);
+	}
+
+	ktp->cmd_retcode_available = BOOL_TRUE; // Answer from server was received
+	ktp->request_done = BOOL_TRUE;
+	ktp->state = KTP_SESSION_STATE_IDLE;
+	// Get exit flag from message
+	if (KTP_STATUS_IS_EXIT(status))
+		ktp->done = BOOL_TRUE;
+
+	// Execute external callback
+	if (ktp->cb[KTP_SESSION_CB_AUTH_ACK].fn)
+		((ktp_session_event_cb_fn)
+			ktp->cb[KTP_SESSION_CB_AUTH_ACK].fn)(
+			ktp, msg,
+			ktp->cb[KTP_SESSION_CB_AUTH_ACK].udata);
+
+	return BOOL_TRUE;
+}
+
+
 static bool_t ktp_session_process_cmd_ack(ktp_session_t *ktp, const faux_msg_t *msg)
 {
 	uint8_t *retcode8bit = NULL;
@@ -443,6 +481,13 @@ static bool_t ktp_session_dispatch(ktp_session_t *ktp, faux_msg_t *msg)
 
 	cmd = faux_msg_get_cmd(msg);
 	switch (cmd) {
+	case KTP_AUTH_ACK:
+		if (ktp->state != KTP_SESSION_STATE_UNAUTHORIZED) {
+			syslog(LOG_WARNING, "Unexpected KTP_AUTH_ACK was received\n");
+			break;
+		}
+		rc = ktp_session_process_auth_ack(ktp, msg);
+		break;
 	case KTP_CMD_ACK:
 		if (ktp->state != KTP_SESSION_STATE_WAIT_FOR_CMD) {
 			syslog(LOG_WARNING, "Unexpected KTP_CMD_ACK was received\n");
@@ -571,7 +616,8 @@ static bool_t ktp_session_req(ktp_session_t *ktp, ktp_cmd_e cmd,
 		status |= KTP_STATUS_DRY_RUN;
 
 	req = ktp_msg_preform(cmd, status);
-	faux_msg_add_param(req, KTP_PARAM_LINE, line, strlen(line));
+	if (line)
+		faux_msg_add_param(req, KTP_PARAM_LINE, line, strlen(line));
 	faux_msg_send_async(req, ktp->async);
 	faux_msg_free(req);
 
@@ -598,6 +644,16 @@ bool_t ktp_session_cmd(ktp_session_t *ktp, const char *line,
 }
 
 
+bool_t ktp_session_auth(ktp_session_t *ktp, faux_error_t *error)
+{
+	if (!ktp_session_req(ktp, KTP_AUTH, NULL, error, BOOL_FALSE))
+		return BOOL_FALSE;
+	ktp->state = KTP_SESSION_STATE_UNAUTHORIZED;
+
+	return BOOL_TRUE;
+}
+
+
 bool_t ktp_session_completion(ktp_session_t *ktp, const char *line, bool_t dry_run)
 {
 	if (!ktp_session_req(ktp, KTP_COMPLETION, line, NULL, dry_run))

+ 31 - 0
klish/ktp/ktpd_session.c

@@ -162,6 +162,34 @@ static char *generate_prompt(ktpd_session_t *ktpd)
 }
 
 
+// Now it's not really an auth function. Just a hand-shake with client and
+// passing prompt to client.
+static bool_t ktpd_session_process_auth(ktpd_session_t *ktpd, faux_msg_t *msg)
+{
+	ktp_cmd_e cmd = KTP_AUTH_ACK;
+	uint32_t status = KTP_STATUS_NONE;
+	char *prompt = NULL;
+	uint8_t retcode8bit = 0;
+
+	assert(ktpd);
+	assert(msg);
+
+	// Prepare ACK message
+	faux_msg_t *ack = ktp_msg_preform(cmd, status);
+	faux_msg_add_param(ack, KTP_PARAM_RETCODE, &retcode8bit, 1);
+	// Generate prompt
+	prompt = generate_prompt(ktpd);
+	if (prompt) {
+		faux_msg_add_param(ack, KTP_PARAM_PROMPT, prompt, strlen(prompt));
+		faux_str_free(prompt);
+	}
+	faux_msg_send_async(ack, ktpd->async);
+	faux_msg_free(ack);
+
+	return BOOL_TRUE;
+}
+
+
 static bool_t ktpd_session_process_cmd(ktpd_session_t *ktpd, faux_msg_t *msg)
 {
 	char *line = NULL;
@@ -685,6 +713,9 @@ static bool_t ktpd_session_dispatch(ktpd_session_t *ktpd, faux_msg_t *msg)
 
 	cmd = faux_msg_get_cmd(msg);
 	switch (cmd) {
+	case KTP_AUTH:
+		ktpd_session_process_auth(ktpd, msg);
+		break;
 	case KTP_CMD:
 		ktpd_session_process_cmd(ktpd, msg);
 		break;

+ 2 - 0
klish/ktp_session.h

@@ -58,6 +58,7 @@ typedef enum {
 typedef enum {
 	KTP_SESSION_CB_STDOUT,
 	KTP_SESSION_CB_STDERR,
+	KTP_SESSION_CB_AUTH_ACK,
 	KTP_SESSION_CB_CMD_ACK_INCOMPLETED,
 	KTP_SESSION_CB_CMD_ACK,
 	KTP_SESSION_CB_COMPLETION_ACK,
@@ -88,6 +89,7 @@ ktp_session_state_e ktp_session_state(const ktp_session_t *ktp);
 
 bool_t ktp_session_cmd(ktp_session_t *ktp, const char *line,
 	faux_error_t *error, bool_t dry_run);
+bool_t ktp_session_auth(ktp_session_t *ktp, faux_error_t *error);
 bool_t ktp_session_completion(ktp_session_t *ktp, const char *line,
 	bool_t dry_run);
 bool_t ktp_session_help(ktp_session_t *ktp, const char *line);