Exemplo n.º 1
0
int httpd_next(int s, httpd_header emit_header, httpd_body emit_body, httpd_response emit_response) {
    struct sockaddr_in address;
    socklen_t addrlen = sizeof(address);
    int req = accept(s, (struct sockaddr*) &address, &addrlen);
    //if (req < 0) printf("ACCEPT=%d, errno=%d\n", req, errno);
    if (req < 0) return 0;

    int len = BUFSIZE;
    char *buffer = malloc(len);

    // -- process request line
    if (fdgetline(&buffer, &len, req) <= 0) return 0;
    char method[8];
    strncpy(method, strtok(buffer, " "), 8);
    method[7] = 0;
    char *path = strdup(strtok(NULL, " "));

    // -- process headers
    int expectedsize = -1;
    while (fdgetline(&buffer, &len, req) > 0) {
        if (emit_header) emit_header(buffer, method, path);
        if (strcmp(buffer, "Content-Length: ") == 0) {
            // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
            // http://stackoverflow.com/questions/2773396/whats-the-content-length-field-in-http-header
            strtok(buffer, " ");
            expectedsize = atoi(strtok(NULL, " "));
        }
    }
    if (emit_header) emit_header(NULL, method, path);

    // TODO: handle POST get parameters, also add paramter getter for path
    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
    // may need to handle different encodings...?
    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7

    // -- process body
    int bodycount = 0;

    // stop reading when got expectedsize bytes,
    // otherwise it'll block as browser keepalive doesn't close, thus no EOF
    int n = 1;
    len--; // remove capacity for 0 termination
    while (n > 0 && bodycount < expectedsize) {
        int remaining = expectedsize - bodycount;
        int n = (len > remaining) ? remaining : len;
        n = read(req, buffer, n);
        if (n < 0) break; // error
        buffer[n] = 0;
        bodycount += n;
        if (n > 0 && emit_body) emit_body(buffer, method, path);
    }
    free(buffer);
    if (emit_body) emit_body(NULL, method, path);

    if (emit_response) emit_response(req, method, path);

    if (path) free(path);
    close(req);
    return 1;
}
Exemplo n.º 2
0
int fdscanf(CLI *c, int fd, const char *format, char *buffer) {
    char line[STRLEN], lformat[STRLEN];
    int ptr, retval;

    fdgetline(c, fd, line);

    retval=sscanf(line, format, buffer);
    if(retval>=0)
        return retval;

    s_log(LOG_DEBUG, "fdscanf falling back to lowercase");
    safecopy(lformat, format);
    for(ptr=0; lformat[ptr]; ptr++)
        lformat[ptr]=tolower(lformat[ptr]);
    for(ptr=0; line[ptr]; ptr++)
        line[ptr]=tolower(line[ptr]);
    return sscanf(line, lformat, buffer);
}
Exemplo n.º 3
0
Arquivo: client.c Projeto: l7s/stunnel
static void auth_user(CLI *c) {
#ifndef _WIN32_WCE
    struct servent *s_ent;    /* structure for getservbyname */
#endif
    SOCKADDR_UNION ident;     /* IDENT socket name */
    char *line, *type, *system, *user;

    if(!c->opt->username)
        return; /* -u option not specified */
    c->fd=s_socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM,
        0, 1, "socket (auth_user)");
    if(c->fd<0)
        longjmp(c->err, 1);
    memcpy(&ident, &c->peer_addr.addr[0], sizeof ident);
#ifndef _WIN32_WCE
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else
#endif
    {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(connect_blocking(c, &ident, addr_len(ident)))
        longjmp(c->err, 1);
    s_log(LOG_DEBUG, "IDENT server connected");
    fdprintf(c, c->fd, "%u , %u",
        ntohs(c->peer_addr.addr[0].in.sin_port),
        ntohs(c->opt->local_addr.addr[0].in.sin_port));
    line=fdgetline(c, c->fd);
    closesocket(c->fd);
    c->fd=-1; /* avoid double close on cleanup */
    type=strchr(line, ':');
    if(!type) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *type++='\0';
    system=strchr(type, ':');
    if(!system) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *system++='\0';
    if(strcmp(type, " USERID ")) {
        s_log(LOG_ERR, "Incorrect INETD response type");
        str_free(line);
        longjmp(c->err, 1);
    }
    user=strchr(system, ':');
    if(!user) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *user++='\0';
    while(*user==' ') /* skip leading spaces */
        ++user;
    if(strcmp(user, c->opt->username)) {
        safestring(user);
        s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)",
            c->accepted_address, user);
        str_free(line);
        longjmp(c->err, 1);
    }
    s_log(LOG_INFO, "IDENT authentication passed");
    str_free(line);
}
Exemplo n.º 4
0
/*
	Returns:
		-1 = exit thread
		 1 = retry
		 0 = connected ok
*/
int connect_source(INPUT *r, int retries, int readbuflen, int *http_code) {
	CHANSRC *src = chansrc_init(r->channel->source);
	if (!src) {
		LOGf("ERR  : Can't parse channel source | Channel: %s Source: %s\n", r->channel->name, r->channel->source);
		FATAL_ERROR;
	}
	r->connected = 0;
	r->reconnect = 0;

	int active = 1;
	int dret = async_resolve_host(src->host, src->port, &(r->src_sockname), 5000, &active);
	if (dret != 0) {
		if (dret == 1)
			proxy_log(r, "Can't resolve host");
		if (dret == 2)
			proxy_log(r, "Timeout resolving host");
		DO_RECONNECT;
	}

	proxy_log(r, "Connecting");

	char buf[1024];
	*http_code = 0;
	if (src->sproto == tcp_sock) {
		r->sock = socket(PF_INET, SOCK_STREAM, 0);
		if (r->sock < 0) {
			log_perror("play(): Could not create SOCK_STREAM socket.", errno);
			FATAL_ERROR;
		}
		//proxy_log(r, "Add");
		if (do_connect(r->sock, (struct sockaddr *)&(r->src_sockname), sizeof(r->src_sockname), PROXY_CONNECT_TIMEOUT) < 0) {
			LOGf("ERR  : Error connecting to %s srv_fd: %i err: %s\n", r->channel->source, r->sock, strerror(errno));
			DO_RECONNECT;
		}

		snprintf(buf,sizeof(buf)-1, "GET /%s HTTP/1.0\nHost: %s:%u\nX-Smart-Client: yes\nUser-Agent: %s %s (%s)\n\n",
		         src->path, src->host, src->port, server_sig, server_ver, config->ident);
		buf[sizeof(buf)-1] = 0;
		fdwrite(r->sock, buf, strlen(buf));

		char xresponse[128];
		memset(xresponse, 0, sizeof(xresponse));
		memset(buf, 0, sizeof(buf));
		regmatch_t res[4];
		while (fdgetline(r->sock,buf,sizeof(buf)-1)) {
			if (buf[0] == '\n' || buf[0] == '\r')
				break;
			if (strstr(buf,"HTTP/1.") != NULL) {
				regex_t http_response;
				regcomp(&http_response, "^HTTP/1.[0-1] (([0-9]{3}) .*)", REG_EXTENDED);
				if (regexec(&http_response,buf,3,res,0) != REG_NOMATCH) {
					char codestr[4];
					if ((unsigned int)res[1].rm_eo-res[1].rm_so < sizeof(xresponse)) {
						strncpy(xresponse, &buf[res[1].rm_so], res[1].rm_eo-res[1].rm_so);
						xresponse[res[1].rm_eo-res[1].rm_so] = '\0';
						chomp(xresponse);
						strncpy(codestr, &buf[res[2].rm_so], res[2].rm_eo-res[2].rm_so);
						codestr[3] = 0;
						*http_code = atoi(codestr);
					}
				}
				regfree(&http_response);
			}
			if (*http_code == 504) { // Extract extra error code
				if (strstr(buf, "X-ErrorCode: ") != NULL) {
					*http_code = atoi(buf+13);
					break;
				}
			}
		}
		if (*http_code == 0) { // No valid HTTP response, retry
			LOGf("DEBUG: Server returned not valid HTTP code | srv_fd: %i\n", r->sock);
			DO_RECONNECT;
		}
		if (*http_code == 504) { // No signal, exit
			LOGf("ERR  : Get no-signal for %s from %s on srv_fd: %i\n", r->channel->name, r->channel->source, r->sock);
			FATAL_ERROR;
		}
		if (*http_code > 300) { // Unhandled or error codes, exit
			LOGf("ERR  : Get code %i for %s from %s on srv_fd: %i exiting.\n", *http_code, r->channel->name, r->channel->source, r->sock);
			FATAL_ERROR;
		}
		// connected ok, continue
	} else {
		if (!IN_MULTICAST(ntohl(r->src_sockname.sin_addr.s_addr))) {
			LOGf("ERR  : %s is not multicast address\n", r->channel->source);
			FATAL_ERROR;
		}
		struct ip_mreq mreq;
		struct sockaddr_in receiving_from;

		r->sock = socket(PF_INET, SOCK_DGRAM, 0);
		if (r->sock < 0) {
			log_perror("play(): Could not create SOCK_DGRAM socket.", errno);
			FATAL_ERROR;
		}
		// LOGf("CONN : Listening on multicast socket %s srv_fd: %i retries left: %i\n", r->channel->source, r->sock, retries);
		int on = 1;
		setsockopt(r->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
		// subscribe to multicast group
		memcpy(&mreq.imr_multiaddr, &(r->src_sockname.sin_addr), sizeof(struct in_addr));
		mreq.imr_interface.s_addr = htonl(INADDR_ANY);
		if (setsockopt(r->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
			LOGf("ERR  : Failed to add IP membership on %s srv_fd: %i\n", r->channel->source, r->sock);
			FATAL_ERROR;
		}
		// bind to the socket so data can be read
		memset(&receiving_from, 0, sizeof(receiving_from));
		receiving_from.sin_family = AF_INET;
		receiving_from.sin_addr   = r->src_sockname.sin_addr;
		receiving_from.sin_port   = htons(src->port);
		if (bind(r->sock, (struct sockaddr *) &receiving_from, sizeof(receiving_from)) < 0) {
			LOGf("ERR  : Failed to bind to %s srv_fd: %i\n", r->channel->source, r->sock);
			FATAL_ERROR;
		}
	}

	if (setsockopt(r->sock, SOL_SOCKET, SO_RCVBUF, (const char *)&readbuflen, sizeof(readbuflen)) < 0)
		log_perror("play(): setsockopt(SO_RCVBUF)", errno);

	r->connected = 1;

//	proxy_log(r, "Connected");
	chansrc_free(&src);
	return 0;
}