Annotation of embedaddon/strongswan/src/medsrv/controller/peer_controller.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2008 Martin Willi
! 3: * Copyright (C) 2008 Philip Boetschi, Adrian Doerig
! 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: #define _GNU_SOURCE
! 18: #include <string.h>
! 19:
! 20: #include "peer_controller.h"
! 21:
! 22: #include <library.h>
! 23: #include <utils/debug.h>
! 24: #include <asn1/asn1.h>
! 25: #include <asn1/oid.h>
! 26: #include <utils/identification.h>
! 27: #include <credentials/keys/public_key.h>
! 28:
! 29: typedef struct private_peer_controller_t private_peer_controller_t;
! 30:
! 31: /**
! 32: * private data of the peer_controller
! 33: */
! 34: struct private_peer_controller_t {
! 35:
! 36: /**
! 37: * public functions
! 38: */
! 39: peer_controller_t public;
! 40:
! 41: /**
! 42: * active user session
! 43: */
! 44: user_t *user;
! 45:
! 46: /**
! 47: * underlying database
! 48: */
! 49: database_t *db;
! 50: };
! 51:
! 52: /**
! 53: * list the configured peer configs
! 54: */
! 55: static void list(private_peer_controller_t *this, fast_request_t *request)
! 56: {
! 57: enumerator_t *query;
! 58:
! 59: query = this->db->query(this->db,
! 60: "SELECT id, alias, keyid FROM peer WHERE user = ? ORDER BY alias",
! 61: DB_UINT, this->user->get_user(this->user),
! 62: DB_UINT, DB_TEXT, DB_BLOB);
! 63:
! 64: if (query)
! 65: {
! 66: u_int id;
! 67: char *alias;
! 68: chunk_t keyid;
! 69: identification_t *identifier;
! 70:
! 71: while (query->enumerate(query, &id, &alias, &keyid))
! 72: {
! 73: request->setf(request, "peers.%d.alias=%s", id, alias);
! 74: identifier = identification_create_from_encoding(ID_KEY_ID, keyid);
! 75: request->setf(request, "peers.%d.identifier=%Y", id, identifier);
! 76: identifier->destroy(identifier);
! 77: }
! 78: query->destroy(query);
! 79: }
! 80: request->render(request, "templates/peer/list.cs");
! 81: }
! 82:
! 83: /**
! 84: * verify a peer alias
! 85: */
! 86: static bool verify_alias(private_peer_controller_t *this, fast_request_t *request,
! 87: char *alias)
! 88: {
! 89: if (!alias || *alias == '\0')
! 90: {
! 91: request->setf(request, "error=Alias is missing.");
! 92: return FALSE;
! 93: }
! 94: while (*alias != '\0')
! 95: {
! 96: switch (*alias)
! 97: {
! 98: case 'a' ... 'z':
! 99: case 'A' ... 'Z':
! 100: case '0' ... '9':
! 101: case '-':
! 102: case '_':
! 103: case '@':
! 104: case '.':
! 105: alias++;
! 106: continue;
! 107: default:
! 108: request->setf(request, "error=Alias invalid, "
! 109: "valid characters: A-Z a-z 0-9 - _ @ .");
! 110: return FALSE;
! 111: }
! 112: }
! 113: return TRUE;
! 114: }
! 115:
! 116: /**
! 117: * parse and verify a public key
! 118: */
! 119: static bool parse_public_key(private_peer_controller_t *this,
! 120: fast_request_t *request, char *public_key,
! 121: chunk_t *encoding, chunk_t *keyid)
! 122: {
! 123: public_key_t *public;
! 124: chunk_t blob, id;
! 125:
! 126: if (!public_key || *public_key == '\0')
! 127: {
! 128: request->setf(request, "error=Public key is missing.");
! 129: return FALSE;
! 130: }
! 131: blob = chunk_clone(chunk_create(public_key, strlen(public_key)));
! 132: public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
! 133: BUILD_BLOB_PEM, blob,
! 134: BUILD_END);
! 135: chunk_free(&blob);
! 136: if (!public)
! 137: {
! 138: request->setf(request, "error=Parsing public key failed.");
! 139: return FALSE;
! 140: }
! 141: /* TODO: use get_encoding() with an encoding type */
! 142: if (!public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &id) ||
! 143: !public->get_encoding(public, PUBKEY_SPKI_ASN1_DER, encoding))
! 144: {
! 145: request->setf(request, "error=Encoding public key failed.");
! 146: return FALSE;
! 147: }
! 148: *keyid = chunk_clone(id);
! 149: public->destroy(public);
! 150: return TRUE;
! 151: }
! 152:
! 153: /**
! 154: * register a new peer
! 155: */
! 156: static void add(private_peer_controller_t *this, fast_request_t *request)
! 157: {
! 158: char *alias = "", *public_key = "";
! 159:
! 160: if (request->get_query_data(request, "back"))
! 161: {
! 162: return request->redirect(request, "peer/list");
! 163: }
! 164: while (request->get_query_data(request, "add"))
! 165: {
! 166: chunk_t encoding, keyid;
! 167:
! 168: alias = request->get_query_data(request, "alias");
! 169: public_key = request->get_query_data(request, "public_key");
! 170:
! 171: if (!verify_alias(this, request, alias))
! 172: {
! 173: break;
! 174: }
! 175: if (!parse_public_key(this, request, public_key, &encoding, &keyid))
! 176: {
! 177: break;
! 178: }
! 179: if (this->db->execute(this->db, NULL,
! 180: "INSERT INTO peer (user, alias, public_key, keyid) "
! 181: "VALUES (?, ?, ?, ?)",
! 182: DB_UINT, this->user->get_user(this->user),
! 183: DB_TEXT, alias, DB_BLOB, encoding,
! 184: DB_BLOB, keyid) <= 0)
! 185: {
! 186: request->setf(request, "error=Peer already exists.");
! 187: free(keyid.ptr);
! 188: free(encoding.ptr);
! 189: break;
! 190: }
! 191: free(keyid.ptr);
! 192: free(encoding.ptr);
! 193: return request->redirect(request, "peer/list");
! 194: }
! 195: request->set(request, "alias", alias);
! 196: request->set(request, "public_key", public_key);
! 197:
! 198: return request->render(request, "templates/peer/add.cs");
! 199: }
! 200:
! 201: /**
! 202: * pem encode a public key into an allocated string
! 203: */
! 204: char* pem_encode(chunk_t der)
! 205: {
! 206: static const char *begin = "-----BEGIN PUBLIC KEY-----\n";
! 207: static const char *end = "-----END PUBLIC KEY-----";
! 208: size_t len;
! 209: char *pem;
! 210: chunk_t base64;
! 211: int i = 0;
! 212:
! 213: base64 = chunk_to_base64(der, NULL);
! 214: len = strlen(begin) + base64.len + base64.len/64 + strlen(end) + 2;
! 215: pem = malloc(len + 1);
! 216:
! 217: strcpy(pem, begin);
! 218: do
! 219: {
! 220: strncat(pem, base64.ptr + i, 64);
! 221: strcat(pem, "\n");
! 222: i += 64;
! 223: }
! 224: while (i < base64.len - 2);
! 225: strcat(pem, end);
! 226:
! 227: free(base64.ptr);
! 228: return pem;
! 229: }
! 230:
! 231: /**
! 232: * edit a peer
! 233: */
! 234: static void edit(private_peer_controller_t *this, fast_request_t *request, int id)
! 235: {
! 236: char *alias = "", *public_key = "", *pem;
! 237: chunk_t encoding, keyid;
! 238:
! 239: if (request->get_query_data(request, "back"))
! 240: {
! 241: return request->redirect(request, "peer/list");
! 242: }
! 243: if (request->get_query_data(request, "delete"))
! 244: {
! 245: this->db->execute(this->db, NULL,
! 246: "DELETE FROM peer WHERE id = ? AND user = ?",
! 247: DB_INT, id, DB_UINT, this->user->get_user(this->user));
! 248: return request->redirect(request, "peer/list");
! 249: }
! 250: if (request->get_query_data(request, "save"))
! 251: {
! 252: while (TRUE)
! 253: {
! 254: alias = request->get_query_data(request, "alias");
! 255: public_key = request->get_query_data(request, "public_key");
! 256:
! 257: if (!verify_alias(this, request, alias))
! 258: {
! 259: break;
! 260: }
! 261: if (!parse_public_key(this, request, public_key, &encoding, &keyid))
! 262: {
! 263: break;
! 264: }
! 265: if (this->db->execute(this->db, NULL,
! 266: "UPDATE peer SET alias = ?, public_key = ?, keyid = ? "
! 267: "WHERE id = ? AND user = ?",
! 268: DB_TEXT, alias, DB_BLOB, encoding, DB_BLOB, keyid,
! 269: DB_INT, id, DB_UINT, this->user->get_user(this->user)) < 0)
! 270: {
! 271: request->setf(request, "error=Peer already exists.");
! 272: free(keyid.ptr);
! 273: free(encoding.ptr);
! 274: break;
! 275: }
! 276: free(keyid.ptr);
! 277: free(encoding.ptr);
! 278: return request->redirect(request, "peer/list");
! 279: }
! 280: }
! 281: else
! 282: {
! 283: enumerator_t *query = this->db->query(this->db,
! 284: "SELECT alias, public_key FROM peer WHERE id = ? AND user = ?",
! 285: DB_INT, id, DB_UINT, this->user->get_user(this->user),
! 286: DB_TEXT, DB_BLOB);
! 287: if (query && query->enumerate(query, &alias, &encoding))
! 288: {
! 289: alias = strdupa(alias);
! 290: pem = pem_encode(encoding);
! 291: public_key = strdupa(pem);
! 292: free(pem);
! 293: }
! 294: else
! 295: {
! 296: return request->redirect(request, "peer/list");
! 297: }
! 298: DESTROY_IF(query);
! 299: }
! 300: request->set(request, "alias", alias);
! 301: request->set(request, "public_key", public_key);
! 302: return request->render(request, "templates/peer/edit.cs");
! 303: }
! 304:
! 305: /**
! 306: * delete a peer from the database
! 307: */
! 308: static void delete(private_peer_controller_t *this, fast_request_t *request, int id)
! 309: {
! 310: this->db->execute(this->db, NULL,
! 311: "DELETE FROM peer WHERE id = ? AND user = ?",
! 312: DB_INT, id, DB_UINT, this->user->get_user(this->user));
! 313: }
! 314:
! 315: METHOD(fast_controller_t, get_name, char*,
! 316: private_peer_controller_t *this)
! 317: {
! 318: return "peer";
! 319: }
! 320:
! 321: METHOD(fast_controller_t, handle, void,
! 322: private_peer_controller_t *this, fast_request_t *request, char *action,
! 323: char *idstr, char *p3, char *p4, char *p5)
! 324: {
! 325: if (action)
! 326: {
! 327: int id = 0;
! 328: if (idstr)
! 329: {
! 330: id = atoi(idstr);
! 331: }
! 332:
! 333: if (streq(action, "list"))
! 334: {
! 335: return list(this, request);
! 336: }
! 337: else if (streq(action, "add"))
! 338: {
! 339: return add(this, request);
! 340: }
! 341: else if (streq(action, "edit") && id)
! 342: {
! 343: return edit(this, request, id);
! 344: }
! 345: else if (streq(action, "delete") && id)
! 346: {
! 347: delete(this, request, id);
! 348: }
! 349: }
! 350: request->redirect(request, "peer/list");
! 351: }
! 352:
! 353: METHOD(fast_controller_t, destroy, void,
! 354: private_peer_controller_t *this)
! 355: {
! 356: free(this);
! 357: }
! 358:
! 359: /*
! 360: * see header file
! 361: */
! 362: fast_controller_t *peer_controller_create(user_t *user, database_t *db)
! 363: {
! 364: private_peer_controller_t *this;
! 365:
! 366: INIT(this,
! 367: .public = {
! 368: .controller = {
! 369: .get_name = _get_name,
! 370: .handle = _handle,
! 371: .destroy = _destroy,
! 372: },
! 373: },
! 374: .user = user,
! 375: .db = db,
! 376: );
! 377:
! 378: return &this->public.controller;
! 379: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>