Skip to content
Snippets Groups Projects
Commit 907db1f5 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

More refinement and bug fixes...

We can now get the path to the users home directory on the remote
system.

This introduces the use of error fields in the sftpc_state struct,
which should allow result-or-error style stuff pretty easily.
parent 36238a27
No related branches found
No related tags found
1 merge request!455Update branch with changes from master
......@@ -5,10 +5,10 @@
extern "C" {
#endif
#include <stdbool.h>
#include <eventwrap.h>
#include <inttypes.h>
#include "eventwrap.h"
#include <stdbool.h>
#include <threadwrap.h>
// draft-ietf-secsh-filexfer-02
......@@ -96,8 +96,14 @@ typedef struct sftp_client_state {
xpevent_t recv_event;
sftp_rx_pkt_t rxp;
sftp_tx_pkt_t txp;
pthread_t thread;
sftp_str_t home;
void *cb_data;
sftp_str_t err_msg;
sftp_str_t err_lang;
pthread_t thread;
uint32_t id;
uint32_t err_id;
uint32_t err_code;
} *sftpc_state_t;
/* sftp_pkt.c */
......@@ -110,7 +116,7 @@ bool sftp_have_full_pkt(sftp_rx_pkt_t pkt);
void sftp_remove_packet(sftp_rx_pkt_t pkt);
uint32_t sftp_get32(sftp_rx_pkt_t pkt);
uint32_t sftp_get64(sftp_rx_pkt_t pkt);
sftp_str_t sftp_getstring(sftp_rx_pkt_t pkt, uint8_t **str);
sftp_str_t sftp_getstring(sftp_rx_pkt_t pkt);
bool sftp_rx_pkt_append(sftp_rx_pkt_t *pkt, uint8_t *inbuf, uint32_t len);
bool sftp_tx_pkt_reset(sftp_tx_pkt_t *pktp);
bool sftp_appendbyte(sftp_tx_pkt_t *pktp, uint8_t u8);
......@@ -132,5 +138,6 @@ void sftpc_finish(sftpc_state_t state);
sftpc_state_t sftpc_begin(bool (*send_cb)(uint8_t *buf, size_t len, void *cb_data), void *cb_data);
bool sftpc_init(sftpc_state_t state);
bool sftpc_recv(sftpc_state_t state, uint8_t *buf, uint32_t sz);
bool sftpc_realpath(sftpc_state_t state, char *path, sftp_str_t *ret);
#endif
......@@ -5,6 +5,51 @@
#include "sftp.h"
static uint32_t
get32(sftpc_state_t state)
{
return sftp_get32(state->rxp);
}
static uint64_t
get64(sftpc_state_t state)
{
return sftp_get64(state->rxp);
}
static sftp_str_t
getstring(sftpc_state_t state)
{
return sftp_getstring(state->rxp);
}
static bool
appendbyte(sftpc_state_t state, uint8_t u)
{
return sftp_appendbyte(&state->txp, u);
}
static bool
append32(sftpc_state_t state, uint32_t u)
{
return sftp_append32(&state->txp, u);
}
static bool
append64(sftpc_state_t state, uint64_t u)
{
return sftp_append64(&state->txp, u);
}
static bool
appendstring(sftpc_state_t state, sftp_str_t *s)
{
bool ret = sftp_appendstring(&state->txp, *s);
free_sftp_str(*s);
*s = NULL;
return ret;
}
void
sftpc_finish(sftpc_state_t state)
{
......@@ -41,42 +86,110 @@ sftpc_begin(bool (*send_cb)(uint8_t *buf, size_t len, void *cb_data), void *cb_d
ret->send_cb = send_cb;
ret->cb_data = cb_data;
ret->thread = pthread_self();
ret->id = 0;
ret->err_lang = NULL;
ret->err_msg = NULL;
return ret;
}
bool
sftpc_init(sftpc_state_t state)
static void
response_handled(sftpc_state_t state)
{
sftp_remove_packet(state->rxp);
if (!sftp_have_full_pkt(state->rxp))
ResetEvent(state->recv_event);
}
static bool
check_state(sftpc_state_t state)
{
assert(state);
if (!state)
goto fail;
return false;
assert(state->thread == pthread_self());
if (state->thread != pthread_self())
goto fail;
if (!sftp_appendbyte(&state->txp, SSH_FXP_INIT))
goto fail;
if (!sftp_append32(&state->txp, SFTP_VERSION))
goto fail;
return false;
return true;
}
static bool
appendheader(sftpc_state_t state, uint8_t type)
{
if (!check_state(state))
return false;
state->err_code = 0;
state->err_id = 0;
free_sftp_str(state->err_lang);
state->err_lang = NULL;
free_sftp_str(state->err_msg);
state->err_msg = NULL;
if (!sftp_tx_pkt_reset(&state->txp))
return false;
if (!sftp_appendbyte(&state->txp, type))
return false;
if (type != SSH_FXP_INIT) {
if (!sftp_append32(&state->txp, ++state->id))
return false;
}
return true;
}
static bool
get_result(sftpc_state_t state)
{
uint8_t *txbuf;
size_t txsz;
if (!sftp_prep_tx_packet(state->txp, &txbuf, &txsz))
goto fail;
return false;
if (!state->send_cb(txbuf, txsz, state->cb_data))
goto fail;
sftp_tx_pkt_reset(&state->txp);
return false;
if (WaitForEvent(state->recv_event, INFINITE) != WAIT_OBJECT_0)
goto fail;
return false;
if (state->rxp->type != SSH_FXP_VERSION) {
uint32_t id = sftp_get32(state->rxp);
if (id != state->id) {
response_handled(state);
return false;
}
}
return true;
}
static void
handle_error(sftpc_state_t state)
{
if (state->rxp->type == SSH_FXP_STATUS) {
state->err_id = get32(state);
state->err_code = get32(state);
if (state->err_msg != NULL)
free_sftp_str(state->err_msg);
state->err_msg = getstring(state);
if (state->err_lang != NULL)
free_sftp_str(state->err_lang);
state->err_lang = getstring(state);
}
response_handled(state);
}
bool
sftpc_init(sftpc_state_t state)
{
if (!appendheader(state, SSH_FXP_INIT))
return false;
if (!append32(state, SFTP_VERSION))
return false;
if (!get_result(state))
return false;
if (state->rxp->type != SSH_FXP_VERSION)
goto fail;
if (sftp_get32(state->rxp) != SFTP_VERSION)
goto fail;
sftp_remove_packet(state->rxp);
if (!sftp_have_full_pkt(state->rxp))
ResetEvent(state->recv_event);
return false;
if (get32(state) != SFTP_VERSION) {
response_handled(state);
return false;
}
response_handled(state);
state->id = 0;
return true;
fail:
sftp_tx_pkt_reset(&state->txp);
return false;
}
bool
......@@ -88,3 +201,31 @@ sftpc_recv(sftpc_state_t state, uint8_t *buf, uint32_t sz)
SetEvent(state->recv_event);
return true;
}
bool
sftpc_realpath(sftpc_state_t state, char *path, sftp_str_t *ret)
{
assert(ret);
if (ret == NULL)
return false;
if (*ret != NULL)
return false;
if (!appendheader(state, SSH_FXP_REALPATH))
return false;
sftp_str_t pstr = sftp_strdup(path);
if (!appendstring(state, &pstr))
return false;
if (!get_result(state))
return false;
if (state->rxp->type == SSH_FXP_NAME) {
if (get32(state) != 1) {
response_handled(state);
return false;
}
*ret = getstring(state);
response_handled(state);
return true;
}
handle_error(state);
return false;
}
......@@ -121,6 +121,7 @@ sftp_remove_packet(sftp_rx_pkt_t pkt)
src += sz;
memmove(&pkt->len, src, newsz);
pkt->used = newsz;
pkt->cur = 0;
// TODO: realloc() smaller?
return;
}
......@@ -161,7 +162,7 @@ sftp_get64(sftp_rx_pkt_t pkt)
* cursor
*/
sftp_str_t
sftp_getstring(sftp_rx_pkt_t pkt, uint8_t **str)
sftp_getstring(sftp_rx_pkt_t pkt)
{
assert(pkt);
uint32_t sz = sftp_get32(pkt);
......@@ -187,11 +188,13 @@ sftp_rx_pkt_append(sftp_rx_pkt_t *pktp, uint8_t *inbuf, uint32_t len)
size_t old_sz;
size_t new_sz;
uint32_t old_used;
uint32_t old_cur;
sftp_rx_pkt_t pkt = *pktp;
if (pkt == NULL) {
old_sz = 0;
old_used = 0;
old_cur = 0;
new_sz = offsetof(struct sftp_rx_pkt, len) + len;
}
else {
......@@ -211,6 +214,7 @@ sftp_rx_pkt_append(sftp_rx_pkt_t *pktp, uint8_t *inbuf, uint32_t len)
*pktp = new_buf;
pkt = *pktp;
pkt->sz = new_sz;
pkt->cur = old_cur;
}
memcpy(&((uint8_t *)&(pkt->len))[old_used], inbuf, len);
pkt->used = old_used + len;
......@@ -265,6 +269,8 @@ sftp_tx_pkt_reset(sftp_tx_pkt_t *pktp)
if (pktp == NULL)
return false;
sftp_tx_pkt_t pkt = *pktp;
if (pkt == NULL)
return true;
pkt->used = 0;
if (pkt->sz == SFTP_MIN_PACKET_ALLOC)
return true;
......@@ -310,8 +316,10 @@ sftp_appendstring(sftp_tx_pkt_t *pktp, sftp_str_t s)
{
assert(pktp);
sftp_append32(pktp, s->len);
if (!grow_tx(pktp, s->len))
return false;
sftp_tx_pkt_t pkt = *pktp;
memcpy(&pkt->data[pkt->used], (uint8_t *)s->c_str, s->len);
memcpy(&(&pkt->type)[pkt->used], (uint8_t *)s->c_str, s->len);
pkt->used += s->len;
return true;
}
......
......@@ -2,9 +2,9 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <xpprintf.h>
#include "sftp.h"
#include "xpprintf.h"
static sftp_str_t
alloc_str(uint32_t len)
......
......@@ -513,10 +513,14 @@ ssh_connect(struct bbslist *bbs)
}
if (cryptStatusOK(status)) {
sftp_state = sftpc_begin(sftp_send, NULL);
if (sftp_state == NULL)
fprintf(stderr, "Failure!\n");
else if (sftpc_init(sftp_state))
fprintf(stderr, "Success!\n");
if (sftp_state != NULL) {
if (sftpc_init(sftp_state)) {
sftp_str_t ret = NULL;
if (sftpc_realpath(sftp_state, ".", &ret)) {
fprintf(stderr, "Home dir: %.*s\n", ret->len, ret->c_str);
}
}
}
}
}
#endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment