/** * Assumes that "tuple" represents a IPv4-UDP or ICMP packet, and filters and updates based on it. * * This is RFC 6146, second halves of both sections 3.5.1 and 3.5.3. * * @param[in] skb tuple's packet. This is actually only used for error reporting. * @param[in] tuple summary of the packet Jool is currently translating. * @return VER_CONTINUE if everything went OK, VER_DROP otherwise. */ static verdict ipv4_simple(struct packet *pkt, struct tuple *tuple4) { int error; struct bib_entry *bib; struct session_entry *session; error = get_bib_ipv4(pkt, tuple4, &bib); if (error == -ESRCH) return VERDICT_ACCEPT; else if (error) return VERDICT_DROP; log_bib(bib); error = sessiondb_get_or_create_ipv4(tuple4, bib, &session); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); bib_return(bib); return VERDICT_DROP; } log_session(session); session_return(session); bib_return(bib); return VERDICT_CONTINUE; }
/** * Assumes that "tuple" represents a IPv6-UDP or ICMP packet, and filters and updates based on it. * * This is RFC 6146, first halves of both sections 3.5.1 and 3.5.3. * * @param[in] skb tuple's packet. This is actually only used for error reporting. * @param[in] tuple summary of the packet Jool is currently translating. * @return VER_CONTINUE if everything went OK, VER_DROP otherwise. */ static verdict ipv6_simple(struct packet *pkt, struct tuple *tuple6) { struct bib_entry *bib; struct session_entry *session; int error; error = bibdb_get_or_create_ipv6(pkt, tuple6, &bib); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); return VERDICT_DROP; } log_bib(bib); error = sessiondb_get_or_create_ipv6(tuple6, bib, &session); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); bib_return(bib); return VERDICT_DROP; } log_session(session); session_return(session); bib_return(bib); return VERDICT_CONTINUE; }
/* * remove utmp and wtmp entries */ void ptytty_unix::logout () { if (!cmd_pid) return; log_session (false, 0); cmd_pid = 0; }
/* * make and write utmp and wtmp entries */ void ptytty_unix::login (int cmd_pid, bool login_shell, const char *hostname) { if (!name || !*name) return; this->cmd_pid = cmd_pid; this->login_shell = login_shell; log_session (true, hostname); }
/** * First half of the filtering and updating done during the CLOSED state of the TCP state machine. * Processes IPv6 SYN packets when there's no state. * Part of RFC 6146 section 3.5.2.2. */ static int tcp_closed_v6_syn(struct packet *pkt, struct tuple *tuple6) { struct bib_entry *bib; struct session_entry *session; int error; error = bibdb_get_or_create_ipv6(pkt, tuple6, &bib); if (error) return error; log_bib(bib); error = create_session_ipv6(tuple6, bib, &session, SESSIONTIMER_TRANS, V6_INIT); if (error) { bib_return(bib); return error; } log_session(session); session_return(session); bib_return(bib); return 0; }
/** * Assumes that "tuple" represents a TCP packet, and filters and updates based on it. * Encapsulates the TCP state machine. * * This is RFC 6146 section 3.5.2. */ static verdict tcp(struct packet *pkt, struct tuple *tuple) { struct session_entry *session; int error; error = sessiondb_get(tuple, &session); if (error != 0 && error != -ESRCH) { log_debug("Error code %d while trying to find a TCP session.", error); inc_stats(pkt, IPSTATS_MIB_INDISCARDS); return VERDICT_DROP; } if (error == -ESRCH) return tcp_closed_state_handle(pkt, tuple); log_session(session); error = sessiondb_tcp_state_machine(pkt, session); session_return(session); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); return VERDICT_DROP; } return VERDICT_CONTINUE; }
/** * Assumes that "tuple" represents a IPv4-UDP or ICMP packet, and filters and updates based on it. * * This is RFC 6146, second halves of both sections 3.5.1 and 3.5.3. * * @param[in] skb tuple's packet. This is actually only used for error reporting. * @param[in] tuple summary of the packet Jool is currently translating. * @return VER_CONTINUE if everything went OK, VER_DROP otherwise. */ static verdict ipv4_simple(struct sk_buff *skb, struct tuple *tuple4) { int error; struct bib_entry *bib; struct session_entry *session; error = get_bib_ipv4(skb, tuple4, &bib); if (error) return VER_DROP; log_bib(bib); error = sessiondb_get_or_create_ipv4(tuple4, bib, &session); if (error) { inc_stats(skb, IPSTATS_MIB_INDISCARDS); bib_return(bib); return VER_DROP; } log_session(session); session_return(session); bib_return(bib); return VER_CONTINUE; }
/** * Second half of the filtering and updating done during the CLOSED state of the TCP state machine. * Processes IPv4 SYN packets when there's no state. * Part of RFC 6146 section 3.5.2.2. */ static verdict tcp_closed_v4_syn(struct packet *pkt, struct tuple *tuple4) { struct bib_entry *bib; struct session_entry *session; int error; verdict result = VERDICT_DROP; if (config_get_drop_external_connections()) { log_debug("Applying policy: Dropping externally initiated TCP connections."); return VERDICT_DROP; } error = bibdb_get(tuple4, &bib); if (error) { if (error != -ESRCH) return VERDICT_DROP; bib = NULL; } log_bib(bib); error = create_session_ipv4(tuple4, bib, &session); if (error) goto end_bib; log_session(session); session->state = V4_INIT; if (!bib || config_get_addr_dependent_filtering()) { error = pktqueue_add(session, pkt); if (error) { if (error == -E2BIG) { /* Fall back to assume there's no Simultaneous Open. */ icmp64_send(pkt, ICMPERR_PORT_UNREACHABLE, 0); } goto end_session; } /* At this point, skb's original skb completely belongs to pktqueue. */ result = VERDICT_STOLEN; error = sessiondb_add(session, SESSIONTIMER_SYN); if (error) { log_debug("Error code %d while adding the session to the DB.", error); pktqueue_remove(session); goto end_session; } } else { error = sessiondb_add(session, SESSIONTIMER_TRANS); if (error) { log_debug("Error code %d while adding the session to the DB.", error); goto end_session; } result = VERDICT_CONTINUE; } /* Fall through. */ end_session: session_return(session); /* Fall through. */ end_bib: if (bib) bib_return(bib); return result; }
int main(int argc, char *argv[], char *envp[]) { static const struct option options[] = { { "debug", 0, NULL, 'd' }, { "verbose", 0, NULL, 'V' }, { "account", 1, NULL, 'a' }, { "password", 1, NULL, 'p' }, { "host", 1, NULL, 'H' }, { "proxy", 1, NULL, 'P' }, { "action", 1, NULL, 'A' }, { "user", 1, NULL, 'u' }, { "group", 1, NULL, 'G' }, { "logfile", 1, NULL, 'L' }, { "shrink-urls", 0, NULL, 's' }, { "help", 0, NULL, 'h' }, { "bash", 0, NULL, 'b' }, { "background", 0, NULL, 'B' }, { "dry-run", 0, NULL, 'n' }, { "page", 1, NULL, 'g' }, { "version", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "replyto", 1, NULL, 'r' }, { "retweet", 1, NULL, 'w' }, { } }; struct session *session; pid_t child; char *tweet; static char password[80]; int retval = 0; int option; char *http_proxy; time_t t; int page_nr; debug = 0; session = session_alloc(); if (!session) { fprintf(stderr, "no more memory...\n"); return -1; } /* get the current time so that we can log it later */ time(&t); session->time = strdup(ctime(&t)); session->time[strlen(session->time)-1] = 0x00; /* Get the home directory so we can try to find a config file */ session->homedir = strdup(getenv("HOME")); /* set up a default config file location (traditionally ~/.bti) */ session->configfile = zalloc(strlen(session->homedir) + 7); sprintf(session->configfile, "%s/.bti", session->homedir); /* Set environment variables first, before reading command line options * or config file values. */ http_proxy = getenv("http_proxy"); if (http_proxy) { if (session->proxy) free(session->proxy); session->proxy = strdup(http_proxy); dbg("http_proxy = %s\n", session->proxy); } bti_parse_configfile(session); while (1) { option = getopt_long_only(argc, argv, "dp:P:H:a:A:u:c:hg:G:sr:nVvw:", options, NULL); if (option == -1) break; switch (option) { case 'd': debug = 1; break; case 'V': session->verbose = 1; break; case 'a': if (session->account) free(session->account); session->account = strdup(optarg); dbg("account = %s\n", session->account); break; case 'g': page_nr = atoi(optarg); dbg("page = %d\n", page_nr); session->page = page_nr; break; case 'r': session->replyto = strdup(optarg); dbg("in_reply_to_status_id = %s\n", session->replyto); break; case 'w': session->retweet = strdup(optarg); dbg("Retweet ID = %s\n", session->retweet); break; case 'p': if (session->password) free(session->password); session->password = strdup(optarg); dbg("password = %s\n", session->password); break; case 'P': if (session->proxy) free(session->proxy); session->proxy = strdup(optarg); dbg("proxy = %s\n", session->proxy); break; case 'A': if (strcasecmp(optarg, "update") == 0) session->action = ACTION_UPDATE; else if (strcasecmp(optarg, "friends") == 0) session->action = ACTION_FRIENDS; else if (strcasecmp(optarg, "user") == 0) session->action = ACTION_USER; else if (strcasecmp(optarg, "replies") == 0) session->action = ACTION_REPLIES; else if (strcasecmp(optarg, "public") == 0) session->action = ACTION_PUBLIC; else if (strcasecmp(optarg, "group") == 0) session->action = ACTION_GROUP; else if (strcasecmp(optarg, "retweet") == 0) session->action = ACTION_RETWEET; else session->action = ACTION_UNKNOWN; dbg("action = %d\n", session->action); break; case 'u': if (session->user) free(session->user); session->user = strdup(optarg); dbg("user = %s\n", session->user); break; case 'G': if (session->group) free(session->group); session->group = strdup(optarg); dbg("group = %s\n", session->group); break; case 'L': if (session->logfile) free(session->logfile); session->logfile = strdup(optarg); dbg("logfile = %s\n", session->logfile); break; case 's': session->shrink_urls = 1; break; case 'H': if (session->hosturl) free(session->hosturl); if (session->hostname) free(session->hostname); if (strcasecmp(optarg, "twitter") == 0) { session->host = HOST_TWITTER; session->hosturl = strdup(twitter_host); session->hostname = strdup(twitter_name); } else if (strcasecmp(optarg, "identica") == 0) { session->host = HOST_IDENTICA; session->hosturl = strdup(identica_host); session->hostname = strdup(identica_name); } else { session->host = HOST_CUSTOM; session->hosturl = strdup(optarg); session->hostname = strdup(optarg); } dbg("host = %d\n", session->host); break; case 'b': session->bash = 1; /* fall-through intended */ case 'B': session->background = 1; break; case 'c': if (session->configfile) free(session->configfile); session->configfile = strdup(optarg); dbg("configfile = %s\n", session->configfile); /* * read the config file now. Yes, this could override * previously set options from the command line, but * the user asked for it... */ bti_parse_configfile(session); break; case 'h': display_help(); goto exit; case 'n': session->dry_run = 1; break; case 'v': display_version(); goto exit; default: display_help(); goto exit; } } session_readline_init(session); /* * Show the version to make it easier to determine what * is going on here */ if (debug) display_version(); if (session->host == HOST_TWITTER) { if (!session->consumer_key || !session->consumer_secret) { if (session->action == ACTION_USER || session->action == ACTION_PUBLIC) { /* * Some actions may still work without * authentication */ session->guest = 1; } else { fprintf(stderr, "Twitter no longer supports HTTP basic authentication.\n" "Both consumer key, and consumer secret are required" " for bti in order to behave as an OAuth consumer.\n"); goto exit; } } if (session->action == ACTION_GROUP) { fprintf(stderr, "Groups only work in Identi.ca.\n"); goto exit; } } else { if (!session->consumer_key || !session->consumer_secret) session->no_oauth = 1; } if (session->no_oauth) { if (!session->account) { fprintf(stdout, "Enter account for %s: ", session->hostname); session->account = session->readline(NULL); } if (!session->password) { read_password(password, sizeof(password), session->hostname); session->password = strdup(password); } } else if (!session->guest) { if (!session->access_token_key || !session->access_token_secret) { request_access_token(session); goto exit; } } if (session->action == ACTION_UNKNOWN) { fprintf(stderr, "Unknown action, valid actions are:\n" "'update', 'friends', 'public', 'replies', 'group' or 'user'.\n"); goto exit; } if (session->action == ACTION_GROUP && !session->group) { fprintf(stdout, "Enter group name: "); session->group = session->readline(NULL); } if (session->action == ACTION_RETWEET) { if (!session->retweet) { char *rtid; fprintf(stdout, "Status ID to retweet: "); rtid = get_string_from_stdin(); session->retweet = zalloc(strlen(rtid) + 10); sprintf(session->retweet, "%s", rtid); free(rtid); } if (!session->retweet || strlen(session->retweet) == 0) { dbg("no retweet?\n"); return -1; } dbg("retweet ID = %s\n", session->retweet); } if (session->action == ACTION_UPDATE) { if (session->background || !session->interactive) tweet = get_string_from_stdin(); else tweet = session->readline("tweet: "); if (!tweet || strlen(tweet) == 0) { dbg("no tweet?\n"); return -1; } if (session->shrink_urls) tweet = shrink_urls(tweet); session->tweet = zalloc(strlen(tweet) + 10); if (session->bash) sprintf(session->tweet, "%c %s", getuid() ? '$' : '#', tweet); else sprintf(session->tweet, "%s", tweet); free(tweet); dbg("tweet = %s\n", session->tweet); } if (session->page == 0) session->page = 1; dbg("config file = %s\n", session->configfile); dbg("host = %d\n", session->host); dbg("action = %d\n", session->action); /* fork ourself so that the main shell can get on * with it's life as we try to connect and handle everything */ if (session->background) { child = fork(); if (child) { dbg("child is %d\n", child); exit(0); } } retval = send_request(session); if (retval && !session->background) fprintf(stderr, "operation failed\n"); log_session(session, retval); exit: session_readline_cleanup(session); session_free(session); return retval;; }