Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ssh/sftpcommon.c')
-rw-r--r--ssh/sftpcommon.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/ssh/sftpcommon.c b/ssh/sftpcommon.c
new file mode 100644
index 00000000..f2f9a3bc
--- /dev/null
+++ b/ssh/sftpcommon.c
@@ -0,0 +1,139 @@
+/*
+ * sftpcommon.c: SFTP code shared between client and server.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "misc.h"
+#include "sftp.h"
+
+static void sftp_pkt_BinarySink_write(
+ BinarySink *bs, const void *data, size_t length)
+{
+ struct sftp_packet *pkt = BinarySink_DOWNCAST(bs, struct sftp_packet);
+
+ assert(length <= 0xFFFFFFFFU - pkt->length);
+
+ sgrowarrayn_nm(pkt->data, pkt->maxlen, pkt->length, length);
+ memcpy(pkt->data + pkt->length, data, length);
+ pkt->length += length;
+}
+
+struct sftp_packet *sftp_pkt_init(int type)
+{
+ struct sftp_packet *pkt;
+ pkt = snew(struct sftp_packet);
+ pkt->data = NULL;
+ pkt->savedpos = -1;
+ pkt->length = 0;
+ pkt->maxlen = 0;
+ pkt->type = type;
+ BinarySink_INIT(pkt, sftp_pkt_BinarySink_write);
+ put_uint32(pkt, 0); /* length field will be filled in later */
+ put_byte(pkt, 0); /* so will the type field */
+ return pkt;
+}
+
+void BinarySink_put_fxp_attrs(BinarySink *bs, struct fxp_attrs attrs)
+{
+ put_uint32(bs, attrs.flags);
+ if (attrs.flags & SSH_FILEXFER_ATTR_SIZE)
+ put_uint64(bs, attrs.size);
+ if (attrs.flags & SSH_FILEXFER_ATTR_UIDGID) {
+ put_uint32(bs, attrs.uid);
+ put_uint32(bs, attrs.gid);
+ }
+ if (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
+ put_uint32(bs, attrs.permissions);
+ }
+ if (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME) {
+ put_uint32(bs, attrs.atime);
+ put_uint32(bs, attrs.mtime);
+ }
+ if (attrs.flags & SSH_FILEXFER_ATTR_EXTENDED) {
+ /*
+ * We currently don't support sending any extended
+ * attributes.
+ */
+ }
+}
+
+const struct fxp_attrs no_attrs = { 0 };
+
+#define put_fxp_attrs(bs, attrs) \
+ BinarySink_put_fxp_attrs(BinarySink_UPCAST(bs), attrs)
+
+bool BinarySource_get_fxp_attrs(BinarySource *src, struct fxp_attrs *attrs)
+{
+ attrs->flags = get_uint32(src);
+ if (attrs->flags & SSH_FILEXFER_ATTR_SIZE)
+ attrs->size = get_uint64(src);
+ if (attrs->flags & SSH_FILEXFER_ATTR_UIDGID) {
+ attrs->uid = get_uint32(src);
+ attrs->gid = get_uint32(src);
+ }
+ if (attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS)
+ attrs->permissions = get_uint32(src);
+ if (attrs->flags & SSH_FILEXFER_ATTR_ACMODTIME) {
+ attrs->atime = get_uint32(src);
+ attrs->mtime = get_uint32(src);
+ }
+ if (attrs->flags & SSH_FILEXFER_ATTR_EXTENDED) {
+ unsigned long count = get_uint32(src);
+ while (count--) {
+ if (get_err(src)) {
+ /* Truncated packet. Don't waste time looking for
+ * attributes that aren't there. Caller should spot
+ * the truncation. */
+ break;
+ }
+ /*
+ * We should try to analyse these, if we ever find one
+ * we recognise.
+ */
+ get_string(src);
+ get_string(src);
+ }
+ }
+ return true;
+}
+
+void sftp_pkt_free(struct sftp_packet *pkt)
+{
+ if (pkt->data)
+ sfree(pkt->data);
+ sfree(pkt);
+}
+
+void sftp_send_prepare(struct sftp_packet *pkt)
+{
+ PUT_32BIT_MSB_FIRST(pkt->data, pkt->length - 4);
+ if (pkt->length >= 5) {
+ /* Rewrite the type code, in case the caller changed its mind
+ * about pkt->type since calling sftp_pkt_init */
+ pkt->data[4] = pkt->type;
+ }
+}
+
+struct sftp_packet *sftp_recv_prepare(unsigned length)
+{
+ struct sftp_packet *pkt;
+
+ pkt = snew(struct sftp_packet);
+ pkt->savedpos = 0;
+ pkt->length = pkt->maxlen = length;
+ pkt->data = snewn(pkt->length, char);
+
+ return pkt;
+}
+
+bool sftp_recv_finish(struct sftp_packet *pkt)
+{
+ BinarySource_INIT(pkt, pkt->data, pkt->length);
+ pkt->type = get_byte(pkt);
+ return !get_err(pkt);
+}