sslsocks.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,158 行 · 第 1/2 页
C
1,158 行
/* * Implementation of Socks protocol. * None of this code is supported any longer. * NSS officially does NOT support Socks. * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. * * $Id: sslsocks.c,v 1.3 2000/09/19 06:05:28 wtc%netscape.com Exp $ */#include "prtypes.h"#include "prnetdb.h"#include "cert.h"#include "ssl.h"#include "sslimpl.h"#include "prsystem.h"#include <stdio.h>#include "nspr.h"#ifdef XP_UNIX#include "prprf.h"#endif#ifdef XP_UNIX#define SOCKS_FILE "/etc/socks.conf"#endif#ifdef XP_MAC#define SOCKS_FILE NULL#endif#ifdef XP_WIN#define SOCKS_FILE NULL#endif#ifdef XP_OS2#define SOCKS_FILE NULL#endif #define SOCKS_VERSION 4#define DEF_SOCKD_PORT 1080#define SOCKS_CONNECT 1#define SOCKS_BIND 2#define SOCKS_RESULT 90#define SOCKS_FAIL 91#define SOCKS_NO_IDENTD 92 /* Failed to connect to Identd on client machine */#define SOCKS_BAD_ID 93 /* Client's Identd reported a different user-id */#define MAKE_IN_ADDR(a,b,c,d) \ PR_htonl(((PRUint32)(a) << 24) | ((PRUint32)(b) << 16) | ((c) << 8) | (d))struct sslSocksInfoStr { PRUint32 sockdHost; PRUint16 sockdPort; char direct; char didBind; PRNetAddr bindAddr; /* Data returned by sockd. */ PRUint32 destHost; PRUint16 destPort;};typedef enum { OP_LESS = 1, OP_EQUAL = 2, OP_LEQUAL = 3, OP_GREATER = 4, OP_NOTEQUAL = 5, OP_GEQUAL = 6, OP_ALWAYS = 7} SocksOp;typedef struct SocksConfItemStr SocksConfItem;struct SocksConfItemStr { SocksConfItem *next; PRUint32 daddr; /* host IP addr, in network byte order. */ PRUint32 dmask; /* mask for IP, in network byte order. */ PRUint16 port; /* port number, in host byte order. */ SocksOp op; char direct;};static PRUint32 ourHost; /* network byte order. */static SocksConfItem *ssl_socks_confs;SECStatusssl_CreateSocksInfo(sslSocket *ss){ sslSocksInfo *si; if (ss->socks) { /* Already been done */ return SECSuccess; } si = (sslSocksInfo*) PORT_ZAlloc(sizeof(sslSocksInfo)); if (si) { ss->socks = si; if (!ss->gather) { ss->gather = ssl_NewGather(); if (!ss->gather) { return SECFailure; } } return SECSuccess; } return SECFailure;}SECStatusssl_CopySocksInfo(sslSocket *ss, sslSocket *os){ SECStatus rv;#ifdef __cplusplus os = os;#endif rv = ssl_CreateSocksInfo(ss); return rv;}voidssl_DestroySocksInfo(sslSocksInfo *si){ if (si) { PORT_Memset(si, 0x2f, sizeof *si); PORT_Free(si); }}/* Sets the global variable ourHost to the IP address returned from * calling GetHostByName on our system's name. * Called from SSL_ReadSocksConfFile(). */static SECStatusGetOurHost(void){ PRStatus rv; PRHostEnt hpbuf; char name[100]; char dbbuf[PR_NETDB_BUF_SIZE]; PR_GetSystemInfo(PR_SI_HOSTNAME, name, sizeof name); rv = PR_GetHostByName(name, dbbuf, sizeof dbbuf, &hpbuf); if (rv != PR_SUCCESS) return SECFailure;#undef h_addr#define h_addr h_addr_list[0] /* address, in network byte order. */ PORT_Memcpy(&ourHost, hpbuf.h_addr, hpbuf.h_length); return SECSuccess;}/*** Setup default SocksConfItem list so that loopback is direct, things to the** same subnet (?) address are direct, everything else uses sockd*/static voidBuildDefaultConfList(void){ SocksConfItem *ci; SocksConfItem **lp; /* Put loopback onto direct list */ lp = &ssl_socks_confs; ci = (SocksConfItem*) PORT_ZAlloc(sizeof(SocksConfItem)); if (!ci) { return; } ci->direct = 1; ci->daddr = MAKE_IN_ADDR(127,0,0,1); ci->dmask = MAKE_IN_ADDR(255,255,255,255); ci->op = OP_ALWAYS; *lp = ci; lp = &ci->next; /* Put our hosts's subnet onto direct list */ ci = (SocksConfItem*) PORT_ZAlloc(sizeof(SocksConfItem)); if (!ci) { return; } ci->direct = 1; ci->daddr = ourHost; ci->dmask = MAKE_IN_ADDR(255,255,255,0); ci->op = OP_ALWAYS; *lp = ci; lp = &ci->next; /* Everything else goes to sockd */ ci = (SocksConfItem*) PORT_ZAlloc(sizeof(SocksConfItem)); if (!ci) { return; } ci->daddr = MAKE_IN_ADDR(255,255,255,255); ci->op = OP_ALWAYS; *lp = ci;}static intFragmentLine(char *cp, char **argv, int maxargc){ int argc = 0; char *save; char ch; save = cp; for (; (ch = *cp) != 0; cp++) { if ((ch == '#') || (ch == '\n')) { /* Done */ break; } if (ch == ':') { break; } if ((ch == ' ') || (ch == '\t')) { /* Seperator. see if it seperated anything */ if (cp - save > 0) { /* Put a null at the end of the word */ *cp = 0; argc++; *argv++ = save; SSL_TRC(20, ("%d: SSL: argc=%d word=\"%s\"", SSL_GETPID(), argc, save)); if (argc == maxargc) { return argc; } } save = cp + 1; } } if (cp - save > 0) { *cp = 0; argc++; *argv = save; SSL_TRC(20, ("%d: SSL: argc=%d word=\"%s\"", SSL_GETPID(), argc, save)); } return argc;}/* XXX inet_addr? */static char *ConvertOne(char *cp, unsigned char *rvp){ char *s = PORT_Strchr(cp, '.'); if (s) { *s = 0; } *rvp = PORT_Atoi(cp) & 0xff; return s ? s+1 : cp;}/* returns host address in network byte order. */static PRUint32ConvertAddr(char *buf){ unsigned char b0, b1, b2, b3; PRUint32 addr; buf = ConvertOne(buf, &b0); buf = ConvertOne(buf, &b1); buf = ConvertOne(buf, &b2); buf = ConvertOne(buf, &b3); addr = ((PRUint32)b0 << 24) | ((PRUint32)b1 << 16) | ((PRUint32)b2 << 8) | (PRUint32)b3; /* host byte order. */ return PR_htonl(addr); /* network byte order. */}static char *ReadLine(char *buf, int len, PRFileDesc *fd){ char c, *p = buf; PRInt32 n; while(len > 0) { n = PR_Read(fd, &c, 1); if (n < 0) return NULL; if (n == 0) { if (p == buf) { return NULL; } *p = '\0'; return buf; } if (c == '\n') { *p = '\0'; return buf; } *p++ = c; len--; } *p = '\0'; return buf;}intSSL_ReadSocksConfFile(PRFileDesc *fp){ SocksConfItem * ci; SocksConfItem **lp; char * file = "socks file"; /* XXX Move to nav */ SocksOp op; int direct; int port = 0; int lineNumber = 0; int rv = GetOurHost(); if (rv < 0) { /* If we can't figure out our host id, use socks. Loser! */ return SECFailure; }#if 0 /* XXX Move to nav */ fp = XP_FileOpen(file, xpSocksConfig, XP_FILE_READ);#endif if (!fp) { BuildDefaultConfList(); return SECSuccess; } /* Parse config file and generate config item list */ lp = &ssl_socks_confs; for (;;) { char * s; char * argv[10]; int argc; PRUint32 daddr; PRUint32 dmask; char buf[1000]; s = ReadLine(buf, sizeof buf, fp); if (!s) { break; } lineNumber++; argc = FragmentLine(buf, argv, 10); if (argc < 3) { if (argc == 0) { /* must be a comment/empty line */ continue; }#ifdef XP_UNIX PR_fprintf(PR_STDERR, "%s:%d: bad config line\n", file, lineNumber);#endif continue; } if (PORT_Strcmp(argv[0], "direct") == 0) { direct = 1; } else if (PORT_Strcmp(argv[0], "sockd") == 0) { direct = 0; } else {#ifdef XP_UNIX PR_fprintf(PR_STDERR, "%s:%d: bad command: \"%s\"\n", file, lineNumber, argv[0]);#endif continue; } /* Look for port spec */ op = OP_ALWAYS; if (argc > 4) { if (PORT_Strcmp(argv[3], "lt") == 0) { op = OP_LESS; } else if (PORT_Strcmp(argv[3], "eq") == 0) { op = OP_EQUAL; } else if (PORT_Strcmp(argv[3], "le") == 0) { op = OP_LEQUAL; } else if (PORT_Strcmp(argv[3], "gt") == 0) { op = OP_GREATER; } else if (PORT_Strcmp(argv[3], "neq") == 0) { op = OP_NOTEQUAL; } else if (PORT_Strcmp(argv[3], "ge") == 0) { op = OP_GEQUAL; } else {#ifdef XP_UNIX PR_fprintf(PR_STDERR, "%s:%d: bad comparison op: \"%s\"\n", file, lineNumber, argv[3]);#endif continue; } port = PORT_Atoi(argv[4]); } ci = (SocksConfItem*) PORT_ZAlloc(sizeof(SocksConfItem)); if (!ci) { break; } daddr = ConvertAddr(argv[1]); /* net byte order. */ dmask = ConvertAddr(argv[2]); /* net byte order. */ ci->daddr = daddr; /* net byte order. */ ci->dmask = dmask; /* net byte order. */ ci->direct = direct; ci->op = op; ci->port = port; /* host byte order. */ daddr = PR_ntohl(daddr); /* host byte order. */ dmask = PR_ntohl(dmask); /* host byte order. */ SSL_TRC(10, ("%d: SSL: line=%d direct=%d addr=%d.%d.%d.%d mask=%d.%d.%d.%d op=%d port=%d", SSL_GETPID(), lineNumber, ci->direct, (daddr >> 24) & 0xff, (daddr >> 16) & 0xff, (daddr >> 8) & 0xff, (daddr >> 0) & 0xff, (dmask >> 24) & 0xff, (dmask >> 16) & 0xff, (dmask >> 8) & 0xff, (dmask >> 0) & 0xff, ci->op, ci->port)); *lp = ci; lp = &ci->next; } if (!ssl_socks_confs) { /* Empty file. Fix it for the user */ BuildDefaultConfList(); } return SECSuccess;}static intChooseAddress(sslSocket *ss, const PRNetAddr *direct){ PRUint32 dstAddr; PRUint16 dstPort; SocksConfItem *ci; int rv; if (!ssl_socks_confs) { rv = SSL_ReadSocksConfFile(NULL); if (rv) { return rv; } } /* ** Scan socks config info and look for a direct match or a force to ** use the sockd. Bail on first hit. */ dstAddr = direct->inet.ip; dstPort = PR_ntohs(direct->inet.port); ci = ssl_socks_confs; while (ci) { SSL_TRC(10, ( "%d: SSL[%d]: match, direct=%d daddr=0x%x mask=0x%x op=%d port=%d", SSL_GETPID(), ss->fd, ci->direct, PR_ntohl(ci->daddr), PR_ntohl(ci->dmask), ci->op, ci->port)); if ((ci->daddr & ci->dmask) == (dstAddr & ci->dmask)) { int portMatch = 0; switch (ci->op) { case OP_LESS: portMatch = dstPort < ci->port; break; case OP_EQUAL: portMatch = dstPort == ci->port; break; case OP_LEQUAL: portMatch = dstPort <= ci->port; break; case OP_GREATER: portMatch = dstPort > ci->port; break; case OP_NOTEQUAL: portMatch = dstPort != ci->port; break; case OP_GEQUAL: portMatch = dstPort >= ci->port; break; case OP_ALWAYS: portMatch = 1; break; } if (portMatch) { SSL_TRC(10, ("%d: SSL[%d]: socks config match", SSL_GETPID(), ss->fd)); return ci->direct; } } ci = ci->next; } SSL_TRC(10, ("%d: SSL[%d]: socks config: no match", SSL_GETPID(), ss->fd)); return 0;}/*** Find port # and host # of socks daemon. Use info in ss->socks struct** when valid. If not valid, try to figure it all out.*/static intFindDaemon(sslSocket *ss, PRNetAddr *out){ sslSocksInfo *si; PRUint32 host; /* network byte order. */ PRUint16 port; /* host byte order. */ PORT_Assert(ss->socks != 0); si = ss->socks; /* For now, assume we are using the socks daemon */ host = si->sockdHost; port = si->sockdPort;#ifdef XP_UNIX if (!port) { static char firstTime = 1; static PRUint16 sockdPort; if (firstTime) { struct servent *sp; firstTime = 0; sp = getservbyname("socks", "tcp"); if (sp) { sockdPort = sp->s_port; } else { SSL_TRC(10, ("%d: SSL[%d]: getservbyname of (socks,tcp) fails", SSL_GETPID(), ss->fd)); } } port = sockdPort; }#endif if (!port) { port = DEF_SOCKD_PORT; } if (host == 0) { SSL_TRC(10, ("%d: SSL[%d]: no socks server found", SSL_GETPID(), ss->fd)); PORT_SetError(PR_INVALID_ARGUMENT_ERROR); return SECFailure; } /* We know the ip addr of the socks server */ out->inet.family = PR_AF_INET; out->inet.port = PR_htons(port); out->inet.ip = host; host = PR_ntohl(host); /* now host byte order. */ SSL_TRC(10, ("%d: SSL[%d]: socks server at %d.%d.%d.%d:%d", SSL_GETPID(), ss->fd, (host >> 24) & 0xff, (host >> 16) & 0xff, (host >> 8) & 0xff, (host >> 0) & 0xff, port)); return SECSuccess;}/*** Send our desired address and our user name to the socks daemon.** cmd is either SOCKS_CONNECT (client) or SOCKS_BIND (server).*/static intSayHello(sslSocket *ss, int cmd, const PRNetAddr *sa, char *user){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?