/* lxp.c: a program to proxy SSL for Lynx using SSLeay */ /* remember to setenv https_proxy=http://127.0.0.1:5010/ */ /* and snews_proxy=nntp://127.0.0.1:5010/ */ /* gcc -O6 -I/usr/local/ssl/include lxp.c -lssl -lcrypto -s -o lxp */ #include #include #include #include #include #include "ssl.h" #define XBUFSIZ 4096 int main(int argc, char *argv[]) { SSL_CTX *ssl_ctx; SSL *ssl_conn; int n, flag; int lstn, acpt = -1, rnet = -1; fd_set fds; struct sockaddr_in sin, rsin; struct hostent *host; char *cp, *pp; char dns[128]; char xbuf[XBUFSIZ]; memset((char *) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; rsin = sin; sin.sin_port = htons(5010); lstn = socket(AF_INET, SOCK_STREAM, 0); bind(lstn, (struct sockaddr *) &sin, sizeof(sin)); ssl_ctx = SSL_CTX_new(); X509_set_default_verify_paths(ssl_ctx->cert); listen(lstn, 3); for (;;) { close(acpt); close(rnet); FD_ZERO(&fds); FD_SET(lstn, &fds); select(lstn + 1, &fds, NULL, NULL, NULL); n = sizeof(sin); acpt = accept(lstn, (struct sockaddr *) &sin, &n); flag = 0; do { /* get entire http header */ if ((n = read(acpt, &xbuf[flag], XBUFSIZ - flag)) < 0) break; flag += n; xbuf[flag] = 0; } while (!strstr(xbuf, "\r\n\r\n")); if (n < 0) continue; cp = strchr(xbuf, ' '); /* point at url */ if (!strncmp(++cp, "https://", 8)) rsin.sin_port = htons(443); else if (!strncmp(cp, "snews://", 8)) rsin.sin_port = htons(563); else continue; cp += 8; if ((pp = strchr(cp, '/')) || (pp = strchr(cp, ' ')) || (pp = strchr(cp, '\r'))) *pp++ = 0; /* isolate hostname */ strncpy(dns, cp, 125); if ((cp = strchr(dns, ':'))) *cp++ = 0, rsin.sin_port = htons(atoi(cp)); n = inet_addr(dns); if (n != -1) memcpy(&rsin.sin_addr, &n, sizeof(n)); else if ((host = gethostbyname(dns)) != NULL) memcpy(&rsin.sin_addr, host->h_addr, host->h_length); else continue; rnet = socket(AF_INET, SOCK_STREAM, 0); if ((n = connect(rnet, (struct sockaddr *) &(rsin), sizeof(sin))) < 0) continue; ssl_conn = SSL_new(ssl_ctx); SSL_set_fd(ssl_conn, rnet); if ((n = SSL_connect(ssl_conn)) < 0) continue; if( (cp = strstr(xbuf, "https://") )) { *cp++ = '/'; /* for lynx proxy https, forward edited header */ strcpy(cp, pp); /* delete https://x.y.z:p/ */ SSL_write(ssl_conn, xbuf, strlen(xbuf)); } do { FD_ZERO(&fds); FD_SET(rnet, &fds); FD_SET(acpt, &fds); select(1 + (rnet > acpt ? rnet : acpt), &fds, NULL, NULL, NULL); if (FD_ISSET(rnet, &fds) && (n = SSL_read(ssl_conn, xbuf, XBUFSIZ)) > 0) write(acpt, xbuf, n); if (FD_ISSET(acpt, &fds) && (n = read(acpt, xbuf, XBUFSIZ)) > 0) SSL_write(ssl_conn, xbuf, n); } while( n > 0 ); SSL_free(ssl_conn); } } .