Return to starterstroke.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2007-2015 Tobias Brunner ! 3: * Copyright (C) 2006 Martin Willi ! 4: * HSR Hochschule fuer Technik Rapperswil ! 5: * ! 6: * This program is free software; you can redistribute it and/or modify it ! 7: * under the terms of the GNU General Public License as published by the ! 8: * Free Software Foundation; either version 2 of the License, or (at your ! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 10: * ! 11: * This program is distributed in the hope that it will be useful, but ! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 14: * for more details. ! 15: */ ! 16: ! 17: #include <unistd.h> ! 18: #include <stdlib.h> ! 19: #include <stdint.h> ! 20: #include <string.h> ! 21: ! 22: #include <credentials/auth_cfg.h> ! 23: ! 24: #include <library.h> ! 25: #include <utils/debug.h> ! 26: ! 27: #include <stroke_msg.h> ! 28: ! 29: #include "starterstroke.h" ! 30: #include "confread.h" ! 31: #include "files.h" ! 32: ! 33: #define IPV4_LEN 4 ! 34: #define IPV6_LEN 16 ! 35: ! 36: static stroke_msg_t *create_stroke_msg(int type) ! 37: { ! 38: stroke_msg_t *msg; ! 39: ! 40: INIT(msg, ! 41: .type = type, ! 42: .length = offsetof(stroke_msg_t, buffer), ! 43: ); ! 44: return msg; ! 45: } ! 46: ! 47: #define push_string(msg, field, str) \ ! 48: push_string_impl(msg, offsetof(stroke_msg_t, field), str) ! 49: #define push_string_end(msg, offset, field, str) \ ! 50: push_string_impl(msg, offset + offsetof(stroke_end_t, field), str) ! 51: ! 52: static void push_string_impl(stroke_msg_t **msg, size_t offset, char *string) ! 53: { ! 54: size_t cur_len = (*msg)->length, str_len; ! 55: ! 56: if (!string) ! 57: { ! 58: return; ! 59: } ! 60: str_len = strlen(string) + 1; ! 61: if (cur_len + str_len >= UINT16_MAX) ! 62: { ! 63: (*msg)->length = UINT16_MAX; ! 64: return; ! 65: } ! 66: while (cur_len + str_len > sizeof(stroke_msg_t) + (*msg)->buflen) ! 67: { ! 68: *msg = realloc(*msg, sizeof(stroke_msg_t) + (*msg)->buflen + ! 69: STROKE_BUF_LEN_INC); ! 70: (*msg)->buflen += STROKE_BUF_LEN_INC; ! 71: } ! 72: (*msg)->length += str_len; ! 73: strcpy((char*)*msg + cur_len, string); ! 74: *(char**)((char*)*msg + offset) = (char*)cur_len; ! 75: } ! 76: ! 77: static int send_stroke_msg(stroke_msg_t *msg) ! 78: { ! 79: stream_t *stream; ! 80: char *uri, buffer[64]; ! 81: int count; ! 82: ! 83: if (msg->length == UINT16_MAX) ! 84: { ! 85: DBG1(DBG_APP, "stroke message exceeds maximum buffer size"); ! 86: free(msg); ! 87: return -1; ! 88: } ! 89: ! 90: /* starter is not called from commandline, and therefore absolutely silent */ ! 91: msg->output_verbosity = -1; ! 92: ! 93: uri = lib->settings->get_str(lib->settings, "%s.plugins.stroke.socket", ! 94: "unix://" CHARON_CTL_FILE, daemon_name); ! 95: stream = lib->streams->connect(lib->streams, uri); ! 96: if (!stream) ! 97: { ! 98: DBG1(DBG_APP, "failed to connect to stroke socket '%s'", uri); ! 99: free(msg); ! 100: return -1; ! 101: } ! 102: ! 103: if (!stream->write_all(stream, msg, msg->length)) ! 104: { ! 105: DBG1(DBG_APP, "sending stroke message failed"); ! 106: stream->destroy(stream); ! 107: free(msg); ! 108: return -1; ! 109: } ! 110: while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0) ! 111: { ! 112: buffer[count] = '\0'; ! 113: DBG1(DBG_APP, "%s", buffer); ! 114: } ! 115: if (count < 0) ! 116: { ! 117: DBG1(DBG_APP, "reading stroke response failed"); ! 118: } ! 119: stream->destroy(stream); ! 120: free(msg); ! 121: return 0; ! 122: } ! 123: ! 124: static char* connection_name(starter_conn_t *conn) ! 125: { ! 126: /* if connection name is '%auto', create a new name like conn_xxxxx */ ! 127: static char buf[32]; ! 128: ! 129: if (streq(conn->name, "%auto")) ! 130: { ! 131: sprintf(buf, "conn_%lu", conn->id); ! 132: return buf; ! 133: } ! 134: return conn->name; ! 135: } ! 136: ! 137: static void add_end(stroke_msg_t **msg, size_t offset, starter_end_t *conn_end) ! 138: { ! 139: stroke_end_t *msg_end; ! 140: ! 141: push_string_end(msg, offset, auth, conn_end->auth); ! 142: push_string_end(msg, offset, auth2, conn_end->auth2); ! 143: push_string_end(msg, offset, id, conn_end->id); ! 144: push_string_end(msg, offset, id2, conn_end->id2); ! 145: push_string_end(msg, offset, rsakey, conn_end->rsakey); ! 146: push_string_end(msg, offset, cert, conn_end->cert); ! 147: push_string_end(msg, offset, cert2, conn_end->cert2); ! 148: push_string_end(msg, offset, cert_policy, conn_end->cert_policy); ! 149: push_string_end(msg, offset, ca, conn_end->ca); ! 150: push_string_end(msg, offset, ca2, conn_end->ca2); ! 151: push_string_end(msg, offset, groups, conn_end->groups); ! 152: push_string_end(msg, offset, groups2, conn_end->groups2); ! 153: push_string_end(msg, offset, updown, conn_end->updown); ! 154: if (conn_end->host) ! 155: { ! 156: push_string_end(msg, offset, address, conn_end->host); ! 157: } ! 158: else ! 159: { ! 160: push_string_end(msg, offset, address, "%any"); ! 161: } ! 162: push_string_end(msg, offset, subnets, conn_end->subnet); ! 163: push_string_end(msg, offset, sourceip, conn_end->sourceip); ! 164: push_string_end(msg, offset, dns, conn_end->dns); ! 165: ! 166: /* we can't assign it earlier as msg might change */ ! 167: msg_end = (stroke_end_t*)((char*)(*msg) + offset); ! 168: msg_end->ikeport = conn_end->ikeport; ! 169: msg_end->sendcert = conn_end->sendcert; ! 170: msg_end->hostaccess = conn_end->hostaccess; ! 171: msg_end->tohost = !conn_end->subnet; ! 172: msg_end->allow_any = conn_end->allow_any; ! 173: msg_end->protocol = conn_end->protocol; ! 174: msg_end->from_port = conn_end->from_port; ! 175: msg_end->to_port = conn_end->to_port; ! 176: } ! 177: ! 178: int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn) ! 179: { ! 180: stroke_msg_t *msg; ! 181: ! 182: msg = create_stroke_msg(STR_ADD_CONN); ! 183: msg->add_conn.version = conn->keyexchange; ! 184: push_string(&msg, add_conn.name, connection_name(conn)); ! 185: push_string(&msg, add_conn.eap_identity, conn->eap_identity); ! 186: push_string(&msg, add_conn.aaa_identity, conn->aaa_identity); ! 187: push_string(&msg, add_conn.xauth_identity, conn->xauth_identity); ! 188: ! 189: msg->add_conn.mode = conn->mode; ! 190: msg->add_conn.proxy_mode = conn->proxy_mode; ! 191: ! 192: if (!(conn->options & SA_OPTION_DONT_REKEY)) ! 193: { ! 194: msg->add_conn.rekey.reauth = !(conn->options & SA_OPTION_DONT_REAUTH); ! 195: msg->add_conn.rekey.ipsec_lifetime = conn->sa_ipsec_life_seconds; ! 196: msg->add_conn.rekey.ike_lifetime = conn->sa_ike_life_seconds; ! 197: msg->add_conn.rekey.margin = conn->sa_rekey_margin; ! 198: msg->add_conn.rekey.life_bytes = conn->sa_ipsec_life_bytes; ! 199: msg->add_conn.rekey.margin_bytes = conn->sa_ipsec_margin_bytes; ! 200: msg->add_conn.rekey.life_packets = conn->sa_ipsec_life_packets; ! 201: msg->add_conn.rekey.margin_packets = conn->sa_ipsec_margin_packets; ! 202: msg->add_conn.rekey.fuzz = conn->sa_rekey_fuzz; ! 203: } ! 204: msg->add_conn.rekey.tries = conn->sa_keying_tries; ! 205: ! 206: msg->add_conn.mobike = conn->options & SA_OPTION_MOBIKE; ! 207: msg->add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP; ! 208: msg->add_conn.fragmentation = conn->fragmentation; ! 209: msg->add_conn.ikedscp = conn->ikedscp; ! 210: msg->add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS; ! 211: msg->add_conn.install_policy = conn->install_policy; ! 212: msg->add_conn.aggressive = conn->aggressive; ! 213: msg->add_conn.pushmode = conn->options & SA_OPTION_MODECFG_PUSH; ! 214: msg->add_conn.crl_policy = (crl_policy_t)cfg->setup.strictcrlpolicy; ! 215: msg->add_conn.unique = cfg->setup.uniqueids; ! 216: push_string(&msg, add_conn.algorithms.ike, conn->ike); ! 217: push_string(&msg, add_conn.algorithms.esp, conn->esp); ! 218: push_string(&msg, add_conn.algorithms.ah, conn->ah); ! 219: msg->add_conn.dpd.delay = conn->dpd_delay; ! 220: msg->add_conn.dpd.timeout = conn->dpd_timeout; ! 221: msg->add_conn.dpd.action = conn->dpd_action; ! 222: msg->add_conn.close_action = conn->close_action; ! 223: msg->add_conn.sha256_96 = conn->sha256_96; ! 224: msg->add_conn.inactivity = conn->inactivity; ! 225: msg->add_conn.ikeme.mediation = conn->me_mediation; ! 226: push_string(&msg, add_conn.ikeme.mediated_by, conn->me_mediated_by); ! 227: push_string(&msg, add_conn.ikeme.peerid, conn->me_peerid); ! 228: msg->add_conn.reqid = conn->reqid; ! 229: msg->add_conn.replay_window = conn->replay_window; ! 230: msg->add_conn.mark_in.value = conn->mark_in.value; ! 231: msg->add_conn.mark_in.mask = conn->mark_in.mask; ! 232: msg->add_conn.mark_out.value = conn->mark_out.value; ! 233: msg->add_conn.mark_out.mask = conn->mark_out.mask; ! 234: msg->add_conn.tfc = conn->tfc; ! 235: ! 236: add_end(&msg, offsetof(stroke_msg_t, add_conn.me), &conn->left); ! 237: add_end(&msg, offsetof(stroke_msg_t, add_conn.other), &conn->right); ! 238: ! 239: if (!msg->add_conn.me.auth && !msg->add_conn.other.auth && ! 240: conn->authby) ! 241: { /* leftauth/rightauth not set, use legacy options */ ! 242: if (streq(conn->authby, "rsa") || streq(conn->authby, "rsasig") || ! 243: streq(conn->authby, "ecdsa") || streq(conn->authby, "ecdsasig") || ! 244: streq(conn->authby, "pubkey")) ! 245: { ! 246: push_string(&msg, add_conn.me.auth, "pubkey"); ! 247: push_string(&msg, add_conn.other.auth, "pubkey"); ! 248: } ! 249: else if (streq(conn->authby, "secret") || streq(conn->authby, "psk")) ! 250: { ! 251: push_string(&msg, add_conn.me.auth, "psk"); ! 252: push_string(&msg, add_conn.other.auth, "psk"); ! 253: } ! 254: else if (streq(conn->authby, "xauthrsasig")) ! 255: { ! 256: push_string(&msg, add_conn.me.auth, "pubkey"); ! 257: push_string(&msg, add_conn.other.auth, "pubkey"); ! 258: if (conn->options & SA_OPTION_XAUTH_SERVER) ! 259: { ! 260: push_string(&msg, add_conn.other.auth2, "xauth"); ! 261: } ! 262: else ! 263: { ! 264: push_string(&msg, add_conn.me.auth2, "xauth"); ! 265: } ! 266: } ! 267: else if (streq(conn->authby, "xauthpsk")) ! 268: { ! 269: push_string(&msg, add_conn.me.auth, "psk"); ! 270: push_string(&msg, add_conn.other.auth, "psk"); ! 271: if (conn->options & SA_OPTION_XAUTH_SERVER) ! 272: { ! 273: push_string(&msg, add_conn.other.auth2, "xauth"); ! 274: } ! 275: else ! 276: { ! 277: push_string(&msg, add_conn.me.auth2, "xauth"); ! 278: } ! 279: } ! 280: } ! 281: return send_stroke_msg(msg); ! 282: } ! 283: ! 284: int starter_stroke_del_conn(starter_conn_t *conn) ! 285: { ! 286: stroke_msg_t *msg; ! 287: ! 288: msg = create_stroke_msg(STR_DEL_CONN); ! 289: push_string(&msg, del_conn.name, connection_name(conn)); ! 290: return send_stroke_msg(msg); ! 291: } ! 292: ! 293: int starter_stroke_route_conn(starter_conn_t *conn) ! 294: { ! 295: stroke_msg_t *msg; ! 296: ! 297: msg = create_stroke_msg(STR_ROUTE); ! 298: push_string(&msg, route.name, connection_name(conn)); ! 299: return send_stroke_msg(msg); ! 300: } ! 301: ! 302: int starter_stroke_unroute_conn(starter_conn_t *conn) ! 303: { ! 304: stroke_msg_t *msg; ! 305: ! 306: msg = create_stroke_msg(STR_UNROUTE); ! 307: push_string(&msg, route.name, connection_name(conn)); ! 308: return send_stroke_msg(msg); ! 309: } ! 310: ! 311: int starter_stroke_initiate_conn(starter_conn_t *conn) ! 312: { ! 313: stroke_msg_t *msg; ! 314: ! 315: msg = create_stroke_msg(STR_INITIATE); ! 316: push_string(&msg, initiate.name, connection_name(conn)); ! 317: return send_stroke_msg(msg); ! 318: } ! 319: ! 320: int starter_stroke_add_ca(starter_ca_t *ca) ! 321: { ! 322: stroke_msg_t *msg; ! 323: ! 324: msg = create_stroke_msg(STR_ADD_CA); ! 325: push_string(&msg, add_ca.name, ca->name); ! 326: push_string(&msg, add_ca.cacert, ca->cacert); ! 327: push_string(&msg, add_ca.crluri, ca->crluri); ! 328: push_string(&msg, add_ca.crluri2, ca->crluri2); ! 329: push_string(&msg, add_ca.ocspuri, ca->ocspuri); ! 330: push_string(&msg, add_ca.ocspuri2, ca->ocspuri2); ! 331: push_string(&msg, add_ca.certuribase, ca->certuribase); ! 332: return send_stroke_msg(msg); ! 333: } ! 334: ! 335: int starter_stroke_del_ca(starter_ca_t *ca) ! 336: { ! 337: stroke_msg_t *msg; ! 338: ! 339: msg = create_stroke_msg(STR_DEL_CA); ! 340: push_string(&msg, del_ca.name, ca->name); ! 341: return send_stroke_msg(msg); ! 342: } ! 343: ! 344: int starter_stroke_configure(starter_config_t *cfg) ! 345: { ! 346: stroke_msg_t *msg; ! 347: ! 348: if (cfg->setup.cachecrls) ! 349: { ! 350: msg = create_stroke_msg(STR_CONFIG); ! 351: msg->config.cachecrl = 1; ! 352: return send_stroke_msg(msg); ! 353: } ! 354: return 0; ! 355: }