📄 sftpc.h
字号:
// sftpc.h// SafeTP command-line client// copyright SafeTP Development Group, Inc., 2000 Terms of use are as specified in license.txt#ifndef __SFTPC_H#define __SFTPC_H#include "sftp.h" // SocketLineReader, SOCKET#include "datablok.h" // DataBlock#include "reply.h" // Reply#include "request.h" // Request#include "digt.h" // DigestComputer#include "crlflex.h" // FromCRLFTranslator#include "objqueue.h" // Queue#include "filkeydb.h" // KeyPolicy, KeyEnvironment, FileKeyDBclass SecurityProvider;class EncryptedInputStreamer;class EncryptedOutputStreamer;class TransferState;// the interpreterclass SFTPC : public KeyPolicy {private: // types // constants enum { UNENCRYPTED_BUFSIZE = 4096 // size of buffer when not encrypting };private: // data // friends (helpers) friend class EncryptedInputStreamer; friend class EncryptedOutputStreamer; // security manager SecurityProvider *security; // manager object string securityName; // name of security mechanism // key database stuff FileKeyDB keyDatabase; // db KeyEnvironment keyEnvironment; // db & policy // server address int serverPort; // TCP port on which we contacted server string serverName; // name given to DNS for resolution IPAddress serverAddress; // IP address of server // open sockets SocketLineReader *control; // control channel // encryption buffer DataBlock dataBuffer; // buffer for {en,de}cryption // protocol state (descriptive) long PBSZ; // negotiated buffer length DigestComputer digt; // calculate expected DIGT response bool sentFirstAuth; // true once first AUTH is sent bool authenticated; // true once control channel is encrypted DataSecurityLevel dataSecLevel; // level of protection applied to data channel // 2228 user options (prescriptive) long requestedPBSZ; // PBSZ we want // 959 user options (prescriptive) bool transferPassively; // use PASV transfers bool asciiTransfers; // use ascii-mode transfers bool localConventionIsCRLF; // true for windows, false for unix // user interface options bool printOutgoing; // print FTP commands as they're sent bool interactivePrompting; // per-file prompting for multiple-file commands bool quitProgram; // true when toplevel loop is to quit bool printHashMarks; // print '#' every 1024 bytes xferred // security preferences bool useRfc959; // act like a normal 959 client (no encryption) bool acceptNewKeysSilently; // when true, new keys are always believed bool auto959Dropdown; // if true, failed AUTH leads to 959 operation bool alwaysAcceptServerIPMismatch; // when true we don't care if server reports different IP // debugging options bool showDiagnostics; // true to print diagnostic output bool showAdats; // true if ADATs are printed bool useDebuggingLogin; // true: supply user/pass statically bool quitAfterNegotiation; // exit program after successful protocol negotiation (for debugging) bool binaryTransferAnyway; // have server send as binary even in text mode bool localGlobbing; // true to glob locally onlyprivate: // funcs // --------- reply stuff ---------- // read the next reply, and if it is encrypted, decrypt it; then return it // also prints the decrypted reply Reply readReply(); // keep reading replies until one is not an intermediate reply Reply readFinalReply(); // just the final code ReplyCode readFinalReplyCode(); // get the reply, throw exception on error reply code ReplyCode readAndCheckFinalReplyCode(); // throw xReply if not success void checkReplyCode(Reply const &reply) const; // deal with ADATs, possibly adding them to DIGT checksum void handleAdatAndDigt(Reply &reply); // --------- request stuff ---------- // all requests pass through here on their way out void sendRequestToWire(Request const &req); // don't process the reply; don't even take it from the socket // encrypts request if appropriate, and initiates data channel admin void sendRequest(Request const &req); // send the request and process the reply (expecting a success reply) void checkedRequest(Request const &req); // a little syntactic sugar void sendRequest(RequestCommand cmd, char const *args=NULL); void checkedRequest(RequestCommand cmd, char const *args=NULL); // ---------- negotiation -------------- // implements dropdown behavior, and calls negotiationPart2 // if it returns false, caller should exit program with 'retval' exit code bool negotiationPart1(int& /*out*/ retval); // manages all communication from AUTH to "23{4,5} Security data exchange complete." // returns false if the AUTH itself is rejected; other failures throw exceptions bool negotiationPart2(); // send DIGT, verify response is as expected (throw otherwise) void compareDigests(); // ------- data channel administration ------- // bind a listener socket, tell server about it, return it SOCKET setupActiveConnection(); // ask the server to bind a listener, and connect to it, and // return the connected socket (this relies on the server being // able to accept() a connection even though the corresponding // data transfer hasn't yet begun) SOCKET setupPassiveConnection(); // first half of establishing a data channel SOCKET dataChannelSetup(RequestCommand cmd); // second half of establishing a data channel; returns data socket SOCKET openDataChannel(SOCKET dataListener); // calls dataChannelSetup and openDataChannel SOCKET startDataTransfer(RequestCommand cmd, char const *arg); // read a reply and verify it's 150 void check150Reply(); // do data transfer for given command and argument (which can be NULL for LIST/NLST) void dataTransfer(RequestCommand cmd, char const *arg, char const *localFname); // ------- data channel, actual data handling ------ // read available data from s into dataBuffer; wait for at least 1 byte void readCleartext(SOCKET socket); // write all data from dataBuffer to s void writeCleartext(SOCKET socket); // read an entire block of data from s, decrypt it into dataBuffer void readAndDecrypt(SOCKET socket); // encrypt all of the data in dataBuffer, send it to 'socket' void encryptAndWrite(SOCKET socket); // auto-multiplexing (encryption vs. no encryption) int readEitherWay(SOCKET socket); // returns # of bytes put into dataBuffer void writeEitherWay(SOCKET socket); // CRLF <-> LF interface to Flex lexers that to real translation static void CRLF_to_LF(StreamInputSource &src, StreamOutputDest &dest); static void CRLF_to_CRLF(StreamInputSource &src, StreamOutputDest &dest); static void CRLF_to_something( StreamInputSource &src, StreamOutputDest &dest, FromCRLFTranslator translator); static void LF_to_CRLF(StreamInputSource &src, StreamOutputDest &dest); typedef void (*CRLFTranslator)(StreamInputSource &src, StreamOutputDest &dest); CRLFTranslator getCRLFTranslator(bool fromCRLF); // highest-level interface to copying between files and sockets; takes // into account both encryption and CRLF issues; both return the number // of bytes sent/received over the network // NOTE: neither the socket nor the file is closed by this fn int copyFromSocketToStream(SOCKET sourceSocket, StreamOutputDest &destStream, bool asciiMode); int copyFromStreamToSocket(StreamInputSource &sourceStream, SOCKET destSocket, bool asciiMode); // ---- internal, online test code ------------ void testSendReceive(char const *fname); // a series of automated tests to verify that various functions // in sftpc and sftpd are working correctly void runTests(bool passive); void testBinaryTransfers(); void testTextTransfers(); void testSendReceiveBlocks( DataBlock const &start, TransferState const &sendState, DataBlock const &end, TransferState const &receiveState); void setTransferState(TransferState const &state); void testMultipleFileCmds(); // debugging support // print a debugging message (or not, depending on 'showDiagnostics') // appends a newline automatically void printDiagnostic(char const *msg); // print all state variables void dumpVariables(); // re-sync with server int emptyResponseQueue(); // ---------- multiple file commands -------------- void mgetCommand(char const *pattern); void mputCommand(char const *pattern); void mlsCommand(char const *pattern); void mdeleteCommand(char const *pattern); void multipleFileCommand(Queue<string> &queue, RequestCommand cmd); Queue<string> getRemoteNames(char const *pattern); static bool getLocalNamesHelper(char const *fname, void *extra); Queue<string> getLocalNames(char const *pattern); // glob a list (queue) of strings void filterStrings(Queue<string> &queue, char const *pattern); // ------- interactive stuff ----------- // process command-line options bool processCommandLine(int argc, char *argv[], int& /*out*/ retval); // handles commands as typed at the keyboard; returns true // to continue in the read loop, false to stop void userCommand(char const *command); // main interactive loop int doit(); // run login loop bool login(); // single-character prompt char getOneChar(char const *prompt, char const *allowable); // --------- protocol state manipulation ---------- // change data encryption status; return false if the server // doesn't support it bool setDataEncryption(DataSecurityLevel newLevel); // change transfer mode void requestAsciiMode(bool ascii); // set the protection buffer size void requestPBSZ(); // --------- state queries -------------- bool isControlChannelEncrypted() const; bool isDataChannelEncrypted() const; bool isDigtActive() const; bool transferModeForCmd(RequestCommand cmd) const; bool negotiatedPBSZ() const;public: SFTPC(); virtual ~SFTPC(); // entry point from OS int main(int argc, char *argv[]); // KeyPolicy funcs virtual void keyReceived(IPAddress addr, DataBlock const &key); virtual void keyMatched(IPAddress addr); virtual MismatchAction getMismatchAction( IPAddress addr, DataBlock const &sentKey, DataBlock const &storedKey, int storedKeyCopies, IPAddress const *copyAddrs); virtual NewServerAction getNewServerAction( IPAddress addr, DataBlock const &sentKey); virtual void serverIPMismatch(IPAddress ipServerReported, IPAddress ipConnectedTo, DataBlock const &serverKeySent);};// reads from a socket, possibly encrypted, as a streamclass EncryptedInputStreamer : public StreamInputSource {private: SFTPC &sftpc; // protocol object we're helping SOCKET dataChannel; // socket from which we read data int &totlen; // running total of # of bytes received int curpos; // how much of sftpc.dataBuffer has been copiedpublic: EncryptedInputStreamer(SFTPC &s, SOCKET d, int &t) : sftpc(s), dataChannel(d), totlen(t), curpos(s.dataBuffer.getDataLen()) {} // this initial value for curpos will force a call to readEitherWay // on the next read() virtual int read(char *buffer, int maxlen);};// writes to a socket, possibly encrypted, as a streamclass EncryptedOutputStreamer : public StreamOutputDest {private: SFTPC &sftpc; // protocol object we're helping SOCKET dataChannel; // socket to which we write data int cleartextLen; // maximum amount to fill sftpc.dataBuffer int &totlen; // running total of # of bytes sent int curpos; // how much of sftpc.dataBuffer has been filledprivate: void sendIt(); // send what is in sftpc.dataBufferpublic: EncryptedOutputStreamer(SFTPC &s, SOCKET d, int c, int &t) : sftpc(s), dataChannel(d), cleartextLen(c), totlen(t), curpos(0) {} virtual ~EncryptedOutputStreamer(); // flushes buffer and sends the final, 0-length block virtual void write(char const *data, int len);};// encapsulate details about data transfer protocol options// (used by test code)class TransferState {public: bool asciiTransfers; // use ascii-mode transfers bool localConventionIsCRLF; // true for windows, false for unix bool binaryTransferAnyway; // have server send as binary even in text modepublic: TransferState(bool a, bool L, bool b) : asciiTransfers(a), localConventionIsCRLF(L), binaryTransferAnyway(b) {} // use default copy ctor and operator=};// stream relay device that echoes characters every so oftenclass EchoStream { int outstanding; // chars waiting to have an echo int echoFreq; // # of chars between echoes char echoChar; // char to echo to coutpublic: EchoStream(int f=1024, char c='#') : outstanding(0), echoFreq(f), echoChar(c) {} void saw(int numChars);};class EchoInputStream : public EchoStream, public StreamInputSource { StreamInputSource &input;public: EchoInputStream(StreamInputSource &i) : input(i) {} // StreamInputSource funcs virtual int read(char *buffer, int buflen);};class EchoOutputStream : public EchoStream, public StreamOutputDest { StreamOutputDest &output;public: EchoOutputStream(StreamOutputDest &o) : output(o) {} // StreamOutputDest funcs virtual void write(char const *data, int len);};#endif // __SFTPC_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -