📄 whack.c
字号:
msg.sa_keying_tries = opt_whole; continue; case CD_FORCEENCAPS: msg.forceencaps = TRUE; continue; case CD_DPDDELAY: msg.dpd_delay = opt_whole; continue; case CD_DPDTIMEOUT: msg.dpd_timeout = opt_whole; continue; case CD_DPDACTION: msg.dpd_action = 255; if( strcmp(optarg, "clear") == 0) { msg.dpd_action = DPD_ACTION_CLEAR; } if( strcmp(optarg, "hold") == 0) { msg.dpd_action = DPD_ACTION_HOLD; } continue; case CD_IKE: /* --ike <ike_alg1,ike_alg2,...> */ msg.ike = optarg; continue; case CD_PFSGROUP: /* --pfsgroup modpXXXX */ msg.pfsgroup = optarg; continue; case CD_ESP: /* --esp <esp_alg1,esp_alg2,...> */ msg.esp = optarg; continue; case CD_CONNIPV4: if (LHAS(cd_seen, CD_CONNIPV6 - CD_FIRST)) diag("--ipv4 conflicts with --ipv6"); /* Since this is the default, the flag is redundant. * So we don't need to set msg.addr_family * and we don't need to check af_used_by * and we don't have to consider defaulting tunnel_addr_family. */ continue; case CD_CONNIPV6: if (LHAS(cd_seen, CD_CONNIPV4 - CD_FIRST)) diag("--ipv6 conflicts with --ipv4"); if (af_used_by != NULL) diagq("--ipv6 must precede", af_used_by); af_used_by = long_opts[long_index].name; msg.addr_family = AF_INET6; /* Consider defaulting tunnel_addr_family to AF_INET6. * Do so only if it hasn't yet been specified or used. */ if (LDISJOINT(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST)) && tunnel_af_used_by == NULL) msg.tunnel_addr_family = AF_INET6; continue; case CD_TUNNELIPV4: if (LHAS(cd_seen, CD_TUNNELIPV6 - CD_FIRST)) diag("--tunnelipv4 conflicts with --tunnelipv6"); if (tunnel_af_used_by != NULL) diagq("--tunnelipv4 must precede", af_used_by); msg.tunnel_addr_family = AF_INET; continue; case CD_TUNNELIPV6: if (LHAS(cd_seen, CD_TUNNELIPV4 - CD_FIRST)) diag("--tunnelipv6 conflicts with --tunnelipv4"); if (tunnel_af_used_by != NULL) diagq("--tunnelipv6 must precede", af_used_by); msg.tunnel_addr_family = AF_INET6; continue; case OPT_XAUTHNAME: gotxauthname = TRUE; xauthname[0]='\0'; strncat(xauthname, optarg, sizeof(xauthname)); xauthnamelen = strlen(xauthname)+1; continue; case OPT_XAUTHPASS: gotxauthpass = TRUE; xauthpass[0]='\0'; strncat(xauthpass, optarg, sizeof(xauthpass)); xauthpasslen = strlen(xauthpass)+1; continue;#ifdef DEBUG case DBGOPT_NONE: /* --debug-none */ msg.debugging = DBG_NONE; continue; case DBGOPT_ALL: /* --debug-all */ msg.debugging |= DBG_ALL; /* note: does not include PRIVATE */ continue; case DBGOPT_RAW: /* --debug-raw */ case DBGOPT_CRYPT: /* --debug-crypt */ case DBGOPT_PARSING: /* --debug-parsing */ case DBGOPT_EMITTING: /* --debug-emitting */ case DBGOPT_CONTROL: /* --debug-control */ case DBGOPT_LIFECYCLE: /* --debug-lifecycle */ case DBGOPT_KLIPS: /* --debug-klips */ case DBGOPT_DNS: /* --debug-dns */ case DBGOPT_OPPO: /* --debug-oppo */ case DBGOPT_CONTROLMORE: /* --debug-controlmore */ case DBGOPT_PFKEY: /* --debug-pfkey */ case DBGOPT_NATT: /* --debug-pfkey */ case DBGOPT_X509: /* --debug-pfkey */ case DBGOPT_DPD: /* --debug-dpd */ case DBGOPT_PRIVATE: /* --debug-private */ case DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER: /* --impair-delay-adns-key-answer */ case DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER: /* --impair-delay-adns-txt-answer */ case DBGOPT_IMPAIR_BUST_MI2: /* --impair_bust_mi2 */ case DBGOPT_IMPAIR_BUST_MR2: /* --impair_bust_mr2 */ msg.debugging |= LELEM(c-DBGOPT_RAW); continue;#endif default: assert(FALSE); /* unknown return value */ } break; } if (optind != argc) { /* If you see this message unexpectedly, perhaps the * case for the previous option ended with "break" * instead of "continue" */ diagq("unexpected argument", argv[optind]); } /* For each possible form of the command, figure out if an argument * suggests whether that form was intended, and if so, whether all * required information was supplied. */ /* check opportunistic initiation simulation request */ switch (opts_seen & (LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE))) { case LELEM(OPT_OPPO_HERE): case LELEM(OPT_OPPO_THERE): diag("--oppohere and --oppothere must be used together"); /*NOTREACHED*/ case LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE): msg.whack_oppo_initiate = TRUE; if (LIN(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST))) opts_seen &= ~LELEM(OPT_CD); break; } /* check connection description */ if (LHAS(opts_seen, OPT_CD)) { if (!LHAS(cd_seen, CD_TO-CD_FIRST)) diag("connection description option, but no --to"); if (!LHAS(end_seen, END_HOST-END_FIRST)) diag("connection missing --host after --to"); if (isanyaddr(&msg.left.host_addr) && isanyaddr(&msg.right.host_addr)) diag("hosts cannot both be 0.0.0.0 or 0::0"); if (msg.policy & POLICY_OPPO) { if ((msg.policy & (POLICY_PSK | POLICY_RSASIG)) != POLICY_RSASIG) diag("only RSASIG is supported for opportunism"); if ((msg.policy & POLICY_PFS) == 0) diag("PFS required for opportunism"); if ((msg.policy & POLICY_ENCRYPT) == 0) diag("encryption required for opportunism"); } check_end(&msg.left, &msg.right, !LHAS(end_seen_before_to, END_NEXTHOP-END_FIRST) , msg.addr_family, msg.tunnel_addr_family); check_end(&msg.right, &msg.left, !LHAS(end_seen, END_NEXTHOP-END_FIRST) , msg.addr_family, msg.tunnel_addr_family); if (subnettypeof(&msg.left.client) != subnettypeof(&msg.right.client)) diag("endpoints clash: one is IPv4 and the other is IPv6"); if (NEVER_NEGOTIATE(msg.policy)) { /* we think this is just a shunt (because he didn't specify * a host authentication method). If he didn't specify a * shunt type, he's probably gotten it wrong. */ if ((msg.policy & POLICY_SHUNT_MASK) == POLICY_SHUNT_TRAP) diag("non-shunt connection must have --psk or --rsasig or both"); } else { /* not just a shunt: a real ipsec connection */ if ((msg.policy & POLICY_ID_AUTH_MASK) == LEMPTY) diag("must specify --rsasig or --psk for a connection"); if (!HAS_IPSEC_POLICY(msg.policy) && (msg.left.has_client || msg.right.has_client)) diag("must not specify clients for ISAKMP-only connection"); } msg.whack_connection = TRUE; } /* decide whether --name is mandatory or forbidden */ if (!LDISJOINT(opts_seen , LELEM(OPT_ROUTE) | LELEM(OPT_UNROUTE) | LELEM(OPT_INITIATE) | LELEM(OPT_TERMINATE) | LELEM(OPT_DELETE) | LELEM(OPT_CD))) { if (!LHAS(opts_seen, OPT_NAME)) diag("missing --name <connection_name>"); } else if (!msg.whack_options) { if (LHAS(opts_seen, OPT_NAME)) diag("no reason for --name"); } if (!LDISJOINT(opts_seen, LELEM(OPT_PUBKEYRSA) | LELEM(OPT_ADDKEY))) { if (!LHAS(opts_seen, OPT_KEYID)) diag("--addkey and --pubkeyrsa require --keyid"); } if (!(msg.whack_connection || msg.whack_key || msg.whack_myid || msg.whack_delete || msg.whack_deletestate || msg.whack_initiate || msg.whack_oppo_initiate || msg.whack_terminate || msg.whack_route || msg.whack_unroute || msg.whack_listen || msg.whack_unlisten || msg.whack_list || msg.whack_purgeocsp || msg.whack_reread || msg.whack_status || msg.whack_options || msg.whack_shutdown)) { diag("no action specified; try --help for hints"); } if(msg.policy & POLICY_AGGRESSIVE) { if(msg.ike == NULL) { diag("can not specify aggressive mode without ike= to set algorithm"); } } update_ports(&msg); /* tricky quick and dirty check for wild values */ if (msg.sa_rekey_margin != 0 && msg.sa_rekey_fuzz * msg.sa_rekey_margin * 4 / msg.sa_rekey_margin / 4 != msg.sa_rekey_fuzz) diag("rekeymargin or rekeyfuzz values are so large that they cause oveflow"); check_life_time (msg.sa_ike_life_seconds, OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM , "ikelifetime", &msg); check_life_time(msg.sa_ipsec_life_seconds, SA_LIFE_DURATION_MAXIMUM , "ipseclifetime", &msg); if(msg.dpd_delay && !msg.dpd_timeout) diag("dpddelay specified, but dpdtimeout is zero, both should be specified"); if(!msg.dpd_delay && msg.dpd_timeout) diag("dpdtimeout specified, but dpddelay is zero, both should be specified"); if(msg.dpd_action != DPD_ACTION_CLEAR && msg.dpd_action != DPD_ACTION_HOLD) { diag("dpdaction can only be \"clear\" or \"hold\", defaulting to \"hold\""); msg.dpd_action = DPD_ACTION_HOLD; } /* pack strings for inclusion in message */ next_str = msg.string; str_roof = &msg.string[sizeof(msg.string)]; /* build esp message as esp="<esp>;<pfsgroup>" */ if (msg.pfsgroup) { snprintf(esp_buf, sizeof (esp_buf), "%s;%s", msg.esp ? msg.esp : "", msg.pfsgroup ? msg.pfsgroup : ""); msg.esp=esp_buf; } if (!pack_str(&msg.name) /* string 1 */ || !pack_str(&msg.left.id) /* string 2 */ || !pack_str(&msg.left.cert) /* string 3 */ || !pack_str(&msg.left.ca) /* string 4 */ || !pack_str(&msg.left.groups) /* string 5 */ || !pack_str(&msg.left.updown) /* string 6 */#ifdef VIRTUAL_IP || !pack_str(&msg.left.virt)#endif || !pack_str(&msg.right.id) /* string 7 */ || !pack_str(&msg.right.cert) /* string 8 */ || !pack_str(&msg.right.ca) /* string 9 */ || !pack_str(&msg.right.groups) /* string 10 */ || !pack_str(&msg.right.updown) /* string 11 */#ifdef VIRTUAL_IP || !pack_str(&msg.right.virt)#endif || !pack_str(&msg.keyid) /* string 12 */ || !pack_str(&msg.myid) /* string 13 */ || !pack_str(&msg.ike) /* string 14 */ || !pack_str(&msg.esp) /* string 15 */ || str_roof - next_str < (ptrdiff_t)msg.keyval.len) /* chunk (sort of string 5) */ diag("too many bytes of strings to fit in message to pluto"); memcpy(next_str, msg.keyval.ptr, msg.keyval.len); msg.keyval.ptr = NULL; next_str += msg.keyval.len; msg.magic = ((opts_seen & ~(LELEM(OPT_SHUTDOWN) | LELEM(OPT_STATUS))) | lst_seen | cd_seen) != LEMPTY || msg.whack_options ? WHACK_MAGIC : WHACK_BASIC_MAGIC; /* send message to Pluto */ if (access(ctl_addr.sun_path, R_OK | W_OK) < 0) { int e = errno; switch (e) { case EACCES: fprintf(stderr, "whack: no right to communicate with pluto (access(\"%s\"))\n" , ctl_addr.sun_path); break; case ENOENT: fprintf(stderr, "whack: Pluto is not running (no \"%s\")\n" , ctl_addr.sun_path); break; default: fprintf(stderr, "whack: access(\"%s\") failed with %d %s\n" , ctl_addr.sun_path, errno, strerror(e)); break; } exit(RC_WHACK_PROBLEM); } else { int sock = socket(AF_UNIX, SOCK_STREAM, 0); int exit_status = 0; ssize_t len = next_str - (char *)&msg; if (sock == -1) { int e = errno; fprintf(stderr, "whack: socket() failed (%d %s)\n", e, strerror(e)); exit(RC_WHACK_PROBLEM); } if (connect(sock, (struct sockaddr *)&ctl_addr , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0) { int e = errno; fprintf(stderr, "whack:%s connect() for \"%s\" failed (%d %s)\n" , e == ECONNREFUSED? " is Pluto running? " : "" , ctl_addr.sun_path, e, strerror(e)); exit(RC_WHACK_PROBLEM); } if (write(sock, &msg, len) != len) { int e = errno; fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e)); exit(RC_WHACK_PROBLEM); } /* for now, just copy reply back to stdout */ { char buf[4097]; /* arbitrary limit on log line length */ char *be = buf; for (;;) { char *ls = buf; ssize_t rl = read(sock, be, (buf + sizeof(buf)-1) - be); if (rl < 0) { int e = errno; fprintf(stderr, "whack: read() failed (%d %s)\n", e, strerror(e)); exit(RC_WHACK_PROBLEM); } if (rl == 0) { if (be != buf) fprintf(stderr, "whack: last line from pluto too long or unterminated\n"); break; } be += rl; *be = '\0'; for (;;) { char *le = strchr(ls, '\n'); if (le == NULL) { /* move last, partial line to start of buffer */ memmove(buf, ls, be-ls); be -= ls - buf; break; } le++; /* include NL in line */ write(1, ls, le - ls); /* figure out prefix number * and how it should affect our exit status */ { unsigned long s = strtoul(ls, NULL, 10); switch (s) { case RC_COMMENT: case RC_LOG: /* ignore */ break; case RC_SUCCESS: /* be happy */ exit_status = 0; break; case RC_ENTERSECRET: if(!gotxauthpass) { xauthpasslen = get_secret(xauthpass , sizeof(xauthpass)); } send_reply(sock, xauthpass, xauthpasslen); break; case RC_XAUTHPROMPT: if(!gotxauthname) { xauthnamelen = get_value(xauthname , sizeof(xauthname)); } send_reply(sock, xauthname, xauthnamelen); break; /* case RC_LOG_SERIOUS: */ default: /* pass through */ exit_status = s; break; } } ls = le; } } } return exit_status; }}/* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -