struct bytestring rfc822_header_unfolded_value(struct rfc822_msg *msg, struct rfc822_header *hdr) { struct bytestring raw = rfc822_header_raw_value(msg, hdr); struct bytestring next, rest; int lines = 0; size_t len = 0; if (!hdr->unfolded.ptr) { rest = raw; while (rest.ptr) { get_line(rest, &next, &rest); lines++; len += next.len; } if (lines <= 1) { hdr->unfolded = bytestring(raw.ptr, len); } else { char *unfold = tal_arr(msg, char, len); char *p = unfold; ALLOC_CHECK(unfold, bytestring_NULL); rest = raw; while (rest.ptr) { get_line(rest, &next, &rest); memcpy(p, next.ptr, next.len); p += next.len; } assert(p == (unfold + len)); hdr->unfolded = bytestring(unfold, len); } }
static void get_line(struct bytestring in, struct bytestring *first, struct bytestring *rest) { size_t rawlen, trimlen; const char *inp = in.ptr; const char *nl; nl = memchr(inp, '\n', in.len); if (!nl) rawlen = in.len; else rawlen = nl - inp + 1; trimlen = rawlen; if ((trimlen > 0) && (inp[trimlen-1] == '\n')) { trimlen--; if ((trimlen > 0) && (inp[trimlen-1] == '\r')) trimlen--; } *first = bytestring(in.ptr, trimlen); if (rawlen < in.len) *rest = bytestring(in.ptr + rawlen, in.len - rawlen); else *rest = bytestring_NULL; }
static struct rfc822_header *next_header_parse(struct rfc822_msg *msg) { const char *h, *eh, *ev, *colon; struct rfc822_header *hi; CHECK(msg, ">next_header_parse"); if (!msg->remainder) return NULL; if (msg->body && (msg->remainder >= msg->body)) return NULL; h = msg->remainder; eh = next_line(h, msg->end); ev = eh; if ((ev > h) && (ev[-1] == '\n')) ev--; if ((ev > h) && (ev[-1] == '\r')) ev--; if (ev == h) { /* Found the end of the headers */ assert(!msg->body || (msg->body == eh)); if (eh < msg->end) msg->body = eh; return NULL; } while ((eh < msg->end) && rfc822_iswsp(*eh)) eh = next_line(eh, msg->end); if (eh >= msg->end) msg->remainder = NULL; else msg->remainder = eh; hi = talz(msg, struct rfc822_header); ALLOC_CHECK(hi, NULL); hi->all = bytestring(h, eh - h); list_add_tail(&msg->headers, &hi->list); colon = memchr(h, ':', hi->all.len); if (colon) { hi->rawname = bytestring(h, colon - h); hi->rawvalue = bytestring(colon + 1, eh - colon - 1); } else { hi->rawname = bytestring_NULL; hi->rawvalue = bytestring_NULL; } CHECK(msg, "<next_header_parse"); return index_header(msg, hi); }
struct bytestring rfc822_body(struct rfc822_msg *msg) { CHECK(msg, ">rfc822_body"); if (!msg->body && msg->remainder) { const char *p, *q; p = memmem(msg->remainder, msg->end - msg->remainder, "\n\r\n", 3); q = memmem(msg->remainder, msg->end - msg->remainder, "\n\n", 2); if (p && (!q || (p < q))) msg->body = p + 3; else if (q && (!p || (q < p))) msg->body = q + 2; if (msg->body >= msg->end) { assert(msg->body == msg->end); msg->body = NULL; } } CHECK(msg, "<rfc822_body"); if (msg->body) return bytestring(msg->body, msg->end - msg->body); else return bytestring_NULL; }
static struct bytestring _splitchr(struct bytestring whole, char delim, size_t start) { const char *p; assert(start <= whole.len); /* Check this first, in case memchr() is not safe with zero length */ if (start == whole.len) return bytestring(whole.ptr + start, 0); p = memchr(whole.ptr + start, delim, whole.len - start); if (p) return bytestring_slice(whole, start, p - whole.ptr); else return bytestring_slice(whole, start, whole.len); }
// download body for this request int fancydm::in(DataBuffer * d, Socket * sock, Socket * peersock, class HTTPHeader * requestheader, class HTTPHeader * docheader, bool wantall, int *headersent, bool * toobig) { //DataBuffer *d = where to stick the data back into //Socket *sock = where to read from //Socket *peersock = browser to send stuff to for keeping it alive //HTTPHeader *docheader = header used for sending first line of reply //HTTPHeader *requestheader = header client used to request //bool wantall = to determine if just content filter or a full scan //int *headersent = to use to send the first line of header if needed // or to mark the header has already been sent //bool *toobig = flag to modify to say if it could not all be downloaded #ifdef DGDEBUG std::cout << "Inside fancy download manager plugin" << std::endl; #endif int rc; off_t newsize; off_t expectedsize = docheader->contentLength(); off_t bytessec = 0; off_t bytesgot = 0; int percentcomplete = 0; unsigned int eta = 0; int timeelapsed = 0; // if using non-persistent connections, some servers will not report // a content-length. in these situations, just download everything. bool geteverything = false; if ((expectedsize < 0) && !(docheader->isPersistent())) geteverything = true; if (expectedsize < 0) expectedsize = 0; bool initialsent = false; String message, jsmessage; char *block = NULL; // buffer for storing a grabbed block from the input stream char *temp = NULL; bool swappedtodisk = false; struct timeval starttime; struct timeval themdays; struct timeval nowadays; gettimeofday(&themdays, NULL); gettimeofday(&starttime, NULL); toobig_unscanned = false; toobig_notdownloaded = false; bool secondstage = false; // buffer size for streaming downloads off_t blocksize = 32768; // set to a sensible minimum if (!wantall && (blocksize > o.max_content_filter_size)) blocksize = o.max_content_filter_size; else if (wantall && (blocksize > o.max_content_ramcache_scan_size)) blocksize = o.max_content_ramcache_scan_size; #ifdef DGDEBUG std::cout << "blocksize: " << blocksize << std::endl; #endif // determine downloaded filename String filename(requestheader->disposition()); if (filename.length() == 0) { filename = requestheader->getUrl(); filename = requestheader->decode(filename); if (filename.contains("?")) filename = filename.before("?"); while (filename.contains("/")) filename = filename.after("/"); } while ((bytesgot < expectedsize) || geteverything) { // send text header to show status if (o.trickle_delay > 0) { gettimeofday(&nowadays, NULL); timeelapsed = nowadays.tv_sec - starttime.tv_sec; if ((!initialsent && timeelapsed > o.initial_trickle_delay) || (initialsent && nowadays.tv_sec - themdays.tv_sec > o.trickle_delay)) { initialsent = true; bytessec = bytesgot / timeelapsed; themdays.tv_sec = nowadays.tv_sec; if ((*headersent) < 1) { #ifdef DGDEBUG std::cout << "sending header for text status" << std::endl; #endif message = "HTTP/1.0 200 OK\nContent-Type: text/html\n\n"; // Output initial template std::deque<String>::iterator i = progresspage.html.begin(); std::deque<String>::iterator penultimate = progresspage.html.end()-1; bool newline; while (i != progresspage.html.end()) { newline = false; message = *i; if (message == "-FILENAME-") { message = filename; } else if (message == "-FILESIZE-") { message = String(expectedsize); } else if (message == "-SERVERIP-") { message = peersock->getLocalIP(); } else if ((i == penultimate) || ((*(i+1))[0] != '-')) { newline = true; } peersock->writeString(message.toCharArray()); // preserve line breaks from the original template file if (newline) peersock->writeString("\n"); i++; } // send please wait message for non-JS-enabled browsers // 1200 "Please wait - downloading to be scanned..." message = "<noscript><p>"; message += o.language_list.getTranslation(1200); message += "</p></noscript>\n"; peersock->writeString(message.toCharArray()); (*headersent) = 2; } #ifdef DGDEBUG std::cout << "trickle delay - sending progress..." << std::endl; #endif message = "Downloading status: "; // Output a call to template's JavaScript progressupdate function jsmessage = "<script language='javascript'>\n<!--\nprogressupdate(" + String(bytesgot) + "," + String(bytessec) + ");\n//-->\n</script>"; peersock->writeString(jsmessage.toCharArray()); // send text only version for non-JS-enabled browsers. // checkme: translation? if (geteverything) { message = "<noscript><p>Time remaining: unknown; " + bytestring(bytessec) + "/s; total downloaded: " + bytestring(bytesgot) + "</p></noscript>\n"; } else { percentcomplete = bytesgot/(expectedsize/100); eta = (expectedsize-bytesgot)/bytessec; message = "<noscript><p>" + String(percentcomplete) + "%, time remaining: " + timestring(eta) + "; " + bytestring(bytessec) + "/s; total downloaded: " + bytestring(bytesgot) + "</p></noscript>\n"; } peersock->writeString(message.toCharArray()); peersock->writeString("<!-- force flush -->\r\n"); } } if (wantall) { if (!swappedtodisk) { // if not swapped to disk and file is too large for RAM, then swap to disk if (bytesgot > o.max_content_ramcache_scan_size) { #ifdef DGDEBUG std::cout << "swapping to disk" << std::endl; #endif d->tempfilefd = d->getTempFileFD(); if (d->tempfilefd < 0) { #ifdef DGDEBUG std::cerr << "error buffering to disk so skipping disk buffering" << std::endl; #endif syslog(LOG_ERR, "%s", "error buffering to disk so skipping disk buffering"); (*toobig) = true; break; } writeEINTR(d->tempfilefd, d->data, d->buffer_length); swappedtodisk = true; d->tempfilesize = d->buffer_length; } } else if (bytesgot > o.max_content_filecache_scan_size) { (*toobig) = true; toobig_unscanned = true; if (geteverything && (upperlimit > 0)) { // multi-stage download enabled, and we don't know content length if ((!secondstage) && initialsent) { secondstage = true; // send download size warning message jsmessage = "<script language='javascript'>\n<!--\ndownloadwarning(" + String(upperlimit) + ");\n//-->\n</script>"; peersock->writeString(jsmessage.toCharArray()); // text-only version message = "<noscript><p>"; // 1201 Warning: file too large to scan. If you suspect that this file is larger than // 1202 , then refresh to download directly. message += o.language_list.getTranslation(1201); message += bytestring(upperlimit); message += o.language_list.getTranslation(1202); message += "</p></noscript>\n"; peersock->writeString(message.toCharArray()); peersock->writeString("<!-- force flush -->\r\n"); // add URL to clean cache (for all groups) String url(requestheader->getUrl()); addToClean(url, o.filter_groups + 1); #ifdef DGDEBUG std::cout << "fancydm: file too big to be scanned, entering second stage of download" << std::endl; #endif } // too large to even download, let alone scan if (bytesgot > upperlimit) { #ifdef DGDEBUG std::cout << "fancydm: file too big to be downloaded, halting second stage of download" << std::endl; #endif toobig_unscanned = false; toobig_notdownloaded = true; break; } } else { // multi-stage download disabled, or we know content length // if swapped to disk and file too large for that too, then give up #ifdef DGDEBUG std::cout << "fancydm: file too big to be scanned, halting download" << std::endl; #endif toobig_unscanned = false; toobig_notdownloaded = true; break; } } } else { if (bytesgot > o.max_content_filter_size) { // if we aren't downloading for virus scanning, and file too large for filtering, give up #ifdef DGDEBUG std::cout << "fancydm: file too big to be filtered, halting download" << std::endl; #endif (*toobig) = true; break; } } if (!swappedtodisk) { if (d->buffer_length >= blocksize) { newsize = d->buffer_length; } else { newsize = blocksize; } #ifdef DGDEBUG std::cout << "newsize: " << newsize << std::endl; #endif // if not getting everything until connection close, grab only what is left if (!geteverything && (newsize > (expectedsize - bytesgot))) newsize = expectedsize - bytesgot; delete[] block; block = new char[newsize]; try { sock->checkForInput(d->timeout); } catch(std::exception & e) { break; } // improved more efficient socket read which uses the buffer better rc = d->bufferReadFromSocket(sock, block, newsize, d->timeout, o.trickle_delay); // grab a block of input, doubled each time if (rc <= 0) { break; // an error occured so end the while() // or none received so pipe is closed } else { /*if (d->data != temp) delete[] temp;*/ temp = new char[d->buffer_length + rc + 1]; // replacement store temp[d->buffer_length + rc] = '\0'; memcpy(temp, d->data, d->buffer_length); // copy the current data memcpy(temp + d->buffer_length, block, rc); // copy the new data delete[]d->data; // delete the current data block d->data = temp; temp = NULL; d->buffer_length += rc; // update data size counter } } else { try { sock->checkForInput(d->timeout); } catch(std::exception & e) { break; } rc = d->bufferReadFromSocket(sock, d->data, // if not getting everything until connection close, grab only what is left (!geteverything && ((expectedsize - bytesgot) < d->buffer_length) ? (expectedsize - bytesgot) : d->buffer_length), d->timeout); if (rc <= 0) { break; } else { lseek(d->tempfilefd, 0, SEEK_END); // not really needed writeEINTR(d->tempfilefd, d->data, rc); d->tempfilesize += rc; #ifdef DGDEBUG std::cout << "written to disk: " << rc << " total: " << d->tempfilesize << std::endl; #endif } } if (d->tempfilesize > 0) { bytesgot = d->tempfilesize; } else { bytesgot = d->buffer_length; } } if (initialsent) { if (!swappedtodisk) { // if we sent textual content then we can't // stream the file to the user so we must save to disk for them // to download by clicking on the magic link // You can get to this point by having a large ram cache, or // slow internet connection with small initial trickle delay. // This should be rare. #ifdef DGDEBUG std::cout << "swapping to disk" << std::endl; #endif d->tempfilefd = d->getTempFileFD(); if (d->tempfilefd < 0) { #ifdef DGDEBUG std::cerr << "error buffering complete to disk so skipping disk buffering" << std::endl; #endif syslog(LOG_ERR, "error buffering complete to disk so skipping disk buffering"); } else { writeEINTR(d->tempfilefd, d->data, d->buffer_length); swappedtodisk = true; d->tempfilesize = d->buffer_length; } } // Output a call to template's JavaScript nowscanning function peersock->writeString("<script language='javascript'>\n<!--\nnowscanning();\n//-->\n</script>\n"); // send text-only version // 1210 "Download Complete. Starting scan..." if (!(toobig_unscanned || toobig_notdownloaded)) { message = "<noscript><p>"; message += o.language_list.getTranslation(1210); message += "</p></noscript>\n"; peersock->writeString(message.toCharArray()); } // only keep full downloads if (!toobig_notdownloaded) (*d).preservetemp = true; (*d).dontsendbody = true; } if (!(*toobig) && !swappedtodisk) { // won't deflate stuff swapped to disk if (d->decompress.contains("deflate")) { #ifdef DGDEBUG std::cout << "zlib format" << std::endl; #endif d->zlibinflate(false); // incoming stream was zlib compressed } else if (d->decompress.contains("gzip")) { #ifdef DGDEBUG std::cout << "gzip format" << std::endl; #endif d->zlibinflate(true); // incoming stream was gzip compressed } } d->bytesalreadysent = 0; /*if (d->data != temp) delete[] temp;*/ delete[] block; return 0; }
void pivacy_cardemu_emulator::process_prove_commitment(bytestring& c_apdu, bytestring& r_apdu) { if (!proof_started || !proof_have_context_and_D || (selected_credential == NULL)) { r_apdu = SW_WRONG_STATE; reset_proof(); } else if ((c_apdu.size() < 5) || (c_apdu[OFS_LC] != (SYSPAR(l_statzk) / 8))) { r_apdu = SW_LENGTH_ERROR; reset_proof(); } else if ((c_apdu[OFS_P1] != 0x00) || (c_apdu[OFS_P2] != 0x00)) { r_apdu = SW_DATA_UNKNOWN; reset_proof(); } else { // Retrieve the nonce bytestring nonce = c_apdu.substr(OFS_CDATA, c_apdu[OFS_LC]); // Generate the proof silvia_prover prover(selected_credential->get_issuer_public_key(), selected_credential->get_silvia_credential()); mpz_class c; mpz_class A_prime; mpz_class e_hat; mpz_class v_prime_hat; std::vector<mpz_class> a_i_hat; std::vector<silvia_attribute*> a_i; prover.prove(curproof_D, nonce.mpz_val(), curproof_context.mpz_val(), c, A_prime, e_hat, v_prime_hat, a_i_hat, a_i); // Save proof output std::vector<mpz_class>::iterator a_i_hat_it = a_i_hat.begin(); std::vector<silvia_attribute*>::iterator a_i_it = a_i.begin(); curproof_A_prime = bytestring(A_prime); curproof_e_hat = bytestring(e_hat); curproof_v_prime_hat = bytestring(v_prime_hat); /* Add hidden master secret */ curproof_attributes.push_back(bytestring(*a_i_hat_it)); a_i_hat_it++; for (std::vector<bool>::iterator i = curproof_D.begin(); i != curproof_D.end(); i++) { if ((*i) == true) { curproof_attributes.push_back(bytestring((*a_i_it)->rep())); a_i_it++; } else { curproof_attributes.push_back(bytestring(*a_i_hat_it)); a_i_hat_it++; } } // Return c r_apdu = bytestring(c); r_apdu += SW_OK; proof_proved = true; } }
std::vector<bytestring> silvia_irma_issuer::get_issue_commands_round_1() { assert(irma_issuer_state == IRMA_ISSUER_SELECTED); std::vector<bytestring> commands; //////////////////////////////////////////////////////////////////// // Step 3: start issuance //////////////////////////////////////////////////////////////////// // FIXME: context is randomly generated and kept as state! mpz_class context_mpz = silvia_rng::i()->get_random(SYSPAR(l_H)); context = bytestring(context_mpz); bytestring id; id += (unsigned char) ((ispec->get_credential_id() & 0xff00) >> 8); id += (unsigned char) (ispec->get_credential_id() & 0x00ff); bytestring attr_count; attr_count += (unsigned char) ((ispec->get_attributes().size() + 1) & 0xff00) >> 8; // +1 for expires attr_count += (unsigned char) ((ispec->get_attributes().size() + 1) & 0x00ff); // +1 for expires // FIXME: actually do something with these flags! bytestring attr_flags = "000000"; bytestring timestamp = (unsigned long) time(NULL); timestamp = timestamp.substr(timestamp.size() - 4); PAD_TO_SYSPAR(context, l_H); silvia_apdu issue_start(0x80, 0x10, 0x00, 0x00); issue_start.append_data(id); issue_start.append_data(attr_count); issue_start.append_data(attr_flags); issue_start.append_data(context); issue_start.append_data(timestamp); commands.push_back(issue_start.get_apdu()); //////////////////////////////////////////////////////////////////// // Step 4: write the public key to the card //////////////////////////////////////////////////////////////////// // n silvia_apdu issue_set_n(0x80, 0x11, 0x00, 0x00); bytestring n(pubkey->get_n()); // Pad if necessary PAD_TO_SYSPAR(n, l_n); issue_set_n.append_data(n); commands.push_back(issue_set_n.get_apdu()); // S silvia_apdu issue_set_S(0x80, 0x11, 0x01, 0x00); bytestring S(pubkey->get_S()); // Pad if necessary PAD_TO_SYSPAR(S, l_n); issue_set_S.append_data(S); commands.push_back(issue_set_S.get_apdu()); // Z silvia_apdu issue_set_Z(0x80, 0x11, 0x02, 0x00); bytestring Z(pubkey->get_Z()); // Pad if necessary PAD_TO_SYSPAR(Z, l_n); issue_set_Z.append_data(Z); commands.push_back(issue_set_Z.get_apdu()); for (int i = 0; i < (ispec->get_attributes().size() + 2); i++) { silvia_apdu issue_set_R(0x80, 0x11, 0x03, (unsigned char) (0x00 + i)); bytestring R(pubkey->get_R()[i]); // Pad if necessary PAD_TO_SYSPAR(R, l_n); issue_set_R.append_data(R); commands.push_back(issue_set_R.get_apdu()); } //////////////////////////////////////////////////////////////////// // Step 5: write the attributes to the card //////////////////////////////////////////////////////////////////// issue_attributes.clear(); // Create the "expires+metadata" attribute bytestring expires_and_metadata; // Add metadata version number expires_and_metadata += IRMA_CREDENTIAL_METADATA_VERSION; // Add expiration date int expires = ispec->get_expires(); expires_and_metadata += (unsigned char) ((expires & 0x00ff0000) >> 16); expires_and_metadata += (unsigned char) ((expires & 0x0000ff00) >> 8); expires_and_metadata += (unsigned char) (expires & 0x000000ff); // Add credential ID expires_and_metadata += (unsigned char) ((ispec->get_credential_id() & 0xff00) >> 8); expires_and_metadata += (unsigned char) (ispec->get_credential_id() & 0x00ff); metadata_attribute = new silvia_integer_attribute(expires_and_metadata.mpz_val()); silvia_apdu write_expires_attr(0x80, 0x12, 0x01, 0x00); write_expires_attr.append_data(metadata_attribute->bs_rep()); commands.push_back(write_expires_attr.get_apdu()); issue_attributes.push_back(metadata_attribute); // Create all other attributes unsigned char ctr = 0x02; for (std::vector<silvia_attribute*>::iterator i = ispec->get_attributes().begin(); i != ispec->get_attributes().end(); i++, ctr++) { silvia_apdu write_attr(0x80, 0x12, ctr, 0x00); write_attr.append_data((*i)->bs_rep()); commands.push_back(write_attr.get_apdu()); issue_attributes.push_back(*i); } issuer->set_attributes(issue_attributes); //////////////////////////////////////////////////////////////////// // Step 6: get issue commitment from card //////////////////////////////////////////////////////////////////// silvia_apdu issue_commitment_nonce(0x80, 0x1a, 0x00, 0x00); bytestring n1(issuer->get_issuer_nonce()); // pad if necessary PAD_TO_SYSPAR(n1, l_statzk); silvia_apdu issue_commitment(0x80, 0x1a, 0x00, 0x00); issue_commitment.append_data(n1); commands.push_back(issue_commitment.get_apdu()); //////////////////////////////////////////////////////////////////// // Step 7: get proof values c, v'^, s^ //////////////////////////////////////////////////////////////////// silvia_apdu get_proof_c(0x80, 0x1b, 0x01, 0x00); silvia_apdu get_proof_v_prime_hat(0x80, 0x1b, 0x02, 0x00); silvia_apdu get_proof_s_hat(0x80, 0x1b, 0x03, 0x00); commands.push_back(get_proof_c.get_apdu()); commands.push_back(get_proof_v_prime_hat.get_apdu()); commands.push_back(get_proof_s_hat.get_apdu()); //////////////////////////////////////////////////////////////////// // Step 8: get card nonce n2 //////////////////////////////////////////////////////////////////// silvia_apdu get_card_nonce_n2(0x80, 0x1c, 0x00, 0x00); commands.push_back(get_card_nonce_n2.get_apdu()); irma_issuer_state = IRMA_ISSUER_WAIT_COMMITMENT; return commands; }