This patch adds a readonly mode to scp and sftp_server. This allows clients to only read files from the server, but not to write them. Patch is based on OpenSSH 3.4p1 *** scp.c@@\main\1 Tue Oct 1 17:25:16 2002 --- scp.c Wed Oct 2 06:05:14 2002 *************** *** 122,127 **** --- 122,130 ---- /* This is set to zero if the progressmeter is not desired. */ int showprogress = 1; + /* deny client write operations */ + int readonly = 0; + /* This is the program to execute for the secured connection. ("ssh" or -S) */ char *ssh_program = _PATH_SSH_PROGRAM; *************** *** 307,312 **** --- 310,319 ---- exit(errs != 0); } if (tflag) { + if (readonly) { + run_err("permission denied"); + exit(1); + } /* Receive data. */ sink(argc, argv); exit(errs != 0); *** sftp-server.c@@\main\1 Tue Oct 1 17:27:26 2002 --- sftp-server.c Tue Nov 5 10:07:54 2002 *************** *** 52,57 **** --- 52,60 ---- /* Version of client */ int version; + /* deny client write operations */ + int readonly = 0; + /* portable attibutes, etc. */ typedef struct Stat Stat; *************** *** 390,395 **** --- 393,404 ---- pflags = get_int(); /* portable flags */ a = get_attrib(); flags = flags_from_portable(pflags); + if (((flags & O_ACCMODE) == O_RDWR) || + ((flags & O_ACCMODE) == O_WRONLY)) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode); fd = open(name, flags, mode); *************** *** 587,592 **** --- 596,606 ---- id = get_int(); name = get_string(NULL); a = get_attrib(); + if (readonly) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } TRACE("setstat id %u name %s", id, name); if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { ret = truncate(name, a->size); *************** *** 802,807 **** --- 816,826 ---- id = get_int(); name = get_string(NULL); + if (readonly) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } TRACE("remove id %u name %s", id, name); ret = unlink(name); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; *************** *** 820,825 **** --- 839,849 ---- id = get_int(); name = get_string(NULL); a = get_attrib(); + if (readonly) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm & 0777 : 0777; TRACE("mkdir id %u name %s mode 0%o", id, name, mode); *************** *** 838,843 **** --- 862,872 ---- id = get_int(); name = get_string(NULL); + if (readonly) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } TRACE("rmdir id %u name %s", id, name); ret = rmdir(name); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; *************** *** 881,886 **** --- 910,920 ---- id = get_int(); oldpath = get_string(NULL); newpath = get_string(NULL); + if (readonly) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } TRACE("rename id %u old %s new %s", id, oldpath, newpath); /* fail if 'newpath' exists */ if (stat(newpath, &st) == -1) { *************** *** 927,932 **** --- 970,980 ---- id = get_int(); oldpath = get_string(NULL); newpath = get_string(NULL); + if (readonly) { + status = SSH2_FX_PERMISSION_DENIED; + send_status(id, status); + return; + } TRACE("symlink id %u old %s new %s", id, oldpath, newpath); /* fail if 'newpath' exists */ if (stat(newpath, &st) == -1) {