static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) { struct sockaddr_in sa; unsigned char buf[4096]; int r = 0, i; BIO *tmpout = NULL; if (out == NULL) tmpout = BIO_new(BIO_s_null()); else if (flags & CMS_TEXT) { tmpout = BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(tmpout, 0); } else tmpout = out; if(!tmpout) { CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE); goto err; } /* Read all content through chain to process digest, decrypt etc */ for (;;) { i=BIO_read(in,buf,sizeof(buf)); if (i <= 0) { if (BIO_method_type(in) == BIO_TYPE_CIPHER) { if (!BIO_get_cipher_status(in)) goto err; } if (i < 0) goto err; break; } if (tmpout && (BIO_write(tmpout, buf, i, 0, sa) != i)) goto err; } if(flags & CMS_TEXT) { if(!SMIME_text(tmpout, out)) { CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR); goto err; } } r = 1; err: if (tmpout && (tmpout != out)) BIO_free(tmpout); return r; }
static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) { unsigned char buf[4096]; int r = 0, i; BIO *tmpout; tmpout = cms_get_text_bio(out, flags); if (!tmpout) { CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE); goto err; } /* Read all content through chain to process digest, decrypt etc */ for (;;) { i = BIO_read(in, buf, sizeof(buf)); if (i <= 0) { if (BIO_method_type(in) == BIO_TYPE_CIPHER) { if (!BIO_get_cipher_status(in)) goto err; } if (i < 0) goto err; break; } if (tmpout && (BIO_write(tmpout, buf, i) != i)) goto err; } if (flags & CMS_TEXT) { if (!SMIME_text(tmpout, out)) { CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR); goto err; } } r = 1; err: if (tmpout != out) BIO_free(tmpout); return r; }
int main(int argc, char** argv) { const char* secret; secret = getenv("TRACKING_SECRET"); if (!secret) { fprintf(stderr, "TRACKING_SECRET not set\n"); return 1; } char input_line[MAX_LINE]; char plaintext[MAX_LINE]; const EVP_CIPHER* cipher = EVP_aes_128_cbc(); while (fgets(input_line, MAX_LINE, stdin) != NULL) { /* split the line into unique_id and query */ char *unique_id, *query; split_fields(input_line, &unique_id, &query, NO_MORE_FIELDS); /* parse the query string to get the value we need */ char *blob = NULL; char *key, *value; while (parse_query_param(&query, &key, &value) >= 0) { if (strcmp(key, "v") == 0) { blob = value; break; } } if (blob == NULL) continue; /* undo url encoding on the query string */ int b64_size = url_decode(blob); if (b64_size < 0) continue; /* split off the initialization vector from the actual ciphertext */ char *initialization_vector, *ciphertext; initialization_vector = blob; initialization_vector[KEY_SIZE] = '\0'; ciphertext = blob + 32; b64_size -= 32; /* base 64 decode and decrypt the ciphertext */ BIO* bio = BIO_new_mem_buf(ciphertext, b64_size); BIO* b64 = BIO_new(BIO_f_base64()); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bio = BIO_push(b64, bio); BIO* aes = BIO_new(BIO_f_cipher()); BIO_set_cipher( aes, cipher, (unsigned char*)secret, (unsigned char*)initialization_vector, 0 /* decryption */ ); bio = BIO_push(aes, bio); /* stream the output through the filters */ int plaintext_length = BIO_read(bio, plaintext, b64_size); plaintext[plaintext_length] = '\0'; if (!BIO_get_cipher_status(bio)) { BIO_free_all(bio); continue; } /* clean up */ BIO_free_all(bio); /* check that the plaintext isn't garbage; if there are * non-ascii characters in it, it's likely bad */ bool non_ascii_junk = false; for (unsigned char* c = (unsigned char*)plaintext; *c != '\0'; c++) { if (*c > 0x7F) { non_ascii_junk = true; break; } } if (non_ascii_junk) { continue; } /* write out the unique id since we don't need it for ourselves */ fputs(unique_id, stdout); /* split the fields out of the plaintext */ char* current_string = plaintext; int field_index = 0; for (int i = 0; i < plaintext_length; i++) { char *c = plaintext + i; if (*c != '|') continue; *c = '\0'; switch (field_index) { case FIELD_USER: /* we don't use the username; skip it */ break; case FIELD_SRPATH: fputc('\t', stdout); fputs(current_string, stdout); fputc('\t', stdout); for (char* c2=current_string; *c2 != '\0'; c2++) { if (*c2 == '-') { *c2 = '\0'; break; } } fputs(current_string, stdout); break; case FIELD_LANG: fputc('\t', stdout); for (char* c2=current_string; *c2 != '\0'; c2++) { *c2 = tolower(*c2); } fputs(current_string, stdout); break; case FIELD_CNAME: assert(0!=1); } current_string = c + 1; field_index += 1; } if (field_index < FIELD_COUNT) { fputc('\t', stdout); fputs(current_string, stdout); field_index += 1; } for (; field_index < FIELD_COUNT; field_index++) fputc('\t', stdout); /* all done! */ fputc('\n', stdout); } return 0; }