📄 spi.c
字号:
/* * All-in-one program to set Security Association parameters * Copyright (C) 1996 John Ioannidis. * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. * * 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. */char spi_c_version[] = "RCSID $Id: spi.c,v 1.106 2004/04/29 04:08:28 mcr Exp $";#include <asm/types.h>#include <sys/types.h>#include <sys/ioctl.h>/* #include <linux/netdevice.h> */#include <net/if.h>/* #include <linux/types.h> */ /* new */#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <errno.h>/* #include <sys/socket.h> */#include <netinet/in.h>#include <arpa/inet.h>/* #include <linux/ip.h> */#include <netdb.h>#include <unistd.h>#include <getopt.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <openswan.h>#if 0#include <linux/autoconf.h> /* CONFIG_IPSEC_PFKEYv2 */#endif #include <signal.h> #include <sys/socket.h> #include <pfkeyv2.h> #include <pfkey.h>#include "openswan/radij.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_ipe4.h"#include "openswan/ipsec_ah.h"#include "openswan/ipsec_esp.h"#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL */#include "constants.h"#include "oswlog.h"#include "alg_info.h"#include "kernel_alg.h"struct encap_msghdr *em;/* * Manual conn support for ipsec_alg (modular algos). * Rather ugly to include from pluto dir but avoids * code duplication. */char *progname;int debug = 0;int saref = 0;char *command;extern char *optarg;extern int optind, opterr, optopt;char scratch[2];char *iv = NULL, *enckey = NULL, *authkey = NULL;size_t ivlen = 0, enckeylen = 0, authkeylen = 0;ip_address edst, dst, src;int address_family = 0;unsigned char proto = 0;int alg = 0;#ifdef KERNEL_ALG/* * Manual connection support for modular algos (ipsec_alg) --Juanjo. */#define XF_OTHER_ALG (XF_CLR-1) /* define magic XF_ symbol for alg_info's */#include <assert.h>const char *alg_string = NULL; /* algorithm string */struct alg_info_esp *alg_info = NULL; /* algorithm info got from string */struct esp_info *esp_info = NULL; /* esp info from 1st (only) element */const char *alg_err; /* auxiliar for parsing errors */int proc_read_ok = 0; /* /proc/net/pf_key_support read ok */#endif /* KERNEL_ALG */int replay_window = 0;char sa[SATOT_BUF];extern unsigned int pfkey_lib_debug; /* used by libfreeswan/pfkey_v2_build */int pfkey_sock;fd_set pfkey_socks;uint32_t pfkey_seq = 0;enum life_severity { life_soft = 0, life_hard = 1, life_maxsever = 2};enum life_type { life_alloc = 0, life_bytes = 1, life_addtime = 2, life_usetime = 3, life_packets = 4, life_maxtype = 5};#define streql(_a,_b) (!strcmp((_a),(_b)))static const char *usage_string = "\Usage:\n\ in the following, <SA> is: --af <inet | inet6> --edst <dstaddr> --spi <spi> --proto <proto>\n\ OR: --said <proto><.|:><spi>@<dstaddr>\n\ <life> is: --life <soft|hard>-<allocations|bytes|addtime|usetime|packets>=<value>[,...]\n\spi --clear\n\spi --help\n\spi --version\n\spi\n\spi --del <SA>\n\spi --ip4 <SA> --src <encap-src> --dst <encap-dst>\n\spi --ip6 <SA> --src <encap-src> --dst <encap-dst>\n\spi --ah <algo> <SA> [<life> ][ --replay_window <replay_window> ] --authkey <key>\n\ where <algo> is one of: hmac-md5-96 | hmac-sha1-96 | something-loaded \n\spi --esp <algo> <SA> [<life> ][ --replay_window <replay-window> ] --enckey <ekey> --authkey <akey>\n\ where <algo> is one of: 3des-md5-96 | 3des-sha1-96\n | something-loaded\spi --esp <algo> <SA> [<life> ][ --replay_window <replay-window> ] --enckey <ekey>\n\ where <algo> is: 3des\n\spi --comp <algo> <SA>\n\ where <algo> is: deflate\n\[ --debug ] is optional to any spi command.\n\[ --label <label> ] is optional to any spi command.\n\[ --listenreply ] is optional, and causes the command to stick\n\ around and listen to what the PF_KEY socket says.\n\";static voidusage(char *s, FILE *f){ /* s argument is actually ignored, at present */ fprintf(f, "%s:%s", s, usage_string); exit(-1);}intparse_life_options(uint32_t life[life_maxsever][life_maxtype], char *life_opt[life_maxsever][life_maxtype], char *optarg){ char *optargp = optarg; char *endptr; do { int life_severity, life_type; char *optargt = optargp; if(strncmp(optargp, "soft", sizeof("soft")-1) == 0) { life_severity = life_soft; optargp += sizeof("soft")-1; } else if(strncmp(optargp, "hard", sizeof("hard")-1) == 0) { life_severity = life_hard; optargp += sizeof("hard")-1; } else { fprintf(stderr, "%s: missing lifetime severity in %s, optargt=0p%p, optargp=0p%p, sizeof(\"soft\")=%d\n", progname, optargt, optargt, optargp, (int)sizeof("soft")); usage(progname, stderr); return(1); } if(debug) { fprintf(stdout, "%s: debug: life_severity=%d, optargt=0p%p=\"%s\", optargp=0p%p=\"%s\", sizeof(\"soft\")=%d\n", progname, life_severity, optargt, optargt, optargp, optargp, (int)sizeof("soft")); } if(*(optargp++) != '-') { fprintf(stderr, "%s: expected '-' after severity of lifetime parameter to --life option.\n", progname); usage(progname, stderr); return(1); } if(debug) { fprintf(stdout, "%s: debug: optargt=0p%p=\"%s\", optargp=0p%p=\"%s\", strlen(optargt)=%d, strlen(optargp)=%d, strncmp(optargp, \"addtime\", sizeof(\"addtime\")-1)=%d\n", progname, optargt, optargt, optargp, optargp, (int)strlen(optargt), (int)strlen(optargp), strncmp(optargp, "addtime", sizeof("addtime")-1)); } if(strncmp(optargp, "allocations", sizeof("allocations")-1) == 0) { life_type = life_alloc; optargp += sizeof("allocations")-1; } else if(strncmp(optargp, "bytes", sizeof("bytes")-1) == 0) { life_type = life_bytes; optargp += sizeof("bytes")-1; } else if(strncmp(optargp, "addtime", sizeof("addtime")-1) == 0) { life_type = life_addtime; optargp += sizeof("addtime")-1; } else if(strncmp(optargp, "usetime", sizeof("usetime")-1) == 0) { life_type = life_usetime; optargp += sizeof("usetime")-1; } else if(strncmp(optargp, "packets", sizeof("packets")-1) == 0) { life_type = life_packets; optargp += sizeof("packets")-1; } else { fprintf(stderr, "%s: missing lifetime type after '-' in %s\n", progname, optargt); usage(progname, stderr); return(1); } if(debug) { fprintf(stdout, "%s: debug: life_type=%d\n", progname, life_type); } if(life_opt[life_severity][life_type] != NULL) { fprintf(stderr, "%s: Error, lifetime parameter redefined:%s, already defined as:0p%p\n", progname, optargt, life_opt[life_severity][life_type]); return(1); } if(*(optargp++) != '=') { fprintf(stderr, "%s: expected '=' after type of lifetime parameter to --life option.\n", progname); usage(progname, stderr); return(1); } if(debug) { fprintf(stdout, "%s: debug: optargt=0p%p, optargt+strlen(optargt)=0p%p, optargp=0p%p, strlen(optargp)=%d\n", progname, optargt, optargt+strlen(optargt), optargp, (int)strlen(optargp)); } if(strlen(optargp) == 0) { fprintf(stderr, "%s: expected value after '=' in --life option. optargt=0p%p, optargt+strlen(optargt)=0p%p, optargp=0p%p\n", progname, optargt, optargt+strlen(optargt), optargp); usage(progname, stderr); return(1); } life[life_severity][life_type] = strtoul(optargp, &endptr, 0); if(!((endptr == optargp + strlen(optargp)) || (endptr == optargp + strcspn(optargp, ", ")))) { fprintf(stderr, "%s: Invalid character='%c' at offset %d in lifetime option parameter: '%s', parameter string is %d characters long, %d valid value characters found.\n", progname, *endptr, (int)(endptr - optarg), optarg, (int)strlen(optarg), (int)(strcspn(optargp, ", ") - 1)); return(1); } life_opt[life_severity][life_type] = optargt; if(debug) { fprintf(stdout, "%s lifetime %s set to %d.\n", progname, optargt, life[life_severity][life_type]); } optargp=endptr+1; } while(*endptr==',' || isspace(*endptr)); return(0);}intpfkey_register(uint8_t satype) { /* for registering SA types that can be negotiated */ int error; ssize_t wlen; struct sadb_ext *extensions[SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; pfkey_extensions_init(extensions); error = pfkey_msg_hdr_build(&extensions[0], SADB_REGISTER, satype, 0, ++pfkey_seq, getpid()); if(error != 0) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); return(1); } error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN); if(error != 0) { fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n", progname, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); return(1); } wlen = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); if(wlen != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { /* cleanup code here */ if(wlen < 0) fprintf(stderr, "%s: Trouble writing to channel PF_KEY: %s\n", progname, strerror(errno)); else fprintf(stderr, "%s: write to channel PF_KEY truncated.\n", progname); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); return(1); } pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); return(0);}static struct option const longopts[] ={ {"ah", 1, 0, 'H'}, {"esp", 1, 0, 'P'}, {"comp", 1, 0, 'Z'}, {"ip4", 0, 0, '4'}, {"ip6", 0, 0, '6'}, {"del", 0, 0, 'd'}, {"authkey", 1, 0, 'A'}, {"enckey", 1, 0, 'E'}, {"edst", 1, 0, 'e'}, {"spi", 1, 0, 's'}, {"proto", 1, 0, 'p'}, {"af", 1, 0, 'a'}, {"replay_window", 1, 0, 'w'}, {"iv", 1, 0, 'i'}, {"dst", 1, 0, 'D'}, {"src", 1, 0, 'S'}, {"said", 1, 0, 'I'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {"clear", 0, 0, 'c'}, {"label", 1, 0, 'l'}, {"debug", 0, 0, 'g'}, {"optionsfrom", 1, 0, '+'}, {"life", 1, 0, 'f'}, {"saref", 0, 0, 'r'}, {"listenreply", 0, 0, 'R'}, {0, 0, 0, 0}};int decode_esp(char *algname){ int esp_alg; if(!strcmp(algname, "3des-md5-96")) { esp_alg = XF_ESP3DESMD596; } else if(!strcmp(algname, "3des-sha1-96")) { esp_alg = XF_ESP3DESSHA196; } else if(!strcmp(algname, "3des")) { esp_alg = XF_ESP3DES;#ifdef KERNEL_ALG } else if((alg_info=alg_info_esp_create_from_str(algname, &alg_err, FALSE))) { int esp_ealg_id, esp_aalg_id; esp_alg = XF_OTHER_ALG; if (alg_info->alg_info_cnt>1) { fprintf(stderr, "%s: Invalid encryption algorithm '%s' " "follows '--esp' option: lead too many(%d) " "transforms\n", progname, algname, alg_info->alg_info_cnt); exit(1); } alg_string=algname; esp_info=&alg_info->esp[0]; if (debug) { fprintf(stdout, "%s: alg_info: cnt=%d ealg[0]=%d aalg[0]=%d\n", progname, alg_info->alg_info_cnt, esp_info->encryptalg, esp_info->authalg); } esp_ealg_id=esp_info->esp_ealg_id; esp_aalg_id=esp_info->esp_aalg_id; if (kernel_alg_proc_read()==0) { err_t ugh; proc_read_ok++; ugh = kernel_alg_esp_enc_ok(esp_ealg_id, 0, 0); if (ugh != NULL) { fprintf(stderr, "%s: ESP encryptalg=%d (\"%s\") " "not present - %s\n", progname, esp_ealg_id, enum_name(&esp_transformid_names, esp_ealg_id), ugh); exit(1); } ugh = kernel_alg_esp_auth_ok(esp_aalg_id, 0); if (ugh != NULL) { fprintf(stderr, "%s: ESP authalg=%d (\"%s\") - %s " "not present\n", progname, esp_aalg_id, enum_name(&auth_alg_names, esp_aalg_id), ugh); exit(1); } }#endif /* KERNEL_ALG */ } else { fprintf(stderr, "%s: Invalid encryption algorithm '%s' follows '--esp' option.\n", progname, algname); exit(1); } return esp_alg;}intmain(int argc, char *argv[]){ char *endptr; __u32 spi = 0; int c, previous = -1;/* int ret; */ ip_said said; size_t sa_len; const char* error_s; char ipaddr_txt[ADDRTOT_BUF]; char ipsaid_txt[SATOT_BUF]; int error = 0; ssize_t io_error; int argcount = argc; pid_t mypid; int listenreply = 0; unsigned char authalg, encryptalg; struct sadb_ext *extensions[SADB_EXT_MAX + 1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -