]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/socks++4.cpp
Security-54.1.3.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / socks++4.cpp
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;
57 } catch (const UnixError &err) {
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