📄 whackinit.c
字号:
/* command interface to Pluto - initiate a connection only. * suitable for setuid use. * * Copyright (C) 2004 Michael Richardson <mcr@xelerance.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: whackinit.c,v 1.1 2004/12/16 01:24:45 mcr Exp $ */#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <netinet/in.h>#include <arpa/inet.h>#include <getopt.h>#include <assert.h>#include <openswan.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "whack.h"static int setup_socket(void);/** * Print the 'ipsec whackinit --help' message */static voidhelp(void){ fprintf(stderr , "Usage:\n\n" "all forms:" " [--ctlbase <path>]" " [--label <string>]" "\n\n" "help: whack" " [--help]" " [--version]" "\n\n" "connection: whack" " whack" " (--initiate | --terminate)" " --name <connection_name>" " [--asynchronous]" " [--xauthname name]" " [--xauthpass pass]" "\n\n" "status: whack" " --status" "\n\n" "Openswan %s\n" , ipsec_version_code());}static const char *label = NULL; /* --label operand, saved for diagnostics */static const char *name = NULL; /* --name operand, saved for diagnostics *//** Print a string as a diagnostic, then exit whack unhappily * * @param mess The error message to print when exiting * @return void */static voiddiag(const char *mess){ if (mess != NULL) { fprintf(stderr, "whackinit error: "); if (label != NULL) fprintf(stderr, "%s ", label); if (name != NULL) fprintf(stderr, "\"%s\" ", name); fprintf(stderr, "%s\n", mess); } exit(RC_WHACK_PROBLEM);}/** * Conditially calls diag if ugh is set. * Prints second arg, if non-NULL, as quoted string * * @param ugh Error message * @param this Optional 2nd part of error message * @return void */static voiddiagq(err_t ugh, const char *this){ if (ugh != NULL) { if (this == NULL) { diag(ugh); } else { char buf[120]; /* arbitrary limit */ snprintf(buf, sizeof(buf), "%s \"%s\"", ugh, this); diag(buf); } }}/** * complex combined operands return one of these enumerated values * Note: these become flags in an lset_t. Since there are more than * 32, we partition them into: * - OPT_* options (most random options) * - LST_* options (list various internal data) * - DBGOPT_* option (DEBUG options) * - END_* options (End description options) * - CD_* options (Connection Description options) */enum option_enums {# define OPT_FIRST OPT_NAME OPT_NAME, OPT_INITIATE, OPT_TERMINATE, OPT_STATUS, OPT_OPPO_HERE, OPT_OPPO_THERE, OPT_ASYNC, OPT_XAUTHNAME, OPT_XAUTHPASS,# define OPT_LAST OPT_ASYNC /* last "normal" option */};/* Carve up space for result from getopt_long. * Stupidly, the only result is an int. * Numeric arg is bit immediately left of basic value. * */#define OPTION_OFFSET 256 /* to get out of the way of letter options */#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' }, { "label", required_argument, NULL, 'l' }, { "name", required_argument, NULL, OPT_NAME + OO }, { "initiate", no_argument, NULL, OPT_INITIATE + OO }, { "terminate", no_argument, NULL, OPT_TERMINATE + OO }, { "status", no_argument, NULL, OPT_STATUS + OO }, { "xauthname", required_argument, NULL, OPT_XAUTHNAME + OO }, { "xauthuser", required_argument, NULL, OPT_XAUTHNAME + OO }, { "xauthpass", required_argument, NULL, OPT_XAUTHPASS + OO },#if 0 /* maybe let users do this? */ { "oppohere", required_argument, NULL, OPT_OPPO_HERE + OO }, { "oppothere", required_argument, NULL, OPT_OPPO_THERE + OO },#endif { "asynchronous", no_argument, NULL, OPT_ASYNC + OO }, /* list options */# 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 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); }}static int setup_socket(){ int sock = socket(AF_UNIX, SOCK_STREAM, 0);#if 0 /* 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); fprintf(stderr, "My uid: %d my euid: %d gid: %d egid: %d\n", getuid(), geteuid(), getgid(), getegid()); 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); }#endif 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; switch (e) { case EACCES: fprintf(stderr, "whack: no right to communicate with pluto (access(\"%s\"))\n" , ctl_addr.sun_path); fprintf(stderr, "My uid: %d my euid: %d gid: %d egid: %d\n", getuid(), geteuid(), getgid(), getegid()); break; case ENOENT: fprintf(stderr, "whack: Pluto is not running (no \"%s\")\n" , ctl_addr.sun_path); break; case ECONNREFUSED: fprintf(stderr, "whack: is Pluto running connect() for \"%s\" failed (%d %s)\n" , ctl_addr.sun_path, e, strerror(e)); break; default: fprintf(stderr, "whack: connect() for \"%s\" failed (%d %s)\n" , ctl_addr.sun_path, e, strerror(e)); break; } exit(RC_WHACK_PROBLEM); } /* give up all root priveledges, if we had any */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -