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

📄 sftpd.cpp

📁 伯克利做的SFTP安全文件传输协议
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// sftpd.cpp// secure ftp proxy daemon// copyright SafeTP Development Group, Inc., 2000  Terms of use are as specified in license.txt#include "str.h"          // string#include <stdio.h>        // printf#include <string.h>       // strlen#include <stdlib.h>       // atoi#include <ctype.h>        // isdigit, isprint#include <signal.h>       // signal#include <errno.h>        // errno#include "socket.h"       // socket funcs#include "sockutil.h"     // utilities#include "exc.h"          // exceptions#include "breaker.h"      // breaker#include "missing.h"      // missing_stricmp#include "nonport.h"      // portableSleep#include "syserr.h"       // xSysError#include "strtokp.h"      // StrtokParse#include "reply.h"        // Reply#include "request.h"      // Request#include "datablok.h"     // DataBlock#include "provider.h"     // SecurityProvider#include "base64t.h"      // Base64Transform#include "globrand.h"     // {read,save}RandomSeed#include "keyutils.h"     // sm_testKey#include "hcl.h"          // inetdStartupHook#ifdef __UNIX__#  include <syslog.h>     // openlog, syslog#endif#include "sftpver.h"      // SFTP_version#include "sftpd.h"        // this module// defined in sdsa.cc (this introduces a dependency I don't// like, so I'm hesitant to simply include sdsa.h)void knownDSAPublicKeyVersions(int &minimum, int &maximum);// for now, 959 compatibility is critical for deployment#ifndef DEFAULT_ALLOW_RFC959#  define DEFAULT_ALLOW_RFC959 1#endif// it probably doesn't matter whether nonreflexive is// allowed or not; anyway it seems unlikely it could be made// to work on the client side(s), because of the necessary// shared security information#ifndef DEFAULT_ALLOW_NONREFLEXIVE_PORT#  define DEFAULT_ALLOW_NONREFLEXIVE_PORT 1#endif// it seems like a good idea to not let people use this// service to, e.g., send mail via SMTP...#ifndef DEFAULT_ALLOW_RESERVED_PORT#  define DEFAULT_ALLOW_RESERVED_PORT 0#endif// allow diagnostic messages to be compiled away, so even the cost// of producing the log message in memory is eliminated#ifndef ALLOW_DIAGNOSTIC_LOGS#  define ALLOW_DIAGNOSTIC_LOGS 1#endif// convenient forms for calling the log function#define log(event, expr) writeToLog(LL_LOG, event, stringb(expr))#if ALLOW_DIAGNOSTIC_LOGS#  define diagnostic(expr) \     writeToLog(LL_DIAGNOSTIC, LE_DEBUG, stringb(expr))#  define socket_diagnostic(expr) \     writeToLog(LL_SOCKET_DIAG, LE_DEBUG, stringb(expr))#  define diagnosticNoLF(expr) \     writeToLog((LogLevel)(LL_DIAGNOSTIC | LL_NO_LF), LE_DEBUG, stringb(expr))#else#  define diagnostic(expr) ((void)0)#  define socket_diagnostic(expr) ((void)0)#  define diagnosticNoLF(expr) ((void)0)#endif// for debugging (see below)bool attachTrigger;void waitForAttach(){  // wait for debugger to attach and set trigger  attachTrigger = false;  while (!attachTrigger) {    portableSleep(1);    breaker();    // so we just set a bkpoint at usual spot to catch this  }}// --------------------- general stuff -----------------------------// this is used by the warning handler, and obviously its presence// means it isn't thread-safe to make multiple instances of SFTPD...SFTPD *SFTPD::instance = NULL;int main(int argc, char *argv[]){  // having troubles...  //waitForAttach();  // immediately hand off to an SFTPD function so we are  // in its scope  SFTPD sftpd;  sftpd.run(argc, argv);  breaker();     // breakpoint  return 0;}void SFTPD::run(int argc, char *argv[]){  try {#   ifdef __UNIX__      // setup syslog logging      openlog("sftpd", LOG_PID, LOG_DAEMON);#   endif    // capture 'warn' module messages    warningHandler = SFTPD::warnHandler;    // setup nonport error handling    nonportFail = xSysError::xsyserror;    // socket api initialization    socket_lib_init();#   ifdef SIGPIPE      // ignore broken-pipe signals      signal(SIGPIPE, SIG_IGN);#   endif    // run the main code    innerRun(argc, argv);  }  catch (xBase &x) {    breaker();     // breakpoint    log(LE_ERROR, "Exception caught: " << x.why());  }  diagnostic("sftpd exiting, " << numSocketsOpen() << " sockets leaked");   // we used to be saving the random seed here, but now we  // use the RandomSeedSaver helper class}PortRange::PortRange()  : restricted(false),    low(0), high(0){}// there should be an entry here for *every* data member, even// if that member doesn't actually need an initializationSFTPD::SFTPD() :  // ------ socket state ------  useStdinStream(false),  client_control(INVALID_SOCKET),  clientControlStream(NULL),  server_control(INVALID_SOCKET),  serverControlStream(NULL),  client_data(INVALID_SOCKET),  server_data(INVALID_SOCKET),  client_listen(INVALID_SOCKET),  server_listen(INVALID_SOCKET),  // ------ protocol state ------  state(STATE_UNCONNECTED),  relayClientAddress(INADDR_NONE),  relayClientPort(0),  serverPassivePort(NONPASV_PORT),  digt(),  // ------ data channel state ------  dataBuffer(),                 // not allocated  maxBlockSize(0),  maxCleartextBlockSize(0),  forceDataRelay(false),  dataSecLevel(DSL_CLEAR),      // until we see PROT  // ------ configuration options ------  allowRfc959(DEFAULT_ALLOW_RFC959),  allowRfc959_anon(false),  allowNonReflexivePorts(DEFAULT_ALLOW_NONREFLEXIVE_PORT),  allowReservedPorts(DEFAULT_ALLOW_RESERVED_PORT),  allowCleartext(false),  requireDataEncryption(false),  useFakeIPAddress(false),      // for -i  fakeIPAddress(0),             // for -i  pasvRange(),  activeRange(),  kerberosFtpdBinary((char*)NULL),  anonExecDropdown(false),  anonFtpdBinary((char*)NULL),  printAdats(false),  printDataChannel(false),  artificialDelay(0),  logLevelMask(LL_LOG),  stdoutLogAnyway(false),  logEventMask(LE_DEFAULTS),  logFile(stderr),  security(NULL){  instance = this;}SFTPD::~SFTPD(){  // attempt to close sockets (don't care about errors here)  //try { closeSocket(client_control); } catch (...) {}  //try { closeSocket(server_control); } catch (...) {}  // update: don't bother because the main driver loop really  //         should handle it, and that way I don't close something twice  // dealloc streams  if (clientControlStream) {    delete clientControlStream;  }  if (serverControlStream) {    delete serverControlStream;  }  // dealloc security  if (security) {    delete security;  }  // close log file  if (logFile != stderr) {    fclose(logFile);  }  // prevent further access via 'instance'  if (instance == this) {    instance = NULL;  }}// this is a convenient way to make sure the randomSeed gets// saved whenever it has been readSFTPD::RandomSeedSaver::~RandomSeedSaver(){  try {    saveRandomSeed();  }  catch (...) {    sftpd->writeToLog(SFTPD::LL_LOG, LE_ERROR, "failed to write random seed");  }}// f-ing egcs-1.1.2 wants to piss on the floor about possibly// uninitalized variables if this code appears below, where it// should, so I'm (very disgruntledly) pulling it up herestatic unsigned long f_ing_strtoul(char const *str, int radix){  char *endptr;  return strtoul(str, &endptr, radix);}void SFTPD::innerRun(int argc, char *argv[]){  // ----------- initial setup --------------  // see if getservbyname has a value (only used when not started by inetd)  // this port and address are what get bound in to a listener socket  int sftpdPort = getServByName("safetp");  IPAddress sftpdInterface = INADDR_ANY;             // by default, bind all interfaces  // the ftp port is tricky..  int ftpdPort = getServByName("raw-ftp");  IPAddress ftpdAddress = INADDR_ANY;                // dummy value    // by default forward to same interface the connection is received on  bool ftpdForwardNonlocally = false;  // use hardcoded values if getservbyname doesn't help  if (sftpdPort == 0) {    sftpdPort = SFTPD_PORT;  }  if (ftpdPort == 0) {    ftpdPort = FTPD_PORT;  }  // in case we see an exception before we know where to log them  xSysError *delayedError = NULL;# ifdef __WIN32__    SOCKET theStdin = INVALID_SOCKET;                // e.h. scope workaround    xSysError *firsterr = NULL;    xSysError *seconderr = NULL;    // the startup hook functions may return INVALID_SOCKET     // if they can easily determine their inetd is not the spawning inetd    // they may also throw an xSysError if there was an error contacting their inetd    try {      theStdin = inetdStartupHookWinetd(argc, argv); // try to load Winetd inetd    }    catch (xSysError &e) {      firsterr = new xSysError(e);             // throw it again later    }    if (theStdin == INVALID_SOCKET) { // failed to load winetd, try HCL      try {        theStdin = inetdStartupHookHCL(argc, argv);  // try to load hummingbird inetd      }      catch (xSysError &e) {        seconderr = new xSysError(e);             // throw it again later      }    }    if (theStdin != INVALID_SOCKET) {      // we're using one of our inetd's so force using this socket      useStdinStream = true;    }    else if (firsterr || seconderr) { // there was some error reported      // we need to set a delayed error that includes the failed state from one or both inetd's      // (because we're not certain which they're intending to use)      string combinedreason = stringb("");      if (firsterr) { // winetd failed        combinedreason = stringb(combinedreason << "Winetd: " << firsterr->why() << "  ");        delete firsterr;         }      if (seconderr) { // winetd failed        combinedreason = stringb(combinedreason << "HCLInetd: " << seconderr->why() << "  ");        delete seconderr;         }      delayedError = new xSysError(xSysError::R_UNKNOWN, "sftpd failed to contact inetd software.", combinedreason);    }# else    SOCKET theStdin = (SOCKET)0;                     // unix stdin# endif  // process command line  {    bool errors = false;    for (int a=1; a<argc; a++) {      bool oneError = false;      if (argv[a][0] != '-') {        oneError = true;      }      else {        // convenience        char const *argString = argv[a] + 2;        // used letters: acdefhilmoprstvxyDKR389        switch (argv[a][1]) {          case 'v': {        // version            int minv, maxv;            knownDSAPublicKeyVersions(minv, maxv);            printf("sftpd version %s\n"                   "  Compiled on " __DATE__ " at " __TIME__ "\n"                   "  Known DSA public key versions: min=%d, max=%d\n",                   SFTP_version, minv, maxv);            return;          }          case '3':          // force data relay            forceDataRelay = true;            break;          case 'p':          // listen port            parseAddrAndPort(sftpdInterface, sftpdPort, argString);            break;          case 'f':          // ftpd port            parseAddrAndPort(ftpdAddress, ftpdPort, argString);            if (ftpdAddress != INADDR_ANY) {              // an address specified here is our cue to send the FTP              // traffic to another host              ftpdForwardNonlocally = true;     // bugfix: was "false"!            }            break;          case 'D':            artificialDelay = atoi(argString);            break;          case 's':          // stdin stream            useStdinStream = true;            break;

⌨️ 快捷键说明

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