00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <gnutls_int.h>
00030 #include "gnutls_auth_int.h"
00031 #include "gnutls_errors.h"
00032 #include <gnutls_cert.h>
00033 #include <auth_cert.h>
00034 #include "gnutls_dh.h"
00035 #include "gnutls_num.h"
00036 #include "libtasn1.h"
00037 #include "gnutls_datum.h"
00038 #include <gnutls_pk.h>
00039 #include <gnutls_algorithms.h>
00040 #include <gnutls_global.h>
00041 #include <gnutls_record.h>
00042 #include <gnutls_sig.h>
00043 #include <gnutls_state.h>
00044 #include <gnutls_pk.h>
00045 #include <gnutls_x509.h>
00046 #include "debug.h"
00047
00048 static MHD_gnutls_cert *alloc_and_load_x509_certs (MHD_gnutls_x509_crt_t *
00049 certs, unsigned);
00050 static MHD_gnutls_privkey *alloc_and_load_x509_key (MHD_gnutls_x509_privkey_t
00051 key);
00052
00053
00054
00055
00056
00057 static int
00058 MHD__gnutls_copy_certificate_auth_info (cert_auth_info_t info,
00059 MHD_gnutls_cert * cert, int ncerts)
00060 {
00061
00062
00063 int ret, i, j;
00064
00065 if (ncerts == 0)
00066 {
00067 info->raw_certificate_list = NULL;
00068 info->ncerts = 0;
00069 return 0;
00070 }
00071
00072 info->raw_certificate_list =
00073 MHD_gnutls_calloc (1, sizeof (MHD_gnutls_datum_t) * ncerts);
00074 if (info->raw_certificate_list == NULL)
00075 {
00076 MHD_gnutls_assert ();
00077 return GNUTLS_E_MEMORY_ERROR;
00078 }
00079
00080 for (i = 0; i < ncerts; i++)
00081 {
00082 if (cert->raw.size > 0)
00083 {
00084 ret =
00085 MHD__gnutls_set_datum (&info->raw_certificate_list[i],
00086 cert[i].raw.data, cert[i].raw.size);
00087 if (ret < 0)
00088 {
00089 MHD_gnutls_assert ();
00090 goto clear;
00091 }
00092 }
00093 }
00094 info->ncerts = ncerts;
00095
00096 return 0;
00097
00098 clear:
00099
00100 for (j = 0; j < i; j++)
00101 MHD__gnutls_free_datum (&info->raw_certificate_list[j]);
00102
00103 MHD_gnutls_free (info->raw_certificate_list);
00104 info->raw_certificate_list = NULL;
00105
00106 return ret;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 inline static int
00116 MHD__gnutls_check_pk_algo_in_list (const enum MHD_GNUTLS_PublicKeyAlgorithm
00117 *pk_algos, int pk_algos_length,
00118 enum MHD_GNUTLS_PublicKeyAlgorithm
00119 algo_to_check)
00120 {
00121 int i;
00122 for (i = 0; i < pk_algos_length; i++)
00123 {
00124 if (algo_to_check == pk_algos[i])
00125 {
00126 return 0;
00127 }
00128 }
00129 return -1;
00130 }
00131
00132
00133
00134
00135
00136 static int
00137 MHD__gnutls_cert_get_issuer_dn (MHD_gnutls_cert * cert,
00138 MHD_gnutls_datum_t * odn)
00139 {
00140 ASN1_TYPE dn;
00141 int len, result;
00142 int start, end;
00143
00144 if ((result = MHD__asn1_create_element
00145 (MHD__gnutls_get_pkix (), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS)
00146 {
00147 MHD_gnutls_assert ();
00148 return MHD_gtls_asn2err (result);
00149 }
00150
00151 result = MHD__asn1_der_decoding (&dn, cert->raw.data, cert->raw.size, NULL);
00152 if (result != ASN1_SUCCESS)
00153 {
00154
00155 MHD_gnutls_assert ();
00156 MHD__asn1_delete_structure (&dn);
00157 return MHD_gtls_asn2err (result);
00158 }
00159
00160 result =
00161 MHD__asn1_der_decoding_startEnd (dn, cert->raw.data, cert->raw.size,
00162 "tbsCertificate.issuer", &start, &end);
00163
00164 if (result != ASN1_SUCCESS)
00165 {
00166
00167 MHD_gnutls_assert ();
00168 MHD__asn1_delete_structure (&dn);
00169 return MHD_gtls_asn2err (result);
00170 }
00171 MHD__asn1_delete_structure (&dn);
00172
00173 len = end - start + 1;
00174
00175 odn->size = len;
00176 odn->data = &cert->raw.data[start];
00177
00178 return 0;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188 static int
00189 _find_x509_cert (const MHD_gtls_cert_credentials_t cred,
00190 opaque * _data, size_t _data_size,
00191 const enum MHD_GNUTLS_PublicKeyAlgorithm *pk_algos,
00192 int pk_algos_length, int *indx)
00193 {
00194 unsigned size;
00195 MHD_gnutls_datum_t odn;
00196 opaque *data = _data;
00197 ssize_t data_size = _data_size;
00198 unsigned i, j;
00199 int result, cert_pk;
00200
00201 *indx = -1;
00202 odn.size = 0;
00203 odn.data = NULL;
00204 do
00205 {
00206
00207 DECR_LENGTH_RET (data_size, 2, 0);
00208 size = MHD_gtls_read_uint16 (data);
00209 DECR_LENGTH_RET (data_size, size, 0);
00210 data += 2;
00211
00212 for (i = 0; i < cred->ncerts; i++)
00213 {
00214 for (j = 0; j < cred->cert_list_length[i]; j++)
00215 {
00216 if ((result =
00217 MHD__gnutls_cert_get_issuer_dn (&cred->cert_list[i][j],
00218 &odn)) != 0)
00219 {
00220 MHD_gnutls_assert ();
00221 return result;
00222 }
00223
00224 if (odn.size != size)
00225 continue;
00226
00227
00228
00229
00230
00231 cert_pk = cred->cert_list[i][0].subject_pk_algorithm;
00232
00233 if ((memcmp (odn.data, data, size) == 0) &&
00234 (MHD__gnutls_check_pk_algo_in_list
00235 (pk_algos, pk_algos_length, cert_pk) == 0))
00236 {
00237 *indx = i;
00238 break;
00239 }
00240 }
00241 if (*indx != -1)
00242 break;
00243 }
00244
00245 if (*indx != -1)
00246 break;
00247
00248
00249 data += size;
00250
00251 }
00252 while (1);
00253
00254 return 0;
00255
00256 }
00257
00258
00259
00260
00261 static int
00262 get_issuers_num (MHD_gtls_session_t session, opaque * data, ssize_t data_size)
00263 {
00264 int issuers_dn_len = 0, result;
00265 unsigned size;
00266
00267
00268
00269
00270
00271
00272 if (data_size == 0 || data == NULL)
00273 return 0;
00274
00275 if (data_size > 0)
00276 do
00277 {
00278
00279
00280 result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00281 DECR_LENGTH_COM (data_size, 2, goto error);
00282 size = MHD_gtls_read_uint16 (data);
00283
00284 result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00285 DECR_LENGTH_COM (data_size, size, goto error);
00286
00287 data += 2;
00288
00289 if (size > 0)
00290 {
00291 issuers_dn_len++;
00292 data += size;
00293 }
00294
00295 if (data_size == 0)
00296 break;
00297
00298 }
00299 while (1);
00300
00301 return issuers_dn_len;
00302
00303 error:
00304 return result;
00305 }
00306
00307
00308
00309
00310 static int
00311 get_issuers (MHD_gtls_session_t session,
00312 MHD_gnutls_datum_t * issuers_dn, int issuers_len,
00313 opaque * data, size_t data_size)
00314 {
00315 int i;
00316 unsigned size;
00317
00318 if (MHD_gnutls_certificate_type_get (session) != MHD_GNUTLS_CRT_X509)
00319 return 0;
00320
00321
00322
00323
00324 if (issuers_len > 0)
00325 {
00326
00327 for (i = 0; i < issuers_len; i++)
00328 {
00329
00330
00331
00332
00333 data_size -= 2;
00334
00335 size = MHD_gtls_read_uint16 (data);
00336
00337 data += 2;
00338
00339 issuers_dn[i].data = data;
00340 issuers_dn[i].size = size;
00341
00342 data += size;
00343 }
00344 }
00345
00346 return 0;
00347 }
00348
00349
00350
00351 static int
00352 call_get_cert_callback (MHD_gtls_session_t session,
00353 MHD_gnutls_datum_t * issuers_dn,
00354 int issuers_dn_length,
00355 enum MHD_GNUTLS_PublicKeyAlgorithm *pk_algos,
00356 int pk_algos_length)
00357 {
00358 unsigned i;
00359 MHD_gnutls_cert *local_certs = NULL;
00360 MHD_gnutls_privkey *local_key = NULL;
00361 MHD_gnutls_retr_st st;
00362 int ret;
00363 enum MHD_GNUTLS_CertificateType type =
00364 MHD_gnutls_certificate_type_get (session);
00365 MHD_gtls_cert_credentials_t cred;
00366
00367 cred = (MHD_gtls_cert_credentials_t)
00368 MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
00369 if (cred == NULL)
00370 {
00371 MHD_gnutls_assert ();
00372 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00373 }
00374
00375 memset (&st, 0, sizeof (st));
00376
00377 if (session->security_parameters.entity == GNUTLS_SERVER)
00378 {
00379 ret = cred->server_get_cert_callback (session, &st);
00380 }
00381 else
00382 {
00383 ret =
00384 cred->client_get_cert_callback (session,
00385 issuers_dn, issuers_dn_length,
00386 pk_algos, pk_algos_length, &st);
00387 }
00388
00389 if (ret < 0)
00390 {
00391 MHD_gnutls_assert ();
00392 return GNUTLS_E_INTERNAL_ERROR;
00393 }
00394
00395 if (st.ncerts == 0)
00396 return 0;
00397
00398 if (type != st.type)
00399 {
00400 MHD_gnutls_assert ();
00401 ret = GNUTLS_E_INVALID_REQUEST;
00402 goto cleanup;
00403 }
00404
00405 if (type == MHD_GNUTLS_CRT_X509)
00406 {
00407 local_certs = alloc_and_load_x509_certs (st.cert.x509, st.ncerts);
00408 if (local_certs != NULL)
00409 local_key = alloc_and_load_x509_key (st.key.x509);
00410
00411 }
00412 else
00413 {
00414 MHD_gnutls_assert ();
00415 ret = GNUTLS_E_INVALID_REQUEST;
00416 goto cleanup;
00417 }
00418
00419 MHD_gtls_selected_certs_set (session, local_certs,
00420 (local_certs != NULL) ? st.ncerts : 0,
00421 local_key, 1);
00422
00423 ret = 0;
00424
00425 cleanup:
00426
00427 if (st.type == MHD_GNUTLS_CRT_X509)
00428 {
00429 if (st.deinit_all)
00430 {
00431 for (i = 0; i < st.ncerts; i++)
00432 {
00433 MHD_gnutls_x509_crt_deinit (st.cert.x509[i]);
00434 }
00435 MHD_gnutls_free (st.cert.x509);
00436 MHD_gnutls_x509_privkey_deinit (st.key.x509);
00437 }
00438 }
00439 return ret;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449 static int
00450 _select_client_cert (MHD_gtls_session_t session,
00451 opaque * _data, size_t _data_size,
00452 enum MHD_GNUTLS_PublicKeyAlgorithm *pk_algos,
00453 int pk_algos_length)
00454 {
00455 int result;
00456 int indx = -1;
00457 MHD_gtls_cert_credentials_t cred;
00458 opaque *data = _data;
00459 ssize_t data_size = _data_size;
00460 int issuers_dn_length;
00461 MHD_gnutls_datum_t *issuers_dn = NULL;
00462
00463 cred = (MHD_gtls_cert_credentials_t)
00464 MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
00465 if (cred == NULL)
00466 {
00467 MHD_gnutls_assert ();
00468 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00469 }
00470
00471 if (cred->client_get_cert_callback != NULL)
00472 {
00473
00474
00475
00476 if (session->security_parameters.cert_type != MHD_GNUTLS_CRT_X509)
00477 issuers_dn_length = 0;
00478 else
00479 {
00480 issuers_dn_length = get_issuers_num (session, data, data_size);
00481 if (issuers_dn_length < 0)
00482 {
00483 MHD_gnutls_assert ();
00484 return issuers_dn_length;
00485 }
00486
00487 if (issuers_dn_length > 0)
00488 {
00489 issuers_dn =
00490 MHD_gnutls_malloc (sizeof (MHD_gnutls_datum_t) *
00491 issuers_dn_length);
00492 if (issuers_dn == NULL)
00493 {
00494 MHD_gnutls_assert ();
00495 return GNUTLS_E_MEMORY_ERROR;
00496 }
00497
00498 result =
00499 get_issuers (session, issuers_dn, issuers_dn_length,
00500 data, data_size);
00501 if (result < 0)
00502 {
00503 MHD_gnutls_assert ();
00504 goto cleanup;
00505 }
00506 }
00507 }
00508
00509 result =
00510 call_get_cert_callback (session, issuers_dn, issuers_dn_length,
00511 pk_algos, pk_algos_length);
00512 goto cleanup;
00513
00514 }
00515 else
00516 {
00517
00518
00519 result = 0;
00520
00521 if (session->security_parameters.cert_type == MHD_GNUTLS_CRT_X509)
00522 result =
00523 _find_x509_cert (cred, _data, _data_size,
00524 pk_algos, pk_algos_length, &indx);
00525 if (result < 0)
00526 {
00527 MHD_gnutls_assert ();
00528 return result;
00529 }
00530
00531 if (indx >= 0)
00532 {
00533 MHD_gtls_selected_certs_set (session,
00534 &cred->cert_list[indx][0],
00535 cred->cert_list_length[indx],
00536 &cred->pkey[indx], 0);
00537 }
00538 else
00539 {
00540 MHD_gtls_selected_certs_set (session, NULL, 0, NULL, 0);
00541 }
00542
00543 result = 0;
00544 }
00545
00546 cleanup:
00547 MHD_gnutls_free (issuers_dn);
00548 return result;
00549
00550 }
00551
00552
00553
00554 static int
00555 MHD_gtls_gen_x509_crt (MHD_gtls_session_t session, opaque ** data)
00556 {
00557 int ret, i;
00558 opaque *pdata;
00559 MHD_gnutls_cert *apr_cert_list;
00560 MHD_gnutls_privkey *apr_pkey;
00561 int apr_cert_list_length;
00562
00563
00564
00565 if ((ret =
00566 MHD_gtls_get_selected_cert (session, &apr_cert_list,
00567 &apr_cert_list_length, &apr_pkey)) < 0)
00568 {
00569 MHD_gnutls_assert ();
00570 return ret;
00571 }
00572
00573 ret = 3;
00574 for (i = 0; i < apr_cert_list_length; i++)
00575 {
00576 ret += apr_cert_list[i].raw.size + 3;
00577
00578
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 (*data) = MHD_gnutls_malloc (ret);
00591 pdata = (*data);
00592
00593 if (pdata == NULL)
00594 {
00595 MHD_gnutls_assert ();
00596 return GNUTLS_E_MEMORY_ERROR;
00597 }
00598 MHD_gtls_write_uint24 (ret - 3, pdata);
00599 pdata += 3;
00600 for (i = 0; i < apr_cert_list_length; i++)
00601 {
00602 MHD_gtls_write_datum24 (pdata, apr_cert_list[i].raw);
00603 pdata += (3 + apr_cert_list[i].raw.size);
00604 }
00605
00606 return ret;
00607 }
00608
00609 int
00610 MHD_gtls_gen_cert_client_certificate (MHD_gtls_session_t session,
00611 opaque ** data)
00612 {
00613 switch (session->security_parameters.cert_type)
00614 {
00615 case MHD_GNUTLS_CRT_X509:
00616 return MHD_gtls_gen_x509_crt (session, data);
00617
00618 default:
00619 MHD_gnutls_assert ();
00620 return GNUTLS_E_INTERNAL_ERROR;
00621 }
00622 }
00623
00624 int
00625 MHD_gtls_gen_cert_server_certificate (MHD_gtls_session_t session,
00626 opaque ** data)
00627 {
00628 switch (session->security_parameters.cert_type)
00629 {
00630 case MHD_GNUTLS_CRT_X509:
00631 return MHD_gtls_gen_x509_crt (session, data);
00632 default:
00633 MHD_gnutls_assert ();
00634 return GNUTLS_E_INTERNAL_ERROR;
00635 }
00636 }
00637
00638
00639
00640
00641 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) MHD_gtls_gcert_deinit(&peer_certificate_list[x])
00642 static int
00643 MHD_gtls_proc_x509_server_certificate (MHD_gtls_session_t session,
00644 opaque * data, size_t data_size)
00645 {
00646 int size, len, ret;
00647 opaque *p = data;
00648 cert_auth_info_t info;
00649 MHD_gtls_cert_credentials_t cred;
00650 ssize_t dsize = data_size;
00651 int i, j, x;
00652 MHD_gnutls_cert *peer_certificate_list;
00653 int peer_certificate_list_size = 0;
00654 MHD_gnutls_datum_t tmp;
00655
00656 cred = (MHD_gtls_cert_credentials_t)
00657 MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
00658 if (cred == NULL)
00659 {
00660 MHD_gnutls_assert ();
00661 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00662 }
00663
00664
00665 if ((ret =
00666 MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
00667 sizeof (cert_auth_info_st), 1)) < 0)
00668 {
00669 MHD_gnutls_assert ();
00670 return ret;
00671 }
00672
00673 info = MHD_gtls_get_auth_info (session);
00674
00675 if (data == NULL || data_size == 0)
00676 {
00677 MHD_gnutls_assert ();
00678
00679 return GNUTLS_E_NO_CERTIFICATE_FOUND;
00680 }
00681
00682 DECR_LEN (dsize, 3);
00683 size = MHD_gtls_read_uint24 (p);
00684 p += 3;
00685
00686
00687
00688
00689 if (size == 0 || size == 3)
00690 {
00691 MHD_gnutls_assert ();
00692
00693 return GNUTLS_E_NO_CERTIFICATE_FOUND;
00694 }
00695
00696 i = dsize;
00697 while (i > 0)
00698 {
00699 DECR_LEN (dsize, 3);
00700 len = MHD_gtls_read_uint24 (p);
00701 p += 3;
00702 DECR_LEN (dsize, len);
00703 peer_certificate_list_size++;
00704 p += len;
00705 i -= len + 3;
00706 }
00707
00708 if (peer_certificate_list_size == 0)
00709 {
00710 MHD_gnutls_assert ();
00711 return GNUTLS_E_NO_CERTIFICATE_FOUND;
00712 }
00713
00714
00715
00716
00717
00718 peer_certificate_list =
00719 MHD_gnutls_malloc (sizeof (MHD_gnutls_cert) *
00720 (peer_certificate_list_size));
00721
00722 if (peer_certificate_list == NULL)
00723 {
00724 MHD_gnutls_assert ();
00725 return GNUTLS_E_MEMORY_ERROR;
00726 }
00727 memset (peer_certificate_list, 0, sizeof (MHD_gnutls_cert) *
00728 peer_certificate_list_size);
00729
00730 p = data + 3;
00731
00732
00733
00734
00735
00736
00737 for (j = 0; j < peer_certificate_list_size; j++)
00738 {
00739 len = MHD_gtls_read_uint24 (p);
00740 p += 3;
00741
00742 tmp.size = len;
00743 tmp.data = p;
00744
00745 if ((ret =
00746 MHD_gtls_x509_raw_cert_to_gcert (&peer_certificate_list
00747 [j], &tmp,
00748 CERT_ONLY_EXTENSIONS)) < 0)
00749 {
00750 MHD_gnutls_assert ();
00751 goto cleanup;
00752 }
00753
00754 p += len;
00755 }
00756
00757
00758 if ((ret =
00759 MHD__gnutls_copy_certificate_auth_info (info,
00760 peer_certificate_list,
00761 peer_certificate_list_size)) <
00762 0)
00763 {
00764 MHD_gnutls_assert ();
00765 goto cleanup;
00766 }
00767
00768 if ((ret =
00769 MHD__gnutls_check_key_usage (&peer_certificate_list[0],
00770 MHD_gnutls_kx_get (session))) < 0)
00771 {
00772 MHD_gnutls_assert ();
00773 goto cleanup;
00774 }
00775
00776 ret = 0;
00777
00778 cleanup:
00779 CLEAR_CERTS;
00780 MHD_gnutls_free (peer_certificate_list);
00781 return ret;
00782
00783 }
00784
00785 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) MHD_gtls_gcert_deinit(&peer_certificate_list[x])
00786
00787 int
00788 MHD_gtls_proc_cert_server_certificate (MHD_gtls_session_t session,
00789 opaque * data, size_t data_size)
00790 {
00791 switch (session->security_parameters.cert_type)
00792 {
00793 case MHD_GNUTLS_CRT_X509:
00794 return MHD_gtls_proc_x509_server_certificate (session, data, data_size);
00795 default:
00796 MHD_gnutls_assert ();
00797 return GNUTLS_E_INTERNAL_ERROR;
00798 }
00799 }
00800
00801 #define MAX_SIGN_ALGOS 2
00802 typedef enum CertificateSigType
00803 { RSA_SIGN = 1, DSA_SIGN
00804 } CertificateSigType;
00805
00806
00807
00808
00809
00810 inline static int
00811 MHD__gnutls_check_supported_sign_algo (CertificateSigType algo)
00812 {
00813 switch (algo)
00814 {
00815 case RSA_SIGN:
00816 return MHD_GNUTLS_PK_RSA;
00817 default:
00818 return -1;
00819 }
00820 }
00821
00822 int
00823 MHD_gtls_proc_cert_cert_req (MHD_gtls_session_t session, opaque * data,
00824 size_t data_size)
00825 {
00826 int size, ret;
00827 opaque *p;
00828 MHD_gtls_cert_credentials_t cred;
00829 ssize_t dsize;
00830 int i, j;
00831 enum MHD_GNUTLS_PublicKeyAlgorithm pk_algos[MAX_SIGN_ALGOS];
00832 int pk_algos_length;
00833 enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
00834
00835 cred = (MHD_gtls_cert_credentials_t)
00836 MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
00837 if (cred == NULL)
00838 {
00839 MHD_gnutls_assert ();
00840 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00841 }
00842
00843 if ((ret =
00844 MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
00845 sizeof (cert_auth_info_st), 0)) < 0)
00846 {
00847 MHD_gnutls_assert ();
00848 return ret;
00849 }
00850
00851 p = data;
00852 dsize = data_size;
00853
00854 DECR_LEN (dsize, 1);
00855 size = p[0];
00856 p++;
00857
00858
00859 pk_algos_length = j = 0;
00860 for (i = 0; i < size; i++, p++)
00861 {
00862 DECR_LEN (dsize, 1);
00863 if ((ret = MHD__gnutls_check_supported_sign_algo (*p)) > 0)
00864 {
00865 if (j < MAX_SIGN_ALGOS)
00866 {
00867 pk_algos[j++] = ret;
00868 pk_algos_length++;
00869 }
00870 }
00871 }
00872
00873 if (pk_algos_length == 0)
00874 {
00875 MHD_gnutls_assert ();
00876 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
00877 }
00878
00879 if (ver == MHD_GNUTLS_PROTOCOL_TLS1_2)
00880 {
00881
00882 int hash_num;
00883 DECR_LEN (dsize, 1);
00884
00885 hash_num = p[0] & 0xFF;
00886 p++;
00887
00888 DECR_LEN (dsize, hash_num);
00889 p += hash_num;
00890 }
00891
00892
00893 DECR_LEN (dsize, 2);
00894 size = MHD_gtls_read_uint16 (p);
00895 p += 2;
00896
00897 DECR_LEN (dsize, size);
00898
00899
00900
00901
00902 if ((ret =
00903 _select_client_cert (session, p, size, pk_algos, pk_algos_length)) < 0)
00904 {
00905 MHD_gnutls_assert ();
00906 return ret;
00907 }
00908
00909
00910
00911
00912 session->key->certificate_requested = 1;
00913
00914 return 0;
00915 }
00916
00917 int
00918 MHD_gtls_gen_cert_client_cert_vrfy (MHD_gtls_session_t session,
00919 opaque ** data)
00920 {
00921 int ret;
00922 MHD_gnutls_cert *apr_cert_list;
00923 MHD_gnutls_privkey *apr_pkey;
00924 int apr_cert_list_length, size;
00925 MHD_gnutls_datum_t signature;
00926
00927 *data = NULL;
00928
00929
00930 if ((ret =
00931 MHD_gtls_get_selected_cert (session, &apr_cert_list,
00932 &apr_cert_list_length, &apr_pkey)) < 0)
00933 {
00934 MHD_gnutls_assert ();
00935 return ret;
00936 }
00937
00938 if (apr_cert_list_length > 0)
00939 {
00940 if ((ret =
00941 MHD_gtls_tls_sign_hdata (session,
00942 &apr_cert_list[0],
00943 apr_pkey, &signature)) < 0)
00944 {
00945 MHD_gnutls_assert ();
00946 return ret;
00947 }
00948 }
00949 else
00950 {
00951 return 0;
00952 }
00953
00954 *data = MHD_gnutls_malloc (signature.size + 2);
00955 if (*data == NULL)
00956 {
00957 MHD__gnutls_free_datum (&signature);
00958 return GNUTLS_E_MEMORY_ERROR;
00959 }
00960 size = signature.size;
00961 MHD_gtls_write_uint16 (size, *data);
00962
00963 memcpy (&(*data)[2], signature.data, size);
00964
00965 MHD__gnutls_free_datum (&signature);
00966
00967 return size + 2;
00968 }
00969
00970 int
00971 MHD_gtls_proc_cert_client_cert_vrfy (MHD_gtls_session_t session,
00972 opaque * data, size_t data_size)
00973 {
00974 int size, ret;
00975 ssize_t dsize = data_size;
00976 opaque *pdata = data;
00977 MHD_gnutls_datum_t sig;
00978 cert_auth_info_t info = MHD_gtls_get_auth_info (session);
00979 MHD_gnutls_cert peer_cert;
00980
00981 if (info == NULL || info->ncerts == 0)
00982 {
00983 MHD_gnutls_assert ();
00984
00985 return GNUTLS_E_INTERNAL_ERROR;
00986 }
00987
00988 DECR_LEN (dsize, 2);
00989 size = MHD_gtls_read_uint16 (pdata);
00990 pdata += 2;
00991
00992 DECR_LEN (dsize, size);
00993
00994 sig.data = pdata;
00995 sig.size = size;
00996
00997 ret = MHD_gtls_raw_cert_to_gcert (&peer_cert,
00998 session->security_parameters.cert_type,
00999 &info->raw_certificate_list[0],
01000 CERT_NO_COPY);
01001
01002 if (ret < 0)
01003 {
01004 MHD_gnutls_assert ();
01005 return ret;
01006 }
01007
01008 if ((ret = MHD_gtls_verify_sig_hdata (session, &peer_cert, &sig)) < 0)
01009 {
01010 MHD_gnutls_assert ();
01011 MHD_gtls_gcert_deinit (&peer_cert);
01012 return ret;
01013 }
01014 MHD_gtls_gcert_deinit (&peer_cert);
01015
01016 return 0;
01017 }
01018
01019 #define CERTTYPE_SIZE 3
01020 int
01021 MHD_gtls_gen_cert_server_cert_req (MHD_gtls_session_t session, opaque ** data)
01022 {
01023 MHD_gtls_cert_credentials_t cred;
01024 int size;
01025 opaque *pdata;
01026 enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
01027
01028
01029
01030
01031
01032
01033 cred = (MHD_gtls_cert_credentials_t)
01034 MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
01035 if (cred == NULL)
01036 {
01037 MHD_gnutls_assert ();
01038 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
01039 }
01040
01041 size = CERTTYPE_SIZE + 2;
01042
01043
01044 if (session->security_parameters.cert_type == MHD_GNUTLS_CRT_X509 &&
01045 session->internals.ignore_rdn_sequence == 0)
01046 size += cred->x509_rdn_sequence.size;
01047
01048 if (ver == MHD_GNUTLS_PROTOCOL_TLS1_2)
01049
01050
01051 size += 1;
01052
01053 (*data) = MHD_gnutls_malloc (size);
01054 pdata = (*data);
01055
01056 if (pdata == NULL)
01057 {
01058 MHD_gnutls_assert ();
01059 return GNUTLS_E_MEMORY_ERROR;
01060 }
01061
01062 pdata[0] = CERTTYPE_SIZE - 1;
01063
01064 pdata[1] = RSA_SIGN;
01065 pdata[2] = DSA_SIGN;
01066 pdata += CERTTYPE_SIZE;
01067
01068 if (ver == MHD_GNUTLS_PROTOCOL_TLS1_2)
01069 {
01070
01071 *pdata = 0;
01072 pdata++;
01073 }
01074
01075 if (session->security_parameters.cert_type == MHD_GNUTLS_CRT_X509 &&
01076 session->internals.ignore_rdn_sequence == 0)
01077 {
01078 MHD_gtls_write_datum16 (pdata, cred->x509_rdn_sequence);
01079
01080 }
01081 else
01082 {
01083 MHD_gtls_write_uint16 (0, pdata);
01084
01085 }
01086
01087 return size;
01088 }
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 int
01099 MHD_gtls_get_selected_cert (MHD_gtls_session_t session,
01100 MHD_gnutls_cert ** apr_cert_list,
01101 int *apr_cert_list_length,
01102 MHD_gnutls_privkey ** apr_pkey)
01103 {
01104 if (session->security_parameters.entity == GNUTLS_SERVER)
01105 {
01106
01107
01108
01109
01110 *apr_cert_list = session->internals.selected_cert_list;
01111 *apr_pkey = session->internals.selected_key;
01112 *apr_cert_list_length = session->internals.selected_cert_list_length;
01113
01114 if (*apr_cert_list_length == 0 || *apr_cert_list == NULL)
01115 {
01116 MHD_gnutls_assert ();
01117 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
01118 }
01119
01120 }
01121 else
01122 {
01123
01124
01125
01126
01127
01128 *apr_cert_list = session->internals.selected_cert_list;
01129 *apr_cert_list_length = session->internals.selected_cert_list_length;
01130 *apr_pkey = session->internals.selected_key;
01131
01132 }
01133
01134 return 0;
01135 }
01136
01137
01138
01139
01140 static MHD_gnutls_cert *
01141 alloc_and_load_x509_certs (MHD_gnutls_x509_crt_t * certs, unsigned ncerts)
01142 {
01143 MHD_gnutls_cert *local_certs;
01144 int ret = 0;
01145 unsigned i, j;
01146
01147 if (certs == NULL)
01148 return NULL;
01149
01150 local_certs = MHD_gnutls_malloc (sizeof (MHD_gnutls_cert) * ncerts);
01151 if (local_certs == NULL)
01152 {
01153 MHD_gnutls_assert ();
01154 return NULL;
01155 }
01156
01157 for (i = 0; i < ncerts; i++)
01158 {
01159 ret = MHD_gtls_x509_crt_to_gcert (&local_certs[i], certs[i], 0);
01160 if (ret < 0)
01161 break;
01162 }
01163
01164 if (ret < 0)
01165 {
01166 MHD_gnutls_assert ();
01167 for (j = 0; j < i; j++)
01168 {
01169 MHD_gtls_gcert_deinit (&local_certs[j]);
01170 }
01171 MHD_gnutls_free (local_certs);
01172 return NULL;
01173 }
01174
01175 return local_certs;
01176 }
01177
01178
01179
01180
01181 static MHD_gnutls_privkey *
01182 alloc_and_load_x509_key (MHD_gnutls_x509_privkey_t key)
01183 {
01184 MHD_gnutls_privkey *local_key;
01185 int ret = 0;
01186
01187 if (key == NULL)
01188 return NULL;
01189
01190 local_key = MHD_gnutls_malloc (sizeof (MHD_gnutls_privkey));
01191 if (local_key == NULL)
01192 {
01193 MHD_gnutls_assert ();
01194 return NULL;
01195 }
01196
01197 ret = MHD__gnutls_x509_privkey_to_gkey (local_key, key);
01198 if (ret < 0)
01199 {
01200 MHD_gnutls_assert ();
01201 return NULL;
01202 }
01203
01204 return local_key;
01205 }
01206
01207 void
01208 MHD_gtls_selected_certs_deinit (MHD_gtls_session_t session)
01209 {
01210 if (session->internals.selected_need_free != 0)
01211 {
01212 int i;
01213
01214 for (i = 0; i < session->internals.selected_cert_list_length; i++)
01215 {
01216 MHD_gtls_gcert_deinit (&session->internals.selected_cert_list[i]);
01217 }
01218 MHD_gnutls_free (session->internals.selected_cert_list);
01219 session->internals.selected_cert_list = NULL;
01220 session->internals.selected_cert_list_length = 0;
01221
01222 MHD_gtls_gkey_deinit (session->internals.selected_key);
01223 if (session->internals.selected_key)
01224 {
01225 MHD_gnutls_free (session->internals.selected_key);
01226 session->internals.selected_key = NULL;
01227 }
01228 }
01229
01230 return;
01231 }
01232
01233 void
01234 MHD_gtls_selected_certs_set (MHD_gtls_session_t session,
01235 MHD_gnutls_cert * certs, int ncerts,
01236 MHD_gnutls_privkey * key, int need_free)
01237 {
01238 MHD_gtls_selected_certs_deinit (session);
01239
01240 session->internals.selected_cert_list = certs;
01241 session->internals.selected_cert_list_length = ncerts;
01242 session->internals.selected_key = key;
01243 session->internals.selected_need_free = need_free;
01244
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258 int
01259 MHD_gtls_server_select_cert (MHD_gtls_session_t session,
01260 enum MHD_GNUTLS_PublicKeyAlgorithm
01261 requested_algo)
01262 {
01263 unsigned i;
01264 int idx, ret;
01265 MHD_gtls_cert_credentials_t cred;
01266
01267 cred = (MHD_gtls_cert_credentials_t)
01268 MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
01269 if (cred == NULL)
01270 {
01271 MHD_gnutls_assert ();
01272 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
01273 }
01274
01275
01276
01277
01278 if (cred->server_get_cert_callback != NULL)
01279 return call_get_cert_callback (session, NULL, 0, NULL, 0);
01280
01281
01282
01283 ret = 0;
01284 idx = -1;
01285
01286
01287 for (i = 0; i < cred->ncerts; i++)
01288 {
01289
01290
01291 if (requested_algo == GNUTLS_PK_ANY ||
01292 requested_algo == cred->cert_list[i][0].subject_pk_algorithm)
01293 {
01294
01295
01296 if (session->security_parameters.cert_type ==
01297 cred->cert_list[i][0].cert_type)
01298 {
01299 idx = i;
01300 break;
01301 }
01302 }
01303 }
01304
01305
01306
01307
01308 if (idx >= 0 && ret == 0)
01309 {
01310 MHD_gtls_selected_certs_set (session,
01311 &cred->cert_list[idx][0],
01312 cred->cert_list_length[idx],
01313 &cred->pkey[idx], 0);
01314 }
01315 else
01316
01317 ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS;
01318
01319 return ret;
01320 }
01321
01322
01323
01324 void
01325 MHD_gtls_free_rsa_info (rsa_info_st * rsa)
01326 {
01327 MHD__gnutls_free_datum (&rsa->modulus);
01328 MHD__gnutls_free_datum (&rsa->exponent);
01329 }