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"
24 #include <asn1/asn1.h>
27 typedef struct private_peer_controller_t private_peer_controller_t
;
30 * private data of the peer_controller
32 struct private_peer_controller_t
{
37 peer_controller_t
public;
51 * list the configured peer configs
53 static void list(private_peer_controller_t
*this, request_t
*request
)
57 query
= this->db
->query(this->db
,
58 "SELECT id, alias, keyid FROM peer WHERE user = ? ORDER BY alias",
59 DB_UINT
, this->user
->get_user(this->user
),
60 DB_UINT
, DB_TEXT
, DB_BLOB
);
67 identification_t
*identifier
;
69 while (query
->enumerate(query
, &id
, &alias
, &keyid
))
71 request
->setf(request
, "peers.%d.alias=%s", id
, alias
);
72 identifier
= identification_create_from_encoding(ID_KEY_ID
, keyid
);
73 request
->setf(request
, "peers.%d.identifier=%Y", id
, identifier
);
74 identifier
->destroy(identifier
);
76 query
->destroy(query
);
78 request
->render(request
, "templates/peer/list.cs");
84 static bool verify_alias(private_peer_controller_t
*this, request_t
*request
,
87 if (!alias
|| *alias
== '\0')
89 request
->setf(request
, "error=Alias is missing.");
92 while (*alias
!= '\0')
106 request
->setf(request
, "error=Alias invalid, "
107 "valid characters: A-Z a-z 0-9 - _ @ .");
115 * parse and verify a public key
117 static bool parse_public_key(private_peer_controller_t
*this,
118 request_t
*request
, char *public_key
,
119 chunk_t
*encoding
, chunk_t
*keyid
)
121 public_key_t
*public;
122 identification_t
*id
;
124 if (!public_key
|| *public_key
== '\0')
126 request
->setf(request
, "error=Public key is missing.");
129 public = lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_ANY
,
130 BUILD_BLOB_ASN1_PEM
, public_key
,
134 request
->setf(request
, "error=Parsing public key failed.");
137 /* TODO: use get_encoding() with an encoding type */
138 *encoding
= asn1_wrap(ASN1_SEQUENCE
, "cm",
139 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
140 asn1_bitstring("m", public->get_encoding(public)));
141 id
= public->get_id(public, ID_PUBKEY_SHA1
);
142 *keyid
= chunk_clone(id
->get_encoding(id
));
143 public->destroy(public);
148 * register a new peer
150 static void add(private_peer_controller_t
*this, request_t
*request
)
152 char *alias
= "", *public_key
= "";
154 if (request
->get_query_data(request
, "back"))
156 return request
->redirect(request
, "peer/list");
158 while (request
->get_query_data(request
, "add"))
160 chunk_t encoding
, keyid
;
162 alias
= request
->get_query_data(request
, "alias");
163 public_key
= request
->get_query_data(request
, "public_key");
165 if (!verify_alias(this, request
, alias
))
169 if (!parse_public_key(this, request
, public_key
, &encoding
, &keyid
))
173 if (this->db
->execute(this->db
, NULL
,
174 "INSERT INTO peer (user, alias, public_key, keyid) "
175 "VALUES (?, ?, ?, ?)",
176 DB_UINT
, this->user
->get_user(this->user
),
177 DB_TEXT
, alias
, DB_BLOB
, encoding
,
178 DB_BLOB
, keyid
) <= 0)
180 request
->setf(request
, "error=Peer already exists.");
187 return request
->redirect(request
, "peer/list");
189 request
->set(request
, "alias", alias
);
190 request
->set(request
, "public_key", public_key
);
192 return request
->render(request
, "templates/peer/add.cs");
196 * pem encode a public key into an allocated string
198 char* pem_encode(chunk_t der
)
200 static const char *begin
= "-----BEGIN PUBLIC KEY-----\n";
201 static const char *end
= "-----END PUBLIC KEY-----";
207 base64
= chunk_to_base64(der
, NULL
);
208 len
= strlen(begin
) + base64
.len
+ base64
.len
/64 + strlen(end
) + 2;
209 pem
= malloc(len
+ 1);
214 strncat(pem
, base64
.ptr
+ i
, 64);
218 while (i
< base64
.len
- 2);
228 static void edit(private_peer_controller_t
*this, request_t
*request
, int id
)
230 char *alias
= "", *public_key
= "", *pem
;
231 chunk_t encoding
, keyid
;
233 if (request
->get_query_data(request
, "back"))
235 return request
->redirect(request
, "peer/list");
237 if (request
->get_query_data(request
, "delete"))
239 this->db
->execute(this->db
, NULL
,
240 "DELETE FROM peer WHERE id = ? AND user = ?",
241 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
));
242 return request
->redirect(request
, "peer/list");
244 if (request
->get_query_data(request
, "save"))
248 alias
= request
->get_query_data(request
, "alias");
249 public_key
= request
->get_query_data(request
, "public_key");
251 if (!verify_alias(this, request
, alias
))
255 if (!parse_public_key(this, request
, public_key
, &encoding
, &keyid
))
259 if (this->db
->execute(this->db
, NULL
,
260 "UPDATE peer SET alias = ?, public_key = ?, keyid = ? "
261 "WHERE id = ? AND user = ?",
262 DB_TEXT
, alias
, DB_BLOB
, encoding
, DB_BLOB
, keyid
,
263 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
)) < 0)
265 request
->setf(request
, "error=Peer already exists.");
272 return request
->redirect(request
, "peer/list");
277 enumerator_t
*query
= this->db
->query(this->db
,
278 "SELECT alias, public_key FROM peer WHERE id = ? AND user = ?",
279 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
),
281 if (query
&& query
->enumerate(query
, &alias
, &encoding
))
283 alias
= strdupa(alias
);
284 pem
= pem_encode(encoding
);
285 public_key
= strdupa(pem
);
290 return request
->redirect(request
, "peer/list");
294 request
->set(request
, "alias", alias
);
295 request
->set(request
, "public_key", public_key
);
296 return request
->render(request
, "templates/peer/edit.cs");
300 * delete a peer from the database
302 static void delete(private_peer_controller_t
*this, request_t
*request
, int id
)
304 this->db
->execute(this->db
, NULL
,
305 "DELETE FROM peer WHERE id = ? AND user = ?",
306 DB_INT
, id
, DB_UINT
, this->user
->get_user(this->user
));
310 * Implementation of controller_t.get_name
312 static char* get_name(private_peer_controller_t
*this)
318 * Implementation of controller_t.handle
320 static void handle(private_peer_controller_t
*this, request_t
*request
,
321 char *action
, char *idstr
)
331 if (streq(action
, "list"))
333 return list(this, request
);
335 else if (streq(action
, "add"))
337 return add(this, request
);
339 else if (streq(action
, "edit") && id
)
341 return edit(this, request
, id
);
343 else if (streq(action
, "delete") && id
)
345 delete(this, request
, id
);
348 request
->redirect(request
, "peer/list");
352 * Implementation of controller_t.destroy
354 static void destroy(private_peer_controller_t
*this)
362 controller_t
*peer_controller_create(user_t
*user
, database_t
*db
)
364 private_peer_controller_t
*this= malloc_thing(private_peer_controller_t
);
366 this->public.controller
.get_name
= (char*(*)(controller_t
*))get_name
;
367 this->public.controller
.handle
= (void(*)(controller_t
*, request_t
*, char*, char*, char*, char*, char*))handle
;
368 this->public.controller
.destroy
= (void(*)(controller_t
*))destroy
;
373 return &this->public.controller
;