X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcsftp%2Fsftp_server.c;h=de0b52ef9d7eaade18f4a1ac0b4418af93a4d1f6;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=119dbf1f36d7c58d5886087fb3e20d96d339d6c6;hpb=83c73dffa89141bc59e62436abb63b3d3efca6bb;p=silc.git diff --git a/lib/silcsftp/sftp_server.c b/lib/silcsftp/sftp_server.c index 119dbf1f..de0b52ef 100644 --- a/lib/silcsftp/sftp_server.c +++ b/lib/silcsftp/sftp_server.c @@ -1,10 +1,10 @@ /* - sftp_server.c + sftp_server.c Author: Pekka Riikonen - Copyright (C) 2001 Pekka Riikonen + Copyright (C) 2001 - 2004 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,51 +18,54 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcsftp.h" #include "silcsftp_fs.h" #include "sftp_util.h" /* SFTP Server context */ typedef struct { - SilcSocketConnection sock; SilcSFTPSendPacketCallback send_packet; void *send_context; SilcSFTPMonitors monitors; SilcSFTPMonitor monitor; void *monitor_context; SilcSFTPFilesystem fs; + SilcBuffer packet; } *SilcSFTPServer; /* General routine to send SFTP packet to the SFTP client. */ static void silc_sftp_send_packet(SilcSFTPServer sftp, - SilcSFTPPacket type, - uint32 len, ...) + SilcSFTPPacket type, + SilcUInt32 len, ...) { - SilcBuffer packet; + SilcBuffer tmp; va_list vp; va_start(vp, len); - packet = silc_sftp_packet_encode_vp(type, len, vp); + tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp); va_end(vp); - - if (!packet) + if (!tmp) return; + sftp->packet = tmp; - SILC_LOG_HEXDUMP(("SFTP packet to client"), packet->data, packet->len); + SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data, + sftp->packet->len); /* Send the packet */ - (*sftp->send_packet)(sftp->sock, packet, sftp->send_context); + (*sftp->send_packet)(sftp->packet, sftp->send_context); - silc_buffer_free(packet); + /* Clear packet */ + sftp->packet->data = sftp->packet->tail = sftp->packet->head; + sftp->packet->len = 0; } /* Sends error to the client */ static void silc_sftp_send_error(SilcSFTPServer sftp, SilcSFTPStatus status, - uint32 id) + SilcUInt32 id) { SILC_LOG_DEBUG(("Send error %d", status)); @@ -83,12 +86,12 @@ static void silc_sftp_server_status(SilcSFTP sftp, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; - uint32 id = (uint32)context; + SilcUInt32 id = SILC_PTR_TO_32(context); int mlen, llen; SILC_LOG_DEBUG(("Status callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); - + if (!message) message = ""; if (!language_tag) @@ -114,9 +117,9 @@ static void silc_sftp_server_handle(SilcSFTP sftp, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; - uint32 id = (uint32)context; + SilcUInt32 id = SILC_PTR_TO_32(context); unsigned char *hdata; - uint32 hdata_len; + SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Handle callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); @@ -145,11 +148,11 @@ static void silc_sftp_server_handle(SilcSFTP sftp, static void silc_sftp_server_data(SilcSFTP sftp, SilcSFTPStatus status, const unsigned char *data, - uint32 data_len, + SilcUInt32 data_len, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; - uint32 id = (uint32)context; + SilcUInt32 id = SILC_PTR_TO_32(context); SILC_LOG_DEBUG(("Data callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); @@ -174,7 +177,7 @@ static void silc_sftp_server_name(SilcSFTP sftp, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; - uint32 id = (uint32)context; + SilcUInt32 id = SILC_PTR_TO_32(context); SilcBuffer namebuf; SILC_LOG_DEBUG(("Name callback")); @@ -205,7 +208,7 @@ static void silc_sftp_server_attr(SilcSFTP sftp, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; - uint32 id = (uint32)context; + SilcUInt32 id = SILC_PTR_TO_32(context); SilcBuffer attr_buf; SILC_LOG_DEBUG(("Attr callback")); @@ -217,6 +220,10 @@ static void silc_sftp_server_attr(SilcSFTP sftp, } attr_buf = silc_sftp_attr_encode(attrs); + if (!attr_buf) { + silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id); + return; + } silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len, SILC_STR_UI_INT(id), @@ -231,11 +238,11 @@ static void silc_sftp_server_attr(SilcSFTP sftp, static void silc_sftp_server_extended(SilcSFTP sftp, SilcSFTPStatus status, const unsigned char *data, - uint32 data_len, + SilcUInt32 data_len, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; - uint32 id = (uint32)context; + SilcUInt32 id = SILC_PTR_TO_32(context); SILC_LOG_DEBUG(("Extended callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); @@ -251,21 +258,20 @@ static void silc_sftp_server_extended(SilcSFTP sftp, SILC_STR_END); } -/* Starts SFTP server by associating the socket connection `sock' to the - created SFTP server context. This function returns the allocated - SFTP client context or NULL on error. The `send_packet' is called +/* Starts SFTP server and returns context to it. This function returns the + allocated SFTP client context or NULL on error. The `send_packet' is called by the library when it needs to send a packet. The `fs' is the structure containing filesystem access callbacks. */ -SilcSFTP silc_sftp_server_start(SilcSocketConnection sock, - SilcSFTPSendPacketCallback send_packet, +SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet, void *send_context, SilcSFTPFilesystem fs) { SilcSFTPServer server; server = silc_calloc(1, sizeof(*server)); - server->sock = sock; + if (!server) + return NULL; server->send_packet = send_packet; server->send_context = send_context; server->fs = fs; @@ -285,6 +291,8 @@ void silc_sftp_server_shutdown(SilcSFTP sftp) SILC_LOG_DEBUG(("Stopping SFTP server %p", server)); + if (server->packet) + silc_buffer_free(server->packet); silc_free(server); } @@ -292,7 +300,7 @@ void silc_sftp_server_shutdown(SilcSFTP sftp) void silc_sftp_server_set_monitor(SilcSFTP sftp, SilcSFTPMonitors monitors, - SilcSFTPMonitor monitor, + SilcSFTPMonitor monitor, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; @@ -313,10 +321,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, SilcSFTPPacket type; char *filename = NULL, *path = NULL; const unsigned char *payload = NULL; - uint32 payload_len; + SilcUInt32 payload_len; int ret; SilcBufferStruct buf; - uint32 id; + SilcUInt32 id; SilcSFTPAttributes attrs; SilcSFTPHandle handle; SilcSFTPMonitorDataStruct mdata; @@ -324,7 +332,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, SILC_LOG_DEBUG(("Start")); /* Parse the packet */ - type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, + type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, &payload_len); if (!type) return; @@ -363,7 +371,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, { SilcSFTPFileOperation pflags; unsigned char *attr_buf; - uint32 attr_len = 0; + SilcUInt32 attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Open request")); @@ -372,7 +380,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&filename), SILC_STR_UI_INT(&pflags), - SILC_STR_UI32_NSTRING(&attr_buf, + SILC_STR_UI32_NSTRING(&attr_buf, &attr_len), SILC_STR_END); if (ret < 0) @@ -381,8 +389,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); + if (!attrs) + goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); + if (!attrs) + goto failure; } /* Call monitor */ @@ -395,7 +407,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Open operation */ server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags, - attrs, silc_sftp_server_handle, (void *)id); + attrs, silc_sftp_server_handle, + SILC_32_TO_PTR(id)); silc_free(filename); silc_sftp_attr_free(attrs); @@ -405,13 +418,13 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, case SILC_SFTP_CLOSE: { unsigned char *hdata; - uint32 hdata_len; + SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Close request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&hdata, + SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_END); if (ret < 0) @@ -434,22 +447,23 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Close operation */ server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); + } break; case SILC_SFTP_READ: { unsigned char *hdata; - uint32 hdata_len; - uint64 offset; - uint32 len; + SilcUInt32 hdata_len; + SilcUInt64 offset; + SilcUInt32 len; SILC_LOG_DEBUG(("Read request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&hdata, + SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_UI_INT64(&offset), SILC_STR_UI_INT(&len), @@ -466,6 +480,11 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, break; } + /* Read operation */ + server->fs->fs->sftp_read(server->fs->fs_context, sftp, + handle, offset, len, + silc_sftp_server_data, SILC_32_TO_PTR(id)); + /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) { mdata.offset = offset; @@ -473,30 +492,25 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata, server->monitor_context); } - - /* Read operation */ - server->fs->fs->sftp_read(server->fs->fs_context, sftp, - handle, offset, len, - silc_sftp_server_data, (void *)id); } break; case SILC_SFTP_WRITE: { unsigned char *hdata; - uint32 hdata_len; - uint64 offset; + SilcUInt32 hdata_len; + SilcUInt64 offset; unsigned char *data; - uint32 data_len; + SilcUInt32 data_len; SILC_LOG_DEBUG(("Read request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&hdata, + SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_UI_INT64(&offset), - SILC_STR_UI32_NSTRING(&data, + SILC_STR_UI32_NSTRING(&data, &data_len), SILC_STR_END); if (ret < 0) @@ -511,6 +525,11 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, break; } + /* Write operation */ + server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset, + (const unsigned char *)data, data_len, + silc_sftp_server_status, SILC_32_TO_PTR(id)); + /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) { mdata.offset = offset; @@ -518,11 +537,6 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata, server->monitor_context); } - - /* Write operation */ - server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset, - (const unsigned char *)data, data_len, - silc_sftp_server_status, (void *)id); } break; @@ -546,7 +560,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Remove operation */ server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(filename); } @@ -575,9 +589,9 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, } /* Rename operation */ - server->fs->fs->sftp_rename(server->fs->fs_context, sftp, + server->fs->fs->sftp_rename(server->fs->fs_context, sftp, filename, newname, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(filename); silc_free(newname); @@ -587,7 +601,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, case SILC_SFTP_MKDIR: { unsigned char *attr_buf; - uint32 attr_len = 0; + SilcUInt32 attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Mkdir request")); @@ -604,8 +618,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); + if (!attrs) + goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); + if (!attrs) + goto failure; } /* Call monitor */ @@ -617,7 +635,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Mkdir operation */ server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_sftp_attr_free(attrs); silc_free(path); @@ -644,7 +662,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Rmdir operation */ server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(path); } @@ -670,7 +688,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Opendir operation */ server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path, - silc_sftp_server_handle, (void *)id); + silc_sftp_server_handle, SILC_32_TO_PTR(id)); silc_free(path); } @@ -679,13 +697,13 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, case SILC_SFTP_READDIR: { unsigned char *hdata; - uint32 hdata_len; + SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Readdir request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&hdata, + SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_END); if (ret < 0) @@ -708,7 +726,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Readdir operation */ server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle, - silc_sftp_server_name, (void *)id); + silc_sftp_server_name, SILC_32_TO_PTR(id)); } break; @@ -732,7 +750,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Stat operation */ server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path, - silc_sftp_server_attr, (void *)id); + silc_sftp_server_attr, SILC_32_TO_PTR(id)); silc_free(path); } @@ -758,7 +776,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Lstat operation */ server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path, - silc_sftp_server_attr, (void *)id); + silc_sftp_server_attr, SILC_32_TO_PTR(id)); silc_free(path); } @@ -767,13 +785,13 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, case SILC_SFTP_FSTAT: { unsigned char *hdata; - uint32 hdata_len; + SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Fstat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&hdata, + SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_END); if (ret < 0) @@ -796,14 +814,14 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Fstat operation */ server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle, - silc_sftp_server_attr, (void *)id); + silc_sftp_server_attr, SILC_32_TO_PTR(id)); } break; case SILC_SFTP_SETSTAT: { unsigned char *attr_buf; - uint32 attr_len = 0; + SilcUInt32 attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Setstat request")); @@ -820,8 +838,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); + if (!attrs) + goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); + if (!attrs) + goto failure; } /* Call monitor */ @@ -833,7 +855,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Setstat operation */ server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_sftp_attr_free(attrs); silc_free(path); @@ -843,14 +865,14 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, case SILC_SFTP_FSETSTAT: { unsigned char *hdata, *attr_buf; - uint32 hdata_len, attr_len = 0; + SilcUInt32 hdata_len, attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Fsetstat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&hdata, + SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_UI32_NSTRING(&attr_buf, &attr_len), @@ -861,8 +883,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); + if (!attrs) + goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); + if (!attrs) + goto failure; } /* Get the handle */ @@ -881,9 +907,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, } /* Fsetstat operation */ - server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp, + server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp, handle, attrs, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, + SILC_32_TO_PTR(id)); silc_sftp_attr_free(attrs); } @@ -909,7 +936,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Readlink operation */ server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path, - silc_sftp_server_name, (void *)id); + silc_sftp_server_name, SILC_32_TO_PTR(id)); silc_free(path); } @@ -939,7 +966,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Symlink operation */ server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target, - silc_sftp_server_status, (void *)id); + silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(path); silc_free(target); @@ -966,7 +993,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, /* Realpath operation */ server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path, - silc_sftp_server_name, (void *)id); + silc_sftp_server_name, SILC_32_TO_PTR(id)); silc_free(path); } @@ -976,7 +1003,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, { char *request = NULL; unsigned char *data; - uint32 data_len; + SilcUInt32 data_len; SILC_LOG_DEBUG(("Extended request")); @@ -1003,9 +1030,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, } /* Extended operation */ - server->fs->fs->sftp_extended(server->fs->fs_context, sftp, + server->fs->fs->sftp_extended(server->fs->fs_context, sftp, request, data, data_len, - silc_sftp_server_extended, (void *)id); + silc_sftp_server_extended, + SILC_32_TO_PTR(id)); silc_free(request); }