~ubuntu-branches/ubuntu/jaunty/freeradius/jaunty-updates

« 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): Chuck Short
  • Date: 2008-09-22 08:42:02 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080922084202-eyjprg3z55481ha5
Tags: 2.1.0+dfsg-0ubuntu1
* New upstream release.
* Fixes FTBFS issue with new libtool.
* Fixes listen on random port. (LP: #261809)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * rlm_eap_tls.c  contains the interfaces that are called from eap
3
3
 *
4
 
 * Version:     $Id: rlm_eap_tls.c,v 1.54 2008/03/22 08:31:03 aland Exp $
 
4
 * Version:     $Id$
5
5
 *
6
6
 *   This program is free software; you can redistribute it and/or modify
7
7
 *   it under the terms of the GNU General Public License as published by
24
24
 */
25
25
 
26
26
#include <freeradius-devel/ident.h>
27
 
RCSID("$Id: rlm_eap_tls.c,v 1.54 2008/03/22 08:31:03 aland Exp $")
 
27
RCSID("$Id$")
28
28
 
29
29
#include <freeradius-devel/autoconf.h>
30
30
 
38
38
#include <sys/stat.h>
39
39
#endif
40
40
 
 
41
static CONF_PARSER cache_config[] = {
 
42
        { "enable", PW_TYPE_BOOLEAN,
 
43
          offsetof(EAP_TLS_CONF, session_cache_enable), NULL, "no" },
 
44
        { "lifetime", PW_TYPE_INTEGER,
 
45
          offsetof(EAP_TLS_CONF, session_timeout), NULL, "24" },
 
46
        { "max_entries", PW_TYPE_INTEGER,
 
47
          offsetof(EAP_TLS_CONF, session_cache_size), NULL, "255" },
 
48
        { "name", PW_TYPE_STRING_PTR,
 
49
          offsetof(EAP_TLS_CONF, session_id_name), NULL, NULL},
 
50
        { NULL, -1, 0, NULL, NULL }           /* end the list */
 
51
};
 
52
 
41
53
static CONF_PARSER module_config[] = {
42
54
        { "rsa_key_exchange", PW_TYPE_BOOLEAN,
43
55
          offsetof(EAP_TLS_CONF, rsa_key), NULL, "no" },
80
92
        { "make_cert_command", PW_TYPE_STRING_PTR,
81
93
          offsetof(EAP_TLS_CONF, make_cert_command), NULL, NULL},
82
94
 
 
95
        { "cache", PW_TYPE_SUBSECTION, 0, NULL, (const void *) cache_config },
 
96
 
83
97
        { NULL, -1, 0, NULL, NULL }           /* end the list */
84
98
};
85
99
 
115
129
        return 0;
116
130
}
117
131
 
 
132
 
 
133
/*
 
134
 *      Generate ephemeral RSA keys.
 
135
 */
 
136
static int generate_eph_rsa_key(SSL_CTX *ctx)
 
137
{
 
138
        RSA *rsa;
 
139
 
 
140
        rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);
 
141
 
 
142
        if (!SSL_CTX_set_tmp_rsa(ctx, rsa)) {
 
143
                radlog(L_ERR, "rlm_eap_tls: Couldn't set ephemeral RSA key");
 
144
                return -1;
 
145
        }
 
146
 
 
147
        RSA_free(rsa);
 
148
        return 0;
 
149
}
 
150
 
 
151
 
 
152
/*
 
153
 *      These functions don't do anything other than print debugging
 
154
 *      messages.
 
155
 *
 
156
 *      FIXME: Write sessions to some long-term storage, so that
 
157
 *             session resumption can still occur after the server
 
158
 *             restarts.
 
159
 */
 
160
#define MAX_SESSION_SIZE (256)
 
161
 
 
162
static void cbtls_remove_session(UNUSED SSL_CTX *ctx, SSL_SESSION *sess)
 
163
{
 
164
        size_t size;
 
165
        char buffer[2 * MAX_SESSION_SIZE + 1];
 
166
 
 
167
        size = sess->session_id_length;
 
168
        if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
 
169
 
 
170
        fr_bin2hex(sess->session_id, buffer, size);
 
171
 
 
172
        DEBUG2("  SSL: Removing session %s from the cache", buffer);
 
173
        SSL_SESSION_free(sess);
 
174
 
 
175
        return;
 
176
}
 
177
 
 
178
static int cbtls_new_session(UNUSED SSL *s, SSL_SESSION *sess)
 
179
{
 
180
        size_t size;
 
181
        char buffer[2 * MAX_SESSION_SIZE + 1];
 
182
 
 
183
        size = sess->session_id_length;
 
184
        if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
 
185
 
 
186
        fr_bin2hex(sess->session_id, buffer, size);
 
187
 
 
188
        DEBUG2("  SSL: adding session %s to cache", buffer);
 
189
 
 
190
        return 1;
 
191
}
 
192
 
 
193
static SSL_SESSION *cbtls_get_session(UNUSED SSL *s,
 
194
                                      unsigned char *data, int len,
 
195
                                      UNUSED int *copy)
 
196
{
 
197
        size_t size;
 
198
        char buffer[2 * MAX_SESSION_SIZE + 1];
 
199
 
 
200
        size = len;
 
201
        if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
 
202
 
 
203
        fr_bin2hex(data, buffer, size);
 
204
 
 
205
        DEBUG2("  SSL: Client requested nonexistent cached session %s",
 
206
               buffer);
 
207
 
 
208
        return NULL;
 
209
}
 
210
 
118
211
/*
119
212
 *      Before trusting a certificate, you must make sure that the
120
213
 *      certificate is 'valid'. There are several steps that your
152
245
        int err, depth;
153
246
        EAP_TLS_CONF *conf;
154
247
        int my_ok = ok;
 
248
        REQUEST *request;
155
249
 
156
250
        client_cert = X509_STORE_CTX_get_current_cert(ctx);
157
251
        err = X509_STORE_CTX_get_error(ctx);
169
263
         */
170
264
        ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
171
265
        handler = (EAP_HANDLER *)SSL_get_ex_data(ssl, 0);
 
266
        request = handler->request;
172
267
        conf = (EAP_TLS_CONF *)SSL_get_ex_data(ssl, 1);
173
268
 
174
269
        /*
239
334
                                /* if this fails, fail the verification */
240
335
                                my_ok = 0;
241
336
                        } else {
242
 
                                DEBUG2("    rlm_eap_tls: checking certificate CN (%s) with xlat'ed value (%s)", common_name, cn_str);
 
337
                                RDEBUG2("checking certificate CN (%s) with xlat'ed value (%s)", common_name, cn_str);
243
338
                                if (strcmp(cn_str, common_name) != 0) {
244
339
                                        radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) does not match specified value (%s)!", common_name, cn_str);
245
340
                                        my_ok = 0;
249
344
        } /* depth == 0 */
250
345
 
251
346
        if (debug_flag > 0) {
252
 
                DEBUG2("chain-depth=%d, ", depth);
253
 
                DEBUG2("error=%d", err);
 
347
                RDEBUG2("chain-depth=%d, ", depth);
 
348
                RDEBUG2("error=%d", err);
254
349
 
255
 
                DEBUG2("--> User-Name = %s", handler->identity);
256
 
                DEBUG2("--> BUF-Name = %s", common_name);
257
 
                DEBUG2("--> subject = %s", subject);
258
 
                DEBUG2("--> issuer  = %s", issuer);
259
 
                DEBUG2("--> verify return:%d", my_ok);
 
350
                RDEBUG2("--> User-Name = %s", handler->identity);
 
351
                RDEBUG2("--> BUF-Name = %s", common_name);
 
352
                RDEBUG2("--> subject = %s", subject);
 
353
                RDEBUG2("--> issuer  = %s", issuer);
 
354
                RDEBUG2("--> verify return:%d", my_ok);
260
355
        }
261
356
        return my_ok;
262
357
}
263
358
 
264
359
 
265
360
/*
 
361
 *      Free cached session data, which is always a list of VALUE_PAIRs
 
362
 */
 
363
static void eaptls_session_free(UNUSED void *parent, void *data_ptr,
 
364
                                UNUSED CRYPTO_EX_DATA *ad, UNUSED int idx,
 
365
                                UNUSED long argl, UNUSED void *argp)
 
366
{
 
367
        VALUE_PAIR *vp = data_ptr;
 
368
        if (!data_ptr) return;
 
369
 
 
370
        pairfree(&vp);
 
371
}
 
372
 
 
373
 
 
374
/*
266
375
 *      Create Global context SSL and use it in every new session
267
376
 *
268
377
 *      - Load the trusted CAs
328
437
        }
329
438
 
330
439
        /* Load the CAs we trust */
331
 
        if (!SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) {
332
 
                radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
333
 
                radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list %s",conf->ca_file );
334
 
                return NULL;
 
440
        if (conf->ca_file || conf->ca_path) {
 
441
                if (!SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) {
 
442
                        radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
 
443
                        radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list %s",conf->ca_file );
 
444
                        return NULL;
 
445
                }
335
446
        }
336
447
        if (conf->ca_file && *conf->ca_file) SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(conf->ca_file));
337
448
        if (!(SSL_CTX_use_PrivateKey_file(ctx, conf->private_key_file, type))) {
393
504
        SSL_CTX_set_info_callback(ctx, cbtls_info);
394
505
 
395
506
        /*
 
507
         *      Callbacks, etc. for session resumption.
 
508
         */                                                   
 
509
        if (conf->session_cache_enable) {
 
510
                SSL_CTX_sess_set_new_cb(ctx, cbtls_new_session);
 
511
                SSL_CTX_sess_set_get_cb(ctx, cbtls_get_session);
 
512
                SSL_CTX_sess_set_remove_cb(ctx, cbtls_remove_session);
 
513
 
 
514
                SSL_CTX_set_quiet_shutdown(ctx, 1);
 
515
        }
 
516
 
 
517
        /*
396
518
         *      Check the certificates for revocation.
397
519
         */
398
520
#ifdef X509_V_FLAG_CRL_CHECK
437
559
                }
438
560
        }
439
561
 
 
562
        /*
 
563
         *      Setup session caching
 
564
         */
 
565
        if (conf->session_cache_enable) {
 
566
                /*
 
567
                 *      Create a unique context Id per EAP-TLS configuration.
 
568
                 */
 
569
                if (conf->session_id_name) {
 
570
                        snprintf(conf->session_context_id,
 
571
                                 sizeof(conf->session_context_id),
 
572
                                 "FreeRADIUS EAP-TLS %s",
 
573
                                 conf->session_id_name);
 
574
                } else {
 
575
                        snprintf(conf->session_context_id,
 
576
                                 sizeof(conf->session_context_id),
 
577
                                 "FreeRADIUS EAP-TLS %p", conf);
 
578
                }
 
579
 
 
580
                /*
 
581
                 *      Cache it, and DON'T auto-clear it.
 
582
                 */
 
583
                SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR);
 
584
                                               
 
585
                SSL_CTX_set_session_id_context(ctx,
 
586
                                               (unsigned char *) conf->session_context_id,
 
587
                                               (unsigned int) strlen(conf->session_context_id));
 
588
 
 
589
                /*
 
590
                 *      Our timeout is in hours, this is in seconds.
 
591
                 */
 
592
                SSL_CTX_set_timeout(ctx, conf->session_timeout * 3600);
 
593
                
 
594
                /*
 
595
                 *      Set the maximum number of entries in the
 
596
                 *      session cache.
 
597
                 */
 
598
                SSL_CTX_sess_set_cache_size(ctx, conf->session_cache_size);
 
599
 
 
600
        } else {
 
601
                SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
 
602
        }
 
603
 
 
604
        /*
 
605
         *      Register the application indices.  We can't use
 
606
         *      hard-coded "0" and "1" as before, because we need to
 
607
         *      set up a "free" handler for the cached session
 
608
         *      information.
 
609
         */
 
610
        if (eaptls_handle_idx < 0) {
 
611
                eaptls_handle_idx = SSL_get_ex_new_index(0, "eaptls_handle_idx",
 
612
                                                          NULL, NULL, NULL);
 
613
        }
 
614
        
 
615
        if (eaptls_conf_idx < 0) {
 
616
                eaptls_conf_idx = SSL_get_ex_new_index(0, "eaptls_conf_idx",
 
617
                                                          NULL, NULL, NULL);
 
618
        }
 
619
 
 
620
        if (eaptls_session_idx < 0) {
 
621
                eaptls_session_idx = SSL_get_ex_new_index(0, "eaptls_session_idx",
 
622
                                                          NULL, NULL,
 
623
                                                          eaptls_session_free);
 
624
        }
 
625
 
440
626
        return ctx;
441
627
}
442
628
 
564
750
                return -1;
565
751
        }
566
752
 
 
753
        if (generate_eph_rsa_key(inst->ctx) < 0) {
 
754
                return -1;
 
755
        }
 
756
 
567
757
        *instance = inst;
568
758
 
569
759
        return 0;
597
787
        VALUE_PAIR      *vp;
598
788
        int             client_cert = TRUE;
599
789
        int             verify_mode = 0;
 
790
        REQUEST         *request = handler->request;
600
791
 
601
792
        inst = (eap_tls_t *)type_arg;
602
793
 
603
794
        /*
 
795
         *      Manually flush the sessions every so often.  If HALF
 
796
         *      of the session lifetime has passed since we last
 
797
         *      flushed, then flush it again.
 
798
         *
 
799
         *      FIXME: Also do it every N sessions?
 
800
         */
 
801
        if (inst->conf->session_cache_enable &&
 
802
            ((inst->conf->session_last_flushed + (inst->conf->session_timeout * 1800)) <= request->timestamp)) {
 
803
                RDEBUG2("Flushing SSL sessions (of #%ld)",
 
804
                        SSL_CTX_sess_number(inst->ctx));
 
805
 
 
806
                SSL_CTX_flush_sessions(inst->ctx, request->timestamp);
 
807
                inst->conf->session_last_flushed = request->timestamp;
 
808
        }
 
809
 
 
810
        /*
604
811
         *      If we're TTLS or PEAP, then do NOT require a client
605
812
         *      certificate.
606
813
         *
632
839
         *      Verify the peer certificate, if asked.
633
840
         */
634
841
        if (client_cert) {
635
 
                DEBUG2(" rlm_eap_tls: Requiring client certificate");
 
842
                RDEBUG2("Requiring client certificate");
636
843
                verify_mode = SSL_VERIFY_PEER;
637
844
                verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
638
845
                verify_mode |= SSL_VERIFY_CLIENT_ONCE;
685
892
        handler->opaque = ((void *)ssn);
686
893
        handler->free_opaque = session_free;
687
894
 
688
 
        DEBUG2("  rlm_eap_tls: Initiate");
 
895
        RDEBUG2("Initiate");
689
896
 
690
897
        /*
691
 
         *      PEAP-specific breakage.
 
898
         *      Set up type-specific information.
692
899
         */
693
 
        if (handler->eap_type == PW_EAP_PEAP) {
 
900
        switch (handler->eap_type) {
 
901
        case PW_EAP_TLS:
 
902
        default:
 
903
                ssn->prf_label = "client EAP encryption";
 
904
                break;
 
905
 
 
906
        case PW_EAP_TTLS:
 
907
                ssn->prf_label = "ttls keying material";
 
908
                break;
 
909
 
 
910
                /*
 
911
                 *      PEAP-specific breakage.
 
912
                 */
 
913
        case PW_EAP_PEAP:
694
914
                /*
695
915
                 *      As it is a poorly designed protocol, PEAP uses
696
916
                 *      bits in the TLS header to indicate PEAP
708
928
                 *      we force it here.
709
929
                 */
710
930
                ssn->length_flag = 0;
 
931
 
 
932
                ssn->prf_label = "client EAP encryption";
 
933
                break;
 
934
        }
 
935
 
 
936
        if (inst->conf->session_cache_enable) {
 
937
                ssn->allow_session_resumption = 1; /* otherwise it's zero */
711
938
        }
712
939
 
713
940
        /*
715
942
         *      related handshaking or application data.
716
943
         */
717
944
        status = eaptls_start(handler->eap_ds, ssn->peap_flag);
718
 
        DEBUG2("  rlm_eap_tls: Start returned %d", status);
 
945
        RDEBUG2("Start returned %d", status);
719
946
        if (status == 0)
720
947
                return 0;
721
948
 
730
957
/*
731
958
 *      Do authentication, by letting EAP-TLS do most of the work.
732
959
 */
733
 
static int eaptls_authenticate(void *arg UNUSED, EAP_HANDLER *handler)
 
960
static int eaptls_authenticate(void *arg, EAP_HANDLER *handler)
734
961
{
735
962
        eaptls_status_t status;
736
963
        tls_session_t *tls_session = (tls_session_t *) handler->opaque;
 
964
        REQUEST *request = handler->request;
 
965
        eap_tls_t *inst = (eap_tls_t *) arg;
737
966
 
738
 
        DEBUG2("  rlm_eap_tls: Authenticate");
 
967
        RDEBUG2("Authenticate");
739
968
 
740
969
        status = eaptls_process(handler);
741
 
        DEBUG2("  eaptls_process returned %d\n", status);
 
970
        RDEBUG2("eaptls_process returned %d\n", status);
742
971
        switch (status) {
743
972
                /*
744
973
                 *      EAP-TLS handshake was successful, return an
760
989
                 *      data.
761
990
                 */
762
991
        case EAPTLS_OK:
763
 
                DEBUG2("  rlm_eap_tls: Received unexpected tunneled data after successful handshake.");
 
992
                RDEBUG2("Received unexpected tunneled data after successful handshake.");
764
993
#ifndef NDEBUG
765
994
                if ((debug_flag > 2) && fr_log_fp) {
766
995
                        unsigned int i;
780
1009
                }
781
1010
#endif
782
1011
 
783
 
                eaptls_fail(handler->eap_ds, 0);
 
1012
                eaptls_fail(handler, 0);
784
1013
                return 0;
785
1014
                break;
786
1015
 
787
1016
                /*
788
1017
                 *      Anything else: fail.
 
1018
                 *
 
1019
                 *      Also, remove the session from the cache so that
 
1020
                 *      the client can't re-use it.
789
1021
                 */
790
1022
        default:
 
1023
                if (inst->conf->session_cache_enable) { 
 
1024
                        SSL_CTX_remove_session(inst->ctx,
 
1025
                                               tls_session->ssl->session);
 
1026
                }
 
1027
 
791
1028
                return 0;
792
1029
        }
793
1030
 
794
1031
        /*
795
 
         *      Success: Return MPPE keys.
796
 
         */
797
 
        eaptls_success(handler->eap_ds, 0);
798
 
        eaptls_gen_mppe_keys(&handler->request->reply->vps,
799
 
                             tls_session->ssl,
800
 
                             "client EAP encryption");
801
 
        return 1;
 
1032
         *      New sessions cause some additional information to be
 
1033
         *      cached.
 
1034
         */
 
1035
        if (!SSL_session_reused(tls_session->ssl)) {
 
1036
                /*
 
1037
                 *      FIXME: Store miscellaneous data.
 
1038
                 */
 
1039
                RDEBUG2("Adding user data to cached session");
 
1040
                
 
1041
#if 0
 
1042
                SSL_SESSION_set_ex_data(tls_session->ssl->session,
 
1043
                                        ssl_session_idx_user_session, session_data);
 
1044
#endif
 
1045
        } else {
 
1046
                /*
 
1047
                 *      FIXME: Retrieve miscellaneous data.
 
1048
                 */
 
1049
#if 0
 
1050
                data = SSL_SESSION_get_ex_data(tls_session->ssl->session,
 
1051
                                               ssl_session_idx_user_session);
 
1052
 
 
1053
                if (!session_data) {
 
1054
                        radlog_request(L_ERR, 0, request,
 
1055
                                       "No user session data in cached session - "
 
1056
                                       " REJECTING");
 
1057
                        return 0;
 
1058
                }
 
1059
#endif
 
1060
 
 
1061
                RDEBUG2("Retrieved session data from cached session");
 
1062
        }
 
1063
 
 
1064
        /*
 
1065
         *      Success: Automatically return MPPE keys.
 
1066
         */
 
1067
        return eaptls_success(handler, 0);
802
1068
}
803
1069
 
804
1070
/*