41
41
#define SECBUFFER_ALERT 17
42
42
#endif
43
43
44
+ // `read_file_and_null_terminate` reads a file into a NUL-terminated string.
45
+ // On success: returns a NUL-terminated string and (optionally) sets `*out_len` excluding NUL.
46
+ // On error: returns NULL.
47
+ static char *
48
+ read_file_and_null_terminate (const char * filename , size_t * out_len )
49
+ {
50
+ BSON_ASSERT_PARAM (filename );
51
+ BSON_OPTIONAL_PARAM (out_len );
52
+
53
+ bool ok = false;
54
+ char * contents = NULL ;
55
+ char errmsg_buf [BSON_ERROR_BUFFER_SIZE ];
56
+
57
+ FILE * file = fopen (filename , "rb" );
58
+ if (!file ) {
59
+ MONGOC_ERROR ("Failed to open file: '%s' with error: '%s'" ,
60
+ filename ,
61
+ bson_strerror_r (errno , errmsg_buf , sizeof errmsg_buf ));
62
+ goto fail ;
63
+ }
64
+
65
+ if (0 != fseek (file , 0 , SEEK_END )) {
66
+ MONGOC_ERROR ("Failed to seek in file: '%s' with error: '%s'" ,
67
+ filename ,
68
+ bson_strerror_r (errno , errmsg_buf , sizeof errmsg_buf ));
69
+ goto fail ;
70
+ }
71
+
72
+ long file_len = ftell (file );
73
+ if (file_len < 0 ) {
74
+ MONGOC_ERROR ("Failed to get length of file: '%s' with error: '%s'" ,
75
+ filename ,
76
+ bson_strerror_r (errno , errmsg_buf , sizeof errmsg_buf ));
77
+ goto fail ;
78
+ }
79
+
80
+ if (file_len > LONG_MAX - 1 ) {
81
+ MONGOC_ERROR ("Failed to get length of file: '%s'. File too large" , filename );
82
+ goto fail ;
83
+ }
84
+
85
+ if (0 != fseek (file , 0 , SEEK_SET )) {
86
+ MONGOC_ERROR ("Failed to seek in file: '%s' with error: '%s'" ,
87
+ filename ,
88
+ bson_strerror_r (errno , errmsg_buf , sizeof errmsg_buf ));
89
+ goto fail ;
90
+ }
91
+
92
+ // Read the whole file into one nul-terminated string:
93
+ contents = (char * ) bson_malloc ((size_t ) file_len + 1u );
94
+ contents [file_len ] = '\0' ;
95
+ if ((size_t ) file_len != fread (contents , 1 , file_len , file )) {
96
+ if (feof (file )) {
97
+ MONGOC_ERROR ("Unexpected EOF reading file: '%s'" , filename );
98
+ goto fail ;
99
+ } else {
100
+ MONGOC_ERROR ("Failed to read file: '%s' with error: '%s'" ,
101
+ filename ,
102
+ bson_strerror_r (errno , errmsg_buf , sizeof errmsg_buf ));
103
+ goto fail ;
104
+ }
105
+ }
106
+ if (out_len ) {
107
+ * out_len = (size_t ) file_len ;
108
+ }
109
+
110
+ ok = true;
111
+ fail :
112
+ if (file ) {
113
+ fclose (file ); // Ignore error.
114
+ }
115
+ if (!ok ) {
116
+ bson_free (contents );
117
+ contents = NULL ;
118
+ }
119
+ return contents ;
120
+ }
121
+
44
122
45
123
PCCERT_CONTEXT
46
124
mongoc_secure_channel_setup_certificate_from_file (const char * filename )
47
125
{
48
126
char * pem ;
49
- FILE * file ;
50
127
bool ret = false;
51
128
bool success ;
52
- long pem_length ;
129
+ size_t pem_length ;
53
130
HCRYPTPROV provider ;
54
131
CERT_BLOB public_blob ;
55
132
const char * pem_public ;
@@ -60,26 +137,11 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename)
60
137
DWORD encrypted_private_len = 0 ;
61
138
LPBYTE encrypted_private = NULL ;
62
139
63
-
64
- file = fopen (filename , "rb" );
65
- if (!file ) {
66
- MONGOC_ERROR ("Couldn't open file '%s'" , filename );
67
- return NULL ;
68
- }
69
-
70
- fseek (file , 0 , SEEK_END );
71
- pem_length = ftell (file );
72
- fseek (file , 0 , SEEK_SET );
73
- if (pem_length < 1 || length > LONG_MAX - 1 ) {
74
- MONGOC_ERROR ("Couldn't determine file size of '%s'" , filename );
75
- return NULL ;
140
+ pem = read_file_and_null_terminate (filename , & pem_length );
141
+ if (!pem ) {
142
+ goto fail ;
76
143
}
77
144
78
- // Read the whole file into one nul-terminated string
79
- pem = (char * ) bson_malloc0 ((size_t ) pem_length + 1u );
80
- fread ((void * ) pem , 1 , pem_length , file );
81
- fclose (file );
82
-
83
145
pem_public = strstr (pem , "-----BEGIN CERTIFICATE-----" );
84
146
pem_private = strstr (pem , "-----BEGIN ENCRYPTED PRIVATE KEY-----" );
85
147
@@ -258,39 +320,18 @@ bool
258
320
mongoc_secure_channel_setup_ca (mongoc_stream_tls_secure_channel_t * secure_channel , mongoc_ssl_opt_t * opt )
259
321
{
260
322
bool ok = false;
261
- FILE * file ;
262
- long length ;
263
323
char * pem = NULL ;
264
324
const char * pem_key ;
265
325
HCERTSTORE cert_store = NULL ;
266
326
PCCERT_CONTEXT cert = NULL ;
267
327
DWORD encrypted_cert_len = 0 ;
268
328
LPBYTE encrypted_cert = NULL ;
269
329
270
- file = fopen (opt -> ca_file , "rb" );
271
- if (!file ) {
272
- MONGOC_ERROR ("Couldn't open file '%s'" , opt -> ca_file );
330
+ pem = read_file_and_null_terminate (opt -> ca_file , NULL );
331
+ if (!pem ) {
273
332
return false;
274
333
}
275
334
276
- fseek (file , 0 , SEEK_END );
277
- length = ftell (file );
278
- fseek (file , 0 , SEEK_SET );
279
- if (length < 1 || length > LONG_MAX - 1 ) {
280
- MONGOC_WARNING ("Couldn't determine file size of '%s'" , opt -> ca_file );
281
- fclose (file );
282
- return false;
283
- }
284
-
285
- // Read the whole file into one nul-terminated string
286
- pem = (char * ) bson_malloc0 ((size_t ) length + 1u );
287
- bool read_ok = (size_t ) length == fread ((void * ) pem , 1 , length , file );
288
- fclose (file );
289
- if (!read_ok ) {
290
- MONGOC_WARNING ("Couldn't read certificate file '%s'" , opt -> ca_file );
291
- goto fail ;
292
- }
293
-
294
335
/* If we have private keys or other fuzz, seek to the good stuff */
295
336
pem_key = strstr (pem , "-----BEGIN CERTIFICATE-----" );
296
337
0 commit comments