]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | // | |
20 | // socks++int - internal Socks implementation | |
21 | // | |
22 | #include "socks++4.h" | |
23 | #include "hosts.h" | |
24 | #include <set> | |
25 | ||
26 | ||
27 | namespace Security { | |
28 | namespace IPPlusPlus { | |
29 | namespace Socks4 { | |
30 | ||
31 | ||
32 | ||
33 | // | |
34 | // Socks4 Protocol implementation | |
35 | // | |
36 | void Server::connect(SocksClientSocket &me, const IPSockAddress &peer) | |
37 | { | |
38 | me.Socket::open(SOCK_STREAM); | |
39 | me.Socket::connect(mServerAddress); | |
40 | Message request(socksConnect, peer); | |
41 | request.send(me, "nobody"); | |
42 | (Message(me)); // read and check reply message | |
43 | me.mPeerAddress = peer; // best guess, Mr. Sulu | |
44 | debug("socks", "%d socks4 connected to %s", me.fd(), string(peer).c_str()); | |
45 | } | |
46 | ||
47 | void Server::connect(SocksClientSocket &me, const Host &host, IPPort port) | |
48 | { | |
49 | // Socks4 has no name resolution support. Do it here | |
50 | //@@@ error reporting sucks here | |
51 | set<IPAddress> addrs = host.addresses(); | |
52 | for (set<IPAddress>::const_iterator it = addrs.begin(); it != addrs.end(); it++) { | |
53 | try { | |
54 | IPSockAddress addr(*it, port); | |
55 | connect(me, addr); | |
56 | return; | |
29654253 | 57 | } catch (const UnixError &err) { |
bac41a7b A |
58 | errno = err.error; |
59 | } | |
60 | } | |
61 | // exhausted | |
62 | UnixError::throwMe(); | |
63 | } | |
64 | ||
65 | ||
66 | void Server::bind(SocksServerSocket &me, const IPAddress &peer, IPPort port) | |
67 | { | |
68 | me.Socket::open(SOCK_STREAM); | |
69 | me.Socket::connect(mServerAddress); | |
70 | Message request(socksBind, IPSockAddress(peer, port)); | |
71 | request.send(me, "nobody"); | |
72 | Message reply(me); | |
73 | me.mLocalAddress = reply.address().defaults(mServerAddress.address()); | |
74 | debug("socks", "%d socks4 bound to %s", me.fd(), string(me.mLocalAddress).c_str()); | |
75 | } | |
76 | ||
77 | void Server::receive(SocksServerSocket &me, SocksClientSocket &receiver) | |
78 | { | |
79 | Message reply(me); | |
80 | receiver.setFd(me.fd(), me.mLocalAddress, reply.address()); | |
81 | me.clear(); // clear our own (don't close on destruction) | |
82 | debug("socks", "%d socks4 inbound connect", receiver.fd()); | |
83 | } | |
84 | ||
85 | ||
86 | // | |
87 | // Message properties | |
88 | // | |
89 | Message::Message(Command cmd, const IPSockAddress &address) | |
90 | : version(4), message(cmd), port(htons(address.port())), addr(address.address()) | |
91 | { | |
92 | } | |
93 | ||
94 | ||
95 | void Message::send(Socket &s, const char *userid) | |
96 | { | |
97 | if (s.write(this, sizeof(*this)) != sizeof(*this)) | |
98 | UnixError::throwMe(); | |
99 | // now append zero-terminated userid (what a crock) | |
100 | size_t length = strlen(userid) + 1; | |
101 | if (s.write(userid, length) != length) { | |
102 | s.close(); | |
103 | UnixError::throwMe(); | |
104 | } | |
105 | } | |
106 | ||
107 | Message::Message(Socket &s) | |
108 | { | |
109 | if (s.read(this, sizeof(*this)) != sizeof(*this)) { | |
110 | s.close(); | |
111 | UnixError::throwMe(); | |
112 | } | |
113 | if (version != 0) { | |
114 | s.close(); | |
115 | UnixError::throwMe(EPROTONOSUPPORT); | |
116 | } | |
117 | switch (message) { | |
118 | case requestAccepted: | |
119 | return; | |
120 | default: | |
121 | UnixError::throwMe(ECONNREFUSED); //@@@ hardly any diagnostics here | |
122 | } | |
123 | } | |
124 | ||
125 | ||
126 | } // end namespace Socks | |
127 | } // end namespace IPPlusPlus | |
128 | } // end namespace Security |