[BACK]Return to sftp-server.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/sftp-server.c between version 1.6 and 1.6.2.2

version 1.6, 2000/09/07 20:27:53 version 1.6.2.2, 2001/02/19 17:19:24
Line 24 
Line 24 
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include "ssh.h"  
 #include "buffer.h"  #include "buffer.h"
 #include "bufaux.h"  #include "bufaux.h"
 #include "getput.h"  #include "getput.h"
   #include "log.h"
 #include "xmalloc.h"  #include "xmalloc.h"
   
 /* version */  #include "sftp.h"
 #define SSH_FILEXFER_VERSION            2  #include "sftp-common.h"
   
 /* client to server */  
 #define SSH_FXP_INIT                    1  
 #define SSH_FXP_OPEN                    3  
 #define SSH_FXP_CLOSE                   4  
 #define SSH_FXP_READ                    5  
 #define SSH_FXP_WRITE                   6  
 #define SSH_FXP_LSTAT                   7  
 #define SSH_FXP_FSTAT                   8  
 #define SSH_FXP_SETSTAT                 9  
 #define SSH_FXP_FSETSTAT                10  
 #define SSH_FXP_OPENDIR                 11  
 #define SSH_FXP_READDIR                 12  
 #define SSH_FXP_REMOVE                  13  
 #define SSH_FXP_MKDIR                   14  
 #define SSH_FXP_RMDIR                   15  
 #define SSH_FXP_REALPATH                16  
 #define SSH_FXP_STAT                    17  
 #define SSH_FXP_RENAME                  18  
   
 /* server to client */  
 #define SSH_FXP_VERSION                 2  
 #define SSH_FXP_STATUS                  101  
 #define SSH_FXP_HANDLE                  102  
 #define SSH_FXP_DATA                    103  
 #define SSH_FXP_NAME                    104  
 #define SSH_FXP_ATTRS                   105  
   
 /* portable open modes */  
 #define SSH_FXF_READ                    0x01  
 #define SSH_FXF_WRITE                   0x02  
 #define SSH_FXF_APPEND                  0x04  
 #define SSH_FXF_CREAT                   0x08  
 #define SSH_FXF_TRUNC                   0x10  
 #define SSH_FXF_EXCL                    0x20  
   
 /* attributes */  
 #define SSH_FXA_HAVE_SIZE               0x01  
 #define SSH_FXA_HAVE_UGID               0x02  
 #define SSH_FXA_HAVE_PERM               0x04  
 #define SSH_FXA_HAVE_TIME               0x08  
   
 /* status messages */  
 #define SSH_FX_OK                       0x00  
 #define SSH_FX_EOF                      0x01  
 #define SSH_FX_NO_SUCH_FILE             0x02  
 #define SSH_FX_PERMISSION_DENIED        0x03  
 #define SSH_FX_FAILURE                  0x04  
 #define SSH_FX_BAD_MESSAGE              0x05  
 #define SSH_FX_NO_CONNECTION            0x06  
 #define SSH_FX_CONNECTION_LOST          0x07  
   
   
 /* helper */  /* helper */
   #define get_int64()                     buffer_get_int64(&iqueue);
 #define get_int()                       buffer_get_int(&iqueue);  #define get_int()                       buffer_get_int(&iqueue);
 #define get_string(lenp)                buffer_get_string(&iqueue, lenp);  #define get_string(lenp)                buffer_get_string(&iqueue, lenp);
 #define TRACE                           log  #define TRACE                           debug
   
 /* input and output queue */  /* input and output queue */
 Buffer iqueue;  Buffer iqueue;
Line 96 
Line 45 
   
 /* portable attibutes, etc. */  /* portable attibutes, etc. */
   
 typedef struct Attrib Attrib;  
 typedef struct Stat Stat;  typedef struct Stat Stat;
   
 struct Attrib  struct Stat {
 {  
         u_int32_t       flags;  
         u_int32_t       size_high;  
         u_int32_t       size_low;  
         u_int64_t       size;  
         u_int32_t       uid;  
         u_int32_t       gid;  
         u_int32_t       perm;  
         u_int32_t       atime;  
         u_int32_t       mtime;  
 };  
   
 struct Stat  
 {  
         char *name;          char *name;
         char *long_name;          char *long_name;
         Attrib attrib;          Attrib attrib;
Line 125 
Line 59 
         int ret = 0;          int ret = 0;
         switch (unixerrno) {          switch (unixerrno) {
         case 0:          case 0:
                 ret = SSH_FX_OK;                  ret = SSH2_FX_OK;
                 break;                  break;
         case ENOENT:          case ENOENT:
         case ENOTDIR:          case ENOTDIR:
         case EBADF:          case EBADF:
         case ELOOP:          case ELOOP:
                 ret = SSH_FX_NO_SUCH_FILE;                  ret = SSH2_FX_NO_SUCH_FILE;
                 break;                  break;
         case EPERM:          case EPERM:
         case EACCES:          case EACCES:
         case EFAULT:          case EFAULT:
                 ret = SSH_FX_PERMISSION_DENIED;                  ret = SSH2_FX_PERMISSION_DENIED;
                 break;                  break;
         case ENAMETOOLONG:          case ENAMETOOLONG:
         case EINVAL:          case EINVAL:
                 ret = SSH_FX_BAD_MESSAGE;                  ret = SSH2_FX_BAD_MESSAGE;
                 break;                  break;
         default:          default:
                 ret = SSH_FX_FAILURE;                  ret = SSH2_FX_FAILURE;
                 break;                  break;
         }          }
         return ret;          return ret;
Line 153 
Line 87 
 flags_from_portable(int pflags)  flags_from_portable(int pflags)
 {  {
         int flags = 0;          int flags = 0;
         if (pflags & SSH_FXF_READ &&          if (pflags & SSH2_FXF_READ &&
             pflags & SSH_FXF_WRITE) {              pflags & SSH2_FXF_WRITE) {
                 flags = O_RDWR;                  flags = O_RDWR;
         } else if (pflags & SSH_FXF_READ) {          } else if (pflags & SSH2_FXF_READ) {
                 flags = O_RDONLY;                  flags = O_RDONLY;
         } else if (pflags & SSH_FXF_WRITE) {          } else if (pflags & SSH2_FXF_WRITE) {
                 flags = O_WRONLY;                  flags = O_WRONLY;
         }          }
         if (pflags & SSH_FXF_CREAT)          if (pflags & SSH2_FXF_CREAT)
                 flags |= O_CREAT;                  flags |= O_CREAT;
         if (pflags & SSH_FXF_TRUNC)          if (pflags & SSH2_FXF_TRUNC)
                 flags |= O_TRUNC;                  flags |= O_TRUNC;
         if (pflags & SSH_FXF_EXCL)          if (pflags & SSH2_FXF_EXCL)
                 flags |= O_EXCL;                  flags |= O_EXCL;
         return flags;          return flags;
 }  }
   
 void  
 attrib_clear(Attrib *a)  
 {  
         a->flags = 0;  
         a->size_low = 0;  
         a->size_high = 0;  
         a->size = 0;  
         a->uid = 0;  
         a->gid = 0;  
         a->perm = 0;  
         a->atime = 0;  
         a->mtime = 0;  
 }  
   
 Attrib *  Attrib *
 decode_attrib(Buffer *b)  
 {  
         static Attrib a;  
         attrib_clear(&a);  
         a.flags = buffer_get_int(b);  
         if (a.flags & SSH_FXA_HAVE_SIZE) {  
                 a.size_high = buffer_get_int(b);  
                 a.size_low = buffer_get_int(b);  
                 a.size = (((u_int64_t) a.size_high) << 32) + a.size_low;  
         }  
         if (a.flags & SSH_FXA_HAVE_UGID) {  
                 a.uid = buffer_get_int(b);  
                 a.gid = buffer_get_int(b);  
         }  
         if (a.flags & SSH_FXA_HAVE_PERM) {  
                 a.perm = buffer_get_int(b);  
         }  
         if (a.flags & SSH_FXA_HAVE_TIME) {  
                 a.atime = buffer_get_int(b);  
                 a.mtime = buffer_get_int(b);  
         }  
         return &a;  
 }  
   
 void  
 encode_attrib(Buffer *b, Attrib *a)  
 {  
         buffer_put_int(b, a->flags);  
         if (a->flags & SSH_FXA_HAVE_SIZE) {  
                 buffer_put_int(b, a->size_high);  
                 buffer_put_int(b, a->size_low);  
         }  
         if (a->flags & SSH_FXA_HAVE_UGID) {  
                 buffer_put_int(b, a->uid);  
                 buffer_put_int(b, a->gid);  
         }  
         if (a->flags & SSH_FXA_HAVE_PERM) {  
                 buffer_put_int(b, a->perm);  
         }  
         if (a->flags & SSH_FXA_HAVE_TIME) {  
                 buffer_put_int(b, a->atime);  
                 buffer_put_int(b, a->mtime);  
         }  
 }  
   
 Attrib *  
 stat_to_attrib(struct stat *st)  
 {  
         static Attrib a;  
         attrib_clear(&a);  
         a.flags = 0;  
         a.flags |= SSH_FXA_HAVE_SIZE;  
         a.size = st->st_size;  
         a.size_low = a.size;  
         a.size_high = (u_int32_t) (a.size >> 32);  
         a.flags |= SSH_FXA_HAVE_UGID;  
         a.uid = st->st_uid;  
         a.gid = st->st_gid;  
         a.flags |= SSH_FXA_HAVE_PERM;  
         a.perm = st->st_mode;  
         a.flags |= SSH_FXA_HAVE_TIME;  
         a.atime = st->st_atime;  
         a.mtime = st->st_mtime;  
         return &a;  
 }  
   
 Attrib *  
 get_attrib(void)  get_attrib(void)
 {  {
         return decode_attrib(&iqueue);          return decode_attrib(&iqueue);
Line 300 
Line 153 
 int  int
 handle_is_ok(int i, int type)  handle_is_ok(int i, int type)
 {  {
         return i >= 0 && i < sizeof(handles)/sizeof(Handle) && handles[i].use == type;          return i >= 0 && i < sizeof(handles)/sizeof(Handle) &&
               handles[i].use == type;
 }  }
   
 int  int
 handle_to_string(int handle, char **stringp, int *hlenp)  handle_to_string(int handle, char **stringp, int *hlenp)
 {  {
         char buf[1024];  
         if (stringp == NULL || hlenp == NULL)          if (stringp == NULL || hlenp == NULL)
                 return -1;                  return -1;
         snprintf(buf, sizeof buf, "%d", handle);          *stringp = xmalloc(sizeof(int32_t));
         *stringp = xstrdup(buf);          PUT_32BIT(*stringp, handle);
         *hlenp = strlen(*stringp);          *hlenp = sizeof(int32_t);
         return 0;          return 0;
 }  }
   
 int  int
 handle_from_string(char *handle, u_int hlen)  handle_from_string(char *handle, u_int hlen)
 {  {
 /* XXX OVERFLOW ? */          int val;
         char *ep;          if (hlen != sizeof(int32_t))
         long lval = strtol(handle, &ep, 10);  
         int val = lval;  
         if (*ep != '\0')  
                 return -1;                  return -1;
           val = GET_32BIT(handle);
         if (handle_is_ok(val, HANDLE_FILE) ||          if (handle_is_ok(val, HANDLE_FILE) ||
             handle_is_ok(val, HANDLE_DIR))              handle_is_ok(val, HANDLE_DIR))
                 return val;                  return val;
Line 350 
Line 201 
 int  int
 handle_to_fd(int handle)  handle_to_fd(int handle)
 {  {
         if (handle_is_ok(handle, HANDLE_FILE))          if (handle_is_ok(handle, HANDLE_FILE))
                 return handles[handle].fd;                  return handles[handle].fd;
         return -1;          return -1;
 }  }
Line 375 
Line 226 
 get_handle(void)  get_handle(void)
 {  {
         char *handle;          char *handle;
         int val;          int val = -1;
         u_int hlen;          u_int hlen;
         handle = get_string(&hlen);          handle = get_string(&hlen);
         val = handle_from_string(handle, hlen);          if (hlen < 256)
                   val = handle_from_string(handle, hlen);
         xfree(handle);          xfree(handle);
         return val;          return val;
 }  }
Line 400 
Line 252 
         Buffer msg;          Buffer msg;
         TRACE("sent status id %d error %d", id, error);          TRACE("sent status id %d error %d", id, error);
         buffer_init(&msg);          buffer_init(&msg);
         buffer_put_char(&msg, SSH_FXP_STATUS);          buffer_put_char(&msg, SSH2_FXP_STATUS);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_int(&msg, error);          buffer_put_int(&msg, error);
         send_msg(&msg);          send_msg(&msg);
Line 422 
Line 274 
 send_data(u_int32_t id, char *data, int dlen)  send_data(u_int32_t id, char *data, int dlen)
 {  {
         TRACE("sent data id %d len %d", id, dlen);          TRACE("sent data id %d len %d", id, dlen);
         send_data_or_handle(SSH_FXP_DATA, id, data, dlen);          send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
 }  }
   
 void  void
Line 432 
Line 284 
         int hlen;          int hlen;
         handle_to_string(handle, &string, &hlen);          handle_to_string(handle, &string, &hlen);
         TRACE("sent handle id %d handle %d", id, handle);          TRACE("sent handle id %d handle %d", id, handle);
         send_data_or_handle(SSH_FXP_HANDLE, id, string, hlen);          send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
         xfree(string);          xfree(string);
 }  }
   
Line 442 
Line 294 
         Buffer msg;          Buffer msg;
         int i;          int i;
         buffer_init(&msg);          buffer_init(&msg);
         buffer_put_char(&msg, SSH_FXP_NAME);          buffer_put_char(&msg, SSH2_FXP_NAME);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_int(&msg, count);          buffer_put_int(&msg, count);
         TRACE("sent names id %d count %d", id, count);          TRACE("sent names id %d count %d", id, count);
Line 461 
Line 313 
         Buffer msg;          Buffer msg;
         TRACE("sent attrib id %d have 0x%x", id, a->flags);          TRACE("sent attrib id %d have 0x%x", id, a->flags);
         buffer_init(&msg);          buffer_init(&msg);
         buffer_put_char(&msg, SSH_FXP_ATTRS);          buffer_put_char(&msg, SSH2_FXP_ATTRS);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         encode_attrib(&msg, a);          encode_attrib(&msg, a);
         send_msg(&msg);          send_msg(&msg);
Line 478 
Line 330 
   
         TRACE("client version %d", version);          TRACE("client version %d", version);
         buffer_init(&msg);          buffer_init(&msg);
         buffer_put_char(&msg, SSH_FXP_VERSION);          buffer_put_char(&msg, SSH2_FXP_VERSION);
         buffer_put_int(&msg, SSH_FILEXFER_VERSION);          buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
         send_msg(&msg);          send_msg(&msg);
         buffer_free(&msg);          buffer_free(&msg);
 }  }
Line 490 
Line 342 
         u_int32_t id, pflags;          u_int32_t id, pflags;
         Attrib *a;          Attrib *a;
         char *name;          char *name;
         int handle, fd, flags, mode, status = SSH_FX_FAILURE;          int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
   
         id = get_int();          id = get_int();
         name = get_string(NULL);          name = get_string(NULL);
         pflags = get_int();          pflags = get_int();             /* portable flags */
         a = get_attrib();          a = get_attrib();
         flags = flags_from_portable(pflags);          flags = flags_from_portable(pflags);
         mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm : 0666;          mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
         TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode);          TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode);
         fd = open(name, flags, mode);          fd = open(name, flags, mode);
         if (fd < 0) {          if (fd < 0) {
Line 508 
Line 360 
                         close(fd);                          close(fd);
                 } else {                  } else {
                         send_handle(id, handle);                          send_handle(id, handle);
                         status = SSH_FX_OK;                          status = SSH2_FX_OK;
                 }                  }
         }          }
         if (status != SSH_FX_OK)          if (status != SSH2_FX_OK)
                 send_status(id, status);                  send_status(id, status);
         xfree(name);          xfree(name);
 }  }
Line 520 
Line 372 
 process_close(void)  process_close(void)
 {  {
         u_int32_t id;          u_int32_t id;
         int handle, ret, status = SSH_FX_FAILURE;          int handle, ret, status = SSH2_FX_FAILURE;
   
         id = get_int();          id = get_int();
         handle = get_handle();          handle = get_handle();
         TRACE("close id %d handle %d", id, handle);          TRACE("close id %d handle %d", id, handle);
         ret = handle_close(handle);          ret = handle_close(handle);
         status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK;          status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
         send_status(id, status);          send_status(id, status);
 }  }
   
Line 534 
Line 386 
 process_read(void)  process_read(void)
 {  {
         char buf[64*1024];          char buf[64*1024];
         u_int32_t id, off_high, off_low, len;          u_int32_t id, len;
         int handle, fd, ret, status = SSH_FX_FAILURE;          int handle, fd, ret, status = SSH2_FX_FAILURE;
         u_int64_t off;          u_int64_t off;
   
         id = get_int();          id = get_int();
         handle = get_handle();          handle = get_handle();
         off_high = get_int();          off = get_int64();
         off_low = get_int();  
         len = get_int();          len = get_int();
   
         off = (((u_int64_t) off_high) << 32) + off_low;          TRACE("read id %d handle %d off %llu len %d", id, handle,
         TRACE("read id %d handle %d off %qd len %d", id, handle, off, len);              (unsigned long long)off, len);
         if (len > sizeof buf) {          if (len > sizeof buf) {
                 len = sizeof buf;                  len = sizeof buf;
                 log("read change len %d", len);                  log("read change len %d", len);
Line 560 
Line 411 
                         if (ret < 0) {                          if (ret < 0) {
                                 status = errno_to_portable(errno);                                  status = errno_to_portable(errno);
                         } else if (ret == 0) {                          } else if (ret == 0) {
                                 status = SSH_FX_EOF;                                  status = SSH2_FX_EOF;
                         } else {                          } else {
                                 send_data(id, buf, ret);                                  send_data(id, buf, ret);
                                 status = SSH_FX_OK;                                  status = SSH2_FX_OK;
                         }                          }
                 }                  }
         }          }
         if (status != SSH_FX_OK)          if (status != SSH2_FX_OK)
                 send_status(id, status);                  send_status(id, status);
 }  }
   
 void  void
 process_write(void)  process_write(void)
 {  {
         u_int32_t id, off_high, off_low;          u_int32_t id;
         u_int64_t off;          u_int64_t off;
         u_int len;          u_int len;
         int handle, fd, ret, status = SSH_FX_FAILURE;          int handle, fd, ret, status = SSH2_FX_FAILURE;
         char *data;          char *data;
   
         id = get_int();          id = get_int();
         handle = get_handle();          handle = get_handle();
         off_high = get_int();          off = get_int64();
         off_low = get_int();  
         data = get_string(&len);          data = get_string(&len);
   
         off = (((u_int64_t) off_high) << 32) + off_low;          TRACE("write id %d handle %d off %llu len %d", id, handle,
         TRACE("write id %d handle %d off %qd len %d", id, handle, off, len);              (unsigned long long)off, len);
         fd = handle_to_fd(handle);          fd = handle_to_fd(handle);
         if (fd >= 0) {          if (fd >= 0) {
                 if (lseek(fd, off, SEEK_SET) < 0) {                  if (lseek(fd, off, SEEK_SET) < 0) {
Line 600 
Line 450 
                                 error("process_write: write failed");                                  error("process_write: write failed");
                                 status = errno_to_portable(errno);                                  status = errno_to_portable(errno);
                         } else if (ret == len) {                          } else if (ret == len) {
                                 status = SSH_FX_OK;                                  status = SSH2_FX_OK;
                         } else {                          } else {
                                 log("nothing at all written");                                  log("nothing at all written");
                         }                          }
Line 613 
Line 463 
 void  void
 process_do_stat(int do_lstat)  process_do_stat(int do_lstat)
 {  {
         Attrib *a;          Attrib a;
         struct stat st;          struct stat st;
         u_int32_t id;          u_int32_t id;
         char *name;          char *name;
         int ret, status = SSH_FX_FAILURE;          int ret, status = SSH2_FX_FAILURE;
   
         id = get_int();          id = get_int();
         name = get_string(NULL);          name = get_string(NULL);
Line 626 
Line 476 
         if (ret < 0) {          if (ret < 0) {
                 status = errno_to_portable(errno);                  status = errno_to_portable(errno);
         } else {          } else {
                 a = stat_to_attrib(&st);                  stat_to_attrib(&st, &a);
                 send_attrib(id, a);                  send_attrib(id, &a);
                 status = SSH_FX_OK;                  status = SSH2_FX_OK;
         }          }
         if (status != SSH_FX_OK)          if (status != SSH2_FX_OK)
                 send_status(id, status);                  send_status(id, status);
         xfree(name);          xfree(name);
 }  }
Line 650 
Line 500 
 void  void
 process_fstat(void)  process_fstat(void)
 {  {
         Attrib *a;          Attrib a;
         struct stat st;          struct stat st;
         u_int32_t id;          u_int32_t id;
         int fd, ret, handle, status = SSH_FX_FAILURE;          int fd, ret, handle, status = SSH2_FX_FAILURE;
   
         id = get_int();          id = get_int();
         handle = get_handle();          handle = get_handle();
Line 664 
Line 514 
                 if (ret < 0) {                  if (ret < 0) {
                         status = errno_to_portable(errno);                          status = errno_to_portable(errno);
                 } else {                  } else {
                         a = stat_to_attrib(&st);                          stat_to_attrib(&st, &a);
                         send_attrib(id, a);                          send_attrib(id, &a);
                         status = SSH_FX_OK;                          status = SSH2_FX_OK;
                 }                  }
         }          }
         if (status != SSH_FX_OK)          if (status != SSH2_FX_OK)
                 send_status(id, status);                  send_status(id, status);
 }  }
   
Line 691 
Line 541 
         u_int32_t id;          u_int32_t id;
         char *name;          char *name;
         int ret;          int ret;
         int status = SSH_FX_OK;          int status = SSH2_FX_OK;
   
         id = get_int();          id = get_int();
         name = get_string(NULL);          name = get_string(NULL);
         a = get_attrib();          a = get_attrib();
         TRACE("setstat id %d name %s", id, name);          TRACE("setstat id %d name %s", id, name);
         if (a->flags & SSH_FXA_HAVE_PERM) {          if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
                 ret = chmod(name, a->perm & 0777);                  ret = chmod(name, a->perm & 0777);
                 if (ret == -1)                  if (ret == -1)
                         status = errno_to_portable(errno);                          status = errno_to_portable(errno);
         }          }
         if (a->flags & SSH_FXA_HAVE_TIME) {          if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
                 ret = utimes(name, attrib_to_tv(a));                  ret = utimes(name, attrib_to_tv(a));
                 if (ret == -1)                  if (ret == -1)
                         status = errno_to_portable(errno);                          status = errno_to_portable(errno);
         }          }
           if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
                   ret = chown(name, a->uid, a->gid);
                   if (ret == -1)
                           status = errno_to_portable(errno);
           }
         send_status(id, status);          send_status(id, status);
         xfree(name);          xfree(name);
 }  }
Line 717 
Line 572 
         Attrib *a;          Attrib *a;
         u_int32_t id;          u_int32_t id;
         int handle, fd, ret;          int handle, fd, ret;
         int status = SSH_FX_OK;          int status = SSH2_FX_OK;
   
         id = get_int();          id = get_int();
         handle = get_handle();          handle = get_handle();
Line 725 
Line 580 
         TRACE("fsetstat id %d handle %d", id, handle);          TRACE("fsetstat id %d handle %d", id, handle);
         fd = handle_to_fd(handle);          fd = handle_to_fd(handle);
         if (fd < 0) {          if (fd < 0) {
                 status = SSH_FX_FAILURE;                  status = SSH2_FX_FAILURE;
         } else {          } else {
                 if (a->flags & SSH_FXA_HAVE_PERM) {                  if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
                         ret = fchmod(fd, a->perm & 0777);                          ret = fchmod(fd, a->perm & 0777);
                         if (ret == -1)                          if (ret == -1)
                                 status = errno_to_portable(errno);                                  status = errno_to_portable(errno);
                 }                  }
                 if (a->flags & SSH_FXA_HAVE_TIME) {                  if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
                         ret = futimes(fd, attrib_to_tv(a));                          ret = futimes(fd, attrib_to_tv(a));
                         if (ret == -1)                          if (ret == -1)
                                 status = errno_to_portable(errno);                                  status = errno_to_portable(errno);
                 }                  }
                   if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
                           ret = fchown(fd, a->uid, a->gid);
                           if (ret == -1)
                                   status = errno_to_portable(errno);
                   }
         }          }
         send_status(id, status);          send_status(id, status);
 }  }
Line 746 
Line 606 
 {  {
         DIR *dirp = NULL;          DIR *dirp = NULL;
         char *path;          char *path;
         int handle, status = SSH_FX_FAILURE;          int handle, status = SSH2_FX_FAILURE;
         u_int32_t id;          u_int32_t id;
   
         id = get_int();          id = get_int();
         path = get_string(NULL);          path = get_string(NULL);
         TRACE("opendir id %d path %s", id, path);          TRACE("opendir id %d path %s", id, path);
         dirp = opendir(path);          dirp = opendir(path);
         if (dirp == NULL) {          if (dirp == NULL) {
                 status = errno_to_portable(errno);                  status = errno_to_portable(errno);
         } else {          } else {
Line 761 
Line 621 
                         closedir(dirp);                          closedir(dirp);
                 } else {                  } else {
                         send_handle(id, handle);                          send_handle(id, handle);
                         status = SSH_FX_OK;                          status = SSH2_FX_OK;
                 }                  }
   
         }          }
         if (status != SSH_FX_OK)          if (status != SSH2_FX_OK)
                 send_status(id, status);                  send_status(id, status);
         xfree(path);          xfree(path);
 }  }
   
   /*
    * drwxr-xr-x    5 markus   markus       1024 Jan 13 18:39 .ssh
    */
 char *  char *
 ls_file(char *name, struct stat *st)  ls_file(char *name, struct stat *st)
 {  {
         char buf[1024];          int sz = 0;
         snprintf(buf, sizeof buf, "0%o %d %d %qd %d %s",          struct passwd *pw;
             st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size,(int) st->st_mtime,          struct group *gr;
             name);          struct tm *ltime = localtime(&st->st_mtime);
           char *user, *group;
           char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
   
           strmode(st->st_mode, mode);
           if ((pw = getpwuid(st->st_uid)) != NULL) {
                   user = pw->pw_name;
           } else {
                   snprintf(ubuf, sizeof ubuf, "%d", st->st_uid);
                   user = ubuf;
           }
           if ((gr = getgrgid(st->st_gid)) != NULL) {
                   group = gr->gr_name;
           } else {
                   snprintf(gbuf, sizeof gbuf, "%d", st->st_gid);
                   group = gbuf;
           }
           if (ltime != NULL) {
                   if (time(NULL) - st->st_mtime < (365*24*60*60)/2)
                           sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
                   else
                           sz = strftime(tbuf, sizeof tbuf, "%b %e  %Y", ltime);
           }
           if (sz == 0)
                   tbuf[0] = '\0';
           snprintf(buf, sizeof buf, "%s %3d %-8.8s %-8.8s %8llu %s %s", mode,
               st->st_nlink, user, group, (unsigned long long)st->st_size, tbuf, name);
         return xstrdup(buf);          return xstrdup(buf);
 }  }
   
Line 795 
Line 684 
         dirp = handle_to_dir(handle);          dirp = handle_to_dir(handle);
         path = handle_to_name(handle);          path = handle_to_name(handle);
         if (dirp == NULL || path == NULL) {          if (dirp == NULL || path == NULL) {
                 send_status(id, SSH_FX_FAILURE);                  send_status(id, SSH2_FX_FAILURE);
         } else {          } else {
                 Attrib *a;  
                 struct stat st;                  struct stat st;
                 char pathname[1024];                  char pathname[1024];
                 Stat *stats;                  Stat *stats;
Line 813 
Line 701 
                             "%s/%s", path, dp->d_name);                              "%s/%s", path, dp->d_name);
                         if (lstat(pathname, &st) < 0)                          if (lstat(pathname, &st) < 0)
                                 continue;                                  continue;
                         a = stat_to_attrib(&st);                          stat_to_attrib(&st, &(stats[count].attrib));
                         stats[count].attrib = *a;  
                         stats[count].name = xstrdup(dp->d_name);                          stats[count].name = xstrdup(dp->d_name);
                         stats[count].long_name = ls_file(dp->d_name, &st);                          stats[count].long_name = ls_file(dp->d_name, &st);
                         count++;                          count++;
                         /* send up to 100 entries in one message */                          /* send up to 100 entries in one message */
                           /* XXX check packet size instead */
                         if (count == 100)                          if (count == 100)
                                 break;                                  break;
                 }                  }
                 send_names(id, count, stats);                  if (count > 0) {
                 for(i = 0; i < count; i++) {                          send_names(id, count, stats);
                         xfree(stats[i].name);                          for(i = 0; i < count; i++) {
                         xfree(stats[i].long_name);                                  xfree(stats[i].name);
                                   xfree(stats[i].long_name);
                           }
                   } else {
                           send_status(id, SSH2_FX_EOF);
                 }                  }
                 xfree(stats);                  xfree(stats);
         }          }
Line 836 
Line 728 
 {  {
         char *name;          char *name;
         u_int32_t id;          u_int32_t id;
         int status = SSH_FX_FAILURE;          int status = SSH2_FX_FAILURE;
         int ret;          int ret;
   
         id = get_int();          id = get_int();
         name = get_string(NULL);          name = get_string(NULL);
         TRACE("remove id %d name %s", id, name);          TRACE("remove id %d name %s", id, name);
         ret = remove(name);          ret = unlink(name);
         status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK;          status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
         send_status(id, status);          send_status(id, status);
         xfree(name);          xfree(name);
 }  }
Line 854 
Line 746 
         Attrib *a;          Attrib *a;
         u_int32_t id;          u_int32_t id;
         char *name;          char *name;
         int ret, mode, status = SSH_FX_FAILURE;          int ret, mode, status = SSH2_FX_FAILURE;
   
         id = get_int();          id = get_int();
         name = get_string(NULL);          name = get_string(NULL);
         a = get_attrib();          a = get_attrib();
         mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm & 0777 : 0777;          mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
               a->perm & 0777 : 0777;
         TRACE("mkdir id %d name %s mode 0%o", id, name, mode);          TRACE("mkdir id %d name %s mode 0%o", id, name, mode);
         ret = mkdir(name, mode);          ret = mkdir(name, mode);
         status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK;          status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
         send_status(id, status);          send_status(id, status);
         xfree(name);          xfree(name);
 }  }
Line 878 
Line 771 
         name = get_string(NULL);          name = get_string(NULL);
         TRACE("rmdir id %d name %s", id, name);          TRACE("rmdir id %d name %s", id, name);
         ret = rmdir(name);          ret = rmdir(name);
         status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK;          status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
         send_status(id, status);          send_status(id, status);
         xfree(name);          xfree(name);
 }  }
Line 892 
Line 785 
   
         id = get_int();          id = get_int();
         path = get_string(NULL);          path = get_string(NULL);
           if (path[0] == '\0') {
                   xfree(path);
                   path = xstrdup(".");
           }
         TRACE("realpath id %d path %s", id, path);          TRACE("realpath id %d path %s", id, path);
         if (realpath(path, resolvedname) == NULL) {          if (realpath(path, resolvedname) == NULL) {
                 send_status(id, errno_to_portable(errno));                  send_status(id, errno_to_portable(errno));
Line 908 
Line 805 
 process_rename(void)  process_rename(void)
 {  {
         u_int32_t id;          u_int32_t id;
           struct stat st;
         char *oldpath, *newpath;          char *oldpath, *newpath;
         int ret, status;          int ret, status = SSH2_FX_FAILURE;
   
         id = get_int();          id = get_int();
         oldpath = get_string(NULL);          oldpath = get_string(NULL);
         newpath = get_string(NULL);          newpath = get_string(NULL);
         TRACE("rename id %d old %s new %s", id, oldpath, newpath);          TRACE("rename id %d old %s new %s", id, oldpath, newpath);
         ret = rename(oldpath, newpath);          /* fail if 'newpath' exists */
         status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK;          if (stat(newpath, &st) == -1) {
                   ret = rename(oldpath, newpath);
                   status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
           }
         send_status(id, status);          send_status(id, status);
         xfree(oldpath);          xfree(oldpath);
         xfree(newpath);          xfree(newpath);
 }  }
   
   void
   process_extended(void)
   {
           u_int32_t id;
           char *request;
   
           id = get_int();
           request = get_string(NULL);
           send_status(id, SSH2_FX_OP_UNSUPPORTED);                /* MUST */
           xfree(request);
   }
   
 /* stolen from ssh-agent */  /* stolen from ssh-agent */
   
 void  void
 process(void)  process(void)
 {  {
         unsigned int msg_len;          u_int msg_len;
         unsigned int type;          u_int type;
         unsigned char *cp;          u_char *cp;
   
         if (buffer_len(&iqueue) < 5)          if (buffer_len(&iqueue) < 5)
                 return;         /* Incomplete message. */                  return;         /* Incomplete message. */
         cp = (unsigned char *) buffer_ptr(&iqueue);          cp = (u_char *) buffer_ptr(&iqueue);
         msg_len = GET_32BIT(cp);          msg_len = GET_32BIT(cp);
         if (msg_len > 256 * 1024) {          if (msg_len > 256 * 1024) {
                 error("bad message ");                  error("bad message ");
Line 945 
Line 857 
         buffer_consume(&iqueue, 4);          buffer_consume(&iqueue, 4);
         type = buffer_get_char(&iqueue);          type = buffer_get_char(&iqueue);
         switch (type) {          switch (type) {
         case SSH_FXP_INIT:          case SSH2_FXP_INIT:
                 process_init();                  process_init();
                 break;                  break;
         case SSH_FXP_OPEN:          case SSH2_FXP_OPEN:
                 process_open();                  process_open();
                 break;                  break;
         case SSH_FXP_CLOSE:          case SSH2_FXP_CLOSE:
                 process_close();                  process_close();
                 break;                  break;
         case SSH_FXP_READ:          case SSH2_FXP_READ:
                 process_read();                  process_read();
                 break;                  break;
         case SSH_FXP_WRITE:          case SSH2_FXP_WRITE:
                 process_write();                  process_write();
                 break;                  break;
         case SSH_FXP_LSTAT:          case SSH2_FXP_LSTAT:
                 process_lstat();                  process_lstat();
                 break;                  break;
         case SSH_FXP_FSTAT:          case SSH2_FXP_FSTAT:
                 process_fstat();                  process_fstat();
                 break;                  break;
         case SSH_FXP_SETSTAT:          case SSH2_FXP_SETSTAT:
                 process_setstat();                  process_setstat();
                 break;                  break;
         case SSH_FXP_FSETSTAT:          case SSH2_FXP_FSETSTAT:
                 process_fsetstat();                  process_fsetstat();
                 break;                  break;
         case SSH_FXP_OPENDIR:          case SSH2_FXP_OPENDIR:
                 process_opendir();                  process_opendir();
                 break;                  break;
         case SSH_FXP_READDIR:          case SSH2_FXP_READDIR:
                 process_readdir();                  process_readdir();
                 break;                  break;
         case SSH_FXP_REMOVE:          case SSH2_FXP_REMOVE:
                 process_remove();                  process_remove();
                 break;                  break;
         case SSH_FXP_MKDIR:          case SSH2_FXP_MKDIR:
                 process_mkdir();                  process_mkdir();
                 break;                  break;
         case SSH_FXP_RMDIR:          case SSH2_FXP_RMDIR:
                 process_rmdir();                  process_rmdir();
                 break;                  break;
         case SSH_FXP_REALPATH:          case SSH2_FXP_REALPATH:
                 process_realpath();                  process_realpath();
                 break;                  break;
         case SSH_FXP_STAT:          case SSH2_FXP_STAT:
                 process_stat();                  process_stat();
                 break;                  break;
         case SSH_FXP_RENAME:          case SSH2_FXP_RENAME:
                 process_rename();                  process_rename();
                 break;                  break;
           case SSH2_FXP_EXTENDED:
                   process_extended();
                   break;
         default:          default:
                 error("Unknown message %d", type);                  error("Unknown message %d", type);
                 break;                  break;
Line 1010 
Line 925 
         ssize_t len, olen;          ssize_t len, olen;
   
         handle_init();          handle_init();
   
   #ifdef DEBUG_SFTP_SERVER
           log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
   #endif
   
         in = dup(STDIN_FILENO);          in = dup(STDIN_FILENO);
         out = dup(STDOUT_FILENO);          out = dup(STDOUT_FILENO);

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.6.2.2