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 = {
129 tmp_ctx = talloc_new(mp7);
130 if (tmp_ctx == NULL) {
134 rc = mscat_read_file(tmp_ctx,
138 DBG_ERR("Failed to read catalog file '%s' - %s",
144 mscat_data.data = blob.data;
145 mscat_data.size = blob.length;
147 rc = gnutls_pkcs7_import(mp7->c,
149 GNUTLS_X509_FMT_DER);
151 DBG_ERR("Failed to import PKCS7 from '%s' - %s",
153 gnutls_strerror(rc));
159 talloc_free(tmp_ctx);
163 int mscat_pkcs7_verify(struct mscat_pkcs7 *mp7,
166 TALLOC_CTX *tmp_ctx = NULL;
167 gnutls_x509_trust_list_t tl = NULL;
168 gnutls_datum_t ca_data;
179 oid = gnutls_pkcs7_get_embedded_data_oid(mp7->c);
181 DBG_ERR("Failed to get oid - %s",
182 gnutls_strerror(errno));
186 cmp = strcmp(oid, PKCS7_CTL_OBJID);
188 DBG_ERR("Invalid oid in catalog file! oid: %s, expected: %s",
194 tmp_ctx = talloc_new(mp7);
195 if (tmp_ctx == NULL) {
199 rc = gnutls_x509_trust_list_init(&tl,
200 0); /* default size */
202 DBG_ERR("Failed to create trust list - %s",
203 gnutls_strerror(rc));
208 /* Load the system trust list */
209 rc = gnutls_x509_trust_list_add_system_trust(tl, 0, 0);
211 DBG_ERR("Failed to add system trust list - %s",
212 gnutls_strerror(rc));
215 DBG_INFO("Loaded %d CAs", rc);
217 if (ca_file != NULL) {
218 rc = mscat_read_file(tmp_ctx,
222 DBG_ERR("Failed to read CA file '%s' - %s",
228 ca_data.data = blob.data;
229 ca_data.size = blob.length;
231 rc = gnutls_x509_trust_list_add_trust_mem(tl,
238 DBG_ERR("Failed to add '%s' to trust list - %s (%d)",
244 DBG_INFO("Loaded %d additional CAs", rc);
248 * Drivers often exist for quite some time, so it is possible that one
249 * of the certificates in the trust list expired.
250 * This is not a big deal, but we need to disable the time checks
251 * or the verification will fail.
253 flags = GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS|
254 GNUTLS_VERIFY_DISABLE_TIME_CHECKS;
256 #if GNUTLS_VERSION_NUMBER >= 0x030600
257 /* The "Microsoft Root Authority" certificate uses SHA1 */
258 flags |= GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1;
261 count = gnutls_pkcs7_get_signature_count(mp7->c);
263 DBG_ERR("Failed to verify catalog file, no signatures found");
267 for (i = 0; i < count; i++) {
268 rc = gnutls_pkcs7_verify(mp7->c,
276 DBG_ERR("Failed to verify catalog file - %s (%d)",
285 gnutls_x509_trust_list_deinit(tl, 1);
286 talloc_free(tmp_ctx);