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