Added SILC Server library.
[silc.git] / lib / silcsftp / sftp_server.c
index f3bda1d64642d4dcdf1f100be04b07b6272efc4e..de0b52ef9d7eaade18f4a1ac0b4418af93a4d1f6 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_server.c 
+  sftp_server.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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
 */
 /* $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;
@@ -38,7 +37,7 @@ typedef struct {
 /* General routine to send SFTP packet to the SFTP client. */
 
 static void silc_sftp_send_packet(SilcSFTPServer sftp,
-                                 SilcSFTPPacket type, 
+                                 SilcSFTPPacket type,
                                  SilcUInt32 len, ...)
 {
   SilcBuffer tmp;
@@ -51,11 +50,11 @@ static void silc_sftp_send_packet(SilcSFTPServer sftp,
     return;
   sftp->packet = tmp;
 
-  SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data, 
+  SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data,
                   sftp->packet->len);
 
   /* Send the packet */
-  (*sftp->send_packet)(sftp->sock, sftp->packet, sftp->send_context);
+  (*sftp->send_packet)(sftp->packet, sftp->send_context);
 
   /* Clear packet */
   sftp->packet->data = sftp->packet->tail = sftp->packet->head;
@@ -87,12 +86,12 @@ static void silc_sftp_server_status(SilcSFTP sftp,
                                    void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)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)
@@ -118,7 +117,7 @@ static void silc_sftp_server_handle(SilcSFTP sftp,
                                    void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   unsigned char *hdata;
   SilcUInt32 hdata_len;
 
@@ -153,7 +152,7 @@ static void silc_sftp_server_data(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
 
   SILC_LOG_DEBUG(("Data callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -178,7 +177,7 @@ static void silc_sftp_server_name(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   SilcBuffer namebuf;
 
   SILC_LOG_DEBUG(("Name callback"));
@@ -209,7 +208,7 @@ static void silc_sftp_server_attr(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   SilcBuffer attr_buf;
 
   SILC_LOG_DEBUG(("Attr callback"));
@@ -221,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),
@@ -239,7 +242,7 @@ static void silc_sftp_server_extended(SilcSFTP sftp,
                                      void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
 
   SILC_LOG_DEBUG(("Extended callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -255,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;
@@ -298,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;
@@ -330,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;
@@ -378,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)
@@ -387,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 */
@@ -401,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);
@@ -417,7 +424,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       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)
@@ -440,7 +447,8 @@ 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;
 
@@ -455,7 +463,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       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),
@@ -472,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;
@@ -479,11 +492,6 @@ 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;
 
@@ -499,10 +507,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       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)
@@ -517,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;
@@ -524,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;
 
@@ -552,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);
     }
@@ -581,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);
@@ -610,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 */
@@ -623,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);
@@ -650,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);
     }
@@ -676,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);
     }
@@ -691,7 +703,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       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)
@@ -714,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;
 
@@ -738,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);
     }
@@ -764,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);
     }
@@ -779,7 +791,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       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)
@@ -802,7 +814,7 @@ 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;
 
@@ -826,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 */
@@ -839,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);
@@ -856,7 +872,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       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),
@@ -867,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 */
@@ -887,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);
     }
@@ -915,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);
     }
@@ -945,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);
@@ -972,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);
     }
@@ -1009,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);
     }