ipsec_dump_policy.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /* $KAME: ipsec_dump_policy.c,v 1.13 2002/06/27 14:35:11 itojun Exp $ */
  2. /*-
  3. * SPDX-License-Identifier: BSD-3-Clause
  4. *
  5. * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the project nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. */
  32. #include <sys/types.h>
  33. #include <sys/param.h>
  34. #include <sys/socket.h>
  35. #include <netipsec/key_var.h>
  36. #include <netinet/in.h>
  37. #include <netipsec/ipsec.h>
  38. #include <arpa/inet.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <netdb.h>
  43. #include "ipsec_strerror.h"
  44. static const char *ipsp_dir_strs[] = {
  45. "any", "in", "out",
  46. };
  47. static const char *ipsp_policy_strs[] = {
  48. "discard", "none", "ipsec", "entrust", "bypass",
  49. };
  50. static char *ipsec_dump_ipsecrequest(char *, size_t,
  51. struct sadb_x_ipsecrequest *, size_t);
  52. static int set_addresses(char *, size_t, struct sockaddr *, struct sockaddr *);
  53. static char *set_address(char *, size_t, struct sockaddr *);
  54. /*
  55. * policy is sadb_x_policy buffer.
  56. * Must call free() later.
  57. * When delimiter == NULL, alternatively ' '(space) is applied.
  58. */
  59. char *
  60. ipsec_dump_policy(c_caddr_t policy, const char *delimiter)
  61. {
  62. const struct sadb_x_policy *xpl = (const struct sadb_x_policy *)policy;
  63. struct sadb_x_ipsecrequest *xisr;
  64. size_t off, buflen;
  65. char *buf;
  66. char isrbuf[1024];
  67. char *newbuf;
  68. /* sanity check */
  69. if (policy == NULL)
  70. return NULL;
  71. if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
  72. __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
  73. return NULL;
  74. }
  75. /* set delimiter */
  76. if (delimiter == NULL)
  77. delimiter = " ";
  78. switch (xpl->sadb_x_policy_dir) {
  79. case IPSEC_DIR_ANY:
  80. case IPSEC_DIR_INBOUND:
  81. case IPSEC_DIR_OUTBOUND:
  82. break;
  83. default:
  84. __ipsec_errcode = EIPSEC_INVAL_DIR;
  85. return NULL;
  86. }
  87. switch (xpl->sadb_x_policy_type) {
  88. case IPSEC_POLICY_DISCARD:
  89. case IPSEC_POLICY_NONE:
  90. case IPSEC_POLICY_IPSEC:
  91. case IPSEC_POLICY_BYPASS:
  92. case IPSEC_POLICY_ENTRUST:
  93. break;
  94. default:
  95. __ipsec_errcode = EIPSEC_INVAL_POLICY;
  96. return NULL;
  97. }
  98. buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir])
  99. + 1 /* space */
  100. + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type])
  101. + 1; /* NUL */
  102. if ((buf = malloc(buflen)) == NULL) {
  103. __ipsec_errcode = EIPSEC_NO_BUFS;
  104. return NULL;
  105. }
  106. snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir],
  107. ipsp_policy_strs[xpl->sadb_x_policy_type]);
  108. if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
  109. __ipsec_errcode = EIPSEC_NO_ERROR;
  110. return buf;
  111. }
  112. /* count length of buffer for use */
  113. off = sizeof(*xpl);
  114. while (off < PFKEY_EXTLEN(xpl)) {
  115. xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off);
  116. off += xisr->sadb_x_ipsecrequest_len;
  117. }
  118. /* validity check */
  119. if (off != PFKEY_EXTLEN(xpl)) {
  120. __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
  121. free(buf);
  122. return NULL;
  123. }
  124. off = sizeof(*xpl);
  125. while (off < PFKEY_EXTLEN(xpl)) {
  126. xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off);
  127. if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr,
  128. PFKEY_EXTLEN(xpl) - off) == NULL) {
  129. free(buf);
  130. return NULL;
  131. }
  132. buflen = strlen(buf) + strlen(delimiter) + strlen(isrbuf) + 1;
  133. newbuf = (char *)realloc(buf, buflen);
  134. if (newbuf == NULL) {
  135. __ipsec_errcode = EIPSEC_NO_BUFS;
  136. free(buf);
  137. return NULL;
  138. }
  139. buf = newbuf;
  140. snprintf(buf + strlen(buf), buflen - strlen(buf),
  141. "%s%s", delimiter, isrbuf);
  142. off += xisr->sadb_x_ipsecrequest_len;
  143. }
  144. __ipsec_errcode = EIPSEC_NO_ERROR;
  145. return buf;
  146. }
  147. static char *
  148. ipsec_dump_ipsecrequest(char *buf, size_t len, struct sadb_x_ipsecrequest *xisr,
  149. size_t bound)
  150. {
  151. const char *proto, *mode, *level;
  152. char abuf[NI_MAXHOST * 2 + 2];
  153. if (xisr->sadb_x_ipsecrequest_len > bound) {
  154. __ipsec_errcode = EIPSEC_INVAL_PROTO;
  155. return NULL;
  156. }
  157. switch (xisr->sadb_x_ipsecrequest_proto) {
  158. case IPPROTO_ESP:
  159. proto = "esp";
  160. break;
  161. case IPPROTO_AH:
  162. proto = "ah";
  163. break;
  164. case IPPROTO_IPCOMP:
  165. proto = "ipcomp";
  166. break;
  167. case IPPROTO_TCP:
  168. proto = "tcp";
  169. break;
  170. default:
  171. __ipsec_errcode = EIPSEC_INVAL_PROTO;
  172. return NULL;
  173. }
  174. switch (xisr->sadb_x_ipsecrequest_mode) {
  175. case IPSEC_MODE_ANY:
  176. mode = "any";
  177. break;
  178. case IPSEC_MODE_TRANSPORT:
  179. mode = "transport";
  180. break;
  181. case IPSEC_MODE_TUNNEL:
  182. mode = "tunnel";
  183. break;
  184. default:
  185. __ipsec_errcode = EIPSEC_INVAL_MODE;
  186. return NULL;
  187. }
  188. abuf[0] = '\0';
  189. if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
  190. struct sockaddr *sa1, *sa2;
  191. caddr_t p;
  192. p = (caddr_t)(xisr + 1);
  193. sa1 = (struct sockaddr *)p;
  194. sa2 = (struct sockaddr *)(p + sa1->sa_len);
  195. if (sizeof(*xisr) + sa1->sa_len + sa2->sa_len !=
  196. xisr->sadb_x_ipsecrequest_len) {
  197. __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
  198. return NULL;
  199. }
  200. if (set_addresses(abuf, sizeof(abuf), sa1, sa2) != 0) {
  201. __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
  202. return NULL;
  203. }
  204. }
  205. switch (xisr->sadb_x_ipsecrequest_level) {
  206. case IPSEC_LEVEL_DEFAULT:
  207. level = "default";
  208. break;
  209. case IPSEC_LEVEL_USE:
  210. level = "use";
  211. break;
  212. case IPSEC_LEVEL_REQUIRE:
  213. level = "require";
  214. break;
  215. case IPSEC_LEVEL_UNIQUE:
  216. level = "unique";
  217. break;
  218. default:
  219. __ipsec_errcode = EIPSEC_INVAL_LEVEL;
  220. return NULL;
  221. }
  222. if (xisr->sadb_x_ipsecrequest_reqid == 0)
  223. snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level);
  224. else {
  225. int ch;
  226. if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX)
  227. ch = '#';
  228. else
  229. ch = ':';
  230. snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level,
  231. ch, xisr->sadb_x_ipsecrequest_reqid);
  232. }
  233. return buf;
  234. }
  235. static int
  236. set_addresses(char *buf, size_t len, struct sockaddr *sa1, struct sockaddr *sa2)
  237. {
  238. char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST];
  239. if (set_address(tmp1, sizeof(tmp1), sa1) == NULL ||
  240. set_address(tmp2, sizeof(tmp2), sa2) == NULL)
  241. return -1;
  242. if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len)
  243. return -1;
  244. snprintf(buf, len, "%s-%s", tmp1, tmp2);
  245. return 0;
  246. }
  247. static char *
  248. set_address(char *buf, size_t len, struct sockaddr *sa)
  249. {
  250. const int niflags = NI_NUMERICHOST;
  251. if (len < 1)
  252. return NULL;
  253. buf[0] = '\0';
  254. if (getnameinfo(sa, sa->sa_len, buf, len, NULL, 0, niflags) != 0)
  255. return NULL;
  256. return buf;
  257. }