]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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++int - internal Socks implementation | |
27 | // | |
28 | #include "socks++4.h" | |
29 | #include "hosts.h" | |
30 | #include <set> | |
31 | ||
32 | ||
33 | namespace Security { | |
34 | namespace IPPlusPlus { | |
35 | namespace Socks4 { | |
36 | ||
37 | ||
38 | ||
39 | // | |
40 | // Socks4 Protocol implementation | |
41 | // | |
42 | void Server::connect(SocksClientSocket &me, const IPSockAddress &peer) | |
43 | { | |
44 | me.Socket::open(SOCK_STREAM); | |
45 | me.Socket::connect(mServerAddress); | |
46 | Message request(socksConnect, peer); | |
47 | request.send(me, "nobody"); | |
48 | (Message(me)); // read and check reply message | |
49 | me.mPeerAddress = peer; // best guess, Mr. Sulu | |
50 | secdebug("socks", "%d socks4 connected to %s", me.fd(), string(peer).c_str()); | |
51 | } | |
52 | ||
53 | void Server::connect(SocksClientSocket &me, const Host &host, IPPort port) | |
54 | { | |
55 | // Socks4 has no name resolution support. Do it here | |
56 | //@@@ error reporting sucks here | |
57 | set<IPAddress> addrs = host.addresses(); | |
58 | for (set<IPAddress>::const_iterator it = addrs.begin(); it != addrs.end(); it++) { | |
59 | try { | |
60 | IPSockAddress addr(*it, port); | |
61 | connect(me, addr); | |
62 | return; | |
63 | } catch (const UnixError &err) { | |
64 | errno = err.error; | |
65 | } | |
66 | } | |
67 | // exhausted | |
68 | UnixError::throwMe(); | |
69 | } | |
70 | ||
71 | ||
72 | void Server::bind(SocksServerSocket &me, const IPAddress &peer, IPPort port) | |
73 | { | |
74 | me.Socket::open(SOCK_STREAM); | |
75 | me.Socket::connect(mServerAddress); | |
76 | Message request(socksBind, IPSockAddress(peer, port)); | |
77 | request.send(me, "nobody"); | |
78 | Message reply(me); | |
79 | me.mLocalAddress = reply.address().defaults(mServerAddress.address()); | |
80 | secdebug("socks", "%d socks4 bound to %s", me.fd(), string(me.mLocalAddress).c_str()); | |
81 | } | |
82 | ||
83 | void Server::receive(SocksServerSocket &me, SocksClientSocket &receiver) | |
84 | { | |
85 | Message reply(me); | |
86 | receiver.setFd(me.fd(), me.mLocalAddress, reply.address()); | |
87 | me.clear(); // clear our own (don't close on destruction) | |
88 | secdebug("socks", "%d socks4 inbound connect", receiver.fd()); | |
89 | } | |
90 | ||
91 | ||
92 | // | |
93 | // Message properties | |
94 | // | |
95 | Message::Message(Command cmd, const IPSockAddress &address) | |
96 | : version(4), message(cmd), port(htons(address.port())), addr(address.address()) | |
97 | { | |
98 | } | |
99 | ||
100 | ||
101 | void Message::send(Socket &s, const char *userid) | |
102 | { | |
103 | if (s.write(this, sizeof(*this)) != sizeof(*this)) | |
104 | UnixError::throwMe(); | |
105 | // now append zero-terminated userid (what a crock) | |
106 | size_t length = strlen(userid) + 1; | |
107 | if (s.write(userid, length) != length) { | |
108 | s.close(); | |
109 | UnixError::throwMe(); | |
110 | } | |
111 | } | |
112 | ||
113 | Message::Message(Socket &s) | |
114 | { | |
115 | if (s.read(this, sizeof(*this)) != sizeof(*this)) { | |
116 | s.close(); | |
117 | UnixError::throwMe(); | |
118 | } | |
119 | if (version != 0) { | |
120 | s.close(); | |
121 | UnixError::throwMe(EPROTONOSUPPORT); | |
122 | } | |
123 | switch (message) { | |
124 | case requestAccepted: | |
125 | return; | |
126 | default: | |
127 | UnixError::throwMe(ECONNREFUSED); //@@@ hardly any diagnostics here | |
128 | } | |
129 | } | |
130 | ||
131 | ||
132 | } // end namespace Socks | |
133 | } // end namespace IPPlusPlus | |
134 | } // end namespace Security |