예제 #1
0
파일: tunnel.c 프로젝트: CeKMTL/polipo
static void
destroyTunnel(TunnelPtr tunnel)
{
    assert(tunnel->fd1 < 0 && tunnel->fd2 < 0);
    releaseAtom(tunnel->hostname);
    if(tunnel->buf1.buf)
        dispose_chunk(tunnel->buf1.buf);
    if(tunnel->buf2.buf)
        dispose_chunk(tunnel->buf2.buf);
    free(tunnel);
}
예제 #2
0
파일: local.c 프로젝트: tricky1997/wifisec
static void
fillSpecialObject(ObjectPtr object, void (*fn) (FILE *, char *), void *closure)
{
	FILE *tmp = NULL;
	char *buf = NULL;
	int rc, len, offset;

	if (object->flags & OBJECT_INPROGRESS)
		return;

	buf = get_chunk();
	if (buf == NULL) {
		abortObject(object, 503, internAtom("Couldn't allocate chunk"));
		goto done;
	}

	tmp = tmpfile();
	if (tmp == NULL) {
		abortObject(object, 503, internAtom(pstrerror(errno)));
		goto done;
	}

	(*fn) (tmp, closure);
	fflush(tmp);

	rewind(tmp);
	offset = 0;
	while (1) {
		len = fread(buf, 1, CHUNK_SIZE, tmp);
		if (len <= 0 && ferror(tmp)) {
			abortObject(object, 503, internAtom(pstrerror(errno)));
			goto done;
		}
		if (len <= 0)
			break;

		rc = objectAddData(object, buf, offset, len);
		if (rc < 0) {
			abortObject(object, 503,
				    internAtom("Couldn't add data to object"));
			goto done;
		}

		offset += len;
	}

	object->length = offset;

      done:
	if (buf)
		dispose_chunk(buf);
	if (tmp)
		fclose(tmp);
	notifyObject(object);
}
예제 #3
0
파일: tunnel.c 프로젝트: tricky1997/wifisec
void do_tunnel(int fd, char *buf, int offset, int len, AtomPtr url)
{
    int n;
    assert(buf);
    (void)offset;
    (void)len;
    n = httpWriteErrorHeaders(buf, CHUNK_SIZE, 0, 1,
                              501, internAtom("CONNECT not available "
                                      "in this version."),
                              1, NULL, url->string, url->length, NULL);
    releaseAtom(url);
    if (n >= 0) {
        write(fd, buf, n);
    }
    dispose_chunk(buf);
    lingeringClose(fd);
    return;
}
예제 #4
0
파일: tunnel.c 프로젝트: CeKMTL/polipo
void
do_tunnel(int fd, char *buf, int offset, int len, AtomPtr url)
{
    int n;
    assert(buf);

    n = httpWriteErrorHeaders(buf, CHUNK_SIZE, 0, 1,
                              501, internAtom("CONNECT not available "
                                              "in this version."),
                              1, NULL, url->string, url->length, NULL);
    releaseAtom(url);
    if(n >= 0) {
        /* This is completely wrong.  The write is non-blocking, and we 
           don't reschedule it if it fails.  But then, if the write
           blocks, we'll simply drop the connection with no error message. */
        write(fd, buf, n);
    }
    dispose_chunk(buf);
    lingeringClose(fd);
    return;
}
예제 #5
0
파일: http.c 프로젝트: strongwillow/polipo
void
initHttp()
{
    char *buf = NULL;
    int namelen;
    int n;
    struct hostent *host;

    initHttpParser();

    atom100Continue = internAtom("100-continue");

    if(clientTimeout <= serverTimeout) {
        clientTimeout = serverTimeout + 1;
        do_log(L_WARN, "Value of clientTimeout too small -- setting to %d.\n",
               clientTimeout);
    }

    if(displayName == NULL)
        displayName = internAtom("Polipo");

    if(authCredentials != NULL && authRealm == NULL)
        authRealm = internAtom("Polipo");

    if(allowedClients) {
        allowedNets = parseNetAddress(allowedClients);
        if(allowedNets == NULL)
            exit(1);
    }

    if(allowedPorts == NULL) {
        allowedPorts = makeIntList(0);
        if(allowedPorts == NULL) {
            do_log(L_ERROR, "Couldn't allocate allowedPorts.\n");
            exit(1);
        }
        intListCons(80, 100, allowedPorts);
        intListCons(1024, 0xFFFF, allowedPorts);
    }

    if(tunnelAllowedPorts == NULL) {
        tunnelAllowedPorts = makeIntList(0);
        if(tunnelAllowedPorts == NULL) {
            do_log(L_ERROR, "Couldn't allocate tunnelAllowedPorts.\n");
            exit(1);
        }
        intListCons(22, 22, tunnelAllowedPorts);   /* ssh */
        intListCons(80, 80, tunnelAllowedPorts);   /* HTTP */
        intListCons(109, 110, tunnelAllowedPorts); /* POP 2 and 3*/
        intListCons(143, 143, tunnelAllowedPorts); /* IMAP 2/4 */
        intListCons(443, 443, tunnelAllowedPorts); /* HTTP/SSL */
        intListCons(873, 873, tunnelAllowedPorts); /* rsync */
        intListCons(993, 993, tunnelAllowedPorts); /* IMAP/SSL */
        intListCons(995, 995, tunnelAllowedPorts); /* POP/SSL */
        intListCons(2401, 2401, tunnelAllowedPorts); /* CVS */
        intListCons(5222, 5223, tunnelAllowedPorts); /* Jabber */
        intListCons(9418, 9418, tunnelAllowedPorts); /* Git */
    }

    if(proxyName)
        return;

    buf = get_chunk();
    if(buf == NULL) {
        do_log(L_ERROR, "Couldn't allocate chunk for host name.\n");
        goto fail;
    }

    n = gethostname(buf, CHUNK_SIZE);
    if(n != 0) {
        do_log_error(L_WARN, errno, "Gethostname");
        strcpy(buf, "polipo");
        goto success;
    }
    /* gethostname doesn't necessarily NUL-terminate on overflow */
    buf[CHUNK_SIZE - 1] = '\0';

    if(strcmp(buf, "(none)") == 0 ||
       strcmp(buf, "localhost") == 0 ||
       strcmp(buf, "localhost.localdomain") == 0) {
        do_log(L_WARN, "Couldn't determine host name -- using ``polipo''.\n");
        strcpy(buf, "polipo");
        goto success;
    }

    if(strchr(buf, '.') != NULL)
        goto success;

    host = gethostbyname(buf);
    if(host == NULL) {
        goto success;
    }

    if(host->h_addrtype != AF_INET)
        goto success;

    host = gethostbyaddr(host->h_addr_list[0], host->h_length,  AF_INET);

    if(!host || !host->h_name || strcmp(host->h_name, "localhost") == 0 ||
       strcmp(host->h_name, "localhost.localdomain") == 0)
        goto success;

    namelen = strlen(host->h_name);
    if(namelen >= CHUNK_SIZE) {
        do_log(L_ERROR, "Host name too long.\n");
        goto success;
    }

    memcpy(buf, host->h_name, namelen + 1);

 success:
    proxyName = internAtom(buf);
    if(proxyName == NULL) {
        do_log(L_ERROR, "Couldn't allocate proxy name.\n");
        goto fail;
    }
    dispose_chunk(buf);
    return;

 fail:
    if(buf)
        dispose_chunk(buf);
    exit(1);
    return;
}
예제 #6
0
파일: local.c 프로젝트: tricky1997/wifisec
int
specialRequestHandler(int status,
		      FdEventHandlerPtr event, StreamRequestPtr srequest)
{
	SpecialRequestPtr request = srequest->data;
	int rc;
	int killed = 0;

	(void)event;
	if (status < 0) {
		kill(request->pid, SIGTERM);
		killed = 1;
		request->object->flags &= ~OBJECT_INPROGRESS;
		abortObject(request->object, 502,
			    internAtomError(-status,
					    "Couldn't read from client"));
		goto done;
	}

	if (srequest->offset > 0) {
		rc = objectAddData(request->object, request->buf,
				   request->offset, srequest->offset);
		if (rc < 0) {
			kill(request->pid, SIGTERM);
			killed = 1;
			request->object->flags &= ~OBJECT_INPROGRESS;
			abortObject(request->object, 503,
				    internAtom
				    ("Couldn't add data to connection"));
			goto done;
		}
		request->offset += srequest->offset;
	}
	if (status) {
		request->object->flags &= ~OBJECT_INPROGRESS;
		request->object->length = request->object->size;
		goto done;
	}

	if (request->object->refcount <= 1) {
		kill(request->pid, SIGTERM);
		killed = 1;
		request->object->flags &= ~OBJECT_INPROGRESS;
		abortObject(request->object, 500, internAtom("Aborted"));
		goto done;
	}
	notifyObject(request->object);
	do_stream(IO_READ | IO_NOTNOW, request->fd, 0, request->buf, CHUNK_SIZE,
		  specialRequestHandler, request);
	return 1;

      done:
	close(request->fd);
	dispose_chunk(request->buf);
	releaseNotifyObject(request->object);
	do {
		rc = waitpid(request->pid, &status, 0);
	} while (rc < 0 && errno == EINTR);
	if (rc < 0) {
		do_log(L_ERROR, "Wait for %d: %d\n", (int)request->pid, errno);
	} else {
		int normal =
		    (WIFEXITED(status) && WEXITSTATUS(status) == 0) ||
		    (killed && WIFSIGNALED(status)
		     && WTERMSIG(status) == SIGTERM);
		char *reason =
		    WIFEXITED(status) ? "with status" : WIFSIGNALED(status) ?
		    "on signal" : "with unknown status";
		int value =
		    WIFEXITED(status) ? WEXITSTATUS(status) :
		    WIFSIGNALED(status) ? WTERMSIG(status) : status;
		do_log(normal ? D_CHILD : L_ERROR, "Child %d exited %s %d.\n",
		       (int)request->pid, reason, value);
	}
	free(request);
	return 1;
}
예제 #7
0
파일: tunnel.c 프로젝트: CeKMTL/polipo
static void
tunnelDispatch(TunnelPtr tunnel)
{
    if(circularBufferEmpty(&tunnel->buf1)) {
        if(tunnel->buf1.buf && 
           !(tunnel->flags & (TUNNEL_READER1 | TUNNEL_WRITER2))) {
            dispose_chunk(tunnel->buf1.buf);
            tunnel->buf1.buf = NULL;
            tunnel->buf1.head = tunnel->buf1.tail = 0;
        }
    }

    if(circularBufferEmpty(&tunnel->buf2)) {
        if(tunnel->buf2.buf &&
           !(tunnel->flags & (TUNNEL_READER2 | TUNNEL_WRITER1))) {
            dispose_chunk(tunnel->buf2.buf);
            tunnel->buf2.buf = NULL;
            tunnel->buf2.head = tunnel->buf2.tail = 0;
        }
    }

    if(tunnel->fd1 >= 0) {
        if(!(tunnel->flags & (TUNNEL_READER1 | TUNNEL_EOF1)) && 
           !circularBufferFull(&tunnel->buf1)) {
            tunnel->flags |= TUNNEL_READER1;
            bufRead(tunnel->fd1, &tunnel->buf1, tunnelRead1Handler, tunnel);
        }
        if(!(tunnel->flags & (TUNNEL_WRITER1 | TUNNEL_EPIPE1)) &&
           !circularBufferEmpty(&tunnel->buf2)) {
            tunnel->flags |= TUNNEL_WRITER1;
            /* There's no IO_NOTNOW in bufWrite, so it might close the
               file descriptor straight away.  Wait until we're
               rescheduled. */
            bufWrite(tunnel->fd1, &tunnel->buf2, tunnelWrite1Handler, tunnel);
            return;
        }
        if(tunnel->fd2 < 0 || (tunnel->flags & TUNNEL_EOF2)) {
            if(!(tunnel->flags & TUNNEL_EPIPE1))
                shutdown(tunnel->fd1, 1);
            tunnel->flags |= TUNNEL_EPIPE1;
        } else if(tunnel->fd1 < 0 || (tunnel->flags & TUNNEL_EPIPE2)) {
            if(!(tunnel->flags & TUNNEL_EOF1))
                shutdown(tunnel->fd1, 0);
            tunnel->flags |= TUNNEL_EOF1;
        }
        if((tunnel->flags & TUNNEL_EOF1) && (tunnel->flags & TUNNEL_EPIPE1)) {
            if(!(tunnel->flags & (TUNNEL_READER1 | TUNNEL_WRITER1))) {
                CLOSE(tunnel->fd1);
                tunnel->fd1 = -1;
            }
        }
    }

    if(tunnel->fd2 >= 0) {
        if(!(tunnel->flags & (TUNNEL_READER2 | TUNNEL_EOF2)) && 
           !circularBufferFull(&tunnel->buf2)) {
            tunnel->flags |= TUNNEL_READER2;
            bufRead(tunnel->fd2, &tunnel->buf2, tunnelRead2Handler, tunnel);
        }
        if(!(tunnel->flags & (TUNNEL_WRITER2 | TUNNEL_EPIPE2)) &&
           !circularBufferEmpty(&tunnel->buf1)) {
            tunnel->flags |= TUNNEL_WRITER2;
            bufWrite(tunnel->fd2, &tunnel->buf1, tunnelWrite2Handler, tunnel);
            return;
        }
        if(tunnel->fd1 < 0 || (tunnel->flags & TUNNEL_EOF1)) {
            if(!(tunnel->flags & TUNNEL_EPIPE2))
                shutdown(tunnel->fd2, 1);
            tunnel->flags |= TUNNEL_EPIPE2;
        } else if(tunnel->fd1 < 0 || (tunnel->flags & TUNNEL_EPIPE1)) {
            if(!(tunnel->flags & TUNNEL_EOF2))
                shutdown(tunnel->fd2, 0);
            tunnel->flags |= TUNNEL_EOF2;
        }
        if((tunnel->flags & TUNNEL_EOF2) && (tunnel->flags & TUNNEL_EPIPE2)) {
            if(!(tunnel->flags & (TUNNEL_READER2 | TUNNEL_WRITER2))) {
                CLOSE(tunnel->fd2);
                tunnel->fd2 = -1;
            }
        }
    }

    if(tunnel->fd1 < 0 && tunnel->fd2 < 0)
        destroyTunnel(tunnel);
    else
        assert(tunnel->flags & (TUNNEL_READER1 | TUNNEL_WRITER1 |
                                TUNNEL_READER2 | TUNNEL_WRITER2));
}
예제 #8
0
파일: tunnel.c 프로젝트: CeKMTL/polipo
void 
do_tunnel(int fd, char *buf, int offset, int len, AtomPtr url)
{
    TunnelPtr tunnel;
    int port;
    char *p, *q;

    tunnel = makeTunnel(fd, buf, offset, len);
    if(tunnel == NULL) {
        do_log(L_ERROR, "Couldn't allocate tunnel.\n");
        releaseAtom(url);
        dispose_chunk(buf);
        CLOSE(fd);
        return;
    }

    if(proxyOffline) {
        do_log(L_INFO, "Attemted CONNECT when disconnected.\n");
        releaseAtom(url);
        tunnelError(tunnel, 502,
                    internAtom("Cannot CONNECT when disconnected."));
        return;
    }

    p = memrchr(url->string, ':', url->length);
    q = NULL;
    if(p)
        port = strtol(p + 1, &q, 10);
    if(!p || q != url->string + url->length) {
        do_log(L_ERROR, "Couldn't parse CONNECT.\n");
        releaseAtom(url);
        tunnelError(tunnel, 400, internAtom("Couldn't parse CONNECT"));
        return;
    }
    tunnel->hostname = internAtomLowerN(url->string, p - url->string);
    if(tunnel->hostname == NULL) {
        releaseAtom(url);
        tunnelError(tunnel, 501, internAtom("Couldn't allocate hostname"));
        return;
    }

    if(!intListMember(port, tunnelAllowedPorts)) {
        releaseAtom(url);
        tunnelError(tunnel, 403, internAtom("Forbidden port"));
        return;
    }
    tunnel->port = port;
    
    if (tunnelIsMatched(url->string, url->length, 
			tunnel->hostname->string, tunnel->hostname->length)) {
        releaseAtom(url);
        tunnelError(tunnel, 404, internAtom("Forbidden tunnel"));
	logTunnel(tunnel,1);
        return;
    }
    
    logTunnel(tunnel,0);
    
    releaseAtom(url);

    if(socksParentProxy)
        do_socks_connect(parentHost ?
                         parentHost->string : tunnel->hostname->string,
                         parentHost ? parentPort : tunnel->port,
                         tunnelSocksHandler, tunnel);
    else
        do_gethostbyname(parentHost ?
                         parentHost->string : tunnel->hostname->string, 0,
                         tunnelDnsHandler, tunnel);
}
예제 #9
0
파일: tunnel.c 프로젝트: Psiphon-Inc/polipo
void
do_tunnel(int fd, char *buf, int offset, int len, AtomPtr url)
{
    TunnelPtr tunnel;
    int port;
    char *p, *q;

    /* PSIPHON */
    if(psiphonStats)
    {
        /* Update the page view stats by printf-ing the URI. Our stdout is piped to
           the client process. */
        printf("PSIPHON-PAGE-VIEW-HTTPS:>>%s<<\n", url->string);
        fflush(NULL);
    }
    /* /PSIPHON */

    tunnel = makeTunnel(fd, buf, offset, len);
    if(tunnel == NULL) {
        do_log(L_ERROR, "Couldn't allocate tunnel.\n");
        releaseAtom(url);
        dispose_chunk(buf);
        CLOSE(fd);
        return;
    }

    if(proxyOffline) {
        do_log(L_INFO, "Attemted CONNECT when disconnected.\n");
        releaseAtom(url);
        tunnelError(tunnel, 502,
                    internAtom("Cannot CONNECT when disconnected."));
        return;
    }

    p = memrchr(url->string, ':', url->length);
    q = NULL;
    if(p)
        port = strtol(p + 1, &q, 10);
    if(!p || q != url->string + url->length) {
        do_log(L_ERROR, "Couldn't parse CONNECT.\n");
        releaseAtom(url);
        tunnelError(tunnel, 400, internAtom("Couldn't parse CONNECT"));
        return;
    }
    tunnel->hostname = internAtomLowerN(url->string, p - url->string);
    if(tunnel->hostname == NULL) {
        releaseAtom(url);
        tunnelError(tunnel, 501, internAtom("Couldn't allocate hostname"));
        return;
    }

    /* PSIPHON
       Checking if tunnel is allowed on a particular port is not needed if the
       proxy accepts connections made only from localhost */
    /*
    if(!intListMember(port, tunnelAllowedPorts)) {
        releaseAtom(url);
        tunnelError(tunnel, 403, internAtom("Forbidden port"));
        return;
    }
    */
    /* /PSIPHON */

    tunnel->port = port;

    if (tunnelIsMatched(url->string, url->length,
			tunnel->hostname->string, tunnel->hostname->length)) {
        releaseAtom(url);
        tunnelError(tunnel, 404, internAtom("Forbidden tunnel"));
	logTunnel(tunnel,1);
        return;
    }

    logTunnel(tunnel,0);

    releaseAtom(url);

    /* PSIPHON split tunneling option*/
    /* This was the original:
    if(socksParentProxy)
        do_socks_connect(parentHost ?
                         parentHost->string : tunnel->hostname->string,
                         parentHost ? parentPort : tunnel->port,
                         tunnelSocksHandler, tunnel);
    */
    if(socksParentProxy) {
        if(splitTunneling)
        {
            do_gethostbyname_socks(parentHost ?
                    parentHost->string : tunnel->hostname->string, 0,
                    tunnelSplitTunnelingDnsHandler, tunnel);
        }
        else
        {
            do_socks_connect(parentHost ?
                    parentHost->string : tunnel->hostname->string,
                    parentHost ? parentPort : tunnel->port,
                    tunnelSocksHandler, tunnel);
        }
    }
    /* /PSIPHON */
    else
        do_gethostbyname(parentHost ?
                         parentHost->string : tunnel->hostname->string, 0,
                         tunnelDnsHandler, tunnel);
}