PageRenderTime 59ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/external/bsd/tcpdump/dist/print-esp.c

https://github.com/rumpkernel/netbsd-userspace-src
C | 712 lines | 513 code | 117 blank | 82 comment | 137 complexity | b1ee658a39ec210628081b28c613e5fc MD5 | raw file
  1. /* NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp */
  2. /*
  3. * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that: (1) source code distributions
  8. * retain the above copyright notice and this paragraph in its entirety, (2)
  9. * distributions including binary code include the above copyright notice and
  10. * this paragraph in its entirety in the documentation or other materials
  11. * provided with the distribution, and (3) all advertising materials mentioning
  12. * features or use of this software display the following acknowledgement:
  13. * ``This product includes software developed by the University of California,
  14. * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  15. * the University nor the names of its contributors may be used to endorse
  16. * or promote products derived from this software without specific prior
  17. * written permission.
  18. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  19. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  20. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21. */
  22. #include <sys/cdefs.h>
  23. #ifndef lint
  24. #if 0
  25. static const char rcsid[] _U_ =
  26. "@(#) Header: /tcpdump/master/tcpdump/print-esp.c,v 1.58 2007-12-07 00:03:07 mcr Exp (LBL)";
  27. #else
  28. __RCSID("$NetBSD: print-esp.c,v 1.5 2013/12/31 17:33:31 christos Exp $");
  29. #endif
  30. #endif
  31. #ifdef HAVE_CONFIG_H
  32. #include "config.h"
  33. #endif
  34. #include <string.h>
  35. #include <tcpdump-stdinc.h>
  36. #include <stdlib.h>
  37. /* Any code in this file that depends on HAVE_LIBCRYPTO depends on
  38. * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined
  39. * is the simplest way of handling the dependency.
  40. */
  41. #ifdef HAVE_LIBCRYPTO
  42. #ifdef HAVE_OPENSSL_EVP_H
  43. #include <openssl/evp.h>
  44. #else
  45. #undef HAVE_LIBCRYPTO
  46. #endif
  47. #endif
  48. #include <stdio.h>
  49. #include "ip.h"
  50. #include "esp.h"
  51. #ifdef INET6
  52. #include "ip6.h"
  53. #endif
  54. #include "netdissect.h"
  55. #include "addrtoname.h"
  56. #include "extract.h"
  57. #ifndef HAVE_SOCKADDR_STORAGE
  58. #ifdef INET6
  59. struct sockaddr_storage {
  60. union {
  61. struct sockaddr_in sin;
  62. struct sockaddr_in6 sin6;
  63. } un;
  64. };
  65. #else
  66. #define sockaddr_storage sockaddr
  67. #endif
  68. #endif /* HAVE_SOCKADDR_STORAGE */
  69. #ifdef HAVE_LIBCRYPTO
  70. struct sa_list {
  71. struct sa_list *next;
  72. struct sockaddr_storage daddr;
  73. u_int32_t spi; /* if == 0, then IKEv2 */
  74. int initiator;
  75. u_char spii[8]; /* for IKEv2 */
  76. u_char spir[8];
  77. const EVP_CIPHER *evp;
  78. int ivlen;
  79. int authlen;
  80. u_char authsecret[256];
  81. int authsecret_len;
  82. u_char secret[256]; /* is that big enough for all secrets? */
  83. int secretlen;
  84. };
  85. /*
  86. * this will adjust ndo_packetp and ndo_snapend to new buffer!
  87. */
  88. USES_APPLE_DEPRECATED_API
  89. int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
  90. int initiator,
  91. u_char spii[8], u_char spir[8],
  92. u_char *buf, u_char *end)
  93. {
  94. struct sa_list *sa;
  95. u_char *iv;
  96. int len;
  97. EVP_CIPHER_CTX ctx;
  98. /* initiator arg is any non-zero value */
  99. if(initiator) initiator=1;
  100. /* see if we can find the SA, and if so, decode it */
  101. for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
  102. if (sa->spi == 0
  103. && initiator == sa->initiator
  104. && memcmp(spii, sa->spii, 8) == 0
  105. && memcmp(spir, sa->spir, 8) == 0)
  106. break;
  107. }
  108. if(sa == NULL) return 0;
  109. if(sa->evp == NULL) return 0;
  110. /*
  111. * remove authenticator, and see if we still have something to
  112. * work with
  113. */
  114. end = end - sa->authlen;
  115. iv = buf;
  116. buf = buf + sa->ivlen;
  117. len = end-buf;
  118. if(end <= buf) return 0;
  119. memset(&ctx, 0, sizeof(ctx));
  120. if (EVP_CipherInit(&ctx, sa->evp, sa->secret, NULL, 0) < 0)
  121. (*ndo->ndo_warning)(ndo, "espkey init failed");
  122. EVP_CipherInit(&ctx, NULL, NULL, iv, 0);
  123. EVP_Cipher(&ctx, buf, buf, len);
  124. EVP_CIPHER_CTX_cleanup(&ctx);
  125. ndo->ndo_packetp = buf;
  126. ndo->ndo_snapend = end;
  127. return 1;
  128. }
  129. USES_APPLE_RST
  130. static void esp_print_addsa(netdissect_options *ndo,
  131. struct sa_list *sa, int sa_def)
  132. {
  133. /* copy the "sa" */
  134. struct sa_list *nsa;
  135. nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
  136. if (nsa == NULL)
  137. (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
  138. *nsa = *sa;
  139. if (sa_def)
  140. ndo->ndo_sa_default = nsa;
  141. nsa->next = ndo->ndo_sa_list_head;
  142. ndo->ndo_sa_list_head = nsa;
  143. }
  144. static u_int hexdigit(netdissect_options *ndo, char hex)
  145. {
  146. if (hex >= '0' && hex <= '9')
  147. return (hex - '0');
  148. else if (hex >= 'A' && hex <= 'F')
  149. return (hex - 'A' + 10);
  150. else if (hex >= 'a' && hex <= 'f')
  151. return (hex - 'a' + 10);
  152. else {
  153. (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
  154. return 0;
  155. }
  156. }
  157. static u_int hex2byte(netdissect_options *ndo, char *hexstring)
  158. {
  159. u_int byte;
  160. byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
  161. return byte;
  162. }
  163. /*
  164. * returns size of binary, 0 on failure.
  165. */
  166. static
  167. int espprint_decode_hex(netdissect_options *ndo,
  168. u_char *binbuf, unsigned int binbuf_len,
  169. char *hex)
  170. {
  171. unsigned int len;
  172. int i;
  173. len = strlen(hex) / 2;
  174. if (len > binbuf_len) {
  175. (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
  176. return 0;
  177. }
  178. i = 0;
  179. while (hex[0] != '\0' && hex[1]!='\0') {
  180. binbuf[i] = hex2byte(ndo, hex);
  181. hex += 2;
  182. i++;
  183. }
  184. return i;
  185. }
  186. /*
  187. * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret
  188. */
  189. USES_APPLE_DEPRECATED_API
  190. static int
  191. espprint_decode_encalgo(netdissect_options *ndo,
  192. char *decode, struct sa_list *sa)
  193. {
  194. size_t i;
  195. const EVP_CIPHER *evp;
  196. int authlen = 0;
  197. char *colon, *p;
  198. colon = strchr(decode, ':');
  199. if (colon == NULL) {
  200. (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
  201. return 0;
  202. }
  203. *colon = '\0';
  204. if (strlen(decode) > strlen("-hmac96") &&
  205. !strcmp(decode + strlen(decode) - strlen("-hmac96"),
  206. "-hmac96")) {
  207. p = strstr(decode, "-hmac96");
  208. *p = '\0';
  209. authlen = 12;
  210. }
  211. if (strlen(decode) > strlen("-cbc") &&
  212. !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
  213. p = strstr(decode, "-cbc");
  214. *p = '\0';
  215. }
  216. evp = EVP_get_cipherbyname(decode);
  217. if (!evp) {
  218. (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
  219. sa->evp = NULL;
  220. sa->authlen = 0;
  221. sa->ivlen = 0;
  222. return 0;
  223. }
  224. sa->evp = evp;
  225. sa->authlen = authlen;
  226. sa->ivlen = EVP_CIPHER_iv_length(evp);
  227. colon++;
  228. if (colon[0] == '0' && colon[1] == 'x') {
  229. /* decode some hex! */
  230. colon += 2;
  231. sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
  232. if(sa->secretlen == 0) return 0;
  233. } else {
  234. i = strlen(colon);
  235. if (i < sizeof(sa->secret)) {
  236. memcpy(sa->secret, colon, i);
  237. sa->secretlen = i;
  238. } else {
  239. memcpy(sa->secret, colon, sizeof(sa->secret));
  240. sa->secretlen = sizeof(sa->secret);
  241. }
  242. }
  243. return 1;
  244. }
  245. USES_APPLE_RST
  246. /*
  247. * for the moment, ignore the auth algorith, just hard code the authenticator
  248. * length. Need to research how openssl looks up HMAC stuff.
  249. */
  250. static int
  251. espprint_decode_authalgo(netdissect_options *ndo,
  252. char *decode, struct sa_list *sa)
  253. {
  254. char *colon;
  255. colon = strchr(decode, ':');
  256. if (colon == NULL) {
  257. (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
  258. return 0;
  259. }
  260. *colon = '\0';
  261. if(strcasecmp(colon,"sha1") == 0 ||
  262. strcasecmp(colon,"md5") == 0) {
  263. sa->authlen = 12;
  264. }
  265. return 1;
  266. }
  267. static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
  268. const char *file, int lineno)
  269. {
  270. /* it's an IKEv2 secret, store it instead */
  271. struct sa_list sa1;
  272. char *init;
  273. char *icookie, *rcookie;
  274. int ilen, rlen;
  275. char *authkey;
  276. char *enckey;
  277. init = strsep(&line, " \t");
  278. icookie = strsep(&line, " \t");
  279. rcookie = strsep(&line, " \t");
  280. authkey = strsep(&line, " \t");
  281. enckey = strsep(&line, " \t");
  282. /* if any fields are missing */
  283. if(!init || !icookie || !rcookie || !authkey || !enckey) {
  284. (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
  285. file, lineno);
  286. return;
  287. }
  288. ilen = strlen(icookie);
  289. rlen = strlen(rcookie);
  290. if((init[0]!='I' && init[0]!='R')
  291. || icookie[0]!='0' || icookie[1]!='x'
  292. || rcookie[0]!='0' || rcookie[1]!='x'
  293. || ilen!=18
  294. || rlen!=18) {
  295. (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
  296. file, lineno);
  297. (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
  298. init, icookie, ilen, rcookie, rlen);
  299. return;
  300. }
  301. sa1.spi = 0;
  302. sa1.initiator = (init[0] == 'I');
  303. if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
  304. return;
  305. if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
  306. return;
  307. if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
  308. if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
  309. esp_print_addsa(ndo, &sa1, FALSE);
  310. }
  311. /*
  312. *
  313. * special form: file /name
  314. * causes us to go read from this file instead.
  315. *
  316. */
  317. static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
  318. const char *file, int lineno)
  319. {
  320. struct sa_list sa1;
  321. int sa_def;
  322. char *spikey;
  323. char *decode;
  324. spikey = strsep(&line, " \t");
  325. sa_def = 0;
  326. memset(&sa1, 0, sizeof(struct sa_list));
  327. /* if there is only one token, then it is an algo:key token */
  328. if (line == NULL) {
  329. decode = spikey;
  330. spikey = NULL;
  331. /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
  332. /* sa1.spi = 0; */
  333. sa_def = 1;
  334. } else
  335. decode = line;
  336. if (spikey && strcasecmp(spikey, "file") == 0) {
  337. /* open file and read it */
  338. FILE *secretfile;
  339. char fileline[1024];
  340. int lineno=0;
  341. char *nl;
  342. char *filename = line;
  343. secretfile = fopen(filename, FOPEN_READ_TXT);
  344. if (secretfile == NULL) {
  345. perror(filename);
  346. exit(3);
  347. }
  348. while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
  349. lineno++;
  350. /* remove newline from the line */
  351. nl = strchr(fileline, '\n');
  352. if (nl)
  353. *nl = '\0';
  354. if (fileline[0] == '#') continue;
  355. if (fileline[0] == '\0') continue;
  356. esp_print_decode_onesecret(ndo, fileline, filename, lineno);
  357. }
  358. fclose(secretfile);
  359. return;
  360. }
  361. if (spikey && strcasecmp(spikey, "ikev2") == 0) {
  362. esp_print_decode_ikeline(ndo, line, file, lineno);
  363. return;
  364. }
  365. if (spikey) {
  366. char *spistr, *foo;
  367. u_int32_t spino;
  368. struct sockaddr_in *sin;
  369. #ifdef INET6
  370. struct sockaddr_in6 *sin6;
  371. #endif
  372. spistr = strsep(&spikey, "@");
  373. spino = strtoul(spistr, &foo, 0);
  374. if (spistr == foo || !spikey) {
  375. (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
  376. return;
  377. }
  378. sa1.spi = spino;
  379. sin = (struct sockaddr_in *)&sa1.daddr;
  380. #ifdef INET6
  381. sin6 = (struct sockaddr_in6 *)&sa1.daddr;
  382. if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) {
  383. #ifdef HAVE_SOCKADDR_SA_LEN
  384. sin6->sin6_len = sizeof(struct sockaddr_in6);
  385. #endif
  386. sin6->sin6_family = AF_INET6;
  387. } else
  388. #endif
  389. if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
  390. #ifdef HAVE_SOCKADDR_SA_LEN
  391. sin->sin_len = sizeof(struct sockaddr_in);
  392. #endif
  393. sin->sin_family = AF_INET;
  394. } else {
  395. (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
  396. return;
  397. }
  398. }
  399. if (decode) {
  400. /* skip any blank spaces */
  401. while (isspace((unsigned char)*decode))
  402. decode++;
  403. if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
  404. return;
  405. }
  406. }
  407. esp_print_addsa(ndo, &sa1, sa_def);
  408. }
  409. USES_APPLE_DEPRECATED_API
  410. static void esp_init(netdissect_options *ndo _U_)
  411. {
  412. OpenSSL_add_all_algorithms();
  413. EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
  414. }
  415. USES_APPLE_RST
  416. void esp_print_decodesecret(netdissect_options *ndo)
  417. {
  418. char *line;
  419. char *p;
  420. static int initialized = 0;
  421. if (!initialized) {
  422. esp_init(ndo);
  423. initialized = 1;
  424. }
  425. p = ndo->ndo_espsecret;
  426. while (p && p[0] != '\0') {
  427. /* pick out the first line or first thing until a comma */
  428. if ((line = strsep(&p, "\n,")) == NULL) {
  429. line = p;
  430. p = NULL;
  431. }
  432. esp_print_decode_onesecret(ndo, line, "cmdline", 0);
  433. }
  434. ndo->ndo_espsecret = NULL;
  435. }
  436. #endif
  437. #ifdef HAVE_LIBCRYPTO
  438. USES_APPLE_DEPRECATED_API
  439. #endif
  440. int
  441. esp_print(netdissect_options *ndo,
  442. const u_char *bp, const int length, const u_char *bp2
  443. #ifndef HAVE_LIBCRYPTO
  444. _U_
  445. #endif
  446. ,
  447. int *nhdr
  448. #ifndef HAVE_LIBCRYPTO
  449. _U_
  450. #endif
  451. ,
  452. int *padlen
  453. #ifndef HAVE_LIBCRYPTO
  454. _U_
  455. #endif
  456. )
  457. {
  458. register const struct newesp *esp;
  459. register const u_char *ep;
  460. #ifdef HAVE_LIBCRYPTO
  461. struct ip *ip;
  462. struct sa_list *sa = NULL;
  463. #ifdef INET6
  464. struct ip6_hdr *ip6 = NULL;
  465. #endif
  466. int advance;
  467. int len;
  468. u_char *secret;
  469. int ivlen = 0;
  470. u_char *ivoff;
  471. u_char *p;
  472. EVP_CIPHER_CTX ctx;
  473. #endif
  474. esp = (struct newesp *)bp;
  475. #ifdef HAVE_LIBCRYPTO
  476. secret = NULL;
  477. advance = 0;
  478. #endif
  479. #if 0
  480. /* keep secret out of a register */
  481. p = (u_char *)&secret;
  482. #endif
  483. /* 'ep' points to the end of available data. */
  484. ep = ndo->ndo_snapend;
  485. if ((u_char *)(esp + 1) >= ep) {
  486. fputs("[|ESP]", stdout);
  487. goto fail;
  488. }
  489. (*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
  490. (*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq));
  491. (*ndo->ndo_printf)(ndo, ", length %u", length);
  492. #ifndef HAVE_LIBCRYPTO
  493. goto fail;
  494. #else
  495. /* initiailize SAs */
  496. if (ndo->ndo_sa_list_head == NULL) {
  497. if (!ndo->ndo_espsecret)
  498. goto fail;
  499. esp_print_decodesecret(ndo);
  500. }
  501. if (ndo->ndo_sa_list_head == NULL)
  502. goto fail;
  503. ip = (struct ip *)bp2;
  504. switch (IP_V(ip)) {
  505. #ifdef INET6
  506. case 6:
  507. ip6 = (struct ip6_hdr *)bp2;
  508. /* we do not attempt to decrypt jumbograms */
  509. if (!EXTRACT_16BITS(&ip6->ip6_plen))
  510. goto fail;
  511. /* if we can't get nexthdr, we do not need to decrypt it */
  512. len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
  513. /* see if we can find the SA, and if so, decode it */
  514. for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
  515. struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr;
  516. if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
  517. sin6->sin6_family == AF_INET6 &&
  518. memcmp(&sin6->sin6_addr, &ip6->ip6_dst,
  519. sizeof(struct in6_addr)) == 0) {
  520. break;
  521. }
  522. }
  523. break;
  524. #endif /*INET6*/
  525. case 4:
  526. /* nexthdr & padding are in the last fragment */
  527. if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
  528. goto fail;
  529. len = EXTRACT_16BITS(&ip->ip_len);
  530. /* see if we can find the SA, and if so, decode it */
  531. for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
  532. struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr;
  533. if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
  534. sin->sin_family == AF_INET &&
  535. sin->sin_addr.s_addr == ip->ip_dst.s_addr) {
  536. break;
  537. }
  538. }
  539. break;
  540. default:
  541. goto fail;
  542. }
  543. /* if we didn't find the specific one, then look for
  544. * an unspecified one.
  545. */
  546. if (sa == NULL)
  547. sa = ndo->ndo_sa_default;
  548. /* if not found fail */
  549. if (sa == NULL)
  550. goto fail;
  551. /* if we can't get nexthdr, we do not need to decrypt it */
  552. if (ep - bp2 < len)
  553. goto fail;
  554. if (ep - bp2 > len) {
  555. /* FCS included at end of frame (NetBSD 1.6 or later) */
  556. ep = bp2 + len;
  557. }
  558. ivoff = (u_char *)(esp + 1) + 0;
  559. ivlen = sa->ivlen;
  560. secret = sa->secret;
  561. ep = ep - sa->authlen;
  562. if (sa->evp) {
  563. memset(&ctx, 0, sizeof(ctx));
  564. if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0)
  565. (*ndo->ndo_warning)(ndo, "espkey init failed");
  566. (void)EVP_CIPHER_CTX_block_size(&ctx);
  567. p = ivoff;
  568. EVP_CipherInit(&ctx, NULL, NULL, p, 0);
  569. EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen));
  570. EVP_CIPHER_CTX_cleanup(&ctx);
  571. advance = ivoff - (u_char *)esp + ivlen;
  572. } else
  573. advance = sizeof(struct newesp);
  574. /* sanity check for pad length */
  575. if (ep - bp < *(ep - 2))
  576. goto fail;
  577. if (padlen)
  578. *padlen = *(ep - 2) + 2;
  579. if (nhdr)
  580. *nhdr = *(ep - 1);
  581. (ndo->ndo_printf)(ndo, ": ");
  582. return advance;
  583. #endif
  584. fail:
  585. return -1;
  586. }
  587. #ifdef HAVE_LIBCRYPTO
  588. USES_APPLE_RST
  589. #endif
  590. /*
  591. * Local Variables:
  592. * c-style: whitesmith
  593. * c-basic-offset: 8
  594. * End:
  595. */