X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/d92624dccee63e8bee8653e8ae845ffad3490b67..a460b361fe6734325bead016ef2dd39e4da302f4:/sftp.c diff --git a/sftp.c b/sftp.c index 9c14e745..b49e2750 100644 --- a/sftp.c +++ b/sftp.c @@ -7,13 +7,10 @@ #include #include +#include "misc.h" #include "int64.h" #include "sftp.h" -#define smalloc malloc -#define srealloc realloc -#define sfree free - #define GET_32BIT(cp) \ (((unsigned long)(unsigned char)(cp)[0] << 24) | \ ((unsigned long)(unsigned char)(cp)[1] << 16) | \ @@ -43,7 +40,7 @@ static void sftp_pkt_ensure(struct sftp_packet *pkt, int length) { if (pkt->maxlen < length) { pkt->maxlen = length + 256; - pkt->data = srealloc(pkt->data, pkt->maxlen); + pkt->data = sresize(pkt->data, pkt->maxlen, char); } } static void sftp_pkt_adddata(struct sftp_packet *pkt, void *data, int len) @@ -59,13 +56,12 @@ static void sftp_pkt_addbyte(struct sftp_packet *pkt, unsigned char byte) static struct sftp_packet *sftp_pkt_init(int pkt_type) { struct sftp_packet *pkt; - pkt = smalloc(sizeof(struct sftp_packet)); + pkt = snew(struct sftp_packet); pkt->data = NULL; pkt->savedpos = -1; pkt->length = 0; pkt->maxlen = 0; sftp_pkt_addbyte(pkt, (unsigned char) pkt_type); - fxp_error_message = NULL; return pkt; } static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value) @@ -232,10 +228,10 @@ struct sftp_packet *sftp_recv(void) if (!sftp_recvdata(x, 4)) return NULL; - pkt = smalloc(sizeof(struct sftp_packet)); + pkt = snew(struct sftp_packet); pkt->savedpos = 0; pkt->length = pkt->maxlen = GET_32BIT(x); - pkt->data = smalloc(pkt->length); + pkt->data = snewn(pkt->length, char); if (!sftp_recvdata(pkt->data, pkt->length)) { sftp_pkt_free(pkt); @@ -253,7 +249,7 @@ struct sftp_packet *sftp_recv(void) static char *mkstr(char *s, int len) { - char *p = smalloc(len + 1); + char *p = snewn(len + 1, char); memcpy(p, s, len); p[len] = '\0'; return p; @@ -340,12 +336,14 @@ int fxp_init(void) } if (pktin->type != SSH_FXP_VERSION) { fxp_internal_error("did not receive FXP_VERSION"); + sftp_pkt_free(pktin); return 0; } remotever = sftp_pkt_getuint32(pktin); if (remotever > SFTP_PROTO_VERSION) { fxp_internal_error ("remote protocol is more advanced than we support"); + sftp_pkt_free(pktin); return 0; } /* @@ -373,9 +371,14 @@ char *fxp_realpath(char *path) sftp_pkt_addstring_str(pktout, path); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return NULL; + } id = sftp_pkt_getuint32(pktin); if (id != 0x123) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return NULL; } if (pktin->type == SSH_FXP_NAME) { @@ -386,11 +389,13 @@ char *fxp_realpath(char *path) count = sftp_pkt_getuint32(pktin); if (count != 1) { fxp_internal_error("REALPATH returned name count != 1\n"); + sftp_pkt_free(pktin); return NULL; } sftp_pkt_getstring(pktin, &path, &len); if (!path) { fxp_internal_error("REALPATH returned malformed FXP_NAME\n"); + sftp_pkt_free(pktin); return NULL; } path = mkstr(path, len); @@ -398,6 +403,7 @@ char *fxp_realpath(char *path) return path; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return NULL; } } @@ -417,9 +423,14 @@ struct fxp_handle *fxp_open(char *path, int type) sftp_pkt_adduint32(pktout, 0); /* (FIXME) empty ATTRS structure */ sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return NULL; + } id = sftp_pkt_getuint32(pktin); if (id != 0x567) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return NULL; } if (pktin->type == SSH_FXP_HANDLE) { @@ -430,15 +441,17 @@ struct fxp_handle *fxp_open(char *path, int type) sftp_pkt_getstring(pktin, &hstring, &len); if (!hstring) { fxp_internal_error("OPEN returned malformed FXP_HANDLE\n"); + sftp_pkt_free(pktin); return NULL; } - handle = smalloc(sizeof(struct fxp_handle)); + handle = snew(struct fxp_handle); handle->hstring = mkstr(hstring, len); handle->hlen = len; sftp_pkt_free(pktin); return handle; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return NULL; } } @@ -456,9 +469,14 @@ struct fxp_handle *fxp_opendir(char *path) sftp_pkt_addstring(pktout, path); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return NULL; + } id = sftp_pkt_getuint32(pktin); if (id != 0x456) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return NULL; } if (pktin->type == SSH_FXP_HANDLE) { @@ -469,15 +487,17 @@ struct fxp_handle *fxp_opendir(char *path) sftp_pkt_getstring(pktin, &hstring, &len); if (!hstring) { fxp_internal_error("OPENDIR returned malformed FXP_HANDLE\n"); + sftp_pkt_free(pktin); return NULL; } - handle = smalloc(sizeof(struct fxp_handle)); + handle = snew(struct fxp_handle); handle->hstring = mkstr(hstring, len); handle->hlen = len; sftp_pkt_free(pktin); return handle; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return NULL; } } @@ -496,12 +516,18 @@ void fxp_close(struct fxp_handle *handle) sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return; + } id = sftp_pkt_getuint32(pktin); if (id != 0x789) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return; } fxp_got_status(pktin); + sftp_pkt_free(pktin); sfree(handle->hstring); sfree(handle); } @@ -517,12 +543,18 @@ int fxp_mkdir(char *path) sftp_pkt_adduint32(pktout, 0); /* (FIXME) empty ATTRS structure */ sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x234) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } id = fxp_got_status(pktin); + sftp_pkt_free(pktin); if (id != 1) { return 0; } @@ -539,12 +571,18 @@ int fxp_rmdir(char *path) sftp_pkt_addstring(pktout, path); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x345) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } id = fxp_got_status(pktin); + sftp_pkt_free(pktin); if (id != 1) { return 0; } @@ -561,12 +599,18 @@ int fxp_remove(char *fname) sftp_pkt_addstring(pktout, fname); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x678) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } id = fxp_got_status(pktin); + sftp_pkt_free(pktin); if (id != 1) { return 0; } @@ -584,12 +628,18 @@ int fxp_rename(char *srcfname, char *dstfname) sftp_pkt_addstring(pktout, dstfname); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x678) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } id = fxp_got_status(pktin); + sftp_pkt_free(pktin); if (id != 1) { return 0; } @@ -610,17 +660,24 @@ int fxp_stat(char *fname, struct fxp_attrs *attrs) sftp_pkt_addstring(pktout, fname); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x678) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } if (pktin->type == SSH_FXP_ATTRS) { *attrs = sftp_pkt_getattrs(pktin); + sftp_pkt_free(pktin); return 1; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return 0; } } @@ -636,17 +693,24 @@ int fxp_fstat(struct fxp_handle *handle, struct fxp_attrs *attrs) sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x678) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } if (pktin->type == SSH_FXP_ATTRS) { *attrs = sftp_pkt_getattrs(pktin); + sftp_pkt_free(pktin); return 1; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return 0; } } @@ -665,12 +729,47 @@ int fxp_setstat(char *fname, struct fxp_attrs attrs) sftp_pkt_addattrs(pktout, attrs); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); + return 0; + } + id = fxp_got_status(pktin); + sftp_pkt_free(pktin); + if (id != 1) { + return 0; + } + return 1; +} +int fxp_fsetstat(struct fxp_handle *handle, struct fxp_attrs attrs) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_FSETSTAT); + sftp_pkt_adduint32(pktout, 0x678); /* request id */ + sftp_pkt_addstring_start(pktout); + sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen); + sftp_pkt_addattrs(pktout, attrs); + sftp_send(pktout); + pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0x678) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } id = fxp_got_status(pktin); + sftp_pkt_free(pktin); if (id != 1) { return 0; } @@ -697,9 +796,14 @@ int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, sftp_pkt_adduint32(pktout, len); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return -1; + } id = sftp_pkt_getuint32(pktin); if (id != 0xBCD) { fxp_internal_error("request ID mismatch"); + sftp_pkt_free(pktin); return -1; } if (pktin->type == SSH_FXP_DATA) { @@ -710,14 +814,16 @@ int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, if (rlen > len || rlen < 0) { fxp_internal_error("READ returned more bytes than requested"); + sftp_pkt_free(pktin); return -1; } memcpy(buffer, str, rlen); - sfree(pktin); + sftp_pkt_free(pktin); return rlen; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return -1; } } @@ -736,17 +842,22 @@ struct fxp_names *fxp_readdir(struct fxp_handle *handle) sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return NULL; + } id = sftp_pkt_getuint32(pktin); if (id != 0xABC) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return NULL; } if (pktin->type == SSH_FXP_NAME) { struct fxp_names *ret; int i; - ret = smalloc(sizeof(struct fxp_names)); + ret = snew(struct fxp_names); ret->nnames = sftp_pkt_getuint32(pktin); - ret->names = smalloc(ret->nnames * sizeof(struct fxp_name)); + ret->names = snewn(ret->nnames, struct fxp_name); for (i = 0; i < ret->nnames; i++) { char *str; int len; @@ -756,9 +867,11 @@ struct fxp_names *fxp_readdir(struct fxp_handle *handle) ret->names[i].longname = mkstr(str, len); ret->names[i].attrs = sftp_pkt_getattrs(pktin); } + sftp_pkt_free(pktin); return ret; } else { fxp_got_status(pktin); + sftp_pkt_free(pktin); return NULL; } } @@ -781,12 +894,18 @@ int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset, sftp_pkt_addstring_data(pktout, buffer, len); sftp_send(pktout); pktin = sftp_recv(); + if (!pktin) { + fxp_internal_error("did not receive a valid SFTP packet\n"); + return 0; + } id = sftp_pkt_getuint32(pktin); if (id != 0xDCB) { fxp_internal_error("request ID mismatch\n"); + sftp_pkt_free(pktin); return 0; } fxp_got_status(pktin); + sftp_pkt_free(pktin); return fxp_errtype == SSH_FX_OK; } @@ -804,3 +923,26 @@ void fxp_free_names(struct fxp_names *names) sfree(names->names); sfree(names); } + +/* + * Duplicate an fxp_name structure. + */ +struct fxp_name *fxp_dup_name(struct fxp_name *name) +{ + struct fxp_name *ret; + ret = snew(struct fxp_name); + ret->filename = dupstr(name->filename); + ret->longname = dupstr(name->longname); + ret->attrs = name->attrs; /* structure copy */ + return ret; +} + +/* + * Free up an fxp_name structure. + */ +void fxp_free_name(struct fxp_name *name) +{ + sfree(name->filename); + sfree(name->longname); + sfree(name); +}