Bug Summary

File:out/../deps/openssl/openssl/crypto/asn1/asn_mime.c
Warning:line 676, column 13
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name asn_mime.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D OPENSSL_NO_HW -D OPENSSL_API_COMPAT=0x10100001L -D STATIC_LEGACY -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -D MODULESDIR="/home/maurizio/node-v18.6.0/out/Release/obj.target/deps/openssl/lib/openssl-modules" -D OPENSSLDIR="/home/maurizio/node-v18.6.0/out/Release/obj.target/deps/openssl" -D OPENSSLDIR="/etc/ssl" -D ENGINESDIR="/dev/null" -D TERMIOS -I ../deps/openssl/openssl -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/openssl/crypto/modes -I ../deps/openssl/openssl/crypto/ec/curve448 -I ../deps/openssl/openssl/crypto/ec/curve448/arch_32 -I ../deps/openssl/openssl/providers/common/include -I ../deps/openssl/openssl/providers/implementations/include -I ../deps/openssl/config -I ../deps/openssl/config/archs/linux-x86_64/asm -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm/crypto -I ../deps/openssl/config/archs/linux-x86_64/asm/crypto/include/internal -I ../deps/openssl/config/archs/linux-x86_64/asm/providers/common/include -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-missing-field-initializers -Wno-old-style-declaration -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c ../deps/openssl/openssl/crypto/asn1/asn_mime.c
1/*
2 * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdio.h>
11#include "crypto/ctype.h"
12#include "internal/cryptlib.h"
13#include <openssl/rand.h>
14#include <openssl/x509.h>
15#include <openssl/asn1.h>
16#include <openssl/asn1t.h>
17#include <openssl/cms.h>
18#include "crypto/evp.h"
19#include "internal/bio.h"
20#include "asn1_local.h"
21
22/*
23 * Generalised MIME like utilities for streaming ASN1. Although many have a
24 * PKCS7/CMS like flavour others are more general purpose.
25 */
26
27/*
28 * MIME format structures Note that all are translated to lower case apart
29 * from parameter values. Quotes are stripped off
30 */
31
32struct mime_param_st {
33 char *param_name; /* Param name e.g. "micalg" */
34 char *param_value; /* Param value e.g. "sha1" */
35};
36
37struct mime_header_st {
38 char *name; /* Name of line e.g. "content-type" */
39 char *value; /* Value of line e.g. "text/plain" */
40 STACK_OF(MIME_PARAM)struct stack_st_MIME_PARAM *params; /* Zero or more parameters */
41};
42
43static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
44 const ASN1_ITEM *it);
45static char *strip_ends(char *name);
46static char *strip_start(char *name);
47static char *strip_end(char *name);
48static MIME_HEADER *mime_hdr_new(const char *name, const char *value);
49static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value);
50static STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *mime_parse_hdr(BIO *bio);
51static int mime_hdr_cmp(const MIME_HEADER *const *a,
52 const MIME_HEADER *const *b);
53static int mime_param_cmp(const MIME_PARAM *const *a,
54 const MIME_PARAM *const *b);
55static void mime_param_free(MIME_PARAM *param);
56static int mime_bound_check(char *line, int linelen, const char *bound, int blen);
57static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO)struct stack_st_BIO **ret);
58static int strip_eol(char *linebuf, int *plen, int flags);
59static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *hdrs, const char *name);
60static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name);
61static void mime_hdr_free(MIME_HEADER *hdr);
62
63#define MAX_SMLEN1024 1024
64#define mime_debug(x) /* x */
65
66/* Output an ASN1 structure in BER format streaming if necessary */
67
68/* unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() */
69int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
70 const ASN1_ITEM *it)
71{
72 /* If streaming create stream BIO and copy all content through it */
73 if (flags & SMIME_STREAM0x1000) {
74 BIO *bio, *tbio;
75 bio = BIO_new_NDEF(out, val, it);
76 if (!bio) {
77 ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,77,__func__), ERR_set_error)((13),((256|((0x1 << 18L)|
(0x2 << 18L)))),((void*)0))
;
78 return 0;
79 }
80 SMIME_crlf_copy(in, bio, flags);
81 (void)BIO_flush(bio)(int)BIO_ctrl(bio,11,0,((void*)0));
82 /* Free up successive BIOs until we hit the old output BIO */
83 do {
84 tbio = BIO_pop(bio);
85 BIO_free(bio);
86 bio = tbio;
87 } while (bio != out);
88 }
89 /*
90 * else just write out ASN1 structure which will have all content stored
91 * internally
92 */
93 else
94 ASN1_item_i2d_bio(it, out, val);
95 return 1;
96}
97
98/* Base 64 read and write of ASN1 structure */
99
100static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
101 const ASN1_ITEM *it)
102{
103 BIO *b64;
104 int r;
105 b64 = BIO_new(BIO_f_base64());
106 if (b64 == NULL((void*)0)) {
107 ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,107,__func__), ERR_set_error)((13),((256|((0x1 << 18L)
|(0x2 << 18L)))),((void*)0))
;
108 return 0;
109 }
110 /*
111 * prepend the b64 BIO so all data is base64 encoded.
112 */
113 out = BIO_push(b64, out);
114 r = i2d_ASN1_bio_stream(out, val, in, flags, it);
115 (void)BIO_flush(out)(int)BIO_ctrl(out,11,0,((void*)0));
116 BIO_pop(out);
117 BIO_free(b64);
118 return r;
119}
120
121/* Streaming ASN1 PEM write */
122
123int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
124 const char *hdr, const ASN1_ITEM *it)
125{
126 int r;
127 BIO_printf(out, "-----BEGIN %s-----\n", hdr);
128 r = B64_write_ASN1(out, val, in, flags, it);
129 BIO_printf(out, "-----END %s-----\n", hdr);
130 return r;
131}
132
133static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x,
134 OSSL_LIB_CTX *libctx, const char *propq)
135{
136 BIO *b64;
137 ASN1_VALUE *val;
138
139 if ((b64 = BIO_new(BIO_f_base64())) == NULL((void*)0)) {
140 ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,140,__func__), ERR_set_error)((13),((256|((0x1 << 18L)
|(0x2 << 18L)))),((void*)0))
;
141 return 0;
142 }
143 bio = BIO_push(b64, bio);
144 val = ASN1_item_d2i_bio_ex(it, bio, x, libctx, propq);
145 if (!val)
146 ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,146,__func__), ERR_set_error)((13),(110),((void*)0))
;
147 (void)BIO_flush(bio)(int)BIO_ctrl(bio,11,0,((void*)0));
148 BIO_pop(bio);
149 BIO_free(b64);
150 return val;
151}
152
153/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
154
155static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR)struct stack_st_X509_ALGOR *mdalgs)
156{
157 const EVP_MD *md;
158 int i, have_unknown = 0, write_comma, ret = 0, md_nid;
159 have_unknown = 0;
160 write_comma = 0;
161 for (i = 0; i < sk_X509_ALGOR_num(mdalgs)OPENSSL_sk_num(ossl_check_const_X509_ALGOR_sk_type(mdalgs)); i++) {
162 if (write_comma)
163 BIO_write(out, ",", 1);
164 write_comma = 1;
165 md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)((X509_ALGOR *)OPENSSL_sk_value(ossl_check_const_X509_ALGOR_sk_type
(mdalgs), (i)))
->algorithm);
166 md = EVP_get_digestbynid(md_nid)EVP_get_digestbyname(OBJ_nid2sn(md_nid));
167 if (md && md->md_ctrl) {
168 int rv;
169 char *micstr;
170 rv = md->md_ctrl(NULL((void*)0), EVP_MD_CTRL_MICALG0x2, 0, &micstr);
171 if (rv > 0) {
172 BIO_puts(out, micstr);
173 OPENSSL_free(micstr)CRYPTO_free(micstr, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 173)
;
174 continue;
175 }
176 if (rv != -2)
177 goto err;
178 }
179 switch (md_nid) {
180 case NID_sha164:
181 BIO_puts(out, "sha1");
182 break;
183
184 case NID_md54:
185 BIO_puts(out, "md5");
186 break;
187
188 case NID_sha256672:
189 BIO_puts(out, "sha-256");
190 break;
191
192 case NID_sha384673:
193 BIO_puts(out, "sha-384");
194 break;
195
196 case NID_sha512674:
197 BIO_puts(out, "sha-512");
198 break;
199
200 case NID_id_GostR3411_94809:
201 BIO_puts(out, "gostr3411-94");
202 goto err;
203
204 case NID_id_GostR3411_2012_256982:
205 BIO_puts(out, "gostr3411-2012-256");
206 goto err;
207
208 case NID_id_GostR3411_2012_512983:
209 BIO_puts(out, "gostr3411-2012-512");
210 goto err;
211
212 default:
213 if (have_unknown) {
214 write_comma = 0;
215 } else {
216 BIO_puts(out, "unknown");
217 have_unknown = 1;
218 }
219 break;
220
221 }
222 }
223
224 ret = 1;
225 err:
226
227 return ret;
228
229}
230
231/* SMIME sender */
232
233int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
234 int ctype_nid, int econt_nid,
235 STACK_OF(X509_ALGOR)struct stack_st_X509_ALGOR *mdalgs, const ASN1_ITEM *it,
236 OSSL_LIB_CTX *libctx, const char *propq)
237{
238 char bound[33], c;
239 int i;
240 const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
241 const char *msg_type = NULL((void*)0);
242
243 if (flags & SMIME_OLDMIME0x400)
244 mime_prefix = "application/x-pkcs7-";
245 else
246 mime_prefix = "application/pkcs7-";
247
248 if (flags & SMIME_CRLFEOL0x800)
249 mime_eol = "\r\n";
250 else
251 mime_eol = "\n";
252 if ((flags & SMIME_DETACHED0x40) && data) {
253 /* We want multipart/signed */
254 /* Generate a random boundary */
255 if (RAND_bytes_ex(libctx, (unsigned char *)bound, 32, 0) <= 0)
256 return 0;
257 for (i = 0; i < 32; i++) {
258 c = bound[i] & 0xf;
259 if (c < 10)
260 c += '0';
261 else
262 c += 'A' - 10;
263 bound[i] = c;
264 }
265 bound[32] = 0;
266 BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
267 BIO_printf(bio, "Content-Type: multipart/signed;");
268 BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
269 BIO_puts(bio, " micalg=\"");
270 asn1_write_micalg(bio, mdalgs);
271 BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
272 bound, mime_eol, mime_eol);
273 BIO_printf(bio, "This is an S/MIME signed message%s%s",
274 mime_eol, mime_eol);
275 /* Now write out the first part */
276 BIO_printf(bio, "------%s%s", bound, mime_eol);
277 if (!asn1_output_data(bio, data, val, flags, it))
278 return 0;
279 BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
280
281 /* Headers for signature */
282
283 BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
284 BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
285 BIO_printf(bio, "Content-Transfer-Encoding: base64%s", mime_eol);
286 BIO_printf(bio, "Content-Disposition: attachment;");
287 BIO_printf(bio, " filename=\"smime.p7s\"%s%s", mime_eol, mime_eol);
288 B64_write_ASN1(bio, val, NULL((void*)0), 0, it);
289 BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound,
290 mime_eol, mime_eol);
291 return 1;
292 }
293
294 /* Determine smime-type header */
295
296 if (ctype_nid == NID_pkcs7_enveloped23) {
297 msg_type = "enveloped-data";
298 } else if (ctype_nid == NID_pkcs7_signed22) {
299 if (econt_nid == NID_id_smime_ct_receipt204)
300 msg_type = "signed-receipt";
301 else if (sk_X509_ALGOR_num(mdalgs)OPENSSL_sk_num(ossl_check_const_X509_ALGOR_sk_type(mdalgs)) >= 0)
302 msg_type = "signed-data";
303 else
304 msg_type = "certs-only";
305 } else if (ctype_nid == NID_id_smime_ct_compressedData786) {
306 msg_type = "compressed-data";
307 cname = "smime.p7z";
308 }
309 /* MIME headers */
310 BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
311 BIO_printf(bio, "Content-Disposition: attachment;");
312 BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
313 BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
314 if (msg_type)
315 BIO_printf(bio, " smime-type=%s;", msg_type);
316 BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
317 BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
318 mime_eol, mime_eol);
319 if (!B64_write_ASN1(bio, val, data, flags, it))
320 return 0;
321 BIO_printf(bio, "%s", mime_eol);
322 return 1;
323}
324
325int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
326 int ctype_nid, int econt_nid,
327 STACK_OF(X509_ALGOR)struct stack_st_X509_ALGOR *mdalgs, const ASN1_ITEM *it)
328{
329 return SMIME_write_ASN1_ex(bio, val, data, flags, ctype_nid, econt_nid,
330 mdalgs, it, NULL((void*)0), NULL((void*)0));
331}
332
333/* Handle output of ASN1 data */
334
335/* cannot constify val because of CMS_dataFinal() */
336static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
337 const ASN1_ITEM *it)
338{
339 BIO *tmpbio;
340 const ASN1_AUX *aux = it->funcs;
341 ASN1_STREAM_ARG sarg;
342 int rv = 1;
343
344 /*
345 * If data is not detached or resigning then the output BIO is already
346 * set up to finalise when it is written through.
347 */
348 if (!(flags & SMIME_DETACHED0x40) || (flags & PKCS7_REUSE_DIGEST0x8000)) {
349 SMIME_crlf_copy(data, out, flags);
350 return 1;
351 }
352
353 if (!aux || !aux->asn1_cb) {
354 ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,354,__func__), ERR_set_error)((13),(202),((void*)0))
;
355 return 0;
356 }
357
358 sarg.out = out;
359 sarg.ndef_bio = NULL((void*)0);
360 sarg.boundary = NULL((void*)0);
361
362 /* Let ASN1 code prepend any needed BIOs */
363
364 if (aux->asn1_cb(ASN1_OP_DETACHED_PRE12, &val, it, &sarg) <= 0)
365 return 0;
366
367 /* Copy data across, passing through filter BIOs for processing */
368 SMIME_crlf_copy(data, sarg.ndef_bio, flags);
369
370 /* Finalize structure */
371 if (aux->asn1_cb(ASN1_OP_DETACHED_POST13, &val, it, &sarg) <= 0)
372 rv = 0;
373
374 /* Now remove any digests prepended to the BIO */
375
376 while (sarg.ndef_bio != out) {
377 tmpbio = BIO_pop(sarg.ndef_bio);
378 BIO_free(sarg.ndef_bio);
379 sarg.ndef_bio = tmpbio;
380 }
381
382 return rv;
383
384}
385
386/*
387 * SMIME reader: handle multipart/signed and opaque signing. in multipart
388 * case the content is placed in a memory BIO pointed to by "bcont". In
389 * opaque this is set to NULL
390 */
391
392ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
393 const ASN1_ITEM *it, ASN1_VALUE **x,
394 OSSL_LIB_CTX *libctx, const char *propq)
395{
396 BIO *asnin;
397 STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *headers = NULL((void*)0);
398 STACK_OF(BIO)struct stack_st_BIO *parts = NULL((void*)0);
399 MIME_HEADER *hdr;
400 MIME_PARAM *prm;
401 ASN1_VALUE *val;
402 int ret;
403
404 if (bcont)
405 *bcont = NULL((void*)0);
406
407 if ((headers = mime_parse_hdr(bio)) == NULL((void*)0)) {
408 ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,408,__func__), ERR_set_error)((13),(207),((void*)0))
;
409 return NULL((void*)0);
410 }
411
412 if ((hdr = mime_hdr_find(headers, "content-type")) == NULL((void*)0)
413 || hdr->value == NULL((void*)0)) {
414 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
415 ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,415,__func__), ERR_set_error)((13),(209),((void*)0))
;
416 return NULL((void*)0);
417 }
418
419 /* Handle multipart/signed */
420
421 if (strcmp(hdr->value, "multipart/signed") == 0) {
422 /* Split into two parts */
423 prm = mime_param_find(hdr, "boundary");
424 if (prm == NULL((void*)0) || prm->param_value == NULL((void*)0)) {
425 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
426 ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,426,__func__), ERR_set_error)((13),(211),((void*)0))
;
427 return NULL((void*)0);
428 }
429 ret = multi_split(bio, flags, prm->param_value, &parts);
430 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
431 if (!ret || (sk_BIO_num(parts)OPENSSL_sk_num(ossl_check_const_BIO_sk_type(parts)) != 2)) {
432 ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,432,__func__), ERR_set_error)((13),(210),((void*)0))
;
433 sk_BIO_pop_free(parts, BIO_vfree)OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(parts),ossl_check_BIO_freefunc_type
(BIO_vfree))
;
434 return NULL((void*)0);
435 }
436
437 /* Parse the signature piece */
438 asnin = sk_BIO_value(parts, 1)((BIO *)OPENSSL_sk_value(ossl_check_const_BIO_sk_type(parts),
(1)))
;
439
440 if ((headers = mime_parse_hdr(asnin)) == NULL((void*)0)) {
441 ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,441,__func__), ERR_set_error)((13),(208),((void*)0))
;
442 sk_BIO_pop_free(parts, BIO_vfree)OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(parts),ossl_check_BIO_freefunc_type
(BIO_vfree))
;
443 return NULL((void*)0);
444 }
445
446 /* Get content type */
447
448 if ((hdr = mime_hdr_find(headers, "content-type")) == NULL((void*)0)
449 || hdr->value == NULL((void*)0)) {
450 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
451 ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,451,__func__), ERR_set_error)((13),(212),((void*)0))
;
452 sk_BIO_pop_free(parts, BIO_vfree)OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(parts),ossl_check_BIO_freefunc_type
(BIO_vfree))
;
453 return NULL((void*)0);
454 }
455
456 if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
457 strcmp(hdr->value, "application/pkcs7-signature")) {
458 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,458,__func__), ERR_set_error)
(ERR_LIB_ASN113, ASN1_R_SIG_INVALID_MIME_TYPE213,
459 "type: %s", hdr->value);
460 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
461 sk_BIO_pop_free(parts, BIO_vfree)OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(parts),ossl_check_BIO_freefunc_type
(BIO_vfree))
;
462 return NULL((void*)0);
463 }
464 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
465 /* Read in ASN1 */
466 if ((val = b64_read_asn1(asnin, it, x, libctx, propq)) == NULL((void*)0)) {
467 ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,467,__func__), ERR_set_error)((13),(204),((void*)0))
;
468 sk_BIO_pop_free(parts, BIO_vfree)OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(parts),ossl_check_BIO_freefunc_type
(BIO_vfree))
;
469 return NULL((void*)0);
470 }
471
472 if (bcont) {
473 *bcont = sk_BIO_value(parts, 0)((BIO *)OPENSSL_sk_value(ossl_check_const_BIO_sk_type(parts),
(0)))
;
474 BIO_free(asnin);
475 sk_BIO_free(parts)OPENSSL_sk_free(ossl_check_BIO_sk_type(parts));
476 } else {
477 sk_BIO_pop_free(parts, BIO_vfree)OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(parts),ossl_check_BIO_freefunc_type
(BIO_vfree))
;
478 }
479 return val;
480 }
481
482 /* OK, if not multipart/signed try opaque signature */
483
484 if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
485 strcmp(hdr->value, "application/pkcs7-mime")) {
486 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,486,__func__), ERR_set_error)
(ERR_LIB_ASN113, ASN1_R_INVALID_MIME_TYPE205,
487 "type: %s", hdr->value);
488 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
489 return NULL((void*)0);
490 }
491
492 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
493
494 if ((val = b64_read_asn1(bio, it, x, libctx, propq)) == NULL((void*)0)) {
495 ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,495,__func__), ERR_set_error)((13),(203),((void*)0))
;
496 return NULL((void*)0);
497 }
498 return val;
499}
500
501ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
502{
503 return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL((void*)0), NULL((void*)0), NULL((void*)0));
504}
505
506/* Copy text from one BIO to another making the output CRLF at EOL */
507int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
508{
509 BIO *bf;
510 char eol;
511 int len;
512 char linebuf[MAX_SMLEN1024];
513 /*
514 * Buffer output so we don't write one line at a time. This is useful
515 * when streaming as we don't end up with one OCTET STRING per line.
516 */
517 bf = BIO_new(BIO_f_buffer());
518 if (bf == NULL((void*)0))
519 return 0;
520 out = BIO_push(bf, out);
521 if (flags & SMIME_BINARY0x80) {
522 while ((len = BIO_read(in, linebuf, MAX_SMLEN1024)) > 0)
523 BIO_write(out, linebuf, len);
524 } else {
525 int eolcnt = 0;
526 if (flags & SMIME_TEXT0x1)
527 BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
528 while ((len = BIO_gets(in, linebuf, MAX_SMLEN1024)) > 0) {
529 eol = strip_eol(linebuf, &len, flags);
530 if (len > 0) {
531 /* Not EOF: write out all CRLF */
532 if (flags & SMIME_ASCIICRLF0x80000) {
533 int i;
534 for (i = 0; i < eolcnt; i++)
535 BIO_write(out, "\r\n", 2);
536 eolcnt = 0;
537 }
538 BIO_write(out, linebuf, len);
539 if (eol)
540 BIO_write(out, "\r\n", 2);
541 } else if (flags & SMIME_ASCIICRLF0x80000) {
542 eolcnt++;
543 } else if (eol) {
544 BIO_write(out, "\r\n", 2);
545 }
546 }
547 }
548 (void)BIO_flush(out)(int)BIO_ctrl(out,11,0,((void*)0));
549 BIO_pop(out);
550 BIO_free(bf);
551 return 1;
552}
553
554/* Strip off headers if they are text/plain */
555int SMIME_text(BIO *in, BIO *out)
556{
557 char iobuf[4096];
558 int len;
559 STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *headers;
560 MIME_HEADER *hdr;
561
562 if ((headers = mime_parse_hdr(in)) == NULL((void*)0)) {
563 ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,563,__func__), ERR_set_error)((13),(207),((void*)0))
;
564 return 0;
565 }
566 if ((hdr = mime_hdr_find(headers, "content-type")) == NULL((void*)0)
567 || hdr->value == NULL((void*)0)) {
568 ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,568,__func__), ERR_set_error)((13),(206),((void*)0))
;
569 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
570 return 0;
571 }
572 if (strcmp(hdr->value, "text/plain")) {
573 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/asn1/asn_mime.c"
,573,__func__), ERR_set_error)
(ERR_LIB_ASN113, ASN1_R_INVALID_MIME_TYPE205,
574 "type: %s", hdr->value);
575 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
576 return 0;
577 }
578 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
579 while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
580 BIO_write(out, iobuf, len);
581 if (len < 0)
582 return 0;
583 return 1;
584}
585
586/*
587 * Split a multipart/XXX message body into component parts: result is
588 * canonical parts in a STACK of bios
589 */
590
591static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO)struct stack_st_BIO **ret)
592{
593 char linebuf[MAX_SMLEN1024];
594 int len, blen;
595 int eol = 0, next_eol = 0;
596 BIO *bpart = NULL((void*)0);
597 STACK_OF(BIO)struct stack_st_BIO *parts;
598 char state, part, first;
599
600 blen = strlen(bound);
601 part = 0;
602 state = 0;
603 first = 1;
604 parts = sk_BIO_new_null()((struct stack_st_BIO *)OPENSSL_sk_new_null());
605 *ret = parts;
606 if (*ret == NULL((void*)0))
607 return 0;
608 while ((len = BIO_get_line(bio, linebuf, MAX_SMLEN1024)) > 0) {
609 state = mime_bound_check(linebuf, len, bound, blen);
610 if (state == 1) {
611 first = 1;
612 part++;
613 } else if (state == 2) {
614 if (!sk_BIO_push(parts, bpart)OPENSSL_sk_push(ossl_check_BIO_sk_type(parts), ossl_check_BIO_type
(bpart))
) {
615 BIO_free(bpart);
616 return 0;
617 }
618 return 1;
619 } else if (part != 0) {
620 /* Strip (possibly CR +) LF from linebuf */
621 next_eol = strip_eol(linebuf, &len, flags);
622 if (first) {
623 first = 0;
624 if (bpart)
625 if (!sk_BIO_push(parts, bpart)OPENSSL_sk_push(ossl_check_BIO_sk_type(parts), ossl_check_BIO_type
(bpart))
) {
626 BIO_free(bpart);
627 return 0;
628 }
629 bpart = BIO_new(BIO_s_mem());
630 if (bpart == NULL((void*)0))
631 return 0;
632 BIO_set_mem_eof_return(bpart, 0)BIO_ctrl(bpart,130,0,((void*)0));
633 } else if (eol) {
634 if (
635#ifndef OPENSSL_NO_CMS
636 (flags & CMS_BINARY0x80) == 0
637#else
638 1
639#endif
640 || (flags & SMIME_CRLFEOL0x800) != 0)
641 BIO_write(bpart, "\r\n", 2);
642 else
643 BIO_write(bpart, "\n", 1);
644 }
645 eol = next_eol;
646 if (len > 0)
647 BIO_write(bpart, linebuf, len);
648 }
649 }
650 BIO_free(bpart);
651 return 0;
652}
653
654/* This is the big one: parse MIME header lines up to message body */
655
656#define MIME_INVALID0 0
657#define MIME_START1 1
658#define MIME_TYPE2 2
659#define MIME_NAME3 3
660#define MIME_VALUE4 4
661#define MIME_QUOTE5 5
662#define MIME_COMMENT6 6
663
664static STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *mime_parse_hdr(BIO *bio)
665{
666 char *p, *q, c;
667 char *ntmp;
668 char linebuf[MAX_SMLEN1024];
669 MIME_HEADER *mhdr = NULL((void*)0), *new_hdr = NULL((void*)0);
670 STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *headers;
671 int len, state, save_state = 0;
672
673 headers = sk_MIME_HEADER_new(mime_hdr_cmp);
674 if (headers == NULL((void*)0))
675 return NULL((void*)0);
676 while ((len = BIO_gets(bio, linebuf, MAX_SMLEN1024)) > 0) {
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'
677 /* If whitespace at line start then continuation line */
678 if (mhdr && ossl_isspace(linebuf[0])(ossl_ctype_check((linebuf[0]), 0x8)))
679 state = MIME_NAME3;
680 else
681 state = MIME_START1;
682 ntmp = NULL((void*)0);
683 /* Go through all characters */
684 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
685 p++) {
686
687 /*
688 * State machine to handle MIME headers if this looks horrible
689 * that's because it *is*
690 */
691
692 switch (state) {
693 case MIME_START1:
694 if (c == ':') {
695 state = MIME_TYPE2;
696 *p = 0;
697 ntmp = strip_ends(q);
698 q = p + 1;
699 }
700 break;
701
702 case MIME_TYPE2:
703 if (c == ';') {
704 mime_debug("Found End Value\n");
705 *p = 0;
706 new_hdr = mime_hdr_new(ntmp, strip_ends(q));
707 if (new_hdr == NULL((void*)0))
708 goto err;
709 if (!sk_MIME_HEADER_push(headers, new_hdr))
710 goto err;
711 mhdr = new_hdr;
712 new_hdr = NULL((void*)0);
713 ntmp = NULL((void*)0);
714 q = p + 1;
715 state = MIME_NAME3;
716 } else if (c == '(') {
717 save_state = state;
718 state = MIME_COMMENT6;
719 }
720 break;
721
722 case MIME_COMMENT6:
723 if (c == ')') {
724 state = save_state;
725 }
726 break;
727
728 case MIME_NAME3:
729 if (c == '=') {
730 state = MIME_VALUE4;
731 *p = 0;
732 ntmp = strip_ends(q);
733 q = p + 1;
734 }
735 break;
736
737 case MIME_VALUE4:
738 if (c == ';') {
739 state = MIME_NAME3;
740 *p = 0;
741 mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
742 ntmp = NULL((void*)0);
743 q = p + 1;
744 } else if (c == '"') {
745 mime_debug("Found Quote\n");
746 state = MIME_QUOTE5;
747 } else if (c == '(') {
748 save_state = state;
749 state = MIME_COMMENT6;
750 }
751 break;
752
753 case MIME_QUOTE5:
754 if (c == '"') {
755 mime_debug("Found Match Quote\n");
756 state = MIME_VALUE4;
757 }
758 break;
759 }
760 }
761
762 if (state == MIME_TYPE2) {
763 new_hdr = mime_hdr_new(ntmp, strip_ends(q));
764 if (new_hdr == NULL((void*)0))
765 goto err;
766 if (!sk_MIME_HEADER_push(headers, new_hdr))
767 goto err;
768 mhdr = new_hdr;
769 new_hdr = NULL((void*)0);
770 } else if (state == MIME_VALUE4) {
771 mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
772 }
773 if (p == linebuf)
774 break; /* Blank line means end of headers */
775 }
776
777 return headers;
778
779 err:
780 mime_hdr_free(new_hdr);
781 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
782 return NULL((void*)0);
783}
784
785static char *strip_ends(char *name)
786{
787 return strip_end(strip_start(name));
788}
789
790/* Strip a parameter of whitespace from start of param */
791static char *strip_start(char *name)
792{
793 char *p, c;
794 /* Look for first non whitespace or quote */
795 for (p = name; (c = *p); p++) {
796 if (c == '"') {
797 /* Next char is start of string if non null */
798 if (p[1])
799 return p + 1;
800 /* Else null string */
801 return NULL((void*)0);
802 }
803 if (!ossl_isspace(c)(ossl_ctype_check((c), 0x8)))
804 return p;
805 }
806 return NULL((void*)0);
807}
808
809/* As above but strip from end of string : maybe should handle brackets? */
810static char *strip_end(char *name)
811{
812 char *p, c;
813 if (!name)
814 return NULL((void*)0);
815 /* Look for first non whitespace or quote */
816 for (p = name + strlen(name) - 1; p >= name; p--) {
817 c = *p;
818 if (c == '"') {
819 if (p - 1 == name)
820 return NULL((void*)0);
821 *p = 0;
822 return name;
823 }
824 if (ossl_isspace(c)(ossl_ctype_check((c), 0x8)))
825 *p = 0;
826 else
827 return name;
828 }
829 return NULL((void*)0);
830}
831
832static MIME_HEADER *mime_hdr_new(const char *name, const char *value)
833{
834 MIME_HEADER *mhdr = NULL((void*)0);
835 char *tmpname = NULL((void*)0), *tmpval = NULL((void*)0), *p;
836
837 if (name) {
838 if ((tmpname = OPENSSL_strdup(name)CRYPTO_strdup(name, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 838)
) == NULL((void*)0))
839 return NULL((void*)0);
840 for (p = tmpname; *p; p++)
841 *p = ossl_tolower(*p);
842 }
843 if (value) {
844 if ((tmpval = OPENSSL_strdup(value)CRYPTO_strdup(value, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 844)
) == NULL((void*)0))
845 goto err;
846 for (p = tmpval; *p; p++)
847 *p = ossl_tolower(*p);
848 }
849 mhdr = OPENSSL_malloc(sizeof(*mhdr))CRYPTO_malloc(sizeof(*mhdr), "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 849)
;
850 if (mhdr == NULL((void*)0))
851 goto err;
852 mhdr->name = tmpname;
853 mhdr->value = tmpval;
854 if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL((void*)0))
855 goto err;
856 return mhdr;
857
858 err:
859 OPENSSL_free(tmpname)CRYPTO_free(tmpname, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 859)
;
860 OPENSSL_free(tmpval)CRYPTO_free(tmpval, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 860)
;
861 OPENSSL_free(mhdr)CRYPTO_free(mhdr, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 861)
;
862 return NULL((void*)0);
863}
864
865static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value)
866{
867 char *tmpname = NULL((void*)0), *tmpval = NULL((void*)0), *p;
868 MIME_PARAM *mparam = NULL((void*)0);
869
870 if (name) {
871 tmpname = OPENSSL_strdup(name)CRYPTO_strdup(name, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 871)
;
872 if (!tmpname)
873 goto err;
874 for (p = tmpname; *p; p++)
875 *p = ossl_tolower(*p);
876 }
877 if (value) {
878 tmpval = OPENSSL_strdup(value)CRYPTO_strdup(value, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 878)
;
879 if (!tmpval)
880 goto err;
881 }
882 /* Parameter values are case sensitive so leave as is */
883 mparam = OPENSSL_malloc(sizeof(*mparam))CRYPTO_malloc(sizeof(*mparam), "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 883)
;
884 if (mparam == NULL((void*)0))
885 goto err;
886 mparam->param_name = tmpname;
887 mparam->param_value = tmpval;
888 if (!sk_MIME_PARAM_push(mhdr->params, mparam))
889 goto err;
890 return 1;
891 err:
892 OPENSSL_free(tmpname)CRYPTO_free(tmpname, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 892)
;
893 OPENSSL_free(tmpval)CRYPTO_free(tmpval, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 893)
;
894 OPENSSL_free(mparam)CRYPTO_free(mparam, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 894)
;
895 return 0;
896}
897
898static int mime_hdr_cmp(const MIME_HEADER *const *a,
899 const MIME_HEADER *const *b)
900{
901 if ((*a)->name == NULL((void*)0) || (*b)->name == NULL((void*)0))
902 return ((*a)->name != NULL((void*)0)) - ((*b)->name != NULL((void*)0));
903
904 return strcmp((*a)->name, (*b)->name);
905}
906
907static int mime_param_cmp(const MIME_PARAM *const *a,
908 const MIME_PARAM *const *b)
909{
910 if ((*a)->param_name == NULL((void*)0) || (*b)->param_name == NULL((void*)0))
911 return ((*a)->param_name != NULL((void*)0)) - ((*b)->param_name != NULL((void*)0));
912 return strcmp((*a)->param_name, (*b)->param_name);
913}
914
915/* Find a header with a given name (if possible) */
916
917static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER)struct stack_st_MIME_HEADER *hdrs, const char *name)
918{
919 MIME_HEADER htmp;
920 int idx;
921
922 htmp.name = (char *)name;
923 htmp.value = NULL((void*)0);
924 htmp.params = NULL((void*)0);
925
926 idx = sk_MIME_HEADER_find(hdrs, &htmp);
927 return sk_MIME_HEADER_value(hdrs, idx);
928}
929
930static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name)
931{
932 MIME_PARAM param;
933 int idx;
934
935 param.param_name = (char *)name;
936 param.param_value = NULL((void*)0);
937 idx = sk_MIME_PARAM_find(hdr->params, &param);
938 return sk_MIME_PARAM_value(hdr->params, idx);
939}
940
941static void mime_hdr_free(MIME_HEADER *hdr)
942{
943 if (hdr == NULL((void*)0))
944 return;
945 OPENSSL_free(hdr->name)CRYPTO_free(hdr->name, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 945)
;
946 OPENSSL_free(hdr->value)CRYPTO_free(hdr->value, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 946)
;
947 if (hdr->params)
948 sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
949 OPENSSL_free(hdr)CRYPTO_free(hdr, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 949)
;
950}
951
952static void mime_param_free(MIME_PARAM *param)
953{
954 OPENSSL_free(param->param_name)CRYPTO_free(param->param_name, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 954)
;
955 OPENSSL_free(param->param_value)CRYPTO_free(param->param_value, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 955)
;
956 OPENSSL_free(param)CRYPTO_free(param, "../deps/openssl/openssl/crypto/asn1/asn_mime.c"
, 956)
;
957}
958
959/*-
960 * Check for a multipart boundary. Returns:
961 * 0 : no boundary
962 * 1 : part boundary
963 * 2 : final boundary
964 */
965static int mime_bound_check(char *line, int linelen, const char *bound, int blen)
966{
967 if (linelen == -1)
968 linelen = strlen(line);
969 if (blen == -1)
970 blen = strlen(bound);
971 /* Quickly eliminate if line length too short */
972 if (blen + 2 > linelen)
973 return 0;
974 /* Check for part boundary */
975 if ((strncmp(line, "--", 2) == 0)
976 && strncmp(line + 2, bound, blen) == 0) {
977 if (strncmp(line + blen + 2, "--", 2) == 0)
978 return 2;
979 else
980 return 1;
981 }
982 return 0;
983}
984
985static int strip_eol(char *linebuf, int *plen, int flags)
986{
987 int len = *plen;
988 char *p, c;
989 int is_eol = 0;
990
991#ifndef OPENSSL_NO_CMS
992 if ((flags & CMS_BINARY0x80) != 0) {
993 if (len <= 0 || linebuf[len - 1] != '\n')
994 return 0;
995 if ((flags & SMIME_CRLFEOL0x800) != 0) {
996 if (len <= 1 || linebuf[len - 2] != '\r')
997 return 0;
998 len--;
999 }
1000 len--;
1001 *plen = len;
1002 return 1;
1003 }
1004#endif
1005
1006 for (p = linebuf + len - 1; len > 0; len--, p--) {
1007 c = *p;
1008 if (c == '\n') {
1009 is_eol = 1;
1010 } else if (is_eol && (flags & SMIME_ASCIICRLF0x80000) != 0 && c == 32) {
1011 /* Strip trailing space on a line; 32 == ASCII for ' ' */
1012 continue;
1013 } else if (c != '\r') {
1014 break;
1015 }
1016 }
1017 *plen = len;
1018 return is_eol;
1019}