~ubuntu-branches/ubuntu/utopic/freerdp/utopic

« back to all changes in this revision

Viewing changes to libfreerdp-core/tls.c

  • Committer: Package Import Robot
  • Author(s): Otavio Salvador, Jeremy Bicha
  • Date: 2012-02-11 10:34:05 UTC
  • mfrom: (1.1.7) (9.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20120211103405-mk0gjhjn70eeyxul
Tags: 1.0.1-1
[ Jeremy Bicha ]
* New upstream release. Closes: #659332.
* Updated symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
176
176
        return status;
177
177
}
178
178
 
179
 
boolean tls_print_error(char *func, SSL *connection, int value)
 
179
boolean tls_print_error(char* func, SSL* connection, int value)
180
180
{
181
181
        switch (SSL_get_error(connection, value))
182
182
        {
206
206
        }
207
207
}
208
208
 
209
 
CryptoCert tls_get_certificate(rdpTls * tls)
 
209
CryptoCert tls_get_certificate(rdpTls* tls)
210
210
{
211
211
        CryptoCert cert;
212
212
        X509* server_cert;
227
227
        return cert;
228
228
}
229
229
 
230
 
rdpTls* tls_new()
231
 
{
232
 
        rdpTls* tls;
233
 
 
234
 
        tls = (rdpTls*) xzalloc(sizeof(rdpTls));
235
 
 
236
 
        if (tls != NULL)
237
 
        {
238
 
                SSL_load_error_strings();
239
 
                SSL_library_init();
240
 
        }
241
 
 
242
 
        return tls;
243
 
}
244
 
 
245
 
int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostname)
246
 
{
247
 
        boolean status;
248
 
        rdpCertStore* certstore;
249
 
        status = x509_verify_cert(cert, settings);
250
 
 
251
 
        if (status != true)
 
230
boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
 
231
{
 
232
        int match;
 
233
        int index;
 
234
        char* common_name;
 
235
        int common_name_length;
 
236
        char** alt_names;
 
237
        int alt_names_count;
 
238
        int* alt_names_lengths;
 
239
        boolean certificate_status;
 
240
        boolean hostname_match = false;
 
241
        rdpCertificateData* certificate_data;
 
242
 
 
243
        /* ignore certificate verification if user explicitly required it (discouraged) */
 
244
        if (tls->settings->ignore_certificate)
 
245
                return true;  /* success! */
 
246
 
 
247
        /* if user explicitly specified a certificate name, use it instead of the hostname */
 
248
        if (tls->settings->certificate_name)
 
249
                hostname = tls->settings->certificate_name;
 
250
 
 
251
        /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
 
252
        certificate_status = x509_verify_certificate(cert, tls->certificate_store->path);
 
253
 
 
254
        /* verify certificate name match */
 
255
        certificate_data = crypto_get_certificate_data(cert->px509, hostname);
 
256
 
 
257
        /* extra common name and alternative names */
 
258
        common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length);
 
259
        alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count, &alt_names_lengths);
 
260
 
 
261
        /* compare against common name */
 
262
 
 
263
        if (common_name != NULL)
 
264
        {
 
265
                if (strlen(hostname) == common_name_length)
 
266
                {
 
267
                        if (memcmp((void*) hostname, (void*) common_name, common_name_length) == 0)
 
268
                                hostname_match = true;
 
269
                }
 
270
        }
 
271
 
 
272
        /* compare against alternative names */
 
273
 
 
274
        if (alt_names != NULL)
 
275
        {
 
276
                for (index = 0; index < alt_names_count; index++)
 
277
                {
 
278
                        if (strlen(hostname) == alt_names_lengths[index])
 
279
                        {
 
280
                                if (memcmp((void*) hostname, (void*) alt_names[index], alt_names_lengths[index]) == 0)
 
281
                                        hostname_match = true;
 
282
                        }
 
283
                }
 
284
        }
 
285
 
 
286
        /* if the certificate is valid and the certificate name matches, verification succeeds */
 
287
        if (certificate_status && hostname_match)
 
288
                return true; /* success! */
 
289
 
 
290
        /* if the certificate is valid but the certificate name does not match, warn user, do not accept */
 
291
        if (certificate_status && !hostname_match)
 
292
                tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
 
293
 
 
294
        /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */
 
295
 
 
296
        if (!certificate_status)
252
297
        {
253
298
                char* issuer;
254
299
                char* subject;
255
300
                char* fingerprint;
256
 
                rdpCertData* certdata;
257
 
 
258
 
                certdata = crypto_get_cert_data(cert->px509, hostname);
259
 
                certstore = certstore_new(certdata, settings->home_path);
260
 
 
261
 
                if (cert_data_match(certstore) == 0)
262
 
                        goto end;
 
301
                boolean accept_certificate = false;
 
302
                boolean verification_status = false;
263
303
 
264
304
                issuer = crypto_cert_issuer(cert->px509);
265
305
                subject = crypto_cert_subject(cert->px509);
266
306
                fingerprint = crypto_cert_fingerprint(cert->px509);
267
307
 
268
 
                if (certstore->match == 1)
269
 
                {
270
 
                        boolean accept_certificate = settings->ignore_certificate;
271
 
 
272
 
                        if (!accept_certificate)
273
 
                        {
274
 
                                freerdp* instance = (freerdp*) settings->instance;
275
 
 
276
 
                                if (instance->VerifyCertificate)
277
 
                                        accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
278
 
 
279
 
                                xfree(issuer);
280
 
                                xfree(subject);
281
 
                                xfree(fingerprint);
282
 
                        }
283
 
 
284
 
                        if (!accept_certificate)
285
 
                                return 1;
286
 
 
287
 
                        cert_data_print(certstore);
288
 
                }
289
 
                else if (certstore->match == -1)
290
 
                {
291
 
                        tls_print_cert_error(hostname, fingerprint);
292
 
                        certstore_free(certstore);
293
 
                        return 1;
294
 
                }
295
 
 
296
 
end:
297
 
                certstore_free(certstore);
 
308
                /* search for matching entry in known_hosts file */
 
309
                match = certificate_data_match(tls->certificate_store, certificate_data);
 
310
 
 
311
                if (match == 1)
 
312
                {
 
313
                        /* no entry was found in known_hosts file, prompt user for manual verification */
 
314
 
 
315
                        freerdp* instance = (freerdp*) tls->settings->instance;
 
316
 
 
317
                        if (!hostname_match)
 
318
                                tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
 
319
 
 
320
                        if (instance->VerifyCertificate)
 
321
                                accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
 
322
 
 
323
                        if (!accept_certificate)
 
324
                        {
 
325
                                /* user did not accept, abort and do not add entry in known_hosts file */
 
326
                                verification_status = false;  /* failure! */
 
327
                        }
 
328
                        else
 
329
                        {
 
330
                                /* user accepted certificate, add entry in known_hosts file */
 
331
                                certificate_data_print(tls->certificate_store, certificate_data);
 
332
                                verification_status = true; /* success! */
 
333
                        }
 
334
                }
 
335
                else if (match == -1)
 
336
                {
 
337
                        /* entry was found in known_hosts file, but fingerprint does not match */
 
338
                        tls_print_certificate_error(hostname, fingerprint);
 
339
                        verification_status = false; /* failure! */
 
340
                }
 
341
                else if (match == 0)
 
342
                {
 
343
                        verification_status = true; /* success! */
 
344
                }
 
345
 
 
346
                xfree(issuer);
 
347
                xfree(subject);
 
348
                xfree(fingerprint);
 
349
 
 
350
                return verification_status;
298
351
        }
299
352
 
300
 
        return 0;
 
353
        return false;
301
354
}
302
355
 
303
 
void tls_print_cert_error(char* hostname, char* fingerprint)
 
356
void tls_print_certificate_error(char* hostname, char* fingerprint)
304
357
{
305
358
        printf("The host key for %s has changed\n", hostname);
306
359
        printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
316
369
        printf("Host key verification failed.\n");
317
370
}
318
371
 
 
372
void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count)
 
373
{
 
374
        int index;
 
375
 
 
376
        printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
 
377
        printf("@           WARNING: CERTIFICATE NAME MISMATCH!           @\n");
 
378
        printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
 
379
        printf("The hostname used for this connection (%s) \n", hostname);
 
380
 
 
381
        if (alt_names_count < 1)
 
382
        {
 
383
                printf("does not match the name given in the certificate:\n");
 
384
                printf("%s\n", common_name);
 
385
        }
 
386
        else
 
387
        {
 
388
                printf("does not match the names given in the certificate:\n");
 
389
                printf("%s", common_name);
 
390
 
 
391
                for (index = 0; index < alt_names_count; index++)
 
392
                {
 
393
                        printf(", %s", alt_names[index]);
 
394
                }
 
395
 
 
396
                printf("\n");
 
397
        }
 
398
 
 
399
        printf("A valid certificate for the wrong name should NOT be trusted!\n");
 
400
}
 
401
 
 
402
rdpTls* tls_new(rdpSettings* settings)
 
403
{
 
404
        rdpTls* tls;
 
405
 
 
406
        tls = (rdpTls*) xzalloc(sizeof(rdpTls));
 
407
 
 
408
        if (tls != NULL)
 
409
        {
 
410
                SSL_load_error_strings();
 
411
                SSL_library_init();
 
412
 
 
413
                tls->settings = settings;
 
414
                tls->certificate_store = certificate_store_new(settings);
 
415
        }
 
416
 
 
417
        return tls;
 
418
}
 
419
 
319
420
void tls_free(rdpTls* tls)
320
421
{
321
422
        if (tls != NULL)
322
423
        {
323
424
                if (tls->ssl)
324
425
                        SSL_free(tls->ssl);
 
426
 
325
427
                if (tls->ctx)
326
428
                        SSL_CTX_free(tls->ctx);
 
429
 
 
430
                certificate_store_free(tls->certificate_store);
 
431
 
327
432
                xfree(tls);
328
433
        }
329
434
}