source: mod_gnutls/test/cert_helper.c @ e9e89b4

asynciodebian/masterdebian/stretch-backportsmainproxy-ticketupstream
Last change on this file since e9e89b4 was 3c123cd, checked in by Fiona Klute <fiona.klute@…>, 5 years ago

Update my name, prepare changelog for the next release

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/**
2 * Helper functions for certificate handling in the mod_gnutls test suite
3 *
4 * Copyright 2016 Fiona Klute
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you
7 * may not use this file except in compliance with the License.  You
8 * may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 * implied.  See the License for the specific language governing
16 * permissions and limitations under the License.
17 */
18#include <gnutls/gnutls.h>
19#include <gnutls/x509.h>
20
21#include <errno.h>
22#include <error.h>
23#include <fcntl.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <unistd.h>
30
31/* certificate buffer size in bytes when reading from STDIN */
32#define CERT_BUF_SIZE 10240
33
34
35
36/**
37 * Read the file "filename" into "cert", plus a NULL byte at the
38 * end. "filename" may be NULL, in that case input is read from
39 * stdin. The size field of data is set accordingly. The data field is
40 * allocated to the needed size, the caller must free it when no
41 * longer needed.
42 *
43 * Returns zero on success, or an error code (errno after the failed
44 * operation).
45 */
46size_t read_cert(const char* filename, gnutls_datum_t* cert)
47{
48    size_t bufsize = CERT_BUF_SIZE;
49    int certfile = STDIN_FILENO;
50
51    if (filename)
52    {
53        certfile = open(filename, O_RDONLY);
54        if (certfile == -1)
55        {
56            error(0, errno, "opening certificate file %s failed",
57                  filename);
58            return errno;
59        }
60        struct stat filestat;
61        if (fstat(certfile, &filestat))
62        {
63            error(0, errno, "fstat on certificate file failed");
64            return errno;
65        }
66        /* buffer size with one extra byte for NULL termination */
67        bufsize = filestat.st_size + 1;
68    }
69
70    cert->data = malloc(bufsize);
71    if (!cert->data)
72    {
73        error(0, errno, "allocating certificate buffer failed");
74        return errno;
75    }
76
77    size_t readbytes = 0;
78    ssize_t r = 0;
79    do
80    {
81        r = read(certfile, (cert->data + readbytes),
82                 (bufsize - 1 - readbytes));
83        if (r > 0)
84            readbytes += r;
85    }
86    while (r > 0 || r == EINTR);
87
88    /* report error, if any */
89    if (r < 0)
90    {
91        error(0, errno, "reading certificate file failed");
92        free(cert->data);
93        cert->data = NULL;
94        cert->size = 0;
95        return errno;
96    }
97
98    /* add terminating NULL byte and trim buffer to required size */
99    cert->data[readbytes] = '\0';
100    cert->size = readbytes + 1;
101    cert->data = realloc(cert->data, cert->size);
102    if (!cert->data)
103    {
104        error(0, errno, "trimming certificate buffer failed");
105        return errno;
106    }
107
108    /* close file if not reading from STDIN */
109    if (filename)
110        close(certfile);
111
112    return GNUTLS_E_SUCCESS;
113}
114
115
116
117/**
118 * Transform a DER encoded X.509 certificate to PEM using GnuTLS
119 * import/export functions. The caller is responsible for releasing
120 * the returned data structure when it is no longer needed. A return
121 * value of NULL indicates an error.
122 */
123gnutls_datum_t* der_to_pem(const gnutls_datum_t* der)
124{
125    gnutls_x509_crt_t cert;
126    gnutls_datum_t* pem = calloc(1, sizeof(gnutls_datum_t));
127
128    gnutls_x509_crt_init(&cert);
129    int rv = gnutls_x509_crt_import(cert, der, GNUTLS_X509_FMT_DER);
130
131    if (rv == GNUTLS_E_SUCCESS)
132    {
133        size_t s = CERT_BUF_SIZE;
134        pem->data = malloc(s);
135        rv = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, pem->data, &s);
136        pem->size = s;
137    }
138
139    if (rv != GNUTLS_E_SUCCESS)
140    {
141        fprintf(stderr, "certificate transformation failed: %s\n",
142                gnutls_strerror(rv));
143        free(pem->data);
144        free(pem);
145        pem = NULL;
146    }
147
148    gnutls_x509_crt_deinit(cert);
149    return pem;
150}
Note: See TracBrowser for help on using the repository browser.