]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/socks++.h
Security-57740.31.2.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / socks++.h
1 /*
2 * Copyright (c) 2000-2004,2011,2014 Apple 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
63 using namespace UnixPlusPlus;
64
65
66 namespace Security {
67 namespace IPPlusPlus {
68
69
70 class SocksServerSocket;
71 class 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 //
78 class SocksServer {
79 public:
80 class Support; friend class Support;
81
82 private:
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
95 public:
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
103 public:
104 static SocksServer *defaultServer() { return global().server(); }
105 static void defaultServer(SocksServer *server) { global().server(server); }
106
107 protected:
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
117 protected:
118 Version mVersion;
119 IPSockAddress mServerAddress;
120
121 public:
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 //
156 class SocksClientSocket : public TCPClientSocket, public SocksServer::Support {
157 public:
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
170 public:
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 //
191 class SocksServerSocket : public TCPServerSocket, public SocksServer::Support {
192 public:
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
210 private:
211 IPAddress mConnectionPeer; // address to say we're peered with
212
213 private:
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