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
22 #include "peer_controller.h"
26 #include <asn1/asn1.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;
124 identification_t
*id
;
126 if (!public_key
|| *public_key
== '\0')
128 request
->setf(request
, "error=Public key is missing.");
131 public = lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_ANY
,
132 BUILD_BLOB_ASN1_PEM
, public_key
,
136 request
->setf(request
, "error=Parsing public key failed.");
139 /* TODO: use get_encoding() with an encoding type */
140 *encoding
= asn1_wrap(ASN1_SEQUENCE
, "cm",
141 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
142 asn1_bitstring("m", public->get_encoding(public)));
143 id
= public->get_id(public, ID_PUBKEY_SHA1
);
144 *keyid
= chunk_clone(id
->get_encoding(id
));
145 public->destroy(public);
150 * register a new peer
152 static void add(private_peer_controller_t
*this, request_t
*request
)
154 char *alias
= "", *public_key
= "";
156 if (request
->get_query_data(request
, "back"))
158 return request
->redirect(request
, "peer/list");
160 while (request
->get_query_data(request
, "add"))
162 chunk_t encoding
, keyid
;
164 alias
= request
->get_query_data(request
, "alias");
165 public_key
= request
->get_query_data(request
, "public_key");
167 if (!verify_alias(this, request
, alias
))
171 if (!parse_public_key(this, request
, public_key
, &encoding
, &keyid
))
175 if (this->db
->execute(this->db
, NULL
,
176 "INSERT INTO peer (user, alias, public_key, keyid) "
177 "VALUES (?, ?, ?, ?)",
178 DB_UINT
, this->user
->get_user(this->user
),
179 DB_TEXT
, alias
, DB_BLOB
, encoding
,
180 DB_BLOB
, keyid
) <= 0)
182 request
->setf(request
, "error=Peer already exists.");
189 return request
->redirect(request
, "peer/list");
191 request
->set(request
, "alias", alias
);
192 request
->set(request
, "public_key", public_key
);
194 return request
->render(request
, "templates/peer/add.cs");
198 * pem encode a public key into an allocated string
200 char* pem_encode(chunk_t der
)
202 static const char *begin
= "-----BEGIN PUBLIC KEY-----\n";
203 static const char *end
= "-----END PUBLIC KEY-----";
209 base64
= chunk_to_base64(der
, NULL
);
210 len
= strlen(begin
) + base64
.len
+ base64
.len
/64 + strlen(end
) + 2;
211 pem
= malloc(len
+ 1);
216 strncat(pem
, base64
.ptr
+ i
, 64);
220 while (i
< base64
.len
- 2);
230 static void edit(private_peer_controller_t
*this, request_t
*request
, int id
)
232 char *alias
= "", *public_key
= "", *pem
;
233 chunk_t encoding
, keyid
;
235 if (request
->get_query_data(request
, "back"))
237 return request
->redirect(request
, "peer/list");
239 if (request
->get_query_data(request
, "delete"))
241 this->db
->execute(this->db
, NULL
,
242 "DELETE FROM peer WHERE id = ? AND user = ?",
243 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
));
244 return request
->redirect(request
, "peer/list");
246 if (request
->get_query_data(request
, "save"))
250 alias
= request
->get_query_data(request
, "alias");
251 public_key
= request
->get_query_data(request
, "public_key");
253 if (!verify_alias(this, request
, alias
))
257 if (!parse_public_key(this, request
, public_key
, &encoding
, &keyid
))
261 if (this->db
->execute(this->db
, NULL
,
262 "UPDATE peer SET alias = ?, public_key = ?, keyid = ? "
263 "WHERE id = ? AND user = ?",
264 DB_TEXT
, alias
, DB_BLOB
, encoding
, DB_BLOB
, keyid
,
265 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
)) < 0)
267 request
->setf(request
, "error=Peer already exists.");
274 return request
->redirect(request
, "peer/list");
279 enumerator_t
*query
= this->db
->query(this->db
,
280 "SELECT alias, public_key FROM peer WHERE id = ? AND user = ?",
281 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
),
283 if (query
&& query
->enumerate(query
, &alias
, &encoding
))
285 alias
= strdupa(alias
);
286 pem
= pem_encode(encoding
);
287 public_key
= strdupa(pem
);
292 return request
->redirect(request
, "peer/list");
296 request
->set(request
, "alias", alias
);
297 request
->set(request
, "public_key", public_key
);
298 return request
->render(request
, "templates/peer/edit.cs");
302 * delete a peer from the database
304 static void delete(private_peer_controller_t
*this, request_t
*request
, int id
)
306 this->db
->execute(this->db
, NULL
,
307 "DELETE FROM peer WHERE id = ? AND user = ?",
308 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
));
312 * Implementation of controller_t.get_name
314 static char* get_name(private_peer_controller_t
*this)
320 * Implementation of controller_t.handle
322 static void handle(private_peer_controller_t
*this, request_t
*request
,
323 char *action
, char *idstr
)
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");
354 * Implementation of controller_t.destroy
356 static void destroy(private_peer_controller_t
*this)
364 controller_t
*peer_controller_create(user_t
*user
, database_t
*db
)
366 private_peer_controller_t
*this= malloc_thing(private_peer_controller_t
);
368 this->public.controller
.get_name
= (char*(*)(controller_t
*))get_name
;
369 this->public.controller
.handle
= (void(*)(controller_t
*, request_t
*, char*, char*, char*, char*, char*))handle
;
370 this->public.controller
.destroy
= (void(*)(controller_t
*))destroy
;
375 return &this->public.controller
;