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

Add support for open/close/read/write operations

This may be all SyncTERM needs unless it wants to add in a Midnight
Commander clone for browsing sftp servers.
parent 10e5b8d2
No related branches found
No related tags found
1 merge request!455Update branch with changes from master
......@@ -2,4 +2,5 @@ MT_OBJS = \
$(MTOBJODIR)$(DIRSEP)sftp_pkt$(OFILE) \
$(MTOBJODIR)$(DIRSEP)sftp_str$(OFILE) \
$(MTOBJODIR)$(DIRSEP)sftp_client$(OFILE) \
$(MTOBJODIR)$(DIRSEP)sftp_attr$(OFILE) \
......@@ -8,34 +8,33 @@
// draft-ietf-secsh-filexfer-02
#define SSH_FXP_INIT UINT8_C(1)
#define SSH_FXP_VERSION UINT8_C(2)
#define SSH_FXP_OPEN UINT8_C(3)
#define SSH_FXP_CLOSE UINT8_C(4)
#define SSH_FXP_READ UINT8_C(5)
#define SSH_FXP_WRITE UINT8_C(6)
#define SSH_FXP_LSTAT UINT8_C(7)
#define SSH_FXP_FSTAT UINT8_C(8)
#define SSH_FXP_SETSTAT UINT8_C(9)
#define SSH_FXP_FSETSTAT UINT8_C(10)
#define SSH_FXP_OPENDIR UINT8_C(11)
#define SSH_FXP_READDIR UINT8_C(12)
#define SSH_FXP_REMOVE UINT8_C(13)
#define SSH_FXP_MKDIR UINT8_C(14)
#define SSH_FXP_RMDIR UINT8_C(15)
#define SSH_FXP_REALPATH UINT8_C(16)
#define SSH_FXP_STAT UINT8_C(17)
#define SSH_FXP_RENAME UINT8_C(18)
#define SSH_FXP_READLINK UINT8_C(19)
#define SSH_FXP_SYMLINK UINT8_C(20)
#define SSH_FXP_STATUS UINT8_C(101)
#define SSH_FXP_HANDLE UINT8_C(102)
#define SSH_FXP_DATA UINT8_C(103)
#define SSH_FXP_NAME UINT8_C(104)
#define SSH_FXP_ATTRS UINT8_C(105)
#define SSH_FXP_EXTENDED UINT8_C(200)
#define SSH_FXP_EXTENDED_REPLY UINT8_C(201)
#define SSH_FXP_INIT UINT8_C(1)
#define SSH_FXP_VERSION UINT8_C(2)
#define SSH_FXP_OPEN UINT8_C(3)
#define SSH_FXP_CLOSE UINT8_C(4)
#define SSH_FXP_READ UINT8_C(5)
#define SSH_FXP_WRITE UINT8_C(6)
#define SSH_FXP_LSTAT UINT8_C(7)
#define SSH_FXP_FSTAT UINT8_C(8)
#define SSH_FXP_SETSTAT UINT8_C(9)
#define SSH_FXP_FSETSTAT UINT8_C(10)
#define SSH_FXP_OPENDIR UINT8_C(11)
#define SSH_FXP_READDIR UINT8_C(12)
#define SSH_FXP_REMOVE UINT8_C(13)
#define SSH_FXP_MKDIR UINT8_C(14)
#define SSH_FXP_RMDIR UINT8_C(15)
#define SSH_FXP_REALPATH UINT8_C(16)
#define SSH_FXP_STAT UINT8_C(17)
#define SSH_FXP_RENAME UINT8_C(18)
#define SSH_FXP_READLINK UINT8_C(19)
#define SSH_FXP_SYMLINK UINT8_C(20)
#define SSH_FXP_STATUS UINT8_C(101)
#define SSH_FXP_HANDLE UINT8_C(102)
#define SSH_FXP_DATA UINT8_C(103)
#define SSH_FXP_NAME UINT8_C(104)
#define SSH_FXP_ATTRS UINT8_C(105)
#define SSH_FXP_EXTENDED UINT8_C(200)
#define SSH_FXP_EXTENDED_REPLY UINT8_C(201)
#define SSH_FX_OK UINT32_C(0)
#define SSH_FX_EOF UINT32_C(1)
......@@ -47,6 +46,19 @@
#define SSH_FX_CONNECTION_LOST UINT32_C(7)
#define SSH_FX_OP_UNSUPPORTED UINT32_C(8)
#define SSH_FXF_READ UINT32_C(0x00000001)
#define SSH_FXF_WRITE UINT32_C(0x00000002)
#define SSH_FXF_APPEND UINT32_C(0x00000004)
#define SSH_FXF_CREAT UINT32_C(0x00000008)
#define SSH_FXF_TRUNC UINT32_C(0x00000010)
#define SSH_FXF_EXCL UINT32_C(0x00000020)
#define SSH_FILEXFER_ATTR_SIZE UINT32_C(0x00000001)
#define SSH_FILEXFER_ATTR_UIDGID UINT32_C(0x00000002)
#define SSH_FILEXFER_ATTR_PERMISSIONS UINT32_C(0x00000004)
#define SSH_FILEXFER_ATTR_ACMODTIME UINT32_C(0x00000008)
#define SSH_FILEXFER_ATTR_EXTENDED UINT32_C(0x80000000)
#define SFTP_MIN_PACKET_ALLOC 4096
#define SFTP_VERSION 3
......@@ -76,16 +88,8 @@ struct sftp_extended_file_attribute {
struct sftp_string *data;
};
struct sftp_file_attributes {
uint32_t flags;
uint64_t size;
uint32_t uid;
uint32_t gid;
uint32_t perm;
uint32_t atime;
uint32_t mtime;
struct sftp_extended_file_attribute ext[];
};
struct sftp_file_attributes;
typedef struct sftp_file_attributes *sftp_file_attr_t;
typedef struct sftp_client_state {
bool (*send_cb)(uint8_t *buf, size_t len, void *cb_data);
......@@ -102,6 +106,14 @@ typedef struct sftp_client_state {
uint32_t err_code;
} *sftpc_state_t;
enum sftp_handle_type {
SFTP_HANDLE_TYPE_DIR,
SFTP_HANDLE_TYPE_FILE,
};
typedef sftp_str_t sftp_filehandle_t;
typedef sftp_str_t sftp_dirhandle_t;
/* sftp_pkt.c */
const char * const sftp_get_type_name(uint8_t type);
bool sftp_have_pkt_sz(sftp_rx_pkt_t pkt);
......@@ -135,5 +147,28 @@ sftpc_state_t sftpc_begin(bool (*send_cb)(uint8_t *buf, size_t len, void *cb_dat
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);
bool sftpc_open(sftpc_state_t state, char *path, uint32_t flags, sftp_file_attr_t attr, sftp_dirhandle_t *handle);
bool sftpc_close(sftpc_state_t state, sftp_filehandle_t *handle);
bool sftpc_read(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset, uint32_t len, sftp_str_t *ret);
bool sftpc_write(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset, sftp_str_t data);
/* sftp_attr.c */
sftp_file_attr_t sftp_fattr_alloc(void);
void sftp_fattr_free(sftp_file_attr_t fattr);
void sftp_fattr_set_size(sftp_file_attr_t fattr, uint64_t sz);
bool sftp_fattr_get_size(sftp_file_attr_t fattr, uint64_t *sz);
void sftp_fattr_set_uid_gid(sftp_file_attr_t fattr, uint32_t uid, uint32_t gid);
bool sftp_fattr_get_uid(sftp_file_attr_t fattr, uint32_t *uid);
bool sftp_fattr_get_gid(sftp_file_attr_t fattr, uint32_t *gid);
void sftp_fattr_set_permissions(sftp_file_attr_t fattr, uint64_t perm);
bool sftp_fattr_get_permissions(sftp_file_attr_t fattr, uint64_t *perm);
void sftp_fattr_set_times(sftp_file_attr_t fattr, uint32_t atime, uint32_t mtime);
bool sftp_fattr_get_atime(sftp_file_attr_t fattr, uint32_t *atime);
bool sftp_fattr_get_mtime(sftp_file_attr_t fattr, uint32_t *mtime);
bool sftp_fattr_add_ext(sftp_file_attr_t *fattr, sftp_str_t type, sftp_str_t data);
sftp_str_t sftp_fattr_get_ext_type(sftp_file_attr_t fattr, uint32_t index);
sftp_str_t sftp_fattr_get_ext_data(sftp_file_attr_t fattr, uint32_t index);
uint32_t sftp_fattr_get_ext_count(sftp_file_attr_t fattr);
bool sftp_appendfattr(sftp_tx_pkt_t *pktp, sftp_file_attr_t fattr);
#endif
......@@ -112,10 +112,11 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="sftp_client.c" />
<ClCompile Include="sftp_attr.c" />
<ClCompile Include="sftp_pkt.c" />
<ClCompile Include="sftp_str.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -42,7 +42,13 @@ append64(sftpc_state_t state, uint64_t u)
}
static bool
appendstring(sftpc_state_t state, sftp_str_t *s)
appendfattr(sftpc_state_t state, sftp_file_attr_t fattr)
{
return sftp_appendfattr(&state->txp, fattr);
}
static bool
appendandfreestring(sftpc_state_t state, sftp_str_t *s)
{
bool ret = sftp_appendstring(&state->txp, *s);
free_sftp_str(*s);
......@@ -50,6 +56,13 @@ appendstring(sftpc_state_t state, sftp_str_t *s)
return ret;
}
static bool
appendstring(sftpc_state_t state, sftp_str_t s)
{
bool ret = sftp_appendstring(&state->txp, s);
return ret;
}
void
sftpc_finish(sftpc_state_t state)
{
......@@ -134,12 +147,27 @@ appendheader(sftpc_state_t state, uint8_t type)
return true;
}
static bool
appendfhandle(sftpc_state_t state, sftp_filehandle_t handle)
{
return appendstring(state, (sftp_str_t)handle);
}
static bool
appenddhandle(sftpc_state_t state, sftp_dirhandle_t handle)
{
return appendstring(state, (sftp_str_t)handle);
}
static bool
get_result(sftpc_state_t state)
{
uint8_t *txbuf;
size_t txsz;
assert(state->thread == pthread_self());
if (state->thread != pthread_self())
return false;
if (!sftp_prep_tx_packet(state->txp, &txbuf, &txsz))
return false;
if (!state->send_cb(txbuf, txsz, state->cb_data))
......@@ -213,7 +241,7 @@ sftpc_realpath(sftpc_state_t state, char *path, sftp_str_t *ret)
if (!appendheader(state, SSH_FXP_REALPATH))
return false;
sftp_str_t pstr = sftp_strdup(path);
if (!appendstring(state, &pstr))
if (!appendandfreestring(state, &pstr))
return false;
if (!get_result(state))
return false;
......@@ -229,3 +257,129 @@ sftpc_realpath(sftpc_state_t state, char *path, sftp_str_t *ret)
handle_error(state);
return false;
}
static bool
parse_handle(sftpc_state_t state, sftp_str_t *handle)
{
assert(state);
if (state == NULL)
return false;
assert(state->rxp);
if (state->rxp == NULL)
return false;
assert(state->rxp->type == SSH_FXP_HANDLE);
if (state->rxp->type != SSH_FXP_HANDLE)
return false;
assert(handle);
if (handle == NULL)
return false;
*handle = getstring(state);
if (*handle == NULL)
return false;
return true;
}
bool
sftpc_open(sftpc_state_t state, char *path, uint32_t flags, sftp_file_attr_t attr, sftp_dirhandle_t *handle)
{
assert(handle);
if (handle == NULL)
return false;
assert(!*handle);
if (*handle != NULL)
return false;
if (!appendheader(state, SSH_FXP_OPEN))
return false;
sftp_str_t pstr = sftp_strdup(path);
if (!appendandfreestring(state, &pstr))
return false;
if (!append32(state, flags))
return false;
sftp_file_attr_t a = attr;
if (a == NULL) {
a = sftp_fattr_alloc();
if (a == NULL)
return false;
}
if (!appendfattr(state, a)) {
if (a != attr)
sftp_fattr_free(a);
return false;
}
if (a != attr)
sftp_fattr_free(a);
if (!get_result(state))
return false;
if (state->rxp->type == SSH_FXP_HANDLE) {
if (!parse_handle(state, (sftp_str_t *)handle)) {
response_handled(state);
return false;
}
response_handled(state);
return true;
}
handle_error(state);
return false;
}
bool
sftpc_close(sftpc_state_t state, sftp_filehandle_t *handle)
{
if (!appendheader(state, SSH_FXP_CLOSE))
return false;
if (!appendfhandle(state, *handle))
return false;
if (!get_result(state))
return false;
handle_error(state);
free_sftp_str(*handle);
*handle = NULL;
return state->err_code == SSH_FX_OK;
}
bool
sftpc_read(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset, uint32_t len, sftp_str_t *ret)
{
assert(ret);
if (ret == NULL)
return false;
assert(*ret == NULL);
if (*ret != NULL)
return false;
if (!appendheader(state, SSH_FXP_READ))
return false;
if (!appendfhandle(state, handle))
return false;
if (!append64(state, offset))
return false;
if (!append32(state, len))
return false;
if (!get_result(state))
return false;
if (state->rxp->type == SSH_FXP_DATA) {
*ret = getstring(state);
return *ret != NULL;
}
handle_error(state);
return false;
}
bool
sftpc_write(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset, sftp_str_t data)
{
assert(data);
if (data == NULL)
return false;
if (!appendheader(state, SSH_FXP_WRITE))
return false;
if (!appendfhandle(state, handle))
return false;
if (!append64(state, offset))
return false;
if (!appendstring(state, data))
return false;
if (!get_result(state))
return false;
handle_error(state);
return state->err_code == SSH_FX_OK;
}
......@@ -250,7 +250,7 @@ error_popup(struct bbslist *bbs, const char *blurb, int status)
char str[1024];
sprintf(str, "Error %d %s", status, blurb);
if (!bbs->hidepopups)
uifcmsg("Error %s", str);
uifcmsg(str, str);
conn_api.terminate = 1;
if (!bbs->hidepopups)
uifc.pop(NULL);
......@@ -301,8 +301,7 @@ ssh_connect(struct bbslist *bbs)
if(cryptStatusError(status)) {
error_popup(bbs, "creating context", status);
}
status = cl.KeysetClose(ssh_keyset);
if (cryptStatusError(status)) {
if (cryptStatusError(cl.KeysetClose(ssh_keyset))) {
error_popup(bbs, "closing keyset", status);
}
}
......@@ -314,7 +313,7 @@ ssh_connect(struct bbslist *bbs)
error_popup(bbs, "creating context", status);
break;
}
status = cl.SetAttributeString(ssh_context, CRYPT_CTXINFO_LABEL, KEY_LABEL, 10);
status = cl.SetAttributeString(ssh_context, CRYPT_CTXINFO_LABEL, KEY_LABEL, strlen(KEY_LABEL));
if (cryptStatusError(status)) {
error_popup(bbs, "setting label", status);
break;
......@@ -417,12 +416,15 @@ ssh_connect(struct bbslist *bbs)
return -1;
}
if (!bbs->hidepopups)
uifc.pop("Setting Private Key");
status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_PRIVATEKEY, ssh_context);
if (cryptStatusError(status)) {
error_popup(bbs, "setting private key", status);
return -1;
if (ssh_context != -1) {
if (!bbs->hidepopups)
uifc.pop("Setting Private Key");
status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_PRIVATEKEY, ssh_context);
cl.DestroyContext(ssh_context);
if (cryptStatusError(status)) {
error_popup(bbs, "setting private key", status);
return -1;
}
}
}
......@@ -625,8 +627,14 @@ ssh_connect(struct bbslist *bbs)
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);
sftp_filehandle_t f = NULL;
if (sftpc_open(sftp_state, ".ssh/authorized_keys", SSH_FXF_READ, NULL, &f)) {
if (sftpc_read(sftp_state, f, 0, 1024, &ret)) {
fprintf(stderr, "First lines... %s\n", ret->c_str);
free_sftp_str(ret);
}
sftpc_close(sftp_state, &f);
}
}
}
......
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