X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=jcc.c;h=edb15588634c1a2db0c40864ff4dc7e70eae24b1;hb=34bf407d7722634d6363c46dd4d0df00f53732ef;hp=c367919f4cee9ef500863ca618259b3ec4161581;hpb=e37a59aca86ce1f33b5979f7456084b11919b3b7;p=privoxy.git diff --git a/jcc.c b/jcc.c index c367919f..edb15588 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.75 2002/03/06 10:02:19 oes Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.78 2002/03/08 21:35:04 oes Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,16 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.75 2002/03/06 10:02:19 oes Exp $"; * * Revisions : * $Log: jcc.c,v $ + * Revision 1.78 2002/03/08 21:35:04 oes + * Added optional group supplement to --user option. Will now use default group of user if no group given + * + * Revision 1.77 2002/03/07 03:52:06 oes + * - Fixed compiler warnings etc + * - Improved handling of failed DNS lookups + * + * Revision 1.76 2002/03/06 22:54:35 jongfoster + * Automated function-comment nitpicking. + * * Revision 1.75 2002/03/06 10:02:19 oes * Fixed stupid bug when --user was not given * @@ -487,6 +497,7 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.75 2002/03/06 10:02:19 oes Exp $"; #ifdef unix #include +#include #endif # include @@ -667,13 +678,18 @@ static void chat(struct client_state *csp) #define IS_ENABLED_AND IS_TOGGLED_ON_AND IS_NOT_FORCED_AND char buf[BUFFER_SIZE]; - char *hdr, *p, *req; + char *hdr; + char *p; + char *req; fd_set rfds; - int n, maxfd, server_body; + int n; + jb_socket maxfd; + int server_body; int ms_iis5_hack = 0; int byte_count = 0; const struct forward_spec * fwd; struct http_request *http; + int len; /* for buffer sizes */ #ifdef FEATURE_KILL_POPUPS int block_popups; /* bool, 1==will block popups */ int block_popups_now = 0; /* bool, 1==currently blocking popups */ @@ -697,11 +713,11 @@ static void chat(struct client_state *csp) while (FOREVER) { - n = read_socket(csp->cfd, buf, sizeof(buf)); + len = read_socket(csp->cfd, buf, sizeof(buf)); - if (n <= 0) break; /* error! */ + if (len <= 0) break; /* error! */ - add_to_iob(csp, buf, n); + add_to_iob(csp, buf, len); req = get_header(csp); @@ -914,13 +930,13 @@ static void chat(struct client_state *csp) { if ( ( p = get_header(csp) ) && ( *p == '\0' ) ) { - n = read_socket(csp->cfd, buf, sizeof(buf)); - if (n <= 0) + len = read_socket(csp->cfd, buf, sizeof(buf)); + if (len <= 0) { log_error(LOG_LEVEL_ERROR, "read from client failed: %E"); return; } - add_to_iob(csp, buf, n); + add_to_iob(csp, buf, len); continue; } @@ -958,8 +974,8 @@ static void chat(struct client_state *csp) ) { /* Write the answer to the client */ - if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length) - || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length)) + if (write_socket(csp->cfd, rsp->head, rsp->head_length) + || write_socket(csp->cfd, rsp->body, rsp->content_length)) { log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); } @@ -994,7 +1010,7 @@ static void chat(struct client_state *csp) csp->sfd = forwarded_connect(fwd, http, csp); - if (csp->sfd < 0) + if (csp->sfd == JB_INVALID_SOCKET) { log_error(LOG_LEVEL_CONNECT, "connect to: %s failed: %E", http->hostport); @@ -1018,8 +1034,8 @@ static void chat(struct client_state *csp) /* Write the answer to the client */ if(rsp) { - if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length) - || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length)) + if (write_socket(csp->cfd, rsp->head, rsp->head_length) + || write_socket(csp->cfd, rsp->body, rsp->content_length)) { log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); } @@ -1046,10 +1062,8 @@ static void chat(struct client_state *csp) * (along with anything else that may be in the buffer) */ - n = strlen(hdr); - - if ((write_socket(csp->sfd, hdr, n) != n) - || (flush_socket(csp->sfd, csp ) < 0)) + if (write_socket(csp->sfd, hdr, strlen(hdr)) + || (flush_socket(csp->sfd, csp) < 0)) { log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E", http->hostport); @@ -1061,8 +1075,8 @@ static void chat(struct client_state *csp) if(rsp) { - if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length) - || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length)) + if (write_socket(csp->cfd, rsp->head, rsp->head_length) + || write_socket(csp->cfd, rsp->body, rsp->content_length)) { log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); } @@ -1083,7 +1097,7 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 2\n", csp->ip_addr_str, http->ocmd); - if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1) < 0) + if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1)) { freez(hdr); return; @@ -1123,14 +1137,14 @@ static void chat(struct client_state *csp) if (FD_ISSET(csp->cfd, &rfds)) { - n = read_socket(csp->cfd, buf, sizeof(buf)); + len = read_socket(csp->cfd, buf, sizeof(buf)); - if (n <= 0) + if (len <= 0) { break; /* "game over, man" */ } - if (write_socket(csp->sfd, buf, n) != n) + if (write_socket(csp->sfd, buf, len)) { log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); return; @@ -1148,9 +1162,9 @@ static void chat(struct client_state *csp) if (FD_ISSET(csp->sfd, &rfds)) { fflush( 0 ); - n = read_socket(csp->sfd, buf, sizeof(buf) - 1); + len = read_socket(csp->sfd, buf, sizeof(buf) - 1); - if (n < 0) + if (len < 0) { log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host); @@ -1161,8 +1175,8 @@ static void chat(struct client_state *csp) if(rsp) { - if ((write_socket(csp->cfd, rsp->head, rsp->head_length) != rsp->head_length) - || (write_socket(csp->cfd, rsp->body, rsp->content_length) != rsp->content_length)) + if (write_socket(csp->cfd, rsp->head, rsp->head_length) + || write_socket(csp->cfd, rsp->body, rsp->content_length)) { log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); } @@ -1175,7 +1189,7 @@ static void chat(struct client_state *csp) /* Add a trailing zero. This lets filter_popups * use string operations. */ - buf[n] = '\0'; + buf[len] = '\0'; #ifdef FEATURE_KILL_POPUPS /* Filter the popups on this read. */ @@ -1203,7 +1217,7 @@ static void chat(struct client_state *csp) * doesn't generate a valid header, then we won't * transmit anything to the client. */ - if (n == 0) + if (len == 0) { if (server_body || http->ssl) @@ -1232,10 +1246,8 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); } - n = strlen(hdr); - - if ((write_socket(csp->cfd, hdr, n) != n) - || (write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length) != (int)csp->content_length)) + if (write_socket(csp->cfd, hdr, strlen(hdr)) + || write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length)) { log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); return; @@ -1254,7 +1266,7 @@ static void chat(struct client_state *csp) * This is NOT the body, so * Let's pretend the server just sent us a blank line. */ - n = sprintf(buf, "\r\n"); + len = sprintf(buf, "\r\n"); /* * Now, let the normal header parsing algorithm below do its @@ -1274,7 +1286,7 @@ static void chat(struct client_state *csp) { if (content_filter) { - add_to_iob(csp, buf, n); + add_to_iob(csp, buf, len); /* * If the buffer limit will be reached on the next read, @@ -1292,11 +1304,11 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); } - n = strlen(hdr); - byte_count += n; + len = strlen(hdr); + byte_count += len; - if (((write_socket(csp->cfd, hdr, n) != n) - || (n = flush_socket(csp->cfd, csp) < 0))) + if (write_socket(csp->cfd, hdr, len) + || (len = flush_socket(csp->cfd, csp) < 0)) { log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); @@ -1305,7 +1317,7 @@ static void chat(struct client_state *csp) } freez(hdr); - byte_count += n; + byte_count += len; content_filter = NULL; server_body = 1; @@ -1314,13 +1326,13 @@ static void chat(struct client_state *csp) } else { - if (write_socket(csp->cfd, buf, n) != n) + if (write_socket(csp->cfd, buf, len)) { log_error(LOG_LEVEL_ERROR, "write to client failed: %E"); return; } } - byte_count += n; + byte_count += len; continue; } else @@ -1331,7 +1343,7 @@ static void chat(struct client_state *csp) */ /* buffer up the data we just read */ - add_to_iob(csp, buf, n); + add_to_iob(csp, buf, len); /* get header lines from the iob */ @@ -1386,13 +1398,6 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); } - n = strlen(hdr); - - /* write the server's (modified) header to - * the client (along with anything else that - * may be in the buffer) - */ - #ifdef FEATURE_KILL_POPUPS /* Start blocking popups if appropriate. */ @@ -1428,24 +1433,33 @@ static void chat(struct client_state *csp) content_filter = gif_deanimate_response; } - /* * Only write if we're not buffering for content modification */ - if (!content_filter && ((write_socket(csp->cfd, hdr, n) != n) - || (n = flush_socket(csp->cfd, csp) < 0))) + if (!content_filter) { - log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); - - /* the write failed, so don't bother - * mentioning it to the client... - * it probably can't hear us anyway. + /* write the server's (modified) header to + * the client (along with anything else that + * may be in the buffer) */ - freez(hdr); - return; - } - if(!content_filter) byte_count += n; + len = strlen(hdr); + + if (write_socket(csp->cfd, hdr, len) + || (len = flush_socket(csp->cfd, csp) < 0)) + { + log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); + + /* the write failed, so don't bother + * mentioning it to the client... + * it probably can't hear us anyway. + */ + freez(hdr); + return; + } + + byte_count += len; + } /* we're finished with the server's header */ @@ -1495,7 +1509,7 @@ static void serve(struct client_state *csp) chat(csp); close_socket(csp->cfd); - if (csp->sfd >= 0) + if (csp->sfd != JB_INVALID_SOCKET) { close_socket(csp->sfd); } @@ -1541,7 +1555,7 @@ static int32 server_thread(void *data) void usage(const char *myname) { printf("JunkBuster proxy version " VERSION " (" HOME_PAGE_URL ")\n" - "Usage: %s [--help] [--version] [--no-daemon] [--pidfile pidfile] [--user user] [configfile]\n" + "Usage: %s [--help] [--version] [--no-daemon] [--pidfile pidfile] [--user user[.group]] [configfile]\n" "Aborting.\n", myname); exit(2); @@ -1581,6 +1595,8 @@ int main(int argc, const char *argv[]) int argc_pos = 0; #ifdef unix struct passwd *pw = NULL; + struct group *grp = NULL; + char *p; #endif Argc = argc; @@ -1625,13 +1641,23 @@ int main(int argc, const char *argv[]) else if (strcmp(argv[argc_pos], "--user" ) == 0) { - if (++argc_pos == argc) usage(argv[0]); - pw = getpwnam(argv[argc_pos]); - - if (pw == NULL) + if (++argc_pos == argc) usage(argv[argc_pos]); + + if ((NULL != (p = strchr(argv[argc_pos], '.'))) && *(p + 1) != '0') + { + *p++ = '\0'; + if (NULL == (grp = getgrnam(p))) + { + log_error(LOG_LEVEL_FATAL, "Group %s not found.", p); + } + } + + if (NULL == (pw = getpwnam(argv[argc_pos]))) { log_error(LOG_LEVEL_FATAL, "User %s not found.", argv[argc_pos]); } + + if (p != NULL) *--p = '\0'; } #endif /* defined(unix) */ else @@ -1789,15 +1815,21 @@ int main(int argc, const char *argv[]) /* * As soon as we have written the PID file, we can switch - * to the user ID indicated by the --user option + * to the user and group ID indicated by the --user option */ write_pid_file(); - if ((NULL != pw) && setuid(pw->pw_uid)) + if (NULL != pw) { - log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions."); + if (((NULL != grp) && setgid(grp->gr_gid)) || (setgid(pw->pw_gid))) + { + log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions."); + } + if (setuid(pw->pw_uid)) + { + log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions."); + } } - } #endif /* defined unix */ @@ -1823,9 +1855,10 @@ int main(int argc, const char *argv[]) * Returns : Port that was opened. * *********************************************************************/ -static int bind_port_helper(struct configuration_spec * config) +static jb_socket bind_port_helper(struct configuration_spec * config) { - int bfd; + int result; + jb_socket bfd; if ( (config->haddr != NULL) && (config->haddr[0] == '1') @@ -1847,18 +1880,31 @@ static int bind_port_helper(struct configuration_spec * config) config->hport, config->haddr); } - bfd = bind_port(config->haddr, config->hport); + result = bind_port(config->haddr, config->hport, &bfd); - if (bfd < 0) + if (result < 0) { - log_error(LOG_LEVEL_FATAL, "can't bind %s:%d: %E " - "- There may be another junkbuster or some other " - "proxy running on port %d", - (NULL != config->haddr) ? config->haddr : "INADDR_ANY", - config->hport, config->hport - ); + switch(result) + { + case -3 : + log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: " + "There may be another junkbuster or some other " + "proxy running on port %d", + (NULL != config->haddr) ? config->haddr : "INADDR_ANY", + config->hport, config->hport); + + case -2 : + log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: " + "The hostname is not resolvable", + (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport); + + default : + log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: because %E", + (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport); + } + /* shouldn't get here */ - return -1; + return JB_INVALID_SOCKET; } config->need_bind = 0; @@ -1881,7 +1927,7 @@ static int bind_port_helper(struct configuration_spec * config) static void listen_loop(void) { struct client_state *csp = NULL; - int bfd; + jb_socket bfd; struct configuration_spec * config; config = load_config(); @@ -1920,7 +1966,7 @@ static void listen_loop(void) } csp->flags |= CSP_FLAG_ACTIVE; - csp->sfd = -1; + csp->sfd = JB_INVALID_SOCKET; csp->config = config = load_config();