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
);