2 * Copyright (c) 2016 Andreas Schneider <asn@samba.org>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/types.h>
25 #include <util/debug.h>
26 #include <util/data_blob.h>
29 #include "mscat_private.h"
31 #define PKCS7_CTL_OBJID "1.3.6.1.4.1.311.10.1"
33 static int mscat_pkcs7_cleanup(struct mscat_pkcs7 *mp7)
36 gnutls_pkcs7_deinit(mp7->c);
42 struct mscat_pkcs7 *mscat_pkcs7_init(TALLOC_CTX *mem_ctx)
44 struct mscat_pkcs7 *pkcs7;
47 pkcs7 = talloc_zero(mem_ctx, struct mscat_pkcs7);
51 talloc_set_destructor(pkcs7, mscat_pkcs7_cleanup);
53 rc = gnutls_pkcs7_init(&pkcs7->c);
62 static int mscat_read_file(TALLOC_CTX *mem_ctx,
69 DATA_BLOB blob = data_blob_null;
73 fp = fopen(filename, "r");
78 rc = fstat(fileno(fp), &sb);
83 if (!S_ISREG(sb.st_mode)) {
88 if (SIZE_MAX - 1 < (unsigned long)sb.st_size) {
93 alloc_size = sb.st_size + 1;
95 blob = data_blob_talloc_zero(mem_ctx, alloc_size);
96 if (blob.data == NULL) {
101 count = fread(blob.data, 1, blob.length, fp);
102 if (count != blob.length) {
108 blob.data[count] = '\0';
116 data_blob_free(&blob);
121 int mscat_pkcs7_import_catfile(struct mscat_pkcs7 *mp7,
125 gnutls_datum_t mscat_data = {
133 tmp_ctx = talloc_new(mp7);
134 if (tmp_ctx == NULL) {
138 rc = mscat_read_file(tmp_ctx,
142 DBG_ERR("Failed to read catalog file '%s' - %s",
148 mscat_data.data = blob.data;
149 mscat_data.size = blob.length;
151 rc = gnutls_pkcs7_import(mp7->c,
153 GNUTLS_X509_FMT_DER);
155 DBG_ERR("Failed to import PKCS7 from '%s' - %s",
157 gnutls_strerror(rc));
163 talloc_free(tmp_ctx);
167 int mscat_pkcs7_verify(struct mscat_pkcs7 *mp7,
170 TALLOC_CTX *tmp_ctx = NULL;
171 gnutls_x509_trust_list_t tl = NULL;
172 gnutls_datum_t ca_data;
183 oid = gnutls_pkcs7_get_embedded_data_oid(mp7->c);
185 DBG_ERR("Failed to get oid - %s",
186 gnutls_strerror(errno));
190 cmp = strcmp(oid, PKCS7_CTL_OBJID);
192 DBG_ERR("Invalid oid in catalog file! oid: %s, expected: %s",
198 tmp_ctx = talloc_new(mp7);
199 if (tmp_ctx == NULL) {
203 rc = gnutls_x509_trust_list_init(&tl,
204 0); /* default size */
206 DBG_ERR("Failed to create trust list - %s",
207 gnutls_strerror(rc));
212 /* Load the system trust list */
213 rc = gnutls_x509_trust_list_add_system_trust(tl, 0, 0);
215 DBG_ERR("Failed to add system trust list - %s",
216 gnutls_strerror(rc));
219 DBG_INFO("Loaded %d CAs", rc);
221 if (ca_file != NULL) {
222 rc = mscat_read_file(tmp_ctx,
226 DBG_ERR("Failed to read CA file '%s' - %s",
232 ca_data.data = blob.data;
233 ca_data.size = blob.length;
235 rc = gnutls_x509_trust_list_add_trust_mem(tl,
242 DBG_ERR("Failed to add '%s' to trust list - %s (%d)",
248 DBG_INFO("Loaded %d additional CAs", rc);
252 * Drivers often exist for quite some time, so it is possible that one
253 * of the certificates in the trust list expired.
254 * This is not a big deal, but we need to disable the time checks
255 * or the verification will fail.
257 flags = GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS|
258 GNUTLS_VERIFY_DISABLE_TIME_CHECKS;
260 #if GNUTLS_VERSION_NUMBER >= 0x030600
261 /* The "Microsoft Root Authority" certificate uses SHA1 */
262 flags |= GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1;
265 count = gnutls_pkcs7_get_signature_count(mp7->c);
267 DBG_ERR("Failed to verify catalog file, no signatures found");
271 for (i = 0; i < count; i++) {
272 rc = gnutls_pkcs7_verify(mp7->c,
280 DBG_ERR("Failed to verify catalog file - %s (%d)",
289 gnutls_x509_trust_list_deinit(tl, 1);
290 talloc_free(tmp_ctx);