int read_config (char *filename, struct parsedfile *config) { FILE *conf; char line[MAXLINE]; int rc = 0; int lineno = 1; struct serverent *server; /* Clear out the structure */ memset(config, 0x0, sizeof(*config)); /* Initialization */ currentcontext = &(config->defaultserver); /* If a filename wasn't provided, use the default */ if (filename == NULL) { strncpy(line, CONF_FILE, sizeof(line) - 1); /* Insure null termination */ line[sizeof(line) - 1] = (char) 0; filename = line; } /* Read the configuration file */ if ((conf = fopen(filename, "r")) == NULL) { show_msg(MSGERR, "Could not open socks configuration file " "(%s), assuming all networks local\n", filename); handle_local(config, 0, "0.0.0.0/0.0.0.0"); rc = 1; /* Severe errors reading configuration */ } else { memset(&(config->defaultserver), 0x0, sizeof(config->defaultserver)); while (NULL != fgets(line, MAXLINE, conf)) { /* This line _SHOULD_ end in \n so we */ /* just chop off the \n and hand it on */ if (strlen(line) > 0) line[strlen(line) - 1] = '\0'; handle_line(config, line, lineno); lineno++; } fclose(conf); /* Always add the 127.0.0.1/255.0.0.0 subnet to local */ handle_local(config, 0, "127.0.0.0/255.0.0.0"); /* Check default server */ check_server(&(config->defaultserver)); server = (config->paths); while (server != NULL) { check_server(server); server = server->next; } } return(rc); }
void assign_local ( void ) { signed long wlen; bool is_okay; u8 *savd_pc = pc; unsigned int savd_lineno = lineno; wlen = get_word(); if ( wlen <= 0 ) { warn_unterm(TKERROR, "Locals Assignment", lineno); return; } local_op = "!"; /* Set to Store */ is_okay = handle_local( statbuf); if( INVERSE(is_okay) ) { tokenization_error ( TKERROR, "Cannot apply -> to %s, only to a declared Local.\n", statbuf ); pc = savd_pc; lineno = savd_lineno; } local_op = "@"; /* Reset to Fetch */ }
static int handle_line(struct parsedfile *config, char *line, int lineno) { char *words[10]; static char savedline[MAXLINE]; int nowords = 0, i; /* Save the input string */ strncpy(savedline, line, MAXLINE - 1); savedline[MAXLINE - 1] = (char) 0; /* Tokenize the input string */ nowords = tokenize(line, 10, words); /* Set the spare slots to an empty string to simplify */ /* processing */ for (i = nowords; i < 10; i++) words[i] = ""; if (nowords > 0) { /* Now this can either be a "path" block starter or */ /* ender, otherwise it has to be a pair (<name> = */ /* <value>) */ if (!strcmp(words[0], "path")) { handle_path(config, lineno, nowords, words); } else if (!strcmp(words[0], "}")) { handle_endpath(config, lineno, nowords, words); } else { /* Has to be a pair */ if ((nowords != 3) || (strcmp(words[1], "="))) { show_msg(MSGERR, "Malformed configuration pair " "on line %d in configuration " "file, \"%s\"\n", lineno, savedline); } else if (!strcmp(words[0], "reaches")) { handle_reaches(config, lineno, words[2]); } else if (!strcmp(words[0], "server")) { handle_server(config, lineno, words[2]); } else if (!strcmp(words[0], "server_port")) { handle_port(config, lineno, words[2]); } else if (!strcmp(words[0], "server_type")) { handle_type(config, lineno, words[2]); } else if (!strcmp(words[0], "default_user")) { handle_defuser(config, lineno, words[2]); } else if (!strcmp(words[0], "default_pass")) { handle_defpass(config, lineno, words[2]); } else if (!strcmp(words[0], "local")) { handle_local(config, lineno, words[2]); } else { show_msg(MSGERR, "Invalid pair type (%s) specified " "on line %d in configuration file, " "\"%s\"\n", words[0], lineno, savedline); } } } return(0); }
static void read_from_cmd_socket(int sock_fd, int event, void *anything) { CMD_Request rx_message; CMD_Reply tx_message; int status, read_length, expected_length, rx_message_length; int localhost, allowed, log_index; union sockaddr_all where_from; socklen_t from_length; IPAddr remote_ip; unsigned short remote_port, rx_command; struct timeval now, cooked_now; rx_message_length = sizeof(rx_message); from_length = sizeof(where_from); status = recvfrom(sock_fd, (char *)&rx_message, rx_message_length, 0, &where_from.sa, &from_length); if (status < 0) { LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket %d", strerror(errno), sock_fd); return; } if (from_length > sizeof (where_from) || from_length <= sizeof (where_from.sa.sa_family)) { DEBUG_LOG(LOGF_CmdMon, "Read command packet without source address"); return; } read_length = status; /* Get current time cheaply */ SCH_GetLastEventTime(&cooked_now, NULL, &now); UTI_SockaddrToIPAndPort(&where_from.sa, &remote_ip, &remote_port); /* Check if it's from localhost (127.0.0.1, ::1, or Unix domain) */ switch (remote_ip.family) { case IPADDR_INET4: assert(sock_fd == sock_fd4); localhost = remote_ip.addr.in4 == INADDR_LOOPBACK; break; #ifdef FEAT_IPV6 case IPADDR_INET6: assert(sock_fd == sock_fd6); localhost = !memcmp(remote_ip.addr.in6, &in6addr_loopback, sizeof (in6addr_loopback)); break; #endif case IPADDR_UNSPEC: /* This should be the Unix domain socket */ if (where_from.sa.sa_family != AF_UNIX) return; assert(sock_fd == sock_fdu); localhost = 1; break; default: assert(0); } DEBUG_LOG(LOGF_CmdMon, "Received %d bytes from %s fd %d", status, UTI_SockaddrToString(&where_from.sa), sock_fd); if (!(localhost || ADF_IsAllowed(access_auth_table, &remote_ip))) { /* The client is not allowed access, so don't waste any more time on him. Note that localhost is always allowed access regardless of the defined access rules - otherwise, we could shut ourselves out completely! */ return; } if (read_length < offsetof(CMD_Request, data) || read_length < offsetof(CMD_Reply, data) || rx_message.pkt_type != PKT_TYPE_CMD_REQUEST || rx_message.res1 != 0 || rx_message.res2 != 0) { /* We don't know how to process anything like this or an error reply would be larger than the request */ DEBUG_LOG(LOGF_CmdMon, "Command packet dropped"); return; } expected_length = PKL_CommandLength(&rx_message); rx_command = ntohs(rx_message.command); tx_message.version = PROTO_VERSION_NUMBER; tx_message.pkt_type = PKT_TYPE_CMD_REPLY; tx_message.res1 = 0; tx_message.res2 = 0; tx_message.command = rx_message.command; tx_message.reply = htons(RPY_NULL); tx_message.status = htons(STT_SUCCESS); tx_message.pad1 = 0; tx_message.pad2 = 0; tx_message.pad3 = 0; tx_message.sequence = rx_message.sequence; tx_message.pad4 = 0; tx_message.pad5 = 0; if (rx_message.version != PROTO_VERSION_NUMBER) { DEBUG_LOG(LOGF_CmdMon, "Command packet has invalid version (%d != %d)", rx_message.version, PROTO_VERSION_NUMBER); if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT_SERVER) { tx_message.status = htons(STT_BADPKTVERSION); transmit_reply(&tx_message, &where_from); } return; } if (rx_command >= N_REQUEST_TYPES || expected_length < (int)offsetof(CMD_Request, data)) { DEBUG_LOG(LOGF_CmdMon, "Command packet has invalid command %d", rx_command); tx_message.status = htons(STT_INVALID); transmit_reply(&tx_message, &where_from); return; } if (read_length < expected_length) { DEBUG_LOG(LOGF_CmdMon, "Command packet is too short (%d < %d)", read_length, expected_length); tx_message.status = htons(STT_BADPKTLENGTH); transmit_reply(&tx_message, &where_from); return; } /* OK, we have a valid message. Now dispatch on message type and process it. */ log_index = CLG_LogCommandAccess(&remote_ip, &cooked_now); /* Don't reply to all requests from hosts other than localhost if the rate is excessive */ if (!localhost && log_index >= 0 && CLG_LimitCommandResponseRate(log_index)) { DEBUG_LOG(LOGF_CmdMon, "Command packet discarded to limit response rate"); return; } if (rx_command >= N_REQUEST_TYPES) { /* This should be already handled */ assert(0); } else { /* Check level of authority required to issue the command. All commands from the Unix domain socket (which is accessible only by the root and chrony user/group) are allowed. */ if (where_from.sa.sa_family == AF_UNIX) { assert(sock_fd == sock_fdu); allowed = 1; } else { switch (permissions[rx_command]) { case PERMIT_AUTH: allowed = 0; break; case PERMIT_LOCAL: allowed = localhost; break; case PERMIT_OPEN: allowed = 1; break; default: assert(0); allowed = 0; } } if (allowed) { switch(rx_command) { case REQ_NULL: /* Do nothing */ break; case REQ_DUMP: handle_dump(&rx_message, &tx_message); break; case REQ_ONLINE: handle_online(&rx_message, &tx_message); break; case REQ_OFFLINE: handle_offline(&rx_message, &tx_message); break; case REQ_BURST: handle_burst(&rx_message, &tx_message); break; case REQ_MODIFY_MINPOLL: handle_modify_minpoll(&rx_message, &tx_message); break; case REQ_MODIFY_MAXPOLL: handle_modify_maxpoll(&rx_message, &tx_message); break; case REQ_MODIFY_MAXDELAY: handle_modify_maxdelay(&rx_message, &tx_message); break; case REQ_MODIFY_MAXDELAYRATIO: handle_modify_maxdelayratio(&rx_message, &tx_message); break; case REQ_MODIFY_MAXDELAYDEVRATIO: handle_modify_maxdelaydevratio(&rx_message, &tx_message); break; case REQ_MODIFY_MAXUPDATESKEW: handle_modify_maxupdateskew(&rx_message, &tx_message); break; case REQ_MODIFY_MAKESTEP: handle_modify_makestep(&rx_message, &tx_message); break; case REQ_LOGON: /* Authentication is no longer supported, log-on always fails */ tx_message.status = htons(STT_FAILED); break; case REQ_SETTIME: handle_settime(&rx_message, &tx_message); break; case REQ_LOCAL2: handle_local(&rx_message, &tx_message); break; case REQ_MANUAL: handle_manual(&rx_message, &tx_message); break; case REQ_N_SOURCES: handle_n_sources(&rx_message, &tx_message); break; case REQ_SOURCE_DATA: handle_source_data(&rx_message, &tx_message); break; case REQ_REKEY: handle_rekey(&rx_message, &tx_message); break; case REQ_ALLOW: handle_allowdeny(&rx_message, &tx_message, 1, 0); break; case REQ_ALLOWALL: handle_allowdeny(&rx_message, &tx_message, 1, 1); break; case REQ_DENY: handle_allowdeny(&rx_message, &tx_message, 0, 0); break; case REQ_DENYALL: handle_allowdeny(&rx_message, &tx_message, 0, 1); break; case REQ_CMDALLOW: handle_cmdallowdeny(&rx_message, &tx_message, 1, 0); break; case REQ_CMDALLOWALL: handle_cmdallowdeny(&rx_message, &tx_message, 1, 1); break; case REQ_CMDDENY: handle_cmdallowdeny(&rx_message, &tx_message, 0, 0); break; case REQ_CMDDENYALL: handle_cmdallowdeny(&rx_message, &tx_message, 0, 1); break; case REQ_ACCHECK: handle_accheck(&rx_message, &tx_message); break; case REQ_CMDACCHECK: handle_cmdaccheck(&rx_message, &tx_message); break; case REQ_ADD_SERVER: handle_add_source(NTP_SERVER, &rx_message, &tx_message); break; case REQ_ADD_PEER: handle_add_source(NTP_PEER, &rx_message, &tx_message); break; case REQ_DEL_SOURCE: handle_del_source(&rx_message, &tx_message); break; case REQ_WRITERTC: handle_writertc(&rx_message, &tx_message); break; case REQ_DFREQ: handle_dfreq(&rx_message, &tx_message); break; case REQ_DOFFSET: handle_doffset(&rx_message, &tx_message); break; case REQ_TRACKING: handle_tracking(&rx_message, &tx_message); break; case REQ_SMOOTHING: handle_smoothing(&rx_message, &tx_message); break; case REQ_SMOOTHTIME: handle_smoothtime(&rx_message, &tx_message); break; case REQ_SOURCESTATS: handle_sourcestats(&rx_message, &tx_message); break; case REQ_RTCREPORT: handle_rtcreport(&rx_message, &tx_message); break; case REQ_TRIMRTC: handle_trimrtc(&rx_message, &tx_message); break; case REQ_CYCLELOGS: handle_cyclelogs(&rx_message, &tx_message); break; case REQ_CLIENT_ACCESSES_BY_INDEX2: handle_client_accesses_by_index(&rx_message, &tx_message); break; case REQ_MANUAL_LIST: handle_manual_list(&rx_message, &tx_message); break; case REQ_MANUAL_DELETE: handle_manual_delete(&rx_message, &tx_message); break; case REQ_MAKESTEP: handle_make_step(&rx_message, &tx_message); break; case REQ_ACTIVITY: handle_activity(&rx_message, &tx_message); break; case REQ_RESELECTDISTANCE: handle_reselect_distance(&rx_message, &tx_message); break; case REQ_RESELECT: handle_reselect(&rx_message, &tx_message); break; case REQ_MODIFY_MINSTRATUM: handle_modify_minstratum(&rx_message, &tx_message); break; case REQ_MODIFY_POLLTARGET: handle_modify_polltarget(&rx_message, &tx_message); break; case REQ_REFRESH: handle_refresh(&rx_message, &tx_message); break; case REQ_SERVER_STATS: handle_server_stats(&rx_message, &tx_message); break; default: DEBUG_LOG(LOGF_CmdMon, "Unhandled command %d", rx_command); tx_message.status = htons(STT_FAILED); break; } } else { tx_message.status = htons(STT_UNAUTH); } } /* Transmit the response */ { /* Include a simple way to lose one message in three to test resend */ static int do_it=1; if (do_it) { transmit_reply(&tx_message, &where_from); } #if 0 do_it = ((do_it + 1) % 3); #endif } }
int read_config (char *filename, struct parsedfile *config) { FILE *conf; char line[MAXLINE]; int rc = 0; int lineno = 1; struct serverent *server; /* Clear out the structure */ memset(config, 0x0, sizeof(*config)); /* Initialization */ currentcontext = &(config->defaultserver); /* Tordns defaults */ config->tordns_cache_size = 256; config->tordns_enabled = 1; /* If a filename wasn't provided, use the default */ if (filename == NULL) { strncpy(line, CONF_FILE, sizeof(line) - 1); /* Insure null termination */ line[sizeof(line) - 1] = (char) 0; filename = line; show_msg(MSGWARN, "Configuration file not provided by TORSOCKS_CONF_FILE " "environment variable, attempting to use defaults in %s.\n", filename); } /* If there is no configuration file use reasonable defaults for Tor */ if ((conf = fopen(filename, "r")) == NULL) { show_msg(MSGERR, "Could not open socks configuration file " "(%s) errno (%d), assuming sensible defaults for Tor.\n", filename, errno); memset(&(config->defaultserver), 0x0, sizeof(config->defaultserver)); check_server(&(config->defaultserver)); handle_local(config, 0, "127.0.0.0/255.0.0.0"); handle_local(config, 0, "10.0.0.0/255.0.0.0"); handle_local(config, 0, "192.168.0.0/255.255.0.0"); handle_local(config, 0, "172.16.0.0/255.240.0.0"); handle_local(config, 0, "169.254.0.0/255.255.0.0"); rc = 1; /* Severe errors reading configuration */ } else { memset(&(config->defaultserver), 0x0, sizeof(config->defaultserver)); while (NULL != fgets(line, MAXLINE, conf)) { /* This line _SHOULD_ end in \n so we */ /* just chop off the \n and hand it on */ if (strlen(line) > 0) line[strlen(line) - 1] = '\0'; handle_line(config, line, lineno); lineno++; } fclose(conf); /* Always add the 127.0.0.1/255.0.0.0 subnet to local */ handle_local(config, 0, "127.0.0.0/255.0.0.0"); /* We always consider this local, because many users' dsl routers act as their DNS. */ handle_local(config, 0, "10.0.0.0/255.0.0.0"); handle_local(config, 0, "192.168.0.0/255.255.0.0"); handle_local(config, 0, "172.16.0.0/255.240.0.0"); handle_local(config, 0, "169.254.0.0/255.255.0.0"); handle_local(config, 0, "192.168.0.0/255.255.0.0"); /* Check default server */ check_server(&(config->defaultserver)); server = (config->paths); while (server != NULL) { check_server(server); server = server->next; } } /* Initialize tordns deadpool_range if not supplied */ if(config->tordns_deadpool_range == NULL) { handle_tordns_deadpool_range(config, 0, "127.0.69.0/255.255.255.0"); } return(rc); }