| 291 } |
291 } |
| 292 |
292 |
| 293 return s; |
293 return s; |
| 294 } |
294 } |
| 295 |
295 |
| |
296 /* Forward declarations are fun! |
| |
297 TODO: This is a stupid place for this */ |
| |
298 static Certificate * |
| |
299 x509_import_from_datum(const gnutls_datum_t dt); |
| |
300 |
| |
301 static GList * |
| |
302 ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) |
| |
303 { |
| |
304 PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); |
| |
305 |
| |
306 /* List of Certificate instances to return */ |
| |
307 GList * peer_certs = NULL; |
| |
308 |
| |
309 /* List of raw certificates as given by GnuTLS */ |
| |
310 const gnutls_datum_t *cert_list; |
| |
311 unsigned int cert_list_size = 0; |
| |
312 |
| |
313 unsigned int i; |
| |
314 |
| |
315 /* This should never, ever happen. */ |
| |
316 g_return_val_if_fail( gnutls_certificate_type_get (gnutls_data->session) == GNUTLS_CRT_X509, NULL); |
| |
317 |
| |
318 /* Get the certificate list from GnuTLS */ |
| |
319 /* TODO: I am _pretty sure_ this doesn't block or do other exciting things */ |
| |
320 cert_list = gnutls_certificate_get_peers(gnutls_data->session, |
| |
321 &cert_list_size); |
| |
322 |
| |
323 /* Convert each certificate to a Certificate and append it to the list */ |
| |
324 for (i = 0; i < cert_list_size; i++) { |
| |
325 Certificate * newcrt = x509_import_from_datum(cert_list[i]); |
| |
326 /* Append is somewhat inefficient on linked lists, but is easy |
| |
327 to read. If someone complains, I'll change it. |
| |
328 TODO: Is anyone complaining? (Maybe elb?) */ |
| |
329 peer_certs = g_list_append(peer_certs, newcrt); |
| |
330 } |
| |
331 |
| |
332 /* cert_list shouldn't need free()-ing */ |
| |
333 /* TODO: double-check this */ |
| |
334 |
| |
335 return peer_certs; |
| |
336 } |
| |
337 |
| 296 /************************************************************************/ |
338 /************************************************************************/ |
| 297 /* X.509 functionality */ |
339 /* X.509 functionality */ |
| 298 /************************************************************************/ |
340 /************************************************************************/ |
| 299 const gchar * SCHEME_NAME = "x509"; |
341 const gchar * SCHEME_NAME = "x509"; |
| 300 |
342 |
| 302 /* TODO: Flesh this out! */ |
344 /* TODO: Flesh this out! */ |
| 303 static CertificateScheme x509_gnutls = { |
345 static CertificateScheme x509_gnutls = { |
| 304 "x509" /* Scheme name */ |
346 "x509" /* Scheme name */ |
| 305 }; |
347 }; |
| 306 |
348 |
| |
349 /** Transforms a gnutls_datum_t containing an X.509 certificate into a Certificate instance under the x509_gnutls scheme |
| |
350 * |
| |
351 * @param dt Datum to transform |
| |
352 * |
| |
353 * @return A newly allocated Certificate structure of the x509_gnutls scheme |
| |
354 */ |
| |
355 static Certificate * |
| |
356 x509_import_from_datum(const gnutls_datum_t dt) |
| |
357 { |
| |
358 /* Internal certificate data structure */ |
| |
359 gnutls_x509_crt_t *certdat; |
| |
360 /* New certificate to return */ |
| |
361 Certificate * crt; |
| |
362 |
| |
363 /* Allocate and prepare the internal certificate data */ |
| |
364 certdat = g_new(gnutls_x509_crt_t, 1); |
| |
365 gnutls_x509_crt_init(certdat); |
| |
366 |
| |
367 /* Perform the actual certificate parse */ |
| |
368 /* Yes, certdat SHOULD be dereferenced */ |
| |
369 gnutls_x509_crt_import(*certdat, &dt, GNUTLS_X509_FMT_PEM); |
| |
370 |
| |
371 /* Allocate the certificate and load it with data */ |
| |
372 crt = g_new(Certificate, 1); |
| |
373 crt->scheme = &x509_gnutls; |
| |
374 crt->data = certdat; |
| |
375 |
| |
376 return crt; |
| |
377 } |
| |
378 |
| 307 /** Imports a PEM-formatted X.509 certificate from the specified file. |
379 /** Imports a PEM-formatted X.509 certificate from the specified file. |
| 308 * @param filename Filename to import from. Format is PEM |
380 * @param filename Filename to import from. Format is PEM |
| 309 * |
381 * |
| 310 * @return A newly allocated Certificate structure of the x509_gnutls scheme |
382 * @return A newly allocated Certificate structure of the x509_gnutls scheme |
| 311 */ |
383 */ |
| 313 x509_import_from_file(const gchar * filename) |
385 x509_import_from_file(const gchar * filename) |
| 314 { |
386 { |
| 315 Certificate *crt; /* Certificate being constructed */ |
387 Certificate *crt; /* Certificate being constructed */ |
| 316 gchar *buf; /* Used to load the raw file data */ |
388 gchar *buf; /* Used to load the raw file data */ |
| 317 gsize buf_sz; /* Size of the above */ |
389 gsize buf_sz; /* Size of the above */ |
| 318 gnutls_datum_t dt; /* Struct to pass to GnuTLS */ |
390 gnutls_datum_t dt; /* Struct to pass down to GnuTLS */ |
| 319 |
|
| 320 /* Internal certificate data structure */ |
|
| 321 gnutls_x509_crt_t *certdat; |
|
| 322 |
391 |
| 323 purple_debug_info("gnutls", |
392 purple_debug_info("gnutls", |
| 324 "Attempting to load X.509 certificate from %s\n", |
393 "Attempting to load X.509 certificate from %s\n", |
| 325 filename); |
394 filename); |
| 326 |
395 |
| 332 &buf, |
401 &buf, |
| 333 &buf_sz, |
402 &buf_sz, |
| 334 NULL /* No error checking for now */ |
403 NULL /* No error checking for now */ |
| 335 ); |
404 ); |
| 336 |
405 |
| 337 /* Allocate and prepare the internal certificate data */ |
|
| 338 certdat = g_new(gnutls_x509_crt_t, 1); |
|
| 339 gnutls_x509_crt_init(certdat); |
|
| 340 |
|
| 341 /* Load the datum struct */ |
406 /* Load the datum struct */ |
| 342 dt.data = (unsigned char *) buf; |
407 dt.data = (unsigned char *) buf; |
| 343 dt.size = buf_sz; |
408 dt.size = buf_sz; |
| 344 |
409 |
| 345 /* Perform the actual certificate parse */ |
410 /* Perform the conversion */ |
| 346 /* Yes, certdat SHOULD be dereferenced */ |
411 crt = x509_import_from_datum(dt); |
| 347 gnutls_x509_crt_import(*certdat, &dt, GNUTLS_X509_FMT_PEM); |
|
| 348 |
412 |
| 349 /* Allocate the certificate and load it with data */ |
|
| 350 crt = g_new(Certificate, 1); |
|
| 351 crt->scheme = &x509_gnutls; |
|
| 352 crt->data = certdat; |
|
| 353 |
|
| 354 /* Cleanup */ |
413 /* Cleanup */ |
| 355 g_free(buf); |
414 g_free(buf); |
| 356 |
415 |
| 357 return crt; |
416 return crt; |
| 358 } |
417 } |