Return to setkey.h CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / sysdep / bsd |
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: }