Navigation


source: freeDiameter/libfdcore/config.c @ 706:4ffbc9f1e922

Last change on this file since 706:4ffbc9f1e922 was 706:4ffbc9f1e922, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 11 years ago

Large UNTESTED commit with the following changes:

  • Improved DiameterIdentity? handling (esp. interationalization issues), and improve efficiency of some string operations in peers, sessions, and dictionary modules (closes #7)
  • Cleanup in the session module to free only unreferenced sessions (#16)
  • Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
  • Improved peer state machine algorithm to counter SCTP multistream race condition.
File size: 20.1 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2011, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36#include "fdcore-internal.h"
37#include <sys/stat.h>
38
39/* Configuration management */
40
41#ifndef GNUTLS_DEFAULT_PRIORITY
42# define GNUTLS_DEFAULT_PRIORITY "NORMAL"
43#endif /* GNUTLS_DEFAULT_PRIORITY */
44#ifndef GNUTLS_DEFAULT_DHBITS
45# define GNUTLS_DEFAULT_DHBITS 1024
46#endif /* GNUTLS_DEFAULT_DHBITS */
47
48/* Initialize the fd_g_config structure to default values -- it should already have been initialized to all-0 */
49int fd_conf_init()
50{
51        TRACE_ENTRY();
52       
53        fd_g_config->cnf_eyec = EYEC_CONFIG;
54       
55        fd_g_config->cnf_timer_tc = 30;
56        fd_g_config->cnf_timer_tw = 30;
57       
58        fd_g_config->cnf_port     = 3868;
59        fd_g_config->cnf_port_tls = 3869;
60        fd_g_config->cnf_sctp_str = 30;
61        fd_g_config->cnf_dispthr  = 4;
62        fd_list_init(&fd_g_config->cnf_endpoints, NULL);
63        fd_list_init(&fd_g_config->cnf_apps, NULL);
64        #ifdef DISABLE_SCTP
65        fd_g_config->cnf_flags.no_sctp = 1;
66        #endif /* DISABLE_SCTP */
67       
68        fd_g_config->cnf_orstateid = (uint32_t) time(NULL);
69       
70        CHECK_FCT( fd_dict_init(&fd_g_config->cnf_dict) );
71        CHECK_FCT( fd_fifo_new(&fd_g_config->cnf_main_ev) );
72       
73        /* TLS parameters */
74        CHECK_GNUTLS_DO( gnutls_certificate_allocate_credentials (&fd_g_config->cnf_sec_data.credentials), return ENOMEM );
75        CHECK_GNUTLS_DO( gnutls_dh_params_init (&fd_g_config->cnf_sec_data.dh_cache), return ENOMEM );
76
77        return 0;
78}
79
80void fd_conf_dump()
81{
82        if (!TRACE_BOOL(INFO))
83                return;
84       
85        fd_log_debug("-- Configuration :\n");
86        fd_log_debug("  Debug trace level ...... : %+d\n", fd_g_debug_lvl);
87        fd_log_debug("  Configuration file ..... : %s\n", fd_g_config->cnf_file);
88        fd_log_debug("  Diameter Identity ...... : %s (l:%Zi)\n", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len);
89        fd_log_debug("  Diameter Realm ......... : %s (l:%Zi)\n", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len);
90        fd_log_debug("  Tc Timer ............... : %u\n", fd_g_config->cnf_timer_tc);
91        fd_log_debug("  Tw Timer ............... : %u\n", fd_g_config->cnf_timer_tw);
92        fd_log_debug("  Local port ............. : %hu\n", fd_g_config->cnf_port);
93        fd_log_debug("  Local secure port ...... : %hu\n", fd_g_config->cnf_port_tls);
94        fd_log_debug("  Number of SCTP streams . : %hu\n", fd_g_config->cnf_sctp_str);
95        fd_log_debug("  Number of server threads : %hu\n", fd_g_config->cnf_dispthr);
96        if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
97                fd_log_debug("  Local endpoints ........ : Default (use all available)\n");
98        } else {
99                fd_log_debug("  Local endpoints ........ : \n");
100                fd_ep_dump( 29, &fd_g_config->cnf_endpoints );
101        }
102        if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) {
103                fd_log_debug("  Local applications ..... : (none)\n");
104        } else {
105                struct fd_list * li = fd_g_config->cnf_apps.next;
106                fd_log_debug("  Local applications ..... : ");
107                while (li != &fd_g_config->cnf_apps) {
108                        struct fd_app * app = (struct fd_app *)li;
109                        if (li != fd_g_config->cnf_apps.next) fd_log_debug("                             ");
110                        fd_log_debug("App: %u\t%s%s\tVnd: %u\n", 
111                                        app->appid,
112                                        app->flags.auth ? "Au" : "--",
113                                        app->flags.acct ? "Ac" : "--",
114                                        app->vndid);
115                        li = li->next;
116                }
117        }
118       
119        fd_log_debug("  Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled");
120        fd_log_debug("          - IPv6 ......... : %s\n", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled");
121        fd_log_debug("          - Relay app .... : %s\n", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled");
122        fd_log_debug("          - TCP .......... : %s\n", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled");
123        #ifdef DISABLE_SCTP
124        fd_log_debug("          - SCTP ......... : DISABLED (at compilation)\n");
125        #else /* DISABLE_SCTP */
126        fd_log_debug("          - SCTP ......... : %s\n", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled");
127        #endif /* DISABLE_SCTP */
128        fd_log_debug("          - Pref. proto .. : %s\n", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP");
129        fd_log_debug("          - TLS method ... : %s\n", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port");
130       
131        fd_log_debug("  TLS :   - Certificate .. : %s\n", fd_g_config->cnf_sec_data.cert_file ?: "(NONE)");
132        fd_log_debug("          - Private key .. : %s\n", fd_g_config->cnf_sec_data.key_file ?: "(NONE)");
133        fd_log_debug("          - CA (trust) ... : %s (%d certs)\n", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr);
134        fd_log_debug("          - CRL .......... : %s\n", fd_g_config->cnf_sec_data.crl_file ?: "(none)");
135        fd_log_debug("          - Priority ..... : %s\n", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')");
136        if (fd_g_config->cnf_sec_data.dh_file)
137                fd_log_debug("          - DH file ...... : %s\n", fd_g_config->cnf_sec_data.dh_file);
138        else
139                fd_log_debug("          - DH bits ...... : %d\n", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
140       
141        fd_log_debug("  Origin-State-Id ........ : %u\n", fd_g_config->cnf_orstateid);
142}
143
144/* Parse the configuration file (using the yacc parser) */
145int fd_conf_parse()
146{
147        extern FILE * fddin;
148        char * orig = NULL;
149       
150        /* Attempt to find the configuration file */
151        if (!fd_g_config->cnf_file)
152                fd_g_config->cnf_file = FD_DEFAULT_CONF_FILENAME;
153       
154        fddin = fopen(fd_g_config->cnf_file, "r");
155        if ((fddin == NULL) && (*fd_g_config->cnf_file != '/')) {
156                /* We got a relative path, attempt to add the default directory prefix */
157                orig = fd_g_config->cnf_file;
158                CHECK_MALLOC( fd_g_config->cnf_file = malloc(strlen(orig) + strlen(DEFAULT_CONF_PATH) + 2) ); /* we will not free it, but not important */
159                sprintf( fd_g_config->cnf_file, DEFAULT_CONF_PATH "/%s", orig );
160                fddin = fopen(fd_g_config->cnf_file, "r");
161        }
162        if (fddin == NULL) {
163                int ret = errno;
164                if (orig) {
165                        fprintf(stderr, "Unable to open configuration file for reading\n"
166                                        "Tried the following locations:\n"
167                                        " - %s\n"
168                                        " - %s\n"
169                                        "Error: %s\n", orig, fd_g_config->cnf_file, strerror(ret));
170                } else {
171                        fprintf(stderr, "Unable to open '%s' for reading: %s\n", fd_g_config->cnf_file, strerror(ret));
172                }
173                return ret;
174        }
175       
176        /* call yacc parser */
177        TRACE_DEBUG (FULL, "Parsing configuration file: %s", fd_g_config->cnf_file);
178        CHECK_FCT(  fddparse(fd_g_config)  );
179       
180        /* close the file */
181        fclose(fddin);
182       
183        /* Check that TLS private key was given */
184        if (! fd_g_config->cnf_sec_data.key_file) {
185                fprintf(stderr, "Missing private key configuration for TLS. Please provide the TLS_cred configuration directive.\n");
186                return EINVAL;
187        }
188       
189        /* If the CA is not provided, let's use the same file (assuming self-signed certificate) */
190        if (! fd_g_config->cnf_sec_data.ca_file) {
191                CHECK_MALLOC( fd_g_config->cnf_sec_data.ca_file = strdup(fd_g_config->cnf_sec_data.cert_file) );
192                CHECK_GNUTLS_DO( fd_g_config->cnf_sec_data.ca_file_nr += gnutls_certificate_set_x509_trust_file( 
193                                        fd_g_config->cnf_sec_data.credentials,
194                                        fd_g_config->cnf_sec_data.ca_file,
195                                        GNUTLS_X509_FMT_PEM),
196                                { 
197                                        TRACE_DEBUG(INFO, "Unable to use the local certificate as trusted security anchor (CA), please provide a valid TLS_CA='...' directive.");
198                                        return EINVAL;
199                                } );
200        }
201       
202       
203        /* Resolve hostname if not provided */
204        if (fd_g_config->cnf_diamid == NULL) {
205                char buf[HOST_NAME_MAX + 1];
206                struct addrinfo hints, *info;
207                int ret;
208               
209                /* local host name */
210                CHECK_SYS(gethostname(buf, sizeof(buf)));
211               
212                /* get FQDN */
213                memset(&hints, 0, sizeof hints);
214                hints.ai_flags = AI_CANONNAME;
215
216                ret = getaddrinfo(buf, NULL, &hints, &info);
217                if (ret != 0) {
218                        fprintf(stderr, "Error resolving local FQDN :\n"
219                                        " '%s' : %s\n"
220                                        "Please provide Identity in configuration file.\n",
221                                        buf, gai_strerror(ret));
222                        return EINVAL;
223                }
224                fd_g_config->cnf_diamid = info->ai_canonname;
225                CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamid, &fd_g_config->cnf_diamid_len, 1) );
226                freeaddrinfo(info);
227        } else {
228                CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamid, &fd_g_config->cnf_diamid_len, 0) );
229        }
230       
231        /* Handle the realm part */
232        if (fd_g_config->cnf_diamrlm == NULL) {
233                char * start = NULL;
234               
235                /* Check the diameter identity is a fqdn */
236                start = strchr(fd_g_config->cnf_diamid, '.');
237                if ((start == NULL) || (start[1] == '\0')) {
238                        fprintf(stderr, "Unable to extract realm from the Identity '%s'.\n"
239                                        "Please fix your Identity setting or provide Realm.\n",
240                                        fd_g_config->cnf_diamid);
241                        return EINVAL;
242                }
243               
244                fd_g_config->cnf_diamrlm = start + 1;
245                CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamrlm, &fd_g_config->cnf_diamrlm_len, 1) );
246        } else {
247                CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamrlm, &fd_g_config->cnf_diamrlm_len, 0) );
248        }
249       
250        /* Validate some flags */
251        if (fd_g_config->cnf_flags.no_ip4 && fd_g_config->cnf_flags.no_ip6) {
252                fprintf(stderr, "IP and IPv6 cannot be disabled at the same time.\n");
253                return EINVAL;
254        }
255        if (fd_g_config->cnf_flags.no_tcp && fd_g_config->cnf_flags.no_sctp) {
256                fprintf(stderr, "TCP and SCTP cannot be disabled at the same time.\n");
257                return EINVAL;
258        }
259       
260        /* Validate local endpoints */
261        if ((!FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) && (fd_g_config->cnf_flags.no_ip4 || fd_g_config->cnf_flags.no_ip6)) {
262                struct fd_list * li;
263                for ( li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
264                        struct fd_endpoint * ep = (struct fd_endpoint *)li;
265                        if ( (fd_g_config->cnf_flags.no_ip4 && (ep->sa.sa_family == AF_INET))
266                           ||(fd_g_config->cnf_flags.no_ip6 && (ep->sa.sa_family == AF_INET6)) ) {
267                                li = li->prev;
268                                fd_list_unlink(&ep->chain);
269                                if (TRACE_BOOL(INFO)) {
270                                        fd_log_debug("Info: Removing local address conflicting with the flags no_IP / no_IP6 : ");
271                                        sSA_DUMP_NODE( &ep->sa, NI_NUMERICHOST );
272                                        fd_log_debug("\n");
273                                }
274                                free(ep);
275                        }
276                }
277        }
278       
279        /* Configure TLS default parameters */
280        if (! fd_g_config->cnf_sec_data.prio_string) {
281                const char * err_pos = NULL;
282                CHECK_GNUTLS_DO( gnutls_priority_init( 
283                                        &fd_g_config->cnf_sec_data.prio_cache,
284                                        GNUTLS_DEFAULT_PRIORITY,
285                                        &err_pos),
286                                 { TRACE_DEBUG(INFO, "Error in priority string at position : %s", err_pos); return EINVAL; } );
287        }
288       
289        /* Verify that our certificate is valid -- otherwise remote peers will reject it */
290        {
291                int ret = 0, i;
292               
293                gnutls_datum_t certfile;
294                size_t alloc = 0;
295               
296                gnutls_x509_crt_t * certs = NULL;
297                unsigned int cert_max = 0;
298               
299                gnutls_x509_crt_t * CA_list;
300                int CA_list_length;
301               
302                gnutls_x509_crl_t * CRL_list;
303                int CRL_list_length;
304               
305                unsigned int verify;
306                time_t now;
307               
308                memset(&certfile, 0, sizeof(certfile));
309               
310                /* Read the certificate file */
311                FILE *stream = fopen (fd_g_config->cnf_sec_data.cert_file, "rb");
312                if (!stream) {
313                        int err = errno;
314                        TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s\n", fd_g_config->cnf_sec_data.cert_file, strerror(err));
315                        return err; 
316                }
317                do {
318                        uint8_t * realloced = NULL;
319                        size_t read = 0;
320                       
321                        if (alloc < certfile.size + BUFSIZ + 1) {
322                                alloc += alloc / 2 + BUFSIZ + 1;
323                                CHECK_MALLOC_DO( realloced = realloc(certfile.data, alloc),
324                                        {
325                                                free(certfile.data);
326                                                return ENOMEM;
327                                        } )
328                                certfile.data = realloced;
329                        }
330                       
331                        read = fread( certfile.data + certfile.size, 1, alloc - certfile.size - 1, stream );
332                        certfile.size += read;
333                       
334                        if (ferror(stream)) {
335                                int err = errno;
336                                TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s\n", fd_g_config->cnf_sec_data.cert_file, strerror(err));
337                                return err; 
338                        }
339                } while (!feof(stream));
340                certfile.data[certfile.size] = '\0';
341                fclose(stream);
342               
343                /* Import the certificate(s) */
344                GNUTLS_TRACE( ret = gnutls_x509_crt_list_import(NULL, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) );
345                if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
346                        CHECK_GNUTLS_DO(ret, return EINVAL);
347                }
348               
349                CHECK_MALLOC( certs = calloc(cert_max, sizeof(gnutls_x509_crt_t)) );
350                CHECK_GNUTLS_DO( gnutls_x509_crt_list_import(certs, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, 0),
351                        {
352                                TRACE_DEBUG(INFO, "Failed to import the data from file '%s'", fd_g_config->cnf_sec_data.cert_file);
353                                free(certfile.data);
354                                return EINVAL;
355                        } );
356                free(certfile.data);
357               
358                ASSERT(cert_max >= 1);
359               
360                /* Now, verify the list against the local CA and CRL */
361                GNUTLS_TRACE( gnutls_certificate_get_x509_cas (fd_g_config->cnf_sec_data.credentials, &CA_list, (unsigned int *) &CA_list_length) );
362                GNUTLS_TRACE( gnutls_certificate_get_x509_crls (fd_g_config->cnf_sec_data.credentials, &CRL_list, (unsigned int *) &CRL_list_length) );
363                CHECK_GNUTLS_DO( gnutls_x509_crt_list_verify(certs, cert_max, CA_list, CA_list_length, CRL_list, CRL_list_length, 0, &verify),
364                        {
365                                TRACE_DEBUG(INFO, "Failed to verify the local certificate '%s' against local credentials. Please check your certificate is valid.", fd_g_config->cnf_sec_data.cert_file);
366                                return EINVAL;
367                        } );
368                if (verify) {
369                        fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
370                        if (verify & GNUTLS_CERT_INVALID)
371                                fd_log_debug(" - The certificate is not trusted (unknown CA? expired?)\n");
372                        if (verify & GNUTLS_CERT_REVOKED)
373                                fd_log_debug(" - The certificate has been revoked.\n");
374                        if (verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
375                                fd_log_debug(" - The certificate hasn't got a known issuer.\n");
376                        if (verify & GNUTLS_CERT_SIGNER_NOT_CA)
377                                fd_log_debug(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.\n");
378                        if (verify & GNUTLS_CERT_INSECURE_ALGORITHM)
379                                fd_log_debug(" - The certificate signature uses a weak algorithm.\n");
380                        return EINVAL;
381                }
382       
383                /* Check the local Identity is valid with the certificate */
384                if (!gnutls_x509_crt_check_hostname (certs[0], fd_g_config->cnf_diamid)) {
385                        fd_log_debug("TLS: Local certificate '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
386                        fd_log_debug(" - The certificate hostname does not match '%s'\n", fd_g_config->cnf_diamid);
387                        return EINVAL;
388                }
389               
390                /* Check validity of all the certificates in the chain */
391                now = time(NULL);
392                for (i = 0; i < cert_max; i++)
393                {
394                        time_t deadline;
395
396                        GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(certs[i]) );
397                        if ((deadline != (time_t)-1) && (deadline < now)) {
398                                fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
399                                fd_log_debug(" - The certificate %d in the chain is expired\n", i);
400                                return EINVAL;
401                        }
402
403                        GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(certs[i]) );
404                        if ((deadline != (time_t)-1) && (deadline > now)) {
405                                fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
406                                fd_log_debug(" - The certificate %d in the chain is not yet activated\n", i);
407                                return EINVAL;
408                        }
409                }
410               
411                /* Everything checked OK, free the certificate list */
412                for (i = 0; i < cert_max; i++)
413                {
414                        GNUTLS_TRACE( gnutls_x509_crt_deinit (certs[i]) );
415                }
416                free(certs);
417        }
418       
419       
420        /* gnutls_certificate_set_verify_limits -- so far the default values are fine... */
421       
422        /* DH */
423        if (fd_g_config->cnf_sec_data.dh_file) {
424                gnutls_datum_t dhparams = { NULL, 0 };
425                size_t alloc = 0;
426                FILE *stream = fopen (fd_g_config->cnf_sec_data.dh_file, "rb");
427                if (!stream) {
428                        int err = errno;
429                        TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s\n", fd_g_config->cnf_sec_data.dh_file, strerror(err));
430                        return err; 
431                }
432                do {
433                        uint8_t * realloced = NULL;
434                        size_t read = 0;
435                       
436                        if (alloc < dhparams.size + BUFSIZ + 1) {
437                                alloc += alloc / 2 + BUFSIZ + 1;
438                                CHECK_MALLOC_DO( realloced = realloc(dhparams.data, alloc),
439                                        {
440                                                free(dhparams.data);
441                                                return ENOMEM;
442                                        } )
443                                dhparams.data = realloced;
444                        }
445                       
446                        read = fread( dhparams.data + dhparams.size, 1, alloc - dhparams.size - 1, stream );
447                        dhparams.size += read;
448                       
449                        if (ferror(stream)) {
450                                int err = errno;
451                                TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s\n", fd_g_config->cnf_sec_data.dh_file, strerror(err));
452                                return err; 
453                        }
454                } while (!feof(stream));
455                dhparams.data[dhparams.size] = '\0';
456                fclose(stream);
457                CHECK_GNUTLS_DO( gnutls_dh_params_import_pkcs3( 
458                                        fd_g_config->cnf_sec_data.dh_cache,
459                                        &dhparams,
460                                        GNUTLS_X509_FMT_PEM),
461                                         { TRACE_DEBUG(INFO, "Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
462                free(dhparams.data);
463               
464        } else {
465                TRACE_DEBUG(INFO, "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
466                CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
467                                        fd_g_config->cnf_sec_data.dh_cache,
468                                        fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS),
469                                         { TRACE_DEBUG(INFO, "Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
470        }                       
471       
472        return 0;
473}
474
475
476/* Destroy contents of fd_g_config structure */
477int fd_conf_deinit()
478{
479        TRACE_ENTRY();
480       
481        if (!fd_g_config)
482                return 0;
483       
484        /* Free the TLS parameters */
485        gnutls_priority_deinit(fd_g_config->cnf_sec_data.prio_cache);
486        gnutls_dh_params_deinit(fd_g_config->cnf_sec_data.dh_cache);
487        gnutls_certificate_free_credentials(fd_g_config->cnf_sec_data.credentials);
488       
489        free(fd_g_config->cnf_sec_data.cert_file); fd_g_config->cnf_sec_data.cert_file = NULL;
490        free(fd_g_config->cnf_sec_data.key_file); fd_g_config->cnf_sec_data.key_file = NULL;
491        free(fd_g_config->cnf_sec_data.ca_file); fd_g_config->cnf_sec_data.ca_file = NULL;
492        free(fd_g_config->cnf_sec_data.crl_file); fd_g_config->cnf_sec_data.crl_file = NULL;
493        free(fd_g_config->cnf_sec_data.prio_string); fd_g_config->cnf_sec_data.prio_string = NULL;
494        free(fd_g_config->cnf_sec_data.dh_file); fd_g_config->cnf_sec_data.dh_file = NULL;
495       
496        /* Destroy dictionary */
497        CHECK_FCT_DO( fd_dict_fini(&fd_g_config->cnf_dict), );
498       
499        /* Destroy the main event queue */
500        CHECK_FCT_DO( fd_fifo_del(&fd_g_config->cnf_main_ev), );
501       
502        /* Destroy the local endpoints and applications */
503        CHECK_FCT_DO(fd_ep_filter(&fd_g_config->cnf_endpoints, 0 ), );
504        CHECK_FCT_DO(fd_app_empty(&fd_g_config->cnf_apps ), );
505       
506        /* Destroy the local identity */       
507        free(fd_g_config->cnf_diamid); fd_g_config->cnf_diamid = NULL;
508        free(fd_g_config->cnf_diamrlm); fd_g_config->cnf_diamrlm = NULL;
509       
510        return 0;
511}
512
513
Note: See TracBrowser for help on using the repository browser.