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,
73 fp = fopen(filename, "r");
78 rc = fstat(fileno(fp), &sb);
83 if (!S_ISREG(sb.st_mode)) {
87 if (SIZE_MAX - 1 < (unsigned long)sb.st_size) {
91 alloc_size = sb.st_size + 1;
93 blob = data_blob_talloc_zero(mem_ctx, alloc_size);
94 if (blob.data == NULL) {
98 count = fread(blob.data, 1, blob.length, fp);
99 if (count != blob.length) {
104 blob.data[count] = '\0';
112 data_blob_free(&blob);
117 int mscat_pkcs7_import_catfile(struct mscat_pkcs7 *mp7,
121 gnutls_datum_t mscat_data = {
127 tmp_ctx = talloc_new(mp7);
128 if (tmp_ctx == NULL) {
132 rc = mscat_read_file(tmp_ctx,
136 DBG_ERR("Failed to read catalog file '%s' - %s",
142 mscat_data.data = blob.data;
143 mscat_data.size = blob.length;
145 rc = gnutls_pkcs7_import(mp7->c,
147 GNUTLS_X509_FMT_DER);
149 DBG_ERR("Failed to import PKCS7 from '%s' - %s",
151 gnutls_strerror(rc));
157 talloc_free(tmp_ctx);
161 int mscat_pkcs7_verify(struct mscat_pkcs7 *mp7,
164 TALLOC_CTX *tmp_ctx = NULL;
165 gnutls_x509_trust_list_t tl = NULL;
166 gnutls_datum_t ca_data;
175 oid = gnutls_pkcs7_get_embedded_data_oid(mp7->c);
177 DBG_ERR("Failed to get oid - %s",
178 gnutls_strerror(errno));
182 cmp = strcmp(oid, PKCS7_CTL_OBJID);
184 DBG_ERR("Invalid oid in catalog file! oid: %s, expected: %s",
190 tmp_ctx = talloc_new(mp7);
191 if (tmp_ctx == NULL) {
195 rc = gnutls_x509_trust_list_init(&tl,
196 0); /* default size */
198 DBG_ERR("Failed to create trust list - %s",
199 gnutls_strerror(rc));
204 /* Load the system trust list */
205 rc = gnutls_x509_trust_list_add_system_trust(tl, 0, 0);
207 DBG_ERR("Failed to add system trust list - %s",
208 gnutls_strerror(rc));
211 DBG_INFO("Loaded %d CAs", rc);
213 if (ca_file != NULL) {
214 rc = mscat_read_file(tmp_ctx,
218 DBG_ERR("Failed to read CA file '%s' - %s",
224 ca_data.data = blob.data;
225 ca_data.size = blob.length;
227 rc = gnutls_x509_trust_list_add_trust_mem(tl,
234 DBG_ERR("Failed to add '%s' to trust list - %s (%d)",
240 DBG_INFO("Loaded %d additional CAs", rc);
244 * Drivers often exist for quite some time, so it is possible that one
245 * of the certificates in the trust list expired.
246 * This is not a big deal, but we need to disable the time checks
247 * or the verification will fail.
249 flags = GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS|
250 GNUTLS_VERIFY_DISABLE_TIME_CHECKS;
252 #if GNUTLS_VERSION_NUMBER >= 0x030600
253 /* The "Microsoft Root Authority" certificate uses SHA1 */
254 flags |= GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1;
257 count = gnutls_pkcs7_get_signature_count(mp7->c);
259 DBG_ERR("Failed to verify catalog file, no signatures found");
263 for (i = 0; i < count; i++) {
264 rc = gnutls_pkcs7_verify(mp7->c,
272 DBG_ERR("Failed to verify catalog file - %s (%d)",
281 gnutls_x509_trust_list_deinit(tl, 1);
282 talloc_free(tmp_ctx);