2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2008 Philip Boetschi, Adrian Doerig
4 * Hochschule fuer Technik Rapperswil
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>.
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
20 #include "peer_controller.h"
23 #include <utils/debug.h>
24 #include <asn1/asn1.h>
26 #include <utils/identification.h>
27 #include <credentials/keys/public_key.h>
29 typedef struct private_peer_controller_t private_peer_controller_t
;
32 * private data of the peer_controller
34 struct private_peer_controller_t
{
39 peer_controller_t
public;
53 * list the configured peer configs
55 static void list(private_peer_controller_t
*this, request_t
*request
)
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
);
69 identification_t
*identifier
;
71 while (query
->enumerate(query
, &id
, &alias
, &keyid
))
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
);
78 query
->destroy(query
);
80 request
->render(request
, "templates/peer/list.cs");
86 static bool verify_alias(private_peer_controller_t
*this, request_t
*request
,
89 if (!alias
|| *alias
== '\0')
91 request
->setf(request
, "error=Alias is missing.");
94 while (*alias
!= '\0')
108 request
->setf(request
, "error=Alias invalid, "
109 "valid characters: A-Z a-z 0-9 - _ @ .");
117 * parse and verify a public key
119 static bool parse_public_key(private_peer_controller_t
*this,
120 request_t
*request
, char *public_key
,
121 chunk_t
*encoding
, chunk_t
*keyid
)
123 public_key_t
*public;
126 if (!public_key
|| *public_key
== '\0')
128 request
->setf(request
, "error=Public key is missing.");
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
,
138 request
->setf(request
, "error=Parsing public key failed.");
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
))
145 request
->setf(request
, "error=Encoding public key failed.");
148 *keyid
= chunk_clone(id
);
149 public->destroy(public);
154 * register a new peer
156 static void add(private_peer_controller_t
*this, request_t
*request
)
158 char *alias
= "", *public_key
= "";
160 if (request
->get_query_data(request
, "back"))
162 return request
->redirect(request
, "peer/list");
164 while (request
->get_query_data(request
, "add"))
166 chunk_t encoding
, keyid
;
168 alias
= request
->get_query_data(request
, "alias");
169 public_key
= request
->get_query_data(request
, "public_key");
171 if (!verify_alias(this, request
, alias
))
175 if (!parse_public_key(this, request
, public_key
, &encoding
, &keyid
))
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)
186 request
->setf(request
, "error=Peer already exists.");
193 return request
->redirect(request
, "peer/list");
195 request
->set(request
, "alias", alias
);
196 request
->set(request
, "public_key", public_key
);
198 return request
->render(request
, "templates/peer/add.cs");
202 * pem encode a public key into an allocated string
204 char* pem_encode(chunk_t der
)
206 static const char *begin
= "-----BEGIN PUBLIC KEY-----\n";
207 static const char *end
= "-----END PUBLIC KEY-----";
213 base64
= chunk_to_base64(der
, NULL
);
214 len
= strlen(begin
) + base64
.len
+ base64
.len
/64 + strlen(end
) + 2;
215 pem
= malloc(len
+ 1);
220 strncat(pem
, base64
.ptr
+ i
, 64);
224 while (i
< base64
.len
- 2);
234 static void edit(private_peer_controller_t
*this, request_t
*request
, int id
)
236 char *alias
= "", *public_key
= "", *pem
;
237 chunk_t encoding
, keyid
;
239 if (request
->get_query_data(request
, "back"))
241 return request
->redirect(request
, "peer/list");
243 if (request
->get_query_data(request
, "delete"))
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");
250 if (request
->get_query_data(request
, "save"))
254 alias
= request
->get_query_data(request
, "alias");
255 public_key
= request
->get_query_data(request
, "public_key");
257 if (!verify_alias(this, request
, alias
))
261 if (!parse_public_key(this, request
, public_key
, &encoding
, &keyid
))
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)
271 request
->setf(request
, "error=Peer already exists.");
278 return request
->redirect(request
, "peer/list");
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
),
287 if (query
&& query
->enumerate(query
, &alias
, &encoding
))
289 alias
= strdupa(alias
);
290 pem
= pem_encode(encoding
);
291 public_key
= strdupa(pem
);
296 return request
->redirect(request
, "peer/list");
300 request
->set(request
, "alias", alias
);
301 request
->set(request
, "public_key", public_key
);
302 return request
->render(request
, "templates/peer/edit.cs");
306 * delete a peer from the database
308 static void delete(private_peer_controller_t
*this, request_t
*request
, int id
)
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
));
315 METHOD(controller_t
, get_name
, char*,
316 private_peer_controller_t
*this)
321 METHOD(controller_t
, handle
, void,
322 private_peer_controller_t
*this, request_t
*request
, char *action
,
323 char *idstr
, char *p3
, char *p4
, char *p5
)
333 if (streq(action
, "list"))
335 return list(this, request
);
337 else if (streq(action
, "add"))
339 return add(this, request
);
341 else if (streq(action
, "edit") && id
)
343 return edit(this, request
, id
);
345 else if (streq(action
, "delete") && id
)
347 delete(this, request
, id
);
350 request
->redirect(request
, "peer/list");
353 METHOD(controller_t
, destroy
, void,
354 private_peer_controller_t
*this)
362 controller_t
*peer_controller_create(user_t
*user
, database_t
*db
)
364 private_peer_controller_t
*this;
369 .get_name
= _get_name
,
378 return &this->public.controller
;