Annotation of embedaddon/bird/sysdep/bsd/setkey.h, revision 1.1.1.1
1.1 misho 1: /*
2: * BIRD -- Manipulation the IPsec SA/SP database using setkey(8) utility
3: *
4: * (c) 2016 CZ.NIC z.s.p.o.
5: */
6:
7: #include <unistd.h>
8: #include <sys/types.h>
9: #include <sys/socket.h>
10: #include <net/pfkeyv2.h>
11: #include <netipsec/ipsec.h>
12:
13: #include "nest/bird.h"
14: #include "lib/unix.h"
15:
16:
17: /*
18: * Open a socket for manage the IPsec SA/SP database entries
19: */
20: static int
21: setkey_open_socket(void)
22: {
23: int s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
24: if (s < 0)
25: {
26: log(L_ERR "SETKEY: socket: %m");
27: return -1;
28: }
29:
30: return s;
31: }
32:
33: static int
34: setkey_send(struct sadb_msg *msg, uint len)
35: {
36: int s = setkey_open_socket();
37: if (s < 0)
38: return -1;
39:
40: if (msg->sadb_msg_type == SADB_ADD)
41: {
42: /* Delete possible current key in the IPsec SA/SP database */
43: msg->sadb_msg_type = SADB_DELETE;
44: send(s, msg, len, 0);
45: msg->sadb_msg_type = SADB_ADD;
46: }
47:
48: if (send(s, msg, len, 0) < 0)
49: {
50: log(L_ERR "SETKEY: send: %m");
51: close(s);
52: return -1;
53: }
54:
55: close(s);
56: return 0;
57: }
58:
59: /*
60: * Perform setkey(8)-like operation for set the password for TCP MD5 Signature.
61: * Could be called with SABD_ADD or SADB_DELETE argument. Note that SADB_ADD
62: * argument is internally processed as a pair of SADB_ADD and SADB_DELETE
63: * operations to implement replace.
64: */
65: static int
66: setkey_md5(sockaddr *src, sockaddr *dst, char *passwd, uint type)
67: {
68: uint passwd_len = passwd ? strlen(passwd) : 0;
69:
70: uint total =
71: sizeof(struct sadb_msg) +
72: sizeof(struct sadb_key) + PFKEY_ALIGN8(passwd_len) +
73: sizeof(struct sadb_sa) +
74: sizeof(struct sadb_x_sa2) +
75: sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa.sa_len) +
76: sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa.sa_len);
77:
78: char *buf = alloca(total);
79: char *pos = buf;
80: uint len;
81:
82: memset(buf, 0, total);
83:
84: struct sadb_msg *msg = (void *) pos;
85: len = sizeof(struct sadb_msg);
86: msg->sadb_msg_version = PF_KEY_V2;
87: msg->sadb_msg_type = type;
88: msg->sadb_msg_satype = SADB_X_SATYPE_TCPSIGNATURE;
89: msg->sadb_msg_len = 0; /* Fix it later */
90: msg->sadb_msg_pid = getpid();
91: pos += len;
92:
93: /* Set authentication algorithm and password */
94: struct sadb_key *key = (void *) pos;
95: len = sizeof(struct sadb_key) + PFKEY_ALIGN8(passwd_len);
96: key->sadb_key_len = PFKEY_UNIT64(len);
97: key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
98: key->sadb_key_bits = passwd_len * 8;
99: memcpy(pos + sizeof(struct sadb_key), passwd, passwd_len);
100: pos += len;
101:
102: struct sadb_sa *sa = (void *) pos;
103: len = sizeof(struct sadb_sa);
104: sa->sadb_sa_len = PFKEY_UNIT64(len);
105: sa->sadb_sa_exttype = SADB_EXT_SA;
106: sa->sadb_sa_spi = htonl((u32) TCP_SIG_SPI);
107: sa->sadb_sa_auth = SADB_X_AALG_TCP_MD5;
108: sa->sadb_sa_encrypt = SADB_EALG_NONE;
109: sa->sadb_sa_flags = SADB_X_EXT_CYCSEQ;
110: pos += len;
111:
112: struct sadb_x_sa2 *sa2 = (void *) pos;
113: len = sizeof(struct sadb_x_sa2);
114: sa2->sadb_x_sa2_len = PFKEY_UNIT64(len);
115: sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
116: sa2->sadb_x_sa2_mode = IPSEC_MODE_ANY;
117: pos += len;
118:
119: /* Set source address */
120: struct sadb_address *saddr = (void *) pos;
121: len = sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa.sa_len);
122: saddr->sadb_address_len = PFKEY_UNIT64(len);
123: saddr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
124: saddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
125: saddr->sadb_address_prefixlen = MAX_PREFIX_LENGTH;
126: memcpy(pos + sizeof(struct sadb_address), &src->sa, src->sa.sa_len);
127: pos += len;
128:
129: /* Set destination address */
130: struct sadb_address *daddr = (void *) pos;
131: len = sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa.sa_len);
132: daddr->sadb_address_len = PFKEY_UNIT64(len);
133: daddr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
134: daddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
135: daddr->sadb_address_prefixlen = MAX_PREFIX_LENGTH;
136: memcpy(pos + sizeof(struct sadb_address), &dst->sa, dst->sa.sa_len);
137: pos += len;
138:
139: len = pos - buf;
140: msg->sadb_msg_len = PFKEY_UNIT64(len);
141:
142: return setkey_send(msg, len);
143: }
144:
145: /*
146: * Manipulation with the IPsec SA/SP database
147: */
148: static int
149: sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd)
150: {
151: sockaddr src, dst;
152: sockaddr_fill(&src, s->af, local, ifa, 0);
153: sockaddr_fill(&dst, s->af, remote, ifa, 0);
154:
155: if (passwd && *passwd)
156: {
157: int len = strlen(passwd);
158: if (len > TCP_KEYLEN_MAX)
159: ERR_MSG("The password for TCP MD5 Signature is too long");
160:
161: if (setkey_md5(&src, &dst, passwd, SADB_ADD) < 0)
162: ERR_MSG("Cannot add TCP-MD5 password into the IPsec SA/SP database");
163: }
164: else
165: {
166: if (setkey_md5(&src, &dst, NULL, SADB_DELETE) < 0)
167: ERR_MSG("Cannot delete TCP-MD5 password from the IPsec SA/SP database");
168: }
169: return 0;
170: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>