1 /*----------------------------------------------------------------------
2 key.c: Main routines for the key(8) tool for manually managing
3 cryptographic keys and security associations inside the
4 Key Engine of the operating system.
6 Future Enhancements should support:
7 multiple sensitivity levels
13 Copyright 1995 by Bao Phan, Randall Atkinson, & Dan McDonald,
14 All Rights Reserved. All Rights have been assigned to the
15 US Naval Research Laboratory. The NRL Copyright Notice and
16 License govern distribution and use of this software.
17 ----------------------------------------------------------------------*/
18 /*----------------------------------------------------------------------
19 # @(#)COPYRIGHT 1.1a (NRL) 17 August 1995
23 All of the documentation and software included in this software
24 distribution from the US Naval Research Laboratory (NRL) are
25 copyrighted by their respective developers.
27 This software and documentation were developed at NRL by various
28 people. Those developers have each copyrighted the portions that they
29 developed at NRL and have assigned All Rights for those portions to
30 NRL. Outside the USA, NRL also has copyright on the software
31 developed at NRL. The affected files all contain specific copyright
32 notices and those notices must be retained in any derived work.
36 NRL grants permission for redistribution and use in source and binary
37 forms, with or without modification, of the software and documentation
38 created at NRL provided that the following conditions are met:
40 1. Redistributions of source code must retain the above copyright
41 notice, this list of conditions and the following disclaimer.
42 2. Redistributions in binary form must reproduce the above copyright
43 notice, this list of conditions and the following disclaimer in the
44 documentation and/or other materials provided with the distribution.
45 3. All advertising materials mentioning features or use of this software
46 must display the following acknowledgement:
48 This product includes software developed at the Information
49 Technology Division, US Naval Research Laboratory.
51 4. Neither the name of the NRL nor the names of its contributors
52 may be used to endorse or promote products derived from this software
53 without specific prior written permission.
55 THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
56 IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
58 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
59 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
60 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
61 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
62 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
63 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
64 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
65 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 The views and conclusions contained in the software and documentation
68 are those of the authors and should not be interpreted as representing
69 official policies, either expressed or implied, of the US Naval
70 Research Laboratory (NRL).
72 ----------------------------------------------------------------------*/
75 * $ANA: keyadmin.c,v 1.2 1996/06/13 19:42:40 wollman Exp $
76 * $DragonFly: src/usr.sbin/keyadmin/keyadmin.c,v 1.3 2003/11/03 19:31:37 eirikn Exp $
79 #include <sys/types.h>
81 #include <sys/socket.h>
82 #include <sys/socketvar.h>
93 #include <netinet/in.h>
96 #include <netinet6/in6.h>
99 #include <netinet6/in6_types.h>
104 #include <netsec/ipsec.h>
106 #include <netkey/key.h>
109 #include <netinet6/support.h>
112 #ifndef INET6 /* XXX */
113 #define hostname2addr(a, b, c) gethostbyname(a)
114 #define addr2hostname(a, b, c, d) gethostbyaddr((a), (b), (c))
117 #include <arpa/inet.h>
119 int parse7(int, char **);
120 int parse4(int, char **);
121 int docmd(int, char **);
123 #define KEYCMD_ARG_MAX 10
125 #define KEYCMD_LOAD 1
126 #define KEYCMD_SAVE 2
129 #define KEYCMD_FLUSH 5
131 #define KEYCMD_DUMP 7
132 #define KEYCMD_HELP 8
133 #define KEYCMD_EXIT 9
134 #define KEYCMD_SHELL 10
142 char parse7usage[] = "<type> <spi> <src> <dst> <transform> <key> [iv]";
143 char parse4usage[] = "<type> <spi> <src> <dst>";
148 int (*parse)(int, char **);
152 { "add", KEYCMD_ADD, parse7, parse7usage,
153 "Adds a specific key entry to the kernel key table." },
154 { "del", KEYCMD_DEL, parse4, parse4usage,
155 "Removes a specific key entry from the kernel key table." },
156 { "get", KEYCMD_GET, parse4, parse4usage,
157 "Retrieves a key entry from the kernel key table." },
158 { "dump", KEYCMD_DUMP, NULL, " ",
159 "Retrieves all key entries from the kernel key table." },
160 { "load", KEYCMD_LOAD, NULL, "{ <filename> | - }",
161 "Loads keys from a file or stdin into the kernel key table." },
162 { "save", KEYCMD_SAVE, NULL, "{ <filename> | - }",
163 "Saves keys from the kernel key table to a file or stdout." },
164 { "help", KEYCMD_HELP, NULL, "[command]",
165 "Provides limited on-line help. Read the man page for more." },
166 { "flush", KEYCMD_FLUSH, NULL, NULL,
167 "Clears the kernel key table." },
168 { "!", KEYCMD_SHELL, NULL, "[command]",
169 "Executes a subshell." },
170 { "exit", KEYCMD_EXIT, NULL, NULL,
171 "Exits the program." },
172 { "quit", KEYCMD_EXIT, NULL, NULL,
173 "Exits the program." },
174 { NULL, 0, NULL, NULL, NULL }
177 /* flags: index into algorithmtabs */
179 struct nametonum keytypes[] = {
181 { "ah", KEY_TYPE_AH, 0 },
182 { "esp", KEY_TYPE_ESP, 1 },
184 { "rsvp", KEY_TYPE_RSVP, 2 },
185 { "ospf", KEY_TYPE_OSPF, 3 },
186 { "rip", KEY_TYPE_RIPV2, 4 },
190 #ifndef IPSEC_ALGTYPE_AUTH_MD5 /* XXX */
191 #define IPSEC_ALGTYPE_AUTH_MD5 1
194 /* flags: true = iv req. */
195 struct nametonum authalgorithms[] = {
196 { "md5", IPSEC_ALGTYPE_AUTH_MD5, 0 },
198 /* These provide no security but are useful for debugging the
199 kernel's ESP and Key Engine and PF_KEY routines */
200 { "dummy", IPSEC_ALGTYPE_AUTH_DUMMY, 0 },
201 { "cksum", IPSEC_ALGTYPE_AUTH_CKSUM, 0 },
206 #ifndef IPSEC_ALGTYPE_ESP_DES_CBC /* XXX */
207 #define IPSEC_ALGTYPE_ESP_DES_CBC 1
210 /* flags: true = iv req. */
211 struct nametonum encralgorithms[] = {
212 { "des-cbc", IPSEC_ALGTYPE_ESP_DES_CBC, 1 },
214 /* These provide no security but are useful for debugging the
215 kernel's ESP and Key Engine and PF_KEY routines */
216 { "dummy", IPSEC_ALGTYPE_ESP_DUMMY, 0 },
222 * These numbers should be defined in a header file somewhere
223 * and shared with the consuming programs, once someone has
224 * actually written the support in those programs (rspvd,
225 * gated, and routed). Probably <protocols/*>...?
227 #define RSVP_AUTHTYPE_MD5 1 /* XXX */
228 struct nametonum rsvpalgorithms[] = {
229 { "md5", RSVP_AUTHTYPE_MD5, 0 },
233 #define OSPF_AUTHTYPE_MD5 1 /* XXX */
234 struct nametonum ospfalgorithms[] = {
235 { "md5", OSPF_AUTHTYPE_MD5, 0 },
239 #define RIPV2_AUTHTYPE_MD5 1 /* XXX */
240 struct nametonum ripalgorithms[] = {
241 { "md5", RIPV2_AUTHTYPE_MD5, 0 },
245 /* NB: It is the ordering here that determines the values for the
246 flags specified above that are used to index into algorithmtabs[] */
247 struct nametonum *algorithmtabs[] = {
256 char buffer[1024] = "\0";
258 #define MAXRCVBUFSIZE 8 * 1024
260 char key_message[sizeof(struct key_msghdr) + MAX_SOCKADDR_SZ * 3
261 + MAX_KEY_SZ + MAX_IV_SZ];
267 int keydumpseqno = 1;
271 /*----------------------------------------------------------------------
272 help: Print appropriate help message on stdout.
274 ----------------------------------------------------------------------*/
281 for (i = 0; keycmds[i].name; i++)
282 if (!strcasecmp(keycmds[i].name, cmdname))
285 if (!keycmds[i].name) {
286 warnx("unknown command: %s", cmdname);
290 printf("%s%s%s\n", keycmds[i].name, keycmds[i].usage ? " " : "",
291 keycmds[i].usage ? keycmds[i].usage : "");
294 puts(keycmds[i].help);
296 for (i = 0; keycmds[i].name; i++)
297 printf("\t%s%s%s\n", keycmds[i].name, keycmds[i].usage ? " " : "",
298 keycmds[i].usage ? keycmds[i].usage : "");
304 /*----------------------------------------------------------------------
305 usage: print suitable usage message on stdout.
307 ----------------------------------------------------------------------*/
312 fprintf(stderr, "usage: keyadmin <command> <args>\n");
315 /*----------------------------------------------------------------------
316 parsekey: parse argument into a binary key and also record
317 the length of the resulting key.
318 ----------------------------------------------------------------------*/
319 int parsekey(key, keylen, arg)
329 if ((i == 1) && (arg[0] == '0')) {
335 printf("Invalid number \"%s\"\n", arg);
340 k = l = thisbyte = 0;
343 if ((arg[k] >= '0') && (arg[k] <= '9'))
344 thisbyte |= arg[k] - '0';
346 if ((arg[k] >= 'a') && (arg[k] <= 'f'))
347 thisbyte |= arg[k] - 'a' + 10;
349 if ((arg[k] >= 'A') && (arg[k] <= 'F'))
350 thisbyte |= arg[k] - 'A' + 10;
352 printf("Invalid hex number \"%s\"\n", arg);
359 thisbyte = (thisbyte << 4);
369 /*----------------------------------------------------------------------
370 parsenametonum: converts command-line name into index number.
372 ----------------------------------------------------------------------*/
373 int parsenametonum(tab, arg)
374 struct nametonum *tab;
379 for (i = 0; tab[i].name; i++)
380 if (!strcasecmp(tab[i].name, arg))
387 /*----------------------------------------------------------------------
388 parsesockaddr: Convert hostname arg into an appropriate sockaddr.
390 ----------------------------------------------------------------------*/
391 int parsesockaddr(sockaddr, arg)
392 struct sockaddr *sockaddr;
395 struct hostent *hostent;
396 struct in_addr in_addr, *in_addrp;
398 struct in_addr6 in_addr6, *in_addr6p;
401 if ((hostent = hostname2addr(arg, AF_INET, 0)))
402 if ((hostent->h_addrtype == AF_INET) &&
403 (hostent->h_length == sizeof(struct in_addr))) {
404 in_addrp = ((struct in_addr *)hostent->h_addr_list[0]);
408 if (ascii2addr(AF_INET, arg, (char *)&in_addr) ==
409 sizeof(struct in_addr)) {
415 if (hostent = hostname2addr(arg, AF_INET6))
416 if ((hostent->h_addrtype == AF_INET6) &&
417 (hostent->h_length == sizeof(struct in_addr6))) {
418 in_addr6p = ((struct in_addr6 *)hostent->h_addr_list[0]);
422 if (ascii2addr(AF_INET6, arg, (char *)&in_addr6)
423 == sizeof(struct in_addr6)) {
424 in_addr6p = &in_addr6;
429 warnx("unknown host \"%s\"", arg);
433 bzero(sockaddr, sizeof(struct sockaddr_in));
434 sockaddr->sa_len = sizeof(struct sockaddr_in);
435 sockaddr->sa_family = AF_INET;
436 ((struct sockaddr_in *)sockaddr)->sin_addr = *in_addrp;
441 bzero(sockaddr, sizeof(struct sockaddr_in6));
442 sockaddr->sa_len = sizeof(struct sockaddr_in6);
443 sockaddr->sa_family = AF_INET6;
444 ((struct sockaddr_in6 *)sockaddr)->sin6_addr = *in_addr6p;
449 /*----------------------------------------------------------------------
450 dummyfromaddr: Creates a zeroed sockaddr of family af.
452 ----------------------------------------------------------------------*/
453 void dummyfromaddr(sa, af)
459 size = (af == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
461 size = sizeof(struct sockaddr_in);
463 bzero((char *)sa, size);
469 * Macros to ensure word alignment.
472 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
473 #define ADVANCE(x, n) \
477 /*----------------------------------------------------------------------
478 parse4: parse keytype, spi, src addr, and dest addr from argv (command line)
479 and stick in structure pointed to by key_messageptr.
480 ----------------------------------------------------------------------*/
481 int parse4(argc, argv)
490 if ((i = parsenametonum(keytypes, argv[0])) < 0)
493 ((struct key_msghdr *)key_message)->type = keytypes[i].num;
495 /* Should we zero check? */
496 ((struct key_msghdr *)key_message)->spi = atoi(argv[1]);
498 if (parsesockaddr(key_message + key_messageptr, argv[2]) != 0)
500 ADVANCE(key_messageptr, ((struct sockaddr *)(key_message +
501 key_messageptr))->sa_len);
503 if (parsesockaddr(key_message + key_messageptr, argv[3]) != 0)
505 ADVANCE(key_messageptr, ((struct sockaddr *)(key_message +
506 key_messageptr))->sa_len);
509 * We need to put a dummy from address since the kernel expects
510 * this to be in the message.
513 dummyfromaddr(key_message + key_messageptr, AF_INET6);
515 dummyfromaddr(key_message + key_messageptr, AF_INET);
517 ADVANCE(key_messageptr, ((struct sockaddr *)(key_message +
518 key_messageptr))->sa_len);
523 /*----------------------------------------------------------------------
524 parse7: parse keytype, spi, src addr, dest addr, alg type, key, and iv
525 from argv (command line)
526 and stick in structure pointed to by key_messageptr.
527 ----------------------------------------------------------------------*/
528 int parse7(argc, argv)
537 if ((i = parsenametonum(keytypes, argv[0])) < 0)
540 ((struct key_msghdr *)key_message)->type = keytypes[i].num;
542 /* Should we zero check? */
543 ((struct key_msghdr *)key_message)->spi = atoi(argv[1]);
545 if (parsesockaddr(key_message + key_messageptr, argv[2]) != 0)
547 ADVANCE(key_messageptr, ((struct sockaddr *)(key_message +
548 key_messageptr))->sa_len);
550 if (parsesockaddr(key_message + key_messageptr, argv[3]) != 0)
552 ADVANCE(key_messageptr, ((struct sockaddr *)(key_message +
553 key_messageptr))->sa_len);
556 * We need to put a dummy from address since the kernel expects
557 * this to be in the message.
560 dummyfromaddr(key_message + key_messageptr, AF_INET6);
562 dummyfromaddr(key_message + key_messageptr, AF_INET);
564 ADVANCE(key_messageptr, ((struct sockaddr *)(key_message +
565 key_messageptr))->sa_len);
567 if ((j = parsenametonum(algorithmtabs[keytypes[i].flags], argv[4])) < 0)
570 ((struct key_msghdr *)key_message)->algorithm =
571 algorithmtabs[keytypes[i].flags][j].num;
573 if ((argc < 7) && algorithmtabs[keytypes[i].flags][j].flags)
576 if (parsekey(key_message + key_messageptr,
577 &(((struct key_msghdr *)key_message)->keylen), argv[5]) != 0)
579 ADVANCE(key_messageptr, ((struct key_msghdr *)key_message)->keylen);
582 if (parsekey(key_message + key_messageptr,
583 &(((struct key_msghdr *)key_message)->ivlen), argv[6]) != 0)
585 ADVANCE(key_messageptr, ((struct key_msghdr *)key_message)->ivlen);
591 /*----------------------------------------------------------------------
594 ----------------------------------------------------------------------*/
595 int parsecmdline(buffer, argv, argc)
600 int i = 0, iargc = 0;
605 while(buffer[i] && (iargc < KEYCMD_ARG_MAX)) {
606 if ((buffer[i] == '\n') || (buffer[i] == '#')) {
609 argv[iargc++] = head;
612 if ((buffer[i] == ' ') || (buffer[i] == '\t')) {
615 argv[iargc++] = head;
616 head = &(buffer[++i]);
623 return iargc ? 0 : 1;
627 /*----------------------------------------------------------------------
628 load: load keys from file filename into Key Engine.
630 ----------------------------------------------------------------------*/
635 char buffer[1024], *buf, *largv[KEYCMD_ARG_MAX], *c;
636 int i, largc, left, line = 0;
638 if (strcmp(filename, "-")) {
639 if (!(fh = fopen(filename, "r")))
647 left = sizeof(buffer);
649 while(fgets(buf, left, fh)) {
651 if ((c = strchr(buffer, '\\'))) {
652 left = (sizeof(buffer) - 1) - (--c - buffer);
655 buffer[sizeof(buffer)-1] = 0;
657 if ((i = parsecmdline(buffer, &(largv[1]), &largc)) < 0)
661 if ((i = docmd(++largc, largv))) {
663 warnx("parse error on line %d of %s", line, filename);
671 left = sizeof(buffer);
678 /*----------------------------------------------------------------------
681 ----------------------------------------------------------------------*/
684 struct key_msghdr *km;
685 struct key_msgdata *kip;
691 if (!(km->key_msglen))
694 cp = (caddr_t)(km + 1);
695 cpmax = (caddr_t)km + km->key_msglen;
697 #define NEXTDATA(x, n) \
698 { x += ROUNDUP(n); if (cp >= cpmax) { \
699 warnx("kernel returned a truncated message!"); return(-1); } }
702 kip->src = (struct sockaddr *)cp;
703 if (!kip->src->sa_len)
706 NEXTDATA(cp, kip->src->sa_len);
709 kip->dst = (struct sockaddr *)cp;
710 if (!kip->dst->sa_len)
713 NEXTDATA(cp, kip->dst->sa_len);
716 kip->from = (struct sockaddr *)cp;
717 if (!kip->from->sa_len)
720 NEXTDATA(cp, kip->from->sa_len);
723 if (kip->keylen = km->keylen) {
725 NEXTDATA(cp, km->keylen);
729 if (kip->ivlen = km->ivlen)
734 printf("key: parsedata: difference=%d\n", cp - cpmax);
739 /*----------------------------------------------------------------------
742 ----------------------------------------------------------------------*/
743 void printkeyiv(fp, cp, len)
749 for (i=0; i<len; i++)
750 fprintf(fp, "%02x", (u_int8_t)*(cp+i));
753 /*----------------------------------------------------------------------
756 ----------------------------------------------------------------------*/
757 void printsockaddr(fp, sa)
766 if (sa->sa_family == AF_INET6) {
767 len = sizeof(struct in_addr6);
768 addrp = (char *)&(((struct sockaddr_in6 *)sa)->sin6_addr);
771 len = sizeof(struct in_addr);
772 addrp = (char *)&(((struct sockaddr_in *)sa)->sin_addr);
777 if((hp = addr2hostname(addrp, len, sa->sa_family, 0)) != NULL)
778 fprintf(fp, "%s", hp->h_name);
780 fprintf(fp, "%s", addr2ascii(sa->sa_family, addrp, len, NULL));
783 /*----------------------------------------------------------------------
786 ----------------------------------------------------------------------*/
788 parsenumtoname(tab, num)
789 struct nametonum *tab;
793 for (i = 0; tab[i].name; i++) {
794 if (num == tab[i].num)
800 /*----------------------------------------------------------------------
803 ----------------------------------------------------------------------*/
805 parsenumtoflag(tab, num)
806 struct nametonum *tab;
810 for (i = 0; tab[i].name; i++) {
811 if (num == tab[i].num)
812 return(tab[i].flags);
818 /*----------------------------------------------------------------------
821 ----------------------------------------------------------------------*/
822 void printkeymsg(kmp, kdp)
823 struct key_msghdr *kmp;
824 struct key_msgdata *kdp;
827 printf("type=%d(%s) ",kmp->type, parsenumtoname(keytypes, kmp->type));
828 printf("spi=%u ", kmp->spi);
829 printf("alogrithm=%u(%s) ", kmp->algorithm,
830 parsenumtoname(algorithmtabs[parsenumtoflag(keytypes, kmp->type)],
832 printf("state=0x%x ",kmp->state);
834 if (kmp->state != 0) {
835 if (kmp->state & K_USED)
837 if (kmp->state & K_UNIQUE)
839 if (kmp->state & K_LARVAL)
841 if (kmp->state & K_ZOMBIE)
843 if (kmp->state & K_DEAD)
845 if (kmp->state & K_INBOUND)
847 if (kmp->state & K_OUTBOUND)
851 printf("sensitivity_label=%d ",kmp->label);
852 printf("lifetype=%d ",kmp->lifetype);
853 printf("lifetime1=%d ",kmp->lifetime1);
854 printf("lifetime2=%d\n",kmp->lifetime2);
855 printf("key (len=%d):\t",kdp->keylen);
856 printkeyiv(stdout, kdp->key, kdp->keylen);
858 printf("iv (len=%d):\t", kdp->ivlen);
859 printkeyiv(stdout, kdp->iv, kdp->ivlen);
862 printsockaddr(stdout, (struct sockaddr *)kdp->src);
865 printsockaddr(stdout, (struct sockaddr *)kdp->dst);
867 /* printf("from:\t");
868 printsockaddr(stdout, (struct sockaddr *)kdp->from); */
872 /*----------------------------------------------------------------------
875 ----------------------------------------------------------------------*/
876 int docmd(argc, argv)
884 if (!argv[0] || !argc)
890 bzero(&key_message, sizeof(key_message));
891 key_messageptr = sizeof(struct key_msghdr);
893 for (i = 0; keycmds[i].name; i++)
894 if (!strcasecmp(keycmds[i].name, argv[0]))
897 if (!keycmds[i].name)
900 if (keycmds[i].parse)
901 if ((j = keycmds[i].parse(argc - 1, &(argv[1]))))
904 ((struct key_msghdr *)key_message)->key_msglen = key_messageptr;
905 ((struct key_msghdr *)key_message)->key_msgvers = 1;
906 ((struct key_msghdr *)key_message)->key_seq = 1;
908 switch(keycmds[i].num) {
913 * For now, we do sanity check of security association
914 * information here until we find a better place.
917 struct key_msghdr *kmp = (struct key_msghdr *)key_message;
919 if ((kmp->type == KEY_TYPE_AH ||
920 kmp->type == KEY_TYPE_ESP) && (kmp->spi < 256)) {
921 warnx("add: spi must be greater than 255");
925 if (kmp->type == KEY_TYPE_ESP &&
926 (kmp->algorithm == IPSEC_ALGTYPE_ESP_DES_CBC
927 #ifdef IPSEC_ALGTYPE_ESP_3DES
928 || kmp->algorithm == IPSEC_ALGTYPE_ESP_3DES
931 if (kmp->keylen != 8) {
932 warnx("add: key must be 8 bytes");
935 if (kmp->ivlen != 4 && kmp->ivlen != 8) {
936 warnx("add: iv must be 4 or 8 bytes");
941 if (kmp->type == KEY_TYPE_AH &&
942 kmp->algorithm == IPSEC_ALGTYPE_AUTH_MD5 && kmp->keylen == 0) {
943 warnx("add: no key specified");
948 ((struct key_msghdr *)key_message)->key_msgtype = KEY_ADD;
949 if (write(keysock, key_message,
950 ((struct key_msghdr *)key_message)->key_msglen) !=
951 ((struct key_msghdr *)key_message)->key_msglen) {
953 warnx("add: security association already exists");
958 read(keysock, key_message, sizeof(key_message));
962 ((struct key_msghdr *)key_message)->key_msgtype = KEY_DELETE;
963 if (write(keysock, key_message,
964 ((struct key_msghdr *)key_message)->key_msglen) !=
965 ((struct key_msghdr *)key_message)->key_msglen) {
966 if (errno == ESRCH) {
967 warnx("delete: security association not found");
974 read(keysock, key_message, sizeof(key_message));
978 ((struct key_msghdr *)key_message)->key_msgtype = KEY_GET;
979 ((struct key_msghdr *)key_message)->key_seq = seqno = keygetseqno++;
981 if (write(keysock, key_message,
982 ((struct key_msghdr *)key_message)->key_msglen) !=
983 ((struct key_msghdr *)key_message)->key_msglen) {
984 if (errno == ESRCH) {
985 warnx("get: security association not found");
991 } /* endif write() */
995 struct key_msgdata keymsgdata;
997 len = sizeof(struct key_msghdr) + MAX_SOCKADDR_SZ * 3
998 + MAX_KEY_SZ + MAX_IV_SZ;
1001 if (read(keysock, key_message, len) < 0) {
1006 if (!((((struct key_msghdr *)&key_message)->key_pid==mypid)
1007 && (((struct key_msghdr *)&key_message)->key_msgtype==KEY_GET)
1008 && (((struct key_msghdr *)&key_message)->key_seq==seqno))) {
1009 fprintf(stderr, ".");
1013 if (((struct key_msghdr *)&key_message)->key_errno != 0) {
1014 printf("Error: kernel reporting errno=%d\n",
1015 ((struct key_msghdr *)&key_message)->key_errno);
1019 if (parsedata((struct key_msghdr *)&key_message, &keymsgdata) < 0) {
1020 printf("get: can't parse reply\n");
1024 printkeymsg((struct key_msghdr *)&key_message, &keymsgdata);
1029 ((struct key_msghdr *)key_message)->key_msgtype = KEY_FLUSH;
1030 if (write(keysock, key_message,
1031 ((struct key_msghdr *)key_message)->key_msglen) !=
1032 ((struct key_msghdr *)key_message)->key_msglen) {
1036 read(keysock, key_message, sizeof(key_message));
1040 return help((argc > 1) ? argv[1] : NULL);
1044 char buffer[1024], *ap, *ep, *c;
1047 ep = buffer + sizeof(buffer) - 1;
1048 for (i = 1, ap = buffer; (i < argc) && (ap < ep); i++) {
1050 while ((*(ap++) = *(c++)) && (ap < ep));
1056 char *c = getenv("SHELL");
1069 return load(argv[1]);
1074 if (!strcmp(argv[1], "-"))
1076 else if ((fd = open(argv[1], O_CREAT | O_RDWR | O_EXCL,
1077 S_IRUSR | S_IWUSR)) < 0) {
1080 } else if (!(fp = fdopen(fd, "w"))) {
1086 ((struct key_msghdr *)key_message)->key_msgtype = KEY_DUMP;
1087 if (write(keysock, key_message,
1088 ((struct key_msghdr *)key_message)->key_msglen) !=
1089 ((struct key_msghdr *)key_message)->key_msglen) {
1095 struct key_msgdata keymsgdata;
1098 if (read(keysock, key_message, sizeof(key_message)) < 0) {
1103 if (!((((struct key_msghdr *)&key_message)->key_pid==mypid)
1104 && (((struct key_msghdr *)&key_message)->key_msgtype==KEY_DUMP)))
1108 * Kernel is done sending secassoc if key_seq == 0
1110 if (((struct key_msghdr *)&key_message)->key_seq == 0) {
1111 if ((keycmds[i].num == KEYCMD_SAVE) && (fp != stdout))
1116 if (parsedata((struct key_msghdr *)&key_message, &keymsgdata) < 0) {
1117 printf("get: can't parse reply\n");
1120 if (keycmds[i].num == KEYCMD_SAVE) {
1121 char *keytype, *algorithm;
1123 keytype = parsenumtoname(keytypes,
1124 ((struct key_msghdr *)&key_message)->type);
1126 algorithm = parsenumtoname(algorithmtabs[parsenumtoflag(keytypes,
1127 ((struct key_msghdr *)&key_message)->type)],
1128 ((struct key_msghdr *)&key_message)->algorithm);
1130 fprintf(fp, "%s %u ", keytype,
1131 ((struct key_msghdr *)&key_message)->spi);
1132 printsockaddr(fp, (struct sockaddr *)(keymsgdata.src));
1134 printsockaddr(fp, (struct sockaddr *)(keymsgdata.dst));
1136 fprintf(fp, "%s ", algorithm);
1137 printkeyiv(fp, keymsgdata.key, keymsgdata.keylen);
1139 printkeyiv(fp, keymsgdata.iv, keymsgdata.ivlen);
1142 printkeymsg((struct key_msghdr *)&key_message, &keymsgdata);
1150 /*----------------------------------------------------------------------
1153 ----------------------------------------------------------------------*/
1154 int main(argc, argv)
1162 errx(1, "this program is intended for the superuser only");
1164 if (!(keysock = socket(PF_KEY, SOCK_RAW, 0))) {
1169 for (rcvsize = MAXRCVBUFSIZE; rcvsize; rcvsize -= 1024) {
1170 if (setsockopt(keysock, SOL_SOCKET, SO_RCVBUF, &rcvsize,
1171 sizeof(rcvsize)) <= 0)
1183 * Attempt to do a single command, based on command line arguments.
1185 if (strcasecmp(argv[1], "add") == 0)
1186 errx(1, "cannot add keys from the command line. RTFM for why");
1187 if ((i = docmd(argc - 1, &(argv[1])))) {
1189 for (j = 0; keycmds[j].name; j++)
1190 if (!strcasecmp(keycmds[j].name, argv[1]))
1193 if (keycmds[j].name) {
1194 fprintf(stderr, "usage: %s%s%s\n", keycmds[j].name,
1195 keycmds[j].usage ? " " : "",
1196 keycmds[j].usage ? keycmds[j].usage : "");
1207 char *iargv[KEYCMD_ARG_MAX];
1212 if (!(fgets(buffer, sizeof(buffer), stdin)))
1214 buffer[sizeof(buffer)-1] = 0;
1216 * get command line, and parse into an argc/argv form.
1218 if ((i = parsecmdline(buffer, iargv, &iargc)) < 0)
1224 * given argc/argv, process argument as if it came from the command
1227 if ((i = docmd(iargc, iargv))) {
1229 for (j = 0; keycmds[j].name; j++)
1230 if (!strcasecmp(keycmds[j].name, iargv[0]))
1233 if (keycmds[j].name) {
1234 fprintf(stderr, "usage: %s%s%s\n", keycmds[j].name,
1235 keycmds[j].usage ? " " : "",
1236 keycmds[j].usage ? keycmds[j].usage : "");
1242 warn("system error");
1244 warnx("unrecognized command");
1245 warnx("type 'help' if you need help");