📄 whack.c
字号:
#define NUMERIC_ARG (1 << 9) /* expect a numeric argument */#define AUX_SHIFT 10 /* amount to shift for aux information */static const struct option long_opts[] = {# define OO OPTION_OFFSET /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "label", required_argument, NULL, 'l' }, { "ctlbase", required_argument, NULL, OPT_CTLBASE + OO }, { "name", required_argument, NULL, OPT_NAME + OO }, { "keyid", required_argument, NULL, OPT_KEYID + OO }, { "addkey", no_argument, NULL, OPT_ADDKEY + OO }, { "pubkeyrsa", required_argument, NULL, OPT_PUBKEYRSA + OO }, { "myid", required_argument, NULL, OPT_MYID + OO }, { "route", no_argument, NULL, OPT_ROUTE + OO }, { "unroute", no_argument, NULL, OPT_UNROUTE + OO }, { "initiate", no_argument, NULL, OPT_INITIATE + OO }, { "terminate", no_argument, NULL, OPT_TERMINATE + OO }, { "delete", no_argument, NULL, OPT_DELETE + OO }, { "deletestate", required_argument, NULL, OPT_DELETESTATE + OO + NUMERIC_ARG }, { "crash", required_argument, NULL, OPT_DELETECRASH + OO }, { "listen", no_argument, NULL, OPT_LISTEN + OO }, { "unlisten", no_argument, NULL, OPT_UNLISTEN + OO }, { "purgeocsp", no_argument, NULL, OPT_PURGEOCSP + OO }, { "rereadsecrets", no_argument, NULL, OPT_REREADSECRETS + OO }, { "rereadcacerts", no_argument, NULL, OPT_REREADCACERTS + OO }, { "rereadaacerts", no_argument, NULL, OPT_REREADAACERTS + OO }, { "rereadocspcerts", no_argument, NULL, OPT_REREADOCSPCERTS + OO }, { "rereadacerts", no_argument, NULL, OPT_REREADACERTS + OO }, { "rereadcrls", no_argument, NULL, OPT_REREADCRLS + OO }, { "rereadall", no_argument, NULL, OPT_REREADALL + OO }, { "status", no_argument, NULL, OPT_STATUS + OO }, { "shutdown", no_argument, NULL, OPT_SHUTDOWN + OO }, { "xauthname", required_argument, NULL, OPT_XAUTHNAME + OO }, { "xauthuser", required_argument, NULL, OPT_XAUTHNAME + OO }, { "xauthpass", required_argument, NULL, OPT_XAUTHPASS + OO }, { "oppohere", required_argument, NULL, OPT_OPPO_HERE + OO }, { "oppothere", required_argument, NULL, OPT_OPPO_THERE + OO }, { "asynchronous", no_argument, NULL, OPT_ASYNC + OO }, /* list options */ { "utc", no_argument, NULL, LST_UTC + OO }, { "listpubkeys", no_argument, NULL, LST_PUBKEYS + OO }, { "listcerts", no_argument, NULL, LST_CERTS + OO }, { "listcacerts", no_argument, NULL, LST_CACERTS + OO }, { "listacerts", no_argument, NULL, LST_ACERTS + OO }, { "listaacerts", no_argument, NULL, LST_AACERTS + OO }, { "listocspcerts", no_argument, NULL, LST_OCSPCERTS + OO }, { "listgroups", no_argument, NULL, LST_GROUPS + OO }, { "listcrls", no_argument, NULL, LST_CRLS + OO }, { "listocsp", no_argument, NULL, LST_OCSP + OO }, { "listcards", no_argument, NULL, LST_CARDS + OO }, { "listevents", no_argument, NULL, LST_EVENTS + OO }, { "listall", no_argument, NULL, LST_ALL + OO }, /* options for an end description */ { "host", required_argument, NULL, END_HOST + OO }, { "id", required_argument, NULL, END_ID + OO }, { "cert", required_argument, NULL, END_CERT + OO }, { "ca", required_argument, NULL, END_CA + OO }, { "groups", required_argument, NULL, END_GROUPS + OO }, { "ikeport", required_argument, NULL, END_IKEPORT + OO + NUMERIC_ARG }, { "nexthop", required_argument, NULL, END_NEXTHOP + OO }, { "client", required_argument, NULL, END_CLIENT + OO }, { "clientwithin", required_argument, NULL, END_CLIENTWITHIN + OO }, { "clientprotoport", required_argument, NULL, END_CLIENTPROTOPORT + OO }, { "dnskeyondemand", no_argument, NULL, END_DNSKEYONDEMAND + OO }, { "srcip", required_argument, NULL, END_SRCIP + OO }, { "updown", required_argument, NULL, END_UPDOWN + OO }, /* options for a connection description */ { "to", no_argument, NULL, CD_TO + OO }, { "psk", no_argument, NULL, CD_PSK + OO }, { "rsasig", no_argument, NULL, CD_RSASIG + OO }, { "encrypt", no_argument, NULL, CD_ENCRYPT + OO }, { "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO }, { "compress", no_argument, NULL, CD_COMPRESS + OO }, { "tunnel", no_argument, NULL, CD_TUNNEL + OO }, { "tunnelipv4", no_argument, NULL, CD_TUNNELIPV4 + OO }, { "tunnelipv6", no_argument, NULL, CD_TUNNELIPV6 + OO }, { "pfs", no_argument, NULL, CD_PFS + OO }, { "aggrmode", no_argument, NULL, CD_AGGRESSIVE + OO }, { "disablearrivalcheck", no_argument, NULL, CD_DISABLEARRIVALCHECK + OO }, { "initiateontraffic", no_argument, NULL , CD_SHUNT0 + (POLICY_SHUNT_TRAP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO }, { "pass", no_argument, NULL , CD_SHUNT0 + (POLICY_SHUNT_PASS >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO }, { "drop", no_argument, NULL , CD_SHUNT0 + (POLICY_SHUNT_DROP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO }, { "reject", no_argument, NULL , CD_SHUNT0 + (POLICY_SHUNT_REJECT >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO }, { "failnone", no_argument, NULL , CD_FAIL0 + (POLICY_FAIL_NONE >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO }, { "failpass", no_argument, NULL , CD_FAIL0 + (POLICY_FAIL_PASS >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO }, { "faildrop", no_argument, NULL , CD_FAIL0 + (POLICY_FAIL_DROP >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO }, { "failreject", no_argument, NULL , CD_FAIL0 + (POLICY_FAIL_REJECT >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO }, { "dontrekey", no_argument, NULL, CD_DONT_REKEY + OO }, { "forceencaps", no_argument, NULL, CD_FORCEENCAPS + OO }, { "dpddelay", required_argument, NULL, CD_DPDDELAY + OO + NUMERIC_ARG }, { "dpdtimeout", required_argument, NULL, CD_DPDTIMEOUT + OO + NUMERIC_ARG }, { "dpdaction", required_argument, NULL, CD_DPDACTION + OO },#ifdef XAUTH { "xauth", no_argument, NULL, END_XAUTHSERVER + OO }, { "xauthserver", no_argument, NULL, END_XAUTHSERVER + OO }, { "xauthclient", no_argument, NULL, END_XAUTHCLIENT + OO },#endif#ifdef MODECFG { "modecfgpull", no_argument, NULL, CD_MODECFGPULL + OO }, { "modecfgserver", no_argument, NULL, END_MODECFGSERVER + OO }, { "modecfgclient", no_argument, NULL, END_MODECFGCLIENT + OO }, { "modeconfigserver", no_argument, NULL, END_MODECFGSERVER + OO }, { "modeconfigclient", no_argument, NULL, END_MODECFGCLIENT + OO },#endif { "sendcert", required_argument, NULL, END_SENDCERT + OO }, { "certtype", required_argument, NULL, END_CERTTYPE + OO + NUMERIC_ARG }, { "ipv4", no_argument, NULL, CD_CONNIPV4 + OO }, { "ipv6", no_argument, NULL, CD_CONNIPV6 + OO }, { "ikelifetime", required_argument, NULL, CD_IKELIFETIME + OO + NUMERIC_ARG }, { "ipseclifetime", required_argument, NULL, CD_IPSECLIFETIME + OO + NUMERIC_ARG }, { "rekeymargin", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG }, { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG }, /* OBSOLETE */ { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG }, { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG }, { "ike", required_argument, NULL, CD_IKE + OO }, { "pfsgroup", required_argument, NULL, CD_PFSGROUP + OO }, { "esp", required_argument, NULL, CD_ESP + OO },#ifdef DEBUG { "debug-none", no_argument, NULL, DBGOPT_NONE + OO }, { "debug-all]", no_argument, NULL, DBGOPT_ALL + OO }, { "debug-raw", no_argument, NULL, DBGOPT_RAW + OO }, { "debug-crypt", no_argument, NULL, DBGOPT_CRYPT + OO }, { "debug-parsing", no_argument, NULL, DBGOPT_PARSING + OO }, { "debug-emitting", no_argument, NULL, DBGOPT_EMITTING + OO }, { "debug-control", no_argument, NULL, DBGOPT_CONTROL + OO }, { "debug-lifecycle", no_argument, NULL, DBGOPT_LIFECYCLE + OO }, { "debug-klips", no_argument, NULL, DBGOPT_KLIPS + OO }, { "debug-dns", no_argument, NULL, DBGOPT_DNS + OO }, { "debug-oppo", no_argument, NULL, DBGOPT_OPPO + OO }, { "debug-controlmore", no_argument, NULL, DBGOPT_CONTROLMORE + OO }, { "debug-pfkey", no_argument, NULL, DBGOPT_PFKEY + OO }, { "debug-nattraversal", no_argument, NULL, DBGOPT_NATT + OO }, { "debug-x509", no_argument, NULL, DBGOPT_X509 + OO }, { "debug-dpd", no_argument, NULL, DBGOPT_DPD + OO }, { "debug-private", no_argument, NULL, DBGOPT_PRIVATE + OO }, { "impair-delay-adns-key-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER + OO }, { "impair-delay-adns-txt-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER + OO }, { "impair-bust-mi2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MI2 + OO }, { "impair-bust-mr2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MR2 + OO },#endif# undef OO { 0,0,0,0 }};struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX };/* helper variables and function to encode strings from whack message */static char *next_str, *str_roof;static boolpack_str(char **p){ const char *s = *p == NULL? "" : *p; /* note: NULL becomes ""! */ size_t len = strlen(s) + 1; if (str_roof - next_str < (ptrdiff_t)len) { return FALSE; /* fishy: no end found */ } else { strcpy(next_str, s); next_str += len; *p = NULL; /* don't send pointers on the wire! */ return TRUE; }}static voidcheck_life_time(time_t life, time_t limit, const char *which, const struct whack_message *msg){ time_t mint = msg->sa_rekey_margin * (100 + msg->sa_rekey_fuzz) / 100; if (life > limit) { char buf[200]; /* arbitrary limit */ snprintf(buf, sizeof(buf) , "%s [%lu seconds] must be less than %lu seconds" , which, (unsigned long)life, (unsigned long)limit); diag(buf); } if ((msg->policy & POLICY_DONT_REKEY) == LEMPTY && life <= mint) { char buf[200]; /* arbitrary limit */ snprintf(buf, sizeof(buf) , "%s [%lu] must be greater than" " rekeymargin*(100+rekeyfuzz)/100 [%lu*(100+%lu)/100 = %lu]" , which , (unsigned long)life , (unsigned long)msg->sa_rekey_margin , (unsigned long)msg->sa_rekey_fuzz , (unsigned long)mint); diag(buf); }}static voidupdate_ports(struct whack_message * m){ int port; if (m->left.port != 0) { port = htons(m->left.port); setportof(port, &m->left.host_addr); setportof(port, &m->left.client.addr); } if (m->right.port != 0) { port = htons(m->right.port); setportof(port, &m->right.host_addr); setportof(port, &m->right.client.addr); }}static voidcheck_end(struct whack_end *this, struct whack_end *that, bool default_nexthop, sa_family_t caf, sa_family_t taf){ if (caf != addrtypeof(&this->host_addr)) diag("address family of host inconsistent"); if (default_nexthop) { if (isanyaddr(&that->host_addr)) diag("our nexthop must be specified when other host is a %any or %opportunistic"); this->host_nexthop = that->host_addr; } if (caf != addrtypeof(&this->host_nexthop)) diag("address family of nexthop inconsistent"); if (this->has_client) { if (taf != subnettypeof(&this->client)) diag("address family of client subnet inconsistent"); } else { /* fill in anyaddr-anyaddr as (missing) client subnet */ ip_address cn; diagq(anyaddr(caf, &cn), NULL); diagq(rangetosubnet(&cn, &cn, &this->client), NULL); } /* check protocol */ if (this->protocol != that->protocol) diagq("the protocol for leftprotoport and rightprotoport must be the same", NULL);}static size_tget_secret(char *buf, size_t bufsize){ const char *secret; int len; fflush(stdout); usleep(20000); /* give fflush time for flushing */ secret = getpass("Enter secret: "); secret = (secret == NULL) ? "" : secret; strncpy(buf, secret, bufsize); len = strlen(buf) + 1; return len;}static intget_value(char *buf, size_t bufsize){ int len; int try; fflush(stdout); usleep(20000); /* give fflush time for flushing - has to go through awk */ try = 3; len = 0; while(try > 0 && len==0) { fprintf(stderr, "Name enter: "); memset(buf, 0, bufsize); if(fgets(buf, bufsize, stdin) != buf) { if(errno == 0) { fprintf(stderr, "Can not read password from standard in\n"); exit(RC_WHACK_PROBLEM); } else { perror("fgets value"); exit(RC_WHACK_PROBLEM); } } /* send the value to pluto, including \0, but fgets adds \n */ len = strlen(buf); if(len == 0) { fprintf(stderr, "answer was empty, retry\n"); } } if(len == 0) { exit(RC_WHACK_PROBLEM); } return len;}static voidsend_reply(int sock, char *buf, ssize_t len){ /* send the secret to pluto */ if (write(sock, buf, len) != len) { int e = errno; fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e)); exit(RC_WHACK_PROBLEM); }}/* This is a hack for initiating ISAKMP exchanges. */intmain(int argc, char **argv){ struct whack_message msg; char esp_buf[256]; /* uses snprintf */ lset_t opts_seen = LEMPTY, lst_seen = LEMPTY, cd_seen = LEMPTY, end_seen = LEMPTY, end_seen_before_to; const char *af_used_by = NULL, *tunnel_af_used_by = NULL; char xauthname[128]; char xauthpass[128]; int xauthnamelen, xauthpasslen; bool gotxauthname = FALSE, gotxauthpass = FALSE; /* check division of numbering space */#ifdef DEBUG assert(OPTION_OFFSET + DBGOPT_LAST < NUMERIC_ARG);#else assert(OPTION_OFFSET + CD_LAST < NUMERIC_ARG);#endif assert(OPT_LAST - OPT_FIRST < (sizeof cd_seen * BITS_PER_BYTE)); assert(LST_LAST - LST_FIRST < (sizeof cd_seen * BITS_PER_BYTE)); assert(END_LAST - END_FIRST < (sizeof cd_seen * BITS_PER_BYTE)); assert(CD_LAST - CD_FIRST < (sizeof cd_seen * BITS_PER_BYTE));#ifdef DEBUG /* must be last so others are less than (sizeof cd_seen * BITS_PER_BYTE) to fit in lset_t */ assert(DBGOPT_LAST - DBGOPT_FIRST < (sizeof cd_seen * BITS_PER_BYTE));#endif /* check that POLICY bit assignment matches with CD_ */ assert(LELEM(CD_DONT_REKEY - CD_POLICY_FIRST) == POLICY_DONT_REKEY); zero(&msg); clear_end(&msg.right); /* left set from this after --to */ msg.name = NULL; msg.keyid = NULL; msg.keyval.ptr = NULL; msg.esp = NULL; msg.ike = NULL; msg.pfsgroup = NULL; msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT; msg.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT; msg.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT; msg.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT; msg.addr_family = AF_INET; msg.tunnel_addr_family = AF_INET; for (;;) { int long_index; unsigned long opt_whole; /* numeric argument for some flags */ /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hp:d:c:o:eatfs" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, &long_index) - OPTION_OFFSET; int aux = 0; /* decode a numeric argument, if expected */ if (0 <= c) { if (c & NUMERIC_ARG) { char *endptr; c -= NUMERIC_ARG; opt_whole = strtoul(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg) diagq("badly formed numeric argument", optarg); } if (c >= (1 << AUX_SHIFT)) { aux = c >> AUX_SHIFT; c -= aux << AUX_SHIFT; } } /* per-class option processing */ if (0 <= c && c < OPT_LAST) { /* OPT_* options get added opts_seen. * Reject repeated options (unless later code intervenes). */ lset_t f = LELEM(c); if (opts_seen & f) diagq("duplicated flag", long_opts[long_index].name); opts_seen |= f; } else if (LST_FIRST <= c && c <= LST_LAST) { /* LST_* options get added lst_seen. * Reject repeated options (unless later code intervenes). */ lset_t f = LELEM(c - LST_FIRST); if (lst_seen & f) diagq("duplicated flag", long_opts[long_index].name); lst_seen |= f; }#ifdef DEBUG else if (DBGOPT_FIRST <= c && c <= DBGOPT_LAST) { /* DBGOPT_* options are treated separately to reduce * potential members of opts_seen. */ msg.whack_options = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -