⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sftpd.cpp

📁 伯克利做的SFTP安全文件传输协议
💻 CPP
📖 第 1 页 / 共 5 页
字号:
          case 'o':            stdoutLogAnyway = true;            break;          case 'd':          // print diagnostics            logLevelMask = (LogLevel)(logLevelMask | LL_DIAGNOSTIC);            if (isdigit(argv[a][2])) {              int d = argv[a][2] - '0';              if (d >= 2) {                logLevelMask = (LogLevel)(logLevelMask | LL_SOCKET_DIAG);              }              if (d >= 3) {                printDataChannel = true;              }            }            break;          case 'a':          // print ADATs            printAdats = true;            break;          case 'l': {        // set log file            FILE *fp = fopen(argString, "a");            if (!fp) {              log(LE_ERROR, "failed to open log file " << argString);              errors = true;              return;            }            else {              if (logFile != stderr) {                fclose(logFile);              }              logFile = fp;              // it's silly to require that people specify -o with -l              stdoutLogAnyway = true;            }            break;          }          case 'm':            logEventMask = (LoggableEvent)              f_ing_strtoul(argv[a]+2, 0 /*auto-radix*/);            break;          case 'x':            if (requireDataEncryption) {     // handle -c before -x              log(LE_ERROR, "-x is incompatible with -c");              errors = true;            }            else {              allowCleartext = true;            }            break;          case '9':            allowRfc959 = false;            allowRfc959_anon = false;            break;          case '8':            // like above, but we do allow dropdown for anon            allowRfc959 = false;            allowRfc959_anon = true;            break;          case 't':            waitForAttach();            break;          case 'y':            if (!changeDirectory(argString)) {              log(LE_ERROR, "failed to chdir to " << argString);              errors = true;            }            break;          case 'K':            kerberosFtpdBinary = argString;            break;          case 'e':            anonExecDropdown = true;            anonFtpdBinary = argString;            break;          case 'i':            // send a different address when authenticating;            // for a server sitting behind an address-translating firewall            fakeIPAddress = resolveHostName(argString);            useFakeIPAddress = true;            break;          case 'c':            requireDataEncryption = true;            // 9/22/00 02:07: tightening-down -c even more: make it            // imply -3, so the direct-to-ftpd route is completely            // closed, and -9 so we never accept unencrypted conns            forceDataRelay = true;            allowRfc959 = false;            allowRfc959_anon = false;            allowCleartext = false;      // in case -c after -x            break;          case 'r':           case 'R': {            // parse low/high            StrtokParse tok(argString, "-");            if (tok != 2) {              log(LE_ERROR, "argument to -" << argv[a][1] <<                            " is malformed");              errors = true;              break;            }            int low = atoi(tok[0]);            int high = atoi(tok[1]);            // may as well sanity-check the values; don't let them            // be 0 because that is atoi's error return            if (!( 1 <= low && low <= 0xFFFF &&                   1 <= high && high <= 0xFFFF &&                   low <= high )) {              log(LE_ERROR, "argument(s) to -" << argv[a][1] <<                            " malformed or out of range [1,65535]");              errors = true;              break;            }            // stash the range in the proper variable            if (argv[a][1] == 'r') {              pasvRange.setRange(low, high);            }            else {              activeRange.setRange(low, high);            }            break;          }          case 'h':            // purpose of defining this is to ensure we reserve            // an option for printing the help text            // (dropthru to next case)          default:            oneError = true;            break;        }      }      if (oneError) {        // "-h" is treated like an error in most respects,        // but shouldn't generate an actual error message        if (!( argv[a][0] == '-' && argv[a][1] == 'h' )) {          // potential problem here: errors in inetd.conf will          // not cause visible error messages...          //fprintf(stderr, "error in argument: %s\n", argv[a]);          // possibly addressed; if the log output file is specified          // early, then the user will see later errors          log(LE_ERROR, "error in argument: " << argv[a]);        }        // cause usage to be printed and program to exit        errors = true;      }    }    // see if we had any trouble before processing command line    if (delayedError) {      xSysError temp(*delayedError);      delete delayedError;     // such a good little soldier!  (Dan was making fun of me for this :) )      THROW(temp);    }    // print usage if any argument errors    if (errors) {      fprintf(stderr,        "usage: sftpd [options]\n"        "  general options:\n"        "    -v             print version\n"        "    -h             print this message\n"        "    -y<directory>  specify directory where keys are (default is cwd)\n"        "  control channel:\n"        "    -s             use stdin as control connection (for use with inetd)\n"        "    -p<N>          listen for incoming connections on port N (default: %d)\n"        "    -p<ADDR>:<N>   listen on interface ADDR (dotted decimal) and port N\n"        "    -f<N>          contact ftpd on port N (default: %d)\n"        "    -f<ADDR>:<N>   contact ftpd at another host (ADDR) and port N;\n"        "                     (this is potentially INSECURE -- see sftpd.html)\n"        "  data channel:\n"        "    -c             require all data transfers to be encrypted\n"        "    -r<low>-<high> restrict ports used for PASV to range [low,high]\n"        "    -R<low>-<high> restrict ports used for PORT to range [low,high]\n"        "  logging:\n"        "    -l<filename>   log to a file instead of stdout or syslog\n"        "    -o             for -s, send log output to stdout instead of syslog\n"        "    -d1            log diagnostic (debugging) messages\n"        "    -d2              .. log even more detailed diagnostic messages\n"        "    -d3              .. and print all data channel traffic to stdout\n"        "    -a             log ADATs\n"        "    -m<mask>       set mask of events to log -- see sftpd.html\n"        "  compatibility:\n"        "    -9             disallow RFC 959 (unencrypted) connections\n"        "    -8             disallow RFC 959 unless the user is anonymous\n"        "    -3             disable 3rd-party transfer optimization\n"        "    -i<address>    use alternate server address for authenication\n"        "    -K<filename>   Kerberos compatibility (specify kftpd image)\n"        "    -e<filename>   Handle anon ftp by exec'ing this ftpd to handle it\n"        //"    -x             allow X-Cleartext and X-Cleartext2 protocols\n"        //"    -t             start and immediately wait for debugger to attach\n"        //"    -Dn            sleep n seconds between data blocks (simulates slow link)\n"        "  for inetd, typical arguments are -s -y/home/safetp -f351\n",        sftpdPort, ftpdPort);      return;    }  }  if (anonExecDropdown && !useStdinStream) {    log(LE_ERROR, "error: can only use the -e switch when run from inetd (-s switch)");      // this is because the exec'd ftpd will expect sockets on stdin and      // stdout, but if we're not run from inetd, then stdin and stdout      // won't even be sockets, let alone the right ones    return;  }  if (ftpdPort == sftpdPort  &&  !ftpdForwardNonlocally) {    log(LE_WARNING, "warning: sftpd may get into an infinite loop; is " <<        ftpdPort << " the right port to contact?  (this warning "        "is triggered by ftpdPort==sftpdPort)");  }  if (useStdinStream) {    // we don't want throwing exceptions to write to stderr because    // that is now connected to the control channel (could redirect    // it, but we probably don't want the exception-thrown records    // in the log file at all at this stage of development)    xBase::logExceptions = false;  }  if (logLevelMask & LL_DIAGNOSTIC) {    // turn on digest echoes    DigestComputer::echoDigestInput = true;  }  // read seed; we wait until now because we don't want to risk  // generating log output until the -s option, if present, has  // been processed  readRandomSeed();  // and now, we want to make sure we will write the updated version,  // to avoid replay potential  RandomSeedSaver seedSaver(this);  // Dan and I both ran into situations where it would have been nice  // for sftpd to report missing keys earlier.. so let's try to do that  if (!sm_testKey("DSA/public.key", true) ||      !sm_testKey("DSA/private.key", true)) {    log(LE_ERROR, "ERROR: at least one of the DSA keys is missing");    // even though in theory there is something useful sftpd can do    // without its keys (namely, test X-CLEARTEXT), that's a very rare    // case; to avoid confusion, bail    return;  }  // ----------- listen for a new connection --------------  if (useStdinStream) {    // we are already connected    client_control = theStdin;      // file descriptor 0 is stdin; note that INVALID_SOCKET is -1,      // so we aren't going to collide with the error value    incOpenSockets();      // since we inherited this socket, rather than opened in directly,      // we have to increment this manually  }  else {    // NOTE: we must run as root here, if sftpdPort is < 1024    // establish a listener on the sftpd port    SOCKET listener = interface_listen_socket(sftpdInterface, sftpdPort);    addEntropy();    // wait for a connection    if (sftpdInterface == INADDR_ANY) {      log(LE_CONTROL_CHANNEL,           "Waiting for connection to sftpd on port " << sftpdPort << "...");    }    else {      log(LE_CONTROL_CHANNEL,           "Waiting for connection to sftpd on interface " <<            formatAddress(sftpdInterface, sftpdPort) << "...");    }    client_control = accept_socket(listener);    addEntropy();    // don't need listener any longer    closeSocket(listener);        // TODO: some people do run sftpd as root; it would be good to    //       drop root privileges here  }  // begin: exceptions should cause a protocol message  try {    // set the default client data transfer port    relayClientAddress = getRemoteAddress(client_control);    relayClientPort = getRemotePort(client_control);    // print connection information    log(LE_CONTROL_CHANNEL, "received connection from host " <<                             formatAddress(relayClientAddress,                                           relayClientPort));    // ----------- connect to ftpd --------------     // it appears that typical ftpd implementations do not allow    // arbitrary PORT command IP addresses when their control    // connection is to localhost (127.0.0.1); therefore, we find out    // which IP address the client connected to, and use that IP when    // connecting to ftpd (unless an alternate has been supplied with    // -f); this is necessary only when data channel protection is    // *off*, because in that situation we let the client's PORT    // commands through unmodified    // decide which address to use for contacting ftpd    if (!ftpdForwardNonlocally) {      // use same interface that client connected to      ftpdAddress = getLocalAddress(client_control);    }    else {      // user has already specified it, and it is stored      // in 'ftpdAddress'    }    // open connection to real ftp server    diagnostic("connecting to ftpd at " <<                formatAddress(ftpdAddress, ftpdPort) << "...");    server_control = connect_socket(ftpdAddress, ftpdPort);    addEntropy();    diagnostic("connected to ftpd");    // display socket info    socket_diagnostic("Control connection to client: " <<                      sockInfo(client_control));    socket_diagnostic("Control connection to ftpd: " <<                      sockInfo(server_control));    // ----------- initial relay --------------    // construct buffering layer on server socket    serverControlStream = new SocketLineReader(server_control);    // annotate initial response from the server    bool readReplyOk = false;    try {      Reply reply(*serverControlStream);      readReplyOk = true;      addEntropy();      reply.append("*** This server can accept secure (encrypted) connections. ***");      reply.append("*** See http://safetp.cs.berkeley.edu for info. ***");      send(reply, client_control);    }    catch (xBase &) {      if (!readReplyOk) {        // the most common cause is the exception reported by reply.cpp about reading        // past the end of the stream, caused by the server accepting the connection        // but immediately closing it without sending a greeting        xfailure("FTP server immediately closed connection; it's probably disabled");      }      else {        // something else; handle normally        throw;      }    }    // new feature: anon dropdown via exec    if (anonExecDropdown) {      possiblyDoAnonExecDropdown(client_control);    }        // only *after* the possible anon dropdown stuff do we    // setup buffering on the client's control channel    clientControlStream = new SocketLineReader(client_control);    // modify session state    state = STATE_UNAUTHENTICATED;  }  catch (xBase &x) {    // report error to user, via protocol stream    unexpected(x);    // the error has been adequately reported; just bail    return;  }  // ----------- main response loop --------------  // enter request-reply loop  for(;;) {    // we'll record which one socket being used, for    // processing during catch-all catch statement

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -