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; }
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); }
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); }
/* 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; }