Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/lib/tls/tlscert.c
Line
Count
Source
1
/* 
2
   Unix SMB/CIFS implementation.
3
4
   auto-generate self signed TLS certificates
5
6
   Copyright (C) Andrew Tridgell 2005
7
   
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
   
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
   
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22
#include "includes.h"
23
#include "lib/util/util_file.h"
24
#include "lib/tls/tls.h"
25
26
#include <gnutls/gnutls.h>
27
#include <gnutls/x509.h>
28
29
#define ORGANISATION_NAME "Samba Administration"
30
#define CA_NAME           "Samba - temporary autogenerated CA certificate"
31
#define UNIT_NAME         "Samba - temporary autogenerated HOST certificate"
32
0
#define LIFETIME          700*24*60*60
33
34
/* FIPS140-2 only allows 2048 or 3072 prime sizes. */
35
#define RSA_BITS gnutls_fips140_mode_enabled() ? 3072 : 4096
36
37
/* 
38
   auto-generate a set of self signed certificates
39
*/
40
void tls_cert_generate(TALLOC_CTX *mem_ctx, 
41
           const char *hostname, 
42
           const char * const *additional_hostnames,
43
           const char *keyfile, const char *certfile,
44
           const char *cafile)
45
0
{
46
0
  gnutls_x509_crt_t cacrt, crt;
47
0
  gnutls_x509_privkey_t key, cakey;
48
0
  uint8_t serial[8];
49
0
  unsigned char keyid[100];
50
0
  char buf[4096];
51
0
  size_t bufsize;
52
0
  size_t keyidsize = sizeof(keyid);
53
0
  time_t activation = time(NULL), expiry = activation + LIFETIME;
54
0
  size_t adhn_idx;
55
0
  int ret;
56
57
0
  if (file_exist(keyfile) || file_exist(certfile) || file_exist(cafile)) {
58
0
    DEBUG(0,("TLS autogeneration skipped - some TLS files already exist\n"));
59
0
    return;
60
0
  }
61
62
0
#define TLSCHECK(call) do { \
63
0
  ret = call; \
64
0
  if (ret < 0) { \
65
0
    DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \
66
0
    goto failed; \
67
0
  } \
68
0
} while (0)
69
70
0
  DEBUG(0,("Attempting to autogenerate TLS self-signed keys for https for hostname '%s'\n", 
71
0
     hostname));
72
73
0
  DEBUG(3,("Generating private key\n"));
74
0
  TLSCHECK(gnutls_x509_privkey_init(&key));
75
0
  TLSCHECK(gnutls_x509_privkey_generate(key,   GNUTLS_PK_RSA, RSA_BITS, 0));
76
77
0
  DEBUG(3,("Generating CA private key\n"));
78
0
  TLSCHECK(gnutls_x509_privkey_init(&cakey));
79
0
  TLSCHECK(gnutls_x509_privkey_generate(cakey, GNUTLS_PK_RSA, RSA_BITS, 0));
80
81
0
  DEBUG(3,("Generating CA certificate\n"));
82
0
  TLSCHECK(gnutls_x509_crt_init(&cacrt));
83
0
  TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt, 
84
0
              GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
85
0
              ORGANISATION_NAME, strlen(ORGANISATION_NAME)));
86
0
  TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt, 
87
0
              GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0,
88
0
              CA_NAME, strlen(CA_NAME)));
89
0
  TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt,
90
0
              GNUTLS_OID_X520_COMMON_NAME, 0,
91
0
              hostname, strlen(hostname)));
92
0
  TLSCHECK(gnutls_x509_crt_set_key(cacrt, cakey));
93
94
0
  PUSH_BE_U64(serial, 0, time(NULL));
95
0
  TLSCHECK(gnutls_x509_crt_set_serial(cacrt, &serial, sizeof(serial)));
96
97
0
  TLSCHECK(gnutls_x509_crt_set_activation_time(cacrt, activation));
98
0
  TLSCHECK(gnutls_x509_crt_set_expiration_time(cacrt, expiry));
99
0
  TLSCHECK(gnutls_x509_crt_set_ca_status(cacrt, 1));
100
0
  TLSCHECK(gnutls_x509_crt_set_key_usage(cacrt, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN));
101
0
  TLSCHECK(gnutls_x509_crt_set_version(cacrt, 3));
102
0
  TLSCHECK(gnutls_x509_crt_get_key_id(cacrt, 0, keyid, &keyidsize));
103
0
  TLSCHECK(gnutls_x509_crt_set_subject_key_id(cacrt, keyid, keyidsize));
104
0
  TLSCHECK(gnutls_x509_crt_sign2(cacrt, cacrt, cakey,
105
0
               GNUTLS_DIG_SHA256, 0));
106
107
0
  DEBUG(3,("Generating TLS certificate\n"));
108
0
  TLSCHECK(gnutls_x509_crt_init(&crt));
109
0
  TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt, 
110
0
              GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
111
0
              ORGANISATION_NAME, strlen(ORGANISATION_NAME)));
112
0
  TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt, 
113
0
              GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0,
114
0
              UNIT_NAME, strlen(UNIT_NAME)));
115
0
  TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt,
116
0
              GNUTLS_OID_X520_COMMON_NAME, 0,
117
0
              hostname, strlen(hostname)));
118
0
  TLSCHECK(gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
119
0
                  hostname, strlen(hostname),
120
0
                  GNUTLS_FSAN_SET));
121
0
  for (adhn_idx = 0;
122
0
       additional_hostnames != NULL &&
123
0
       additional_hostnames[adhn_idx] != NULL;
124
0
       adhn_idx++)
125
0
  {
126
0
    const char *adhn = additional_hostnames[adhn_idx];
127
128
0
    TLSCHECK(gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
129
0
                    adhn, strlen(adhn),
130
0
                    GNUTLS_FSAN_APPEND));
131
0
  }
132
0
  TLSCHECK(gnutls_x509_crt_set_key(crt, key));
133
0
  TLSCHECK(gnutls_x509_crt_set_serial(crt, &serial, sizeof(serial)));
134
0
  TLSCHECK(gnutls_x509_crt_set_activation_time(crt, activation));
135
0
  TLSCHECK(gnutls_x509_crt_set_expiration_time(crt, expiry));
136
0
  TLSCHECK(gnutls_x509_crt_set_ca_status(crt, 0));
137
0
  TLSCHECK(gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0));
138
0
  TLSCHECK(gnutls_x509_crt_set_version(crt, 3));
139
0
  TLSCHECK(gnutls_x509_crt_get_key_id(crt, 0, keyid, &keyidsize));
140
0
  TLSCHECK(gnutls_x509_crt_set_subject_key_id(crt, keyid, keyidsize));
141
0
  TLSCHECK(gnutls_x509_crt_sign2(crt, crt, key,
142
0
               GNUTLS_DIG_SHA256, 0));
143
0
  TLSCHECK(gnutls_x509_crt_sign2(crt, cacrt, cakey,
144
0
               GNUTLS_DIG_SHA256, 0));
145
146
0
  DEBUG(3,("Exporting TLS keys\n"));
147
148
0
  bufsize = sizeof(buf);
149
0
  TLSCHECK(gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buf, &bufsize));
150
0
  if (!file_save(certfile, buf, bufsize)) {
151
0
    DEBUG(0,("Unable to save certificate in %s parent dir exists ?\n", certfile));
152
0
    goto failed;
153
0
  }
154
155
0
  bufsize = sizeof(buf);
156
0
  TLSCHECK(gnutls_x509_crt_export(cacrt, GNUTLS_X509_FMT_PEM, buf, &bufsize));
157
0
  if (!file_save(cafile, buf, bufsize)) {
158
0
    DEBUG(0,("Unable to save ca cert in %s parent dir exists ?\n", cafile));
159
0
    goto failed;
160
0
  }
161
162
0
  bufsize = sizeof(buf);
163
0
  TLSCHECK(gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buf, &bufsize));
164
0
  if (!file_save_mode(keyfile, buf, bufsize, 0600)) {
165
0
    DEBUG(0,("Unable to save privatekey in %s parent dir exists ?\n", keyfile));
166
0
    goto failed;
167
0
  }
168
169
0
  gnutls_x509_privkey_deinit(key);
170
0
  gnutls_x509_privkey_deinit(cakey);
171
0
  gnutls_x509_crt_deinit(cacrt);
172
0
  gnutls_x509_crt_deinit(crt);
173
174
0
  DEBUG(0,("TLS self-signed keys generated OK\n"));
175
0
  return;
176
177
0
failed:
178
  DEBUG(0,("TLS certificate generation failed\n"));
179
0
}