~yolanda.robla/ubuntu/saucy/freeradius/dep-8-tests

« back to all changes in this revision

Viewing changes to src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c

  • Committer: Bazaar Package Importer
  • Author(s): Josip Rodin
  • Date: 2010-10-14 21:51:51 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20101014215151-po7jgf8lyf0zq5ht
Tags: 2.1.10+dfsg-1
* New upstream version, closes a bunch of reproducible SNAFUs,
  including two tagged as security issues, CVE-2010-3696, CVE-2010-3697,
  closes: #600176.
* Build-depend on newer Libtool because of lt_dladvise_init(), also
  upstream now has a configure check so we no longer need a patch,
  yet we still don't want the old behaviour. Noticed by John Morrissey,
  closes: #584151.
* Added the /etc/default/freeradius file as suggested by
  Rudy Gevaert and Matthew Newton, closes: #564716.
* Stop symlinking /dev/urandom into /etc/freeradius/certs/random,
  it breaks grep -r in /etc. Instead, replace it inside eap.conf,
  both in the new shipped conffile and in postinst.

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
        { NULL, -1, 0, NULL, NULL }           /* end the list */
56
56
};
57
57
 
 
58
static CONF_PARSER verify_config[] = {
 
59
        { "tmpdir", PW_TYPE_STRING_PTR,
 
60
          offsetof(EAP_TLS_CONF, verify_tmp_dir), NULL, NULL},
 
61
        { "client", PW_TYPE_STRING_PTR,
 
62
          offsetof(EAP_TLS_CONF, verify_client_cert_cmd), NULL, NULL},
 
63
        { NULL, -1, 0, NULL, NULL }           /* end the list */
 
64
};
 
65
 
58
66
static CONF_PARSER module_config[] = {
59
67
        { "rsa_key_exchange", PW_TYPE_BOOLEAN,
60
68
          offsetof(EAP_TLS_CONF, rsa_key), NULL, "no" },
99
107
 
100
108
        { "cache", PW_TYPE_SUBSECTION, 0, NULL, (const void *) cache_config },
101
109
 
 
110
        { "verify", PW_TYPE_SUBSECTION, 0, NULL, (const void *) verify_config },
 
111
 
102
112
        { NULL, -1, 0, NULL, NULL }           /* end the list */
103
113
};
104
114
 
214
224
}
215
225
 
216
226
/*
 
227
 *      For creating certificate attributes.
 
228
 */
 
229
static const char *cert_attr_names[5][2] = {
 
230
  { "TLS-Client-Cert-Serial",           "TLS-Cert-Serial" },
 
231
  { "TLS-Client-Cert-Expiration",       "TLS-Cert-Expiration" },
 
232
  { "TLS-Client-Cert-Subject",          "TLS-Cert-Subject" },
 
233
  { "TLS-Client-Cert-Issuer",           "TLS-Cert-Issuer" },
 
234
  { "TLS-Client-Cert-Common-Name",      "TLS-Cert-Common-Name" }
 
235
};
 
236
 
 
237
#define EAPTLS_SERIAL           (0)
 
238
#define EAPTLS_EXPIRATION       (1)
 
239
#define EAPTLS_SUBJECT          (2)
 
240
#define EAPTLS_ISSUER           (3)
 
241
#define EAPTLS_CN               (4)
 
242
 
 
243
/*
217
244
 *      Before trusting a certificate, you must make sure that the
218
245
 *      certificate is 'valid'. There are several steps that your
219
246
 *      application can take in determining if a certificate is
244
271
        char issuer[1024]; /* Used for the issuer name */
245
272
        char common_name[1024];
246
273
        char cn_str[1024];
 
274
        char buf[64];
247
275
        EAP_HANDLER *handler = NULL;
248
276
        X509 *client_cert;
249
277
        SSL *ssl;
250
 
        int err, depth;
 
278
        int err, depth, lookup;
251
279
        EAP_TLS_CONF *conf;
252
280
        int my_ok = ok;
253
281
        REQUEST *request;
 
282
        ASN1_INTEGER *sn = NULL;
 
283
        ASN1_TIME *asn_time = NULL;
254
284
 
255
285
        client_cert = X509_STORE_CTX_get_current_cert(ctx);
256
286
        err = X509_STORE_CTX_get_error(ctx);
257
287
        depth = X509_STORE_CTX_get_error_depth(ctx);
258
288
 
259
 
        if (!my_ok) {
260
 
                radlog(L_ERR,"--> verify error:num=%d:%s\n",err,
261
 
                        X509_verify_cert_error_string(err));
262
 
                return my_ok;
263
 
        }
 
289
        lookup = depth;
 
290
 
 
291
        /*
 
292
         *      Log client/issuing cert.  If there's an error, log
 
293
         *      issuing cert.
 
294
         */
 
295
        if ((lookup > 1) && !my_ok) lookup = 1;
264
296
 
265
297
        /*
266
298
         * Retrieve the pointer to the SSL of the connection currently treated
272
304
        conf = (EAP_TLS_CONF *)SSL_get_ex_data(ssl, 1);
273
305
 
274
306
        /*
 
307
         *      Get the Serial Number
 
308
         */
 
309
        buf[0] = '\0';
 
310
        sn = X509_get_serialNumber(client_cert);
 
311
 
 
312
        /*
 
313
         *      For this next bit, we create the attributes *only* if
 
314
         *      we're at the client or issuing certificate.
 
315
         */
 
316
        if ((lookup <= 1) && sn && (sn->length < (sizeof(buf) / 2))) {
 
317
                char *p = buf;
 
318
                int i;
 
319
 
 
320
                for (i = 0; i < sn->length; i++) {
 
321
                        sprintf(p, "%02x", (unsigned int)sn->data[i]);
 
322
                        p += 2;
 
323
                }
 
324
                pairadd(&handler->certs,
 
325
                        pairmake(cert_attr_names[EAPTLS_SERIAL][lookup], buf, T_OP_SET));
 
326
        }
 
327
 
 
328
 
 
329
        /*
 
330
         *      Get the Expiration Date
 
331
         */
 
332
        buf[0] = '\0';
 
333
        asn_time = X509_get_notAfter(client_cert);
 
334
        if ((lookup <= 1) && asn_time && (asn_time->length < MAX_STRING_LEN)) {
 
335
                memcpy(buf, (char*) asn_time->data, asn_time->length);
 
336
                buf[asn_time->length] = '\0';
 
337
                pairadd(&handler->certs,
 
338
                        pairmake(cert_attr_names[EAPTLS_EXPIRATION][lookup], buf, T_OP_SET));
 
339
        }
 
340
 
 
341
        /*
275
342
         *      Get the Subject & Issuer
276
343
         */
277
344
        subject[0] = issuer[0] = '\0';
278
345
        X509_NAME_oneline(X509_get_subject_name(client_cert), subject,
279
346
                          sizeof(subject));
 
347
        subject[sizeof(subject) - 1] = '\0';
 
348
        if ((lookup <= 1) && subject[0] && (strlen(subject) < MAX_STRING_LEN)) {
 
349
                pairadd(&handler->certs,
 
350
                        pairmake(cert_attr_names[EAPTLS_SUBJECT][lookup], subject, T_OP_SET));
 
351
        }
 
352
 
280
353
        X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer,
281
354
                          sizeof(issuer));
282
 
 
283
 
        subject[sizeof(subject) - 1] = '\0';
284
355
        issuer[sizeof(issuer) - 1] = '\0';
 
356
        if ((lookup <= 1) && issuer[0] && (strlen(issuer) < MAX_STRING_LEN)) {
 
357
                pairadd(&handler->certs,
 
358
                        pairmake(cert_attr_names[EAPTLS_ISSUER][lookup], issuer, T_OP_SET));
 
359
        }
285
360
 
286
361
        /*
287
362
         *      Get the Common Name
289
364
        X509_NAME_get_text_by_NID(X509_get_subject_name(client_cert),
290
365
                                  NID_commonName, common_name, sizeof(common_name));
291
366
        common_name[sizeof(common_name) - 1] = '\0';
 
367
        if ((lookup <= 1) && common_name[0] && (strlen(common_name) < MAX_STRING_LEN)) {
 
368
                pairadd(&handler->certs,
 
369
                        pairmake(cert_attr_names[EAPTLS_CN][lookup], common_name, T_OP_SET));
 
370
        }
 
371
 
 
372
        if (!my_ok) {
 
373
                const char *p = X509_verify_cert_error_string(err);
 
374
                radlog(L_ERR,"--> verify error:num=%d:%s\n",err, p);
 
375
                radius_pairmake(request, &request->packet->vps,
 
376
                                "Module-Failure-Message", p, T_OP_SET);
 
377
                return my_ok;
 
378
        }
292
379
 
293
380
        switch (ctx->error) {
294
381
 
346
433
                                }
347
434
                        }
348
435
                } /* check_cert_cn */
 
436
 
 
437
                while (conf->verify_client_cert_cmd) {
 
438
                        char filename[256];
 
439
                        FILE *fp;
 
440
 
 
441
                        snprintf(filename, sizeof(filename), "%s/%s.client.XXXXXXXX",
 
442
                                 conf->verify_tmp_dir, progname);
 
443
                        if (mkstemp(filename) < 0) {
 
444
                                RDEBUG("Failed creating file in %s: %s",
 
445
                                       conf->verify_tmp_dir, strerror(errno));
 
446
                                break;                                 
 
447
                        }
 
448
 
 
449
                        fp = fopen(filename, "w");
 
450
                        if (!fp) {
 
451
                                RDEBUG("Failed opening file %s: %s",
 
452
                                       filename, strerror(errno));
 
453
                                break;
 
454
                        }
 
455
 
 
456
                        if (!PEM_write_X509(fp, client_cert)) {
 
457
                                fclose(fp);
 
458
                                RDEBUG("Failed writing certificate to file");
 
459
                                goto do_unlink;
 
460
                        }
 
461
                        fclose(fp);
 
462
 
 
463
                        if (!radius_pairmake(request, &request->packet->vps,
 
464
                                             "TLS-Client-Cert-Filename",
 
465
                                             filename, T_OP_SET)) {
 
466
                                RDEBUG("Failed creating TLS-Client-Cert-Filename");
 
467
                                
 
468
                                goto do_unlink;
 
469
                        }
 
470
 
 
471
                        RDEBUG("Verifying client certificate: %s",
 
472
                               conf->verify_client_cert_cmd);
 
473
                        if (radius_exec_program(conf->verify_client_cert_cmd,
 
474
                                                request, 1, NULL, 0, 
 
475
                                                request->packet->vps,
 
476
                                                NULL, 1) != 0) {
 
477
                                radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) fails external verification!", common_name);
 
478
                                my_ok = 0;
 
479
                        } else {
 
480
                                RDEBUG("Client certificate CN %s passed external validation", common_name);
 
481
                        }
 
482
 
 
483
                do_unlink:
 
484
                        unlink(filename);
 
485
                        break;
 
486
                }
 
487
 
 
488
 
349
489
        } /* depth == 0 */
350
490
 
351
491
        if (debug_flag > 0) {
521
661
         */
522
662
        ctx_options |= SSL_OP_NO_SSLv2;
523
663
        ctx_options |= SSL_OP_NO_SSLv3;
 
664
#ifdef SSL_OP_NO_TICKET
 
665
        ctx_options |= SSL_OP_NO_TICKET ;
 
666
#endif
524
667
 
525
668
        /*
526
669
         *      SSL_OP_SINGLE_DH_USE must be used in order to prevent
808
951
        }
809
952
 
810
953
        if (generate_eph_rsa_key(inst->ctx) < 0) {
 
954
                eaptls_detach(inst);
811
955
                return -1;
812
956
        }
813
957
 
 
958
        if (conf->verify_tmp_dir) {
 
959
                char filename[256];
 
960
 
 
961
                if (chmod(conf->verify_tmp_dir, S_IRWXU) < 0) {
 
962
                        radlog(L_ERR, "rlm_eap_tls: Failed changing permissions on %s: %s", conf->verify_tmp_dir, strerror(errno));
 
963
                        eaptls_detach(inst);
 
964
                        return -1;
 
965
                }
 
966
        }
 
967
 
 
968
        if (conf->verify_client_cert_cmd && !conf->verify_tmp_dir) {
 
969
                radlog(L_ERR, "rlm_eap_tls: You MUST set the verify directory in order to use verify_client_cmd");
 
970
                eaptls_detach(inst);
 
971
                return -1;
 
972
        }
 
973
 
814
974
        *instance = inst;
815
975
 
816
976
        return 0;
848
1008
 
849
1009
        inst = (eap_tls_t *)type_arg;
850
1010
 
 
1011
        handler->tls = TRUE;
 
1012
        handler->finished = FALSE;
 
1013
 
851
1014
        /*
852
1015
         *      Manually flush the sessions every so often.  If HALF
853
1016
         *      of the session lifetime has passed since we last