Annotation of src/usr.bin/nc/socks.c, Revision 1.1
1.1 ! jakob 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. All advertising materials mentioning features or use of this software
! 15: * must display the following acknowledgement:
! 16: * This product includes software developed by Niklas Hallqvist.
! 17: * 4. The name of the author may not be used to endorse or promote products
! 18: * derived from this software without specific prior written permission.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 30: */
! 31:
! 32: #include <sys/types.h>
! 33: #include <sys/socket.h>
! 34: #include <netinet/in.h>
! 35: #include <arpa/inet.h>
! 36:
! 37: #include <err.h>
! 38: #include <netdb.h>
! 39: #include <stdio.h>
! 40: #include <stdlib.h>
! 41: #include <string.h>
! 42: #include <unistd.h>
! 43:
! 44: #define SOCKS_PORT "1080"
! 45: #define SOCKS_VERSION 5
! 46: #define SOCKS_NOAUTH 0
! 47: #define SOCKS_NOMETHOD 0xff
! 48: #define SOCKS_CONNECT 1
! 49: #define SOCKS_IPV4 1
! 50: #define SOCKS_MAXCMDSZ 10
! 51:
! 52: static in_addr_t
! 53: decode_addr (const char *s)
! 54: {
! 55: struct hostent *hp = gethostbyname (s);
! 56: struct in_addr retval;
! 57:
! 58: if (hp)
! 59: return *(in_addr_t *)hp->h_addr_list[0];
! 60: if (inet_aton (s, &retval))
! 61: return retval.s_addr;
! 62: errx (1, "cannot decode address \"%s\"", s);
! 63: }
! 64:
! 65: static in_port_t
! 66: decode_port (const char *s)
! 67: {
! 68: struct servent *sp;
! 69: in_port_t port;
! 70: char *p;
! 71:
! 72: port = strtol (s, &p, 10);
! 73: if (s == p) {
! 74: sp = getservbyname (s, "tcp");
! 75: if (sp)
! 76: return sp->s_port;
! 77: }
! 78: if (*s != '\0' && *p == '\0')
! 79: return htons (port);
! 80: errx (1, "cannot decode port \"%s\"", s);
! 81: }
! 82:
! 83: int
! 84: socks_connect (char *host, char *port, struct addrinfo hints,
! 85: char *proxyhost, char *proxyport, struct addrinfo proxyhints)
! 86: {
! 87: char *proxyport_default;
! 88: int proxyfd;
! 89: unsigned char buf[SOCKS_MAXCMDSZ];
! 90: ssize_t cnt;
! 91: in_addr_t serveraddr;
! 92: in_port_t serverport;
! 93:
! 94: if (proxyport)
! 95: proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
! 96: else
! 97: proxyfd = remote_connect(proxyhost, SOCKS_PORT, proxyhints);
! 98:
! 99: if (!proxyfd)
! 100: return -1;
! 101:
! 102: serveraddr = decode_addr (host);
! 103: serverport = decode_port (port);
! 104:
! 105: /* Version 5, one method: no authentication */
! 106: buf[0] = SOCKS_VERSION;
! 107: buf[1] = 1;
! 108: buf[2] = SOCKS_NOAUTH;
! 109: cnt = write (proxyfd, buf, 3);
! 110: if (cnt == -1)
! 111: err (1, "write failed");
! 112: if (cnt != 3)
! 113: errx (1, "short write, %d (expected 3)", cnt);
! 114:
! 115: read (proxyfd, buf, 2);
! 116: if (buf[1] == SOCKS_NOMETHOD)
! 117: errx (1, "authentication method negotiation failed");
! 118:
! 119: /* Version 5, connect: IPv4 address */
! 120: buf[0] = SOCKS_VERSION;
! 121: buf[1] = SOCKS_CONNECT;
! 122: buf[2] = 0;
! 123: buf[3] = SOCKS_IPV4;
! 124: memcpy (buf + 4, &serveraddr, sizeof serveraddr);
! 125: memcpy (buf + 8, &serverport, sizeof serverport);
! 126:
! 127: /* XXX Handle short writes better */
! 128: cnt = write (proxyfd, buf, 10);
! 129: if (cnt == -1)
! 130: err (1, "write failed");
! 131: if (cnt != 10)
! 132: errx (1, "short write, %d (expected 10)", cnt);
! 133:
! 134: /* XXX Handle short reads better */
! 135: cnt = read (proxyfd, buf, sizeof buf);
! 136: if (cnt == -1)
! 137: err (1, "read failed");
! 138: if (cnt != 10)
! 139: errx (1, "unexpected reply size %d (expected 10)", cnt);
! 140: if (buf[1] != 0)
! 141: errx (1, "connection failed, SOCKS error %d", buf[1]);
! 142:
! 143: return proxyfd;
! 144: }