1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// socks - socks version of IP sockets
27//
28// This Socks implementation replaces the TCP-functional layer of the socket interface
29// (TCPClientSocket and TCPServerSocket), not the raw Socket layer. Remember what
30// Socks was invented for -- it's NOT a generic socket abstraction layer, valiant efforts
31// of the various -lsocks libraries nonwithstanding.
32// Do note that these are not virtual overrides, but textual replacements.
33//
34// This implementation supports Socks versions 4 and 5, as well as direct (un-socksed) sockets.
35// The choice is per socket object.
36//
37// API Synopsis:
38//	SocksServer *server = SocksServer::make(version, IP-address);
39//	SocksServer::defaultServer(server);	// for new sockets
40//	SocksClientSocket clientSocket(...);
41//		clientSocket.server(server);		// for this socket
42//	SocksServerSocket serverSocket(...);	// only supports .receive()
43// Otherwise, Socks{Client,Server}Socket is functionally equivalent to {Client,Server}Socket.
44// Sockets without a Server (explicit or by default) are direct.
45//
46// Minimum replacement strategy:
47//	#define TCPClientSocket SocksClientSocket
48//	#define TCPServerSocket SocksServerSocket
49//	SocksServer::defaultServer(SocksServer::make(...));
50//
51// Limitations:
52// There is no UDP Socks support.
53// @@@ Nonblocking sockets may not work quite right.
54//
55#ifndef _H_SOCKSPLUSPLUS
56#define _H_SOCKSPLUSPLUS
57
58#include "ip++.h"
59#include <security_utilities/threading.h>
60#include <security_utilities/globalizer.h>
61
62
63using namespace UnixPlusPlus;
64
65
66namespace Security {
67namespace IPPlusPlus {
68
69
70class SocksServerSocket;
71class SocksClientSocket;
72
73
74//
75// A particular Socks server and version. Get one by calling SocksServer::make().
76// You can express "no socks server" (direct connect) with a NULL pointer (or version==0).
77//
78class SocksServer {
79public:
80    class Support; friend class Support;
81
82private:
83    struct Global {
84        mutable Mutex lock;			// lock for mGlobalServerAddress
85        SocksServer *mServer;		// global default server
86        ThreadNexus<IPAddress> lastConnected; // last address connected to (for aux. bind)
87
88        Global() : mServer(NULL) { }
89
90        void server(SocksServer *srv)	{ StLock<Mutex> _(lock); mServer = srv; }
91        SocksServer *server() const		{ StLock<Mutex> _(lock); return mServer; }
92    };
93    static ModuleNexus<Global> global; // global state
94
95public:
96    typedef unsigned int Version;
97
98    static SocksServer *make(Version version, const IPSockAddress &addr);
99
100    const IPSockAddress &address() const	{ return mServerAddress; }
101    Version version() const					{ return mVersion; }
102
103public:
104    static SocksServer *defaultServer()		{ return global().server(); }
105    static void defaultServer(SocksServer *server) { global().server(server); }
106
107protected:
108	virtual ~SocksServer();
109
110    virtual void connect(SocksClientSocket &me, const IPSockAddress &peer) = 0;
111    virtual void connect(SocksClientSocket &me, const Host &host, IPPort port) = 0;
112    virtual void bind(SocksServerSocket &me, const IPAddress &peer, IPPort port) = 0;
113    virtual void receive(SocksServerSocket &me, SocksClientSocket &receiver) = 0;
114
115    SocksServer(Version v, const IPSockAddress &addr) : mVersion(v), mServerAddress(addr) { }
116
117protected:
118    Version mVersion;
119    IPSockAddress mServerAddress;
120
121public:
122    class Support {
123    public:
124        SocksServer *server() const		{ return mServer; }
125        void server(SocksServer *srv)	{ mServer = srv; }
126
127        IPSockAddress localAddress(const Socket &me) const;
128        IPSockAddress peerAddress(const Socket &me) const;
129
130    protected:
131        Support() : mServer(defaultServer()) { }
132
133        void connect(SocksClientSocket &me, const IPSockAddress &peer)
134        { mServer->connect(me, peer); }
135        void connect(SocksClientSocket &me, const Host &host, IPPort port)
136        { mServer->connect(me, host, port); }
137        void bind(SocksServerSocket &me, const IPAddress &peer, IPPort port)
138        { mServer->bind(me, peer, port); }
139        void receive(SocksServerSocket &me, SocksClientSocket &receiver)
140        { mServer->receive(me, receiver); }
141
142        void lastConnected(IPAddress addr)	{ global().lastConnected() = addr; }
143        IPAddress lastConnected() const		{ return global().lastConnected(); }
144
145    public:
146        SocksServer *mServer;				// server for this socket
147        IPSockAddress mLocalAddress;		// my own address, as reported by server
148        IPSockAddress mPeerAddress;			// peer address
149    };
150};
151
152
153//
154// The Socks version of a TCPClientSocket
155//
156class SocksClientSocket : public TCPClientSocket, public SocksServer::Support {
157public:
158    SocksClientSocket() { }
159    SocksClientSocket(const IPSockAddress &peer)				{ open(peer); }
160    SocksClientSocket(const IPAddress &addr, IPPort port)		{ open(addr, port); }
161    SocksClientSocket(const Host &host, IPPort port)			{ open(host, port); }
162
163    void open(const IPSockAddress &peer);
164    void open(const IPAddress &addr, IPPort port);
165    void open(const Host &host, IPPort port);
166
167    IPSockAddress localAddress() const		{ return Support::localAddress(*this); }
168    IPSockAddress peerAddress() const		{ return Support::peerAddress(*this); }
169
170public:
171    void setFd(int fd, const IPSockAddress &local, const IPSockAddress &peer);
172};
173
174
175//
176// The Socks version of a TCPServerSocket.
177// Note that this version only supports the receive() access method.
178// By the nature of things, the queue-length argument is ignored (it's always 1).
179//
180// A note about setMainConnection: There is a structural problem
181// with the Socks protocol. When a SocksServerSocket goes active,
182// the protocol requires the IP address of the host the connection will be
183// coming from. Typical Socks library layers simply assume that this will
184// be the address of the last server connected to by another (TCP) socket.
185// We do this heuristic too, but it's unreliable: it's a per-thread global, and will
186// fail if you interleave multiple socks "sessions" in the same thread. For this
187// case (or if you just want to be safe and explicit), you can call setMainConnection to
188// explicitly link this socket to a TCPClientSocket whose peer we should use.
189// Do note that this call does not exist in the plain (non-socks) socket layer.
190//
191class SocksServerSocket : public TCPServerSocket, public SocksServer::Support {
192public:
193    SocksServerSocket() { }
194    SocksServerSocket(const IPSockAddress &local, int = 1) { open(local); }
195    SocksServerSocket(IPPort port, int = 1)					{ open(port); }
196
197    void open(const IPSockAddress &local, int = 1);
198    void open(IPPort port = 0, int = 1)
199    { open(IPSockAddress(IPAddress::any, port)); }
200
201    void receive(SocksClientSocket &client);		// accept incoming and close listener
202
203    IPSockAddress localAddress() const		{ return Support::localAddress(*this); }
204    IPSockAddress peerAddress() const		{ return Support::peerAddress(*this); }
205
206    // this special call is not an overlay of TCPServerSocket - it exists only for Socks
207    void setMainConnection(TCPClientSocket &main)
208    { mConnectionPeer = main.peerAddress().address(); }
209
210private:
211    IPAddress mConnectionPeer;						// address to say we're peered with
212
213private:
214    void operator () (TCPClientSocket &newClient);	// not supported by Socks
215};
216
217
218}	// end namespace IPPlusPlus
219}	// end namespace Security
220
221
222#endif //_H_IPPLUSPLUS
223