/* * Network proxy abstraction in PuTTY * * A proxy layer, if necessary, wedges itself between the * network code and the higher level backend. * * Supported proxies: HTTP CONNECT, generic telnet, SOCKS 4 & 5 */ #ifndef PUTTY_PROXY_H #define PUTTY_PROXY_H typedef struct ProxySocket ProxySocket; typedef struct ProxyNegotiator ProxyNegotiator; typedef struct ProxyNegotiatorVT ProxyNegotiatorVT; struct ProxySocket { const char *error; Socket *sub_socket; Plug *plug; SockAddr *remote_addr; int remote_port; /* Parameters needed to make further connections to the proxy */ SockAddr *proxy_addr; int proxy_port; bool proxy_privport, proxy_oobinline, proxy_nodelay, proxy_keepalive; bufchain pending_output_data; bufchain pending_oob_output_data; bufchain pending_input_data; bool pending_eof; bool freeze; /* should we freeze the underlying socket when * we are done with the proxy negotiation? this * simply caches the value of sk_set_frozen calls. */ ProxyNegotiator *pn; /* non-NULL if still negotiating */ bufchain output_from_negotiator; /* configuration, used to look up proxy settings */ Conf *conf; /* for interaction with the Seat */ Interactor *clientitr; LogPolicy *clientlp; Seat *clientseat; Socket sock; Plug plugimpl; Interactor interactor; }; struct ProxyNegotiator { const ProxyNegotiatorVT *vt; /* Standard fields for any ProxyNegotiator. new() and free() don't * have to set these up; that's done centrally, to save duplication. */ ProxySocket *ps; bufchain *input; bufchain_sink output[1]; Interactor *itr; /* NULL if we are not able to interact with the user */ /* Set to report success during proxy negotiation. */ bool done; /* Set to report an error during proxy negotiation. The main * ProxySocket will free it, and will then guarantee never to call * process_queue again. */ char *error; /* Set to report user abort during proxy negotiation. */ bool aborted; /* Set to request the centralised code to make a fresh connection * to the proxy server, e.g. because an HTTP proxy slammed the * connection shut after sending 407 Proxy Auth Required. */ bool reconnect; }; struct ProxyNegotiatorVT { ProxyNegotiator *(*new)(const ProxyNegotiatorVT *); void (*process_queue)(ProxyNegotiator *); void (*free)(ProxyNegotiator *); const char *type; }; static inline ProxyNegotiator *proxy_negotiator_new( const ProxyNegotiatorVT *vt) { return vt->new(vt); } static inline void proxy_negotiator_process_queue(ProxyNegotiator *pn) { pn->vt->process_queue(pn); } static inline void proxy_negotiator_free(ProxyNegotiator *pn) { pn->vt->free(pn); } extern const ProxyNegotiatorVT http_proxy_negotiator_vt; extern const ProxyNegotiatorVT socks4_proxy_negotiator_vt; extern const ProxyNegotiatorVT socks5_proxy_negotiator_vt; extern const ProxyNegotiatorVT telnet_proxy_negotiator_vt; /* * Centralised functions to allow ProxyNegotiators to get hold of a * prompts_t, and to deal with SeatPromptResults coming back. */ prompts_t *proxy_new_prompts(ProxySocket *ps); void proxy_spr_abort(ProxyNegotiator *pn, SeatPromptResult spr); /* * This may be reused by local-command proxies on individual * platforms. */ #define TELNET_CMD_MISSING_USERNAME 0x0001 #define TELNET_CMD_MISSING_PASSWORD 0x0002 char *format_telnet_command(SockAddr *addr, int port, Conf *conf, unsigned *flags_out); DeferredSocketOpener *local_proxy_opener( SockAddr *addr, int port, Plug *plug, Conf *conf, Interactor *itr); void local_proxy_opener_set_socket(DeferredSocketOpener *opener, Socket *socket); char *platform_setup_local_proxy(Socket *socket, const char *cmd); #include "cproxy.h" #endif