static void dosum (const char *file) { FILE *f; unsigned char result[16]; int i; f = fopen (file, "rb"); if (!f) { fprintf (stderr, "opening %s: %s\n", file, xstrerror (errno)); exit (1); } /* Some executable formats have timestamps in the first 16 bytes, yuck. */ if (fseek (f, 16, SEEK_SET) != 0) { fprintf (stderr, "seeking in %s: %s\n", file, xstrerror (errno)); exit (1); } if (md5_stream (f, result) != 0 || fclose (f) != 0) { fprintf (stderr, "reading %s: %s\n", file, xstrerror (errno)); exit (1); } fputs ("const unsigned char executable_checksum[16] = { ", stdout); for (i = 0; i < 16; i++) printf ("%#02x%s", result[i], i == 15 ? " };\n" : ", "); }
char *file_md5sum_alloc(const char *file_name) { static const int md5sum_bin_len = 16; static const int md5sum_hex_len = 32; static const unsigned char bin2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; int i, err; FILE *file; char *md5sum_hex; unsigned char md5sum_bin[md5sum_bin_len]; md5sum_hex = xcalloc(1, md5sum_hex_len + 1); file = fopen(file_name, "r"); if (file == NULL) { opkg_perror(ERROR, "Failed to open file %s", file_name); free(md5sum_hex); return NULL; } err = md5_stream(file, md5sum_bin); if (err) { opkg_msg(ERROR, "Could't compute md5sum for %s.\n", file_name); fclose(file); free(md5sum_hex); return NULL; } fclose(file); for (i = 0; i < md5sum_bin_len; i++) { md5sum_hex[i * 2] = bin2hex[md5sum_bin[i] >> 4]; md5sum_hex[i * 2 + 1] = bin2hex[md5sum_bin[i] & 0xf]; } md5sum_hex[md5sum_hex_len] = '\0'; return md5sum_hex; }
static int lmd5(lua_State *L) { char buff[16]; char tmp[32]; size_t l; int i; int t = lua_type(L, 1); if (t == LUA_TSTRING) { const char *message = luaL_checklstring(L, 1, &l); md5(message, l, buff); } else if (t == LUA_TFUNCTION) { md5_stream(L, buff); } else { return luaL_error(L, "Invalid type %s, should be string or function", lua_typename(L, lua_type(L, 1))); } for (i=0;i<16;i++) { sprintf(tmp+2*i,"%02x",(unsigned char)buff[i]); } lua_pushlstring(L, tmp, 32); return 1; }
char *file_md5sum_alloc(const char *file_name) { int err; FILE *file; unsigned char md5sum_bin[16]; file = fopen(file_name, "r"); if (file == NULL) { opkg_perror(ERROR, "Failed to open file %s", file_name); return NULL; } err = md5_stream(file, md5sum_bin); if (err) { opkg_msg(ERROR, "Could't compute md5sum for %s.\n", file_name); fclose(file); return NULL; } fclose(file); return md5_to_string(md5sum_bin); }
/* .Call so manages R_alloc stack */ SEXP Rmd5(SEXP files) { SEXP ans; int i, j, nfiles = length(files), res; const char *path; char out[33]; FILE *fp; unsigned char resblock[16]; if(!isString(files)) error(_("argument 'files' must be character")); PROTECT(ans = allocVector(STRSXP, nfiles)); for(i = 0; i < nfiles; i++) { path = translateChar(STRING_ELT(files, i)); #ifdef WIN32 fp = fopen(path, "rb"); #else fp = fopen(path, "r"); #endif if(!fp) { SET_STRING_ELT(ans, i, NA_STRING); } else { res = md5_stream(fp, &resblock); if(res) { warning(_("md5 failed on file '%s'"), path); SET_STRING_ELT(ans, i, NA_STRING); } else { for(j = 0; j < 16; j++) sprintf (out+2*j, "%02x", resblock[j]); SET_STRING_ELT(ans, i, mkChar(out)); } fclose(fp); } } UNPROTECT(1); return ans; }
int main (int argc, char **argv) { FILE *fp, *fp2; int j, wrong = 0, miss = 0, res; char *p, fname[500], line[500]; /* < MAX_PATH + 32+ some */ char onfile[33], out[33]; unsigned char resblock[16]; if(argc < 2) strcpy(fname, "../MD5"); else strcpy(fname, argv[1]); fp = fopen(fname, "r"); if(!fp) { fprintf(stderr, "Cannot open file %s\n", fname); exit(2); } chdir(dirname(fname)); if(access("unins000.dat", 4) == 0) read_unist_file("unins000.dat"); onfile[32] = '\0'; while(fgets(line, 500, fp)) { p = line + (strlen(line) - 1); if(*p == '\n') *p = '\0'; #ifdef DEBUG printf("%s: ", line+34); #endif /* the next two files get altered during installation */ if(strcmp(line+34, "etc/Rconsole") == 0) continue; if(strcmp(line+34, "etc/Rprofile.site") == 0) continue; if(line[33] == '*') fp2 = fopen(line+34, "rb"); else fp2 = fopen(line+34, "r"); if(!fp2) { int i, found = 0; for(i = 0; i < nnames; i++) { if(strcmp(line+34, nameList[i]) == 0) { found = 1; break; } } #ifdef DEBUG printf("missing\n"); #endif if(found || nnames == 0) { fprintf(stderr, "file %s: missing\n", line+34); miss++; } continue; } strncpy(onfile, line, 32); res = md5_stream(fp2, &resblock); if(res) { #ifdef DEBUG printf("md5 failed\n"); #endif continue; } else { for(j = 0; j < 16; j++) snprintf (out+2*j, 3, "%02x", resblock[j]); out[32] = '\0'; if(strcmp(onfile, out) == 0) { #ifdef DEBUG printf("OK\n"); #endif } else { #ifdef DEBUG printf("changed\n"); printf(" %s vs %s\n", onfile, out); #endif fprintf(stderr, "file %s: changed\n", line+34); wrong++; } } fclose(fp2); } fclose(fp); if(miss) fprintf(stderr, "WARNING: %d files missing\n", miss); if(wrong) fprintf(stderr, "WARNING: %d files changed\n", wrong); if(wrong || miss) { fprintf(stderr, "Press ENTER to finish"); getc(stdin); exit(10); } fprintf(stderr, "No errors detected\n"); exit(0); }
/* Decompress an open file. Call fatal_return(() on error return the number of bytes that have been retrieved */ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 expected_size) { uchar md5_stored[MD5_DIGEST_SIZE]; struct timeval start,end; i64 total = 0, u; double tdiff; if (!NO_MD5) md5_init_ctx (&control->ctx); gettimeofday(&start,NULL); do { u = runzip_chunk(control, fd_in, expected_size, total); if (unlikely(u == -1)) { print_err("Failed to runzip_chunk in runzip_fd\n"); return -1; } total += u; if (TMP_OUTBUF) { if (unlikely(!flush_tmpoutbuf(control))) { print_err("Failed to flush_tmpoutbuf in runzip_fd\n"); return -1; } } else if (STDOUT) { if (unlikely(!dump_tmpoutfile(control, fd_out))) { print_err("Failed to dump_tmpoutfile in runzip_fd\n"); return -1; } } if (TMP_INBUF) clear_tmpinbuf(control); else if (STDIN && !DECOMPRESS) { if (unlikely(!clear_tmpinfile(control))) { print_err("Failed to clear_tmpinfile in runzip_fd\n"); return -1; } } } while (total < expected_size || (!expected_size && !control->eof)); gettimeofday(&end,NULL); if (!ENCRYPT) { tdiff = end.tv_sec - start.tv_sec; if (!tdiff) tdiff = 1; print_progress("\nAverage DeCompression Speed: %6.3fMB/s\n", (total / 1024 / 1024) / tdiff); } if (!NO_MD5) { int i,j; md5_finish_ctx (&control->ctx, control->md5_resblock); if (HAS_MD5) { i64 fdinend = seekto_fdinend(control); if (unlikely(fdinend == -1)) failure_return(("Failed to seekto_fdinend in rzip_fd\n"), -1); if (unlikely(seekto_fdin(control, fdinend - MD5_DIGEST_SIZE) == -1)) failure_return(("Failed to seekto_fdin in rzip_fd\n"), -1); if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE)) fatal_return(("Failed to read md5 data in runzip_fd\n"), -1); if (ENCRYPT) if (unlikely(!lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass))) return -1; for (i = 0; i < MD5_DIGEST_SIZE; i++) if (md5_stored[i] != control->md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", md5_stored[j] & 0xFF); print_output("\nOutput file:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", control->md5_resblock[j] & 0xFF); failure_return(("\n"), -1); } } if (HASH_CHECK || MAX_VERBOSE) { print_output("MD5: "); for (i = 0; i < MD5_DIGEST_SIZE; i++) print_output("%02x", control->md5_resblock[i] & 0xFF); print_output("\n"); } if (CHECK_FILE) { FILE *md5_fstream; int i, j; if (TMP_OUTBUF) close_tmpoutbuf(control); memcpy(md5_stored, control->md5_resblock, MD5_DIGEST_SIZE); if (unlikely(seekto_fdhist(control, 0) == -1)) fatal_return(("Failed to seekto_fdhist in runzip_fd\n"), -1); if (unlikely((md5_fstream = fdopen(fd_hist, "r")) == NULL)) fatal_return(("Failed to fdopen fd_hist in runzip_fd\n"), -1); if (unlikely(md5_stream(md5_fstream, control->md5_resblock))) fatal_return(("Failed to md5_stream in runzip_fd\n"), -1); /* We don't close the file here as it's closed in main */ for (i = 0; i < MD5_DIGEST_SIZE; i++) if (md5_stored[i] != control->md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", md5_stored[j] & 0xFF); print_output("\nOutput file:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", control->md5_resblock[j] & 0xFF); failure_return(("\n"), -1); } print_output("MD5 integrity of written file matches archive\n"); if (!HAS_MD5) print_output("Note this lrzip archive did not have a stored md5 value.\n" "The archive decompression was validated with crc32 and the md5 hash was " "calculated on decompression\n"); } } return total; }
/* Return Digest authentication credentials header value for the given * session. */ static char *request_digest(http_auth_session *sess) { struct md5_ctx a2, rdig; unsigned char a2_md5[16], rdig_md5[16]; char a2_md5_ascii[33], rdig_md5_ascii[33]; char nc_value[9] = {0}, *ret; const char *qop_value; /* qop-value */ size_t retlen; /* Increase the nonce-count */ if (sess->qop != http_auth_qop_none) { sess->nonce_count++; snprintf(nc_value, 9, "%08x", sess->nonce_count); DEBUG(DEBUG_HTTPAUTH, "Nonce count is %d, nc is [%s]\n", sess->nonce_count, nc_value); } qop_value = qop_values[sess->qop]; /* Calculate H(A2). */ md5_init_ctx(&a2); md5_process_bytes(sess->method, strlen(sess->method), &a2); md5_process_bytes(":", 1, &a2); md5_process_bytes(sess->uri, strlen(sess->uri), &a2); if (sess->qop == http_auth_qop_auth_int) { /* Calculate H(entity-body) */ if (sess->got_body) { char tmp_md5_ascii[33]; unsigned char tmp_md5[16]; if (sess->body_stream != NULL) { DEBUG(DEBUG_HTTPAUTH, "Digesting body stream.\n"); md5_stream(sess->body_stream, tmp_md5); rewind(sess->body_stream); /* leave it at the beginning */ } else if (sess->body_buffer) { DEBUG(DEBUG_HTTPAUTH, "Digesting body buffer.\n"); md5_buffer(sess->body_buffer, strlen(sess->body_buffer), tmp_md5); } md5_to_ascii(tmp_md5, tmp_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "H(entity-body) is [%s]\n", tmp_md5_ascii); /* Append to A2 */ md5_process_bytes(":", 1, &a2); md5_process_bytes(tmp_md5_ascii, 32, &a2); } else { /* No entity-body. */ DEBUG(DEBUG_HTTPAUTH, "Digesting empty entity-body.\n"); md5_process_bytes(":" DIGEST_MD5_EMPTY, 33, &a2); } } md5_finish_ctx(&a2, a2_md5); md5_to_ascii(a2_md5, a2_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "H(A2): %s\n", a2_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "Calculating Request-Digest.\n"); /* Now, calculation of the Request-Digest. * The first section is the regardless of qop value * H(A1) ":" unq(nonce-value) ":" */ md5_init_ctx(&rdig); /* Use the calculated H(A1) */ md5_process_bytes(sess->h_a1, 32, &rdig); md5_process_bytes(":", 1, &rdig); md5_process_bytes(sess->unq_nonce, strlen(sess->unq_nonce), &rdig); md5_process_bytes(":", 1, &rdig); if (sess->qop != http_auth_qop_none) { /* Add on: * nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" */ DEBUG(DEBUG_HTTPAUTH, "Have qop directive, digesting: [%s:%s:%s]\n", nc_value, sess->unq_cnonce, qop_value); md5_process_bytes(nc_value, 8, &rdig); md5_process_bytes(":", 1, &rdig); md5_process_bytes(sess->unq_cnonce, strlen(sess->unq_cnonce), &rdig); md5_process_bytes(":", 1, &rdig); /* Store a copy of this structure (see note below) */ sess->stored_rdig = rdig; md5_process_bytes(qop_value, strlen(qop_value), &rdig); md5_process_bytes(":", 1, &rdig); } else { /* Store a copy of this structure... we do this because the * calculation of the rspauth= field in the Auth-Info header * is the same as this digest, up to this point. */ sess->stored_rdig = rdig; } /* And finally, H(A2) */ md5_process_bytes(a2_md5_ascii, 32, &rdig); md5_finish_ctx(&rdig, rdig_md5); md5_to_ascii(rdig_md5, rdig_md5_ascii); /* Buffer size calculation. */ retlen = 6 /* Digest */ + 1 + 8 + 1 + 2 + strlen(sess->username) /* username="******" */ + 2 + 5 + 1 + 2 + strlen(sess->unq_realm) /* , realm="..." */ + 2 + 5 + 1 + 2 + strlen(sess->unq_nonce) /* , nonce="..." */ + 2 + 3 + 1 + 2 + strlen(sess->uri) /* , uri="..." */ + 2 + 8 + 1 + 2 + 32 /* , response="..." */ + 2 + 9 + 1 + 2 + strlen(algorithm_names[sess->alg]) /* , algorithm="..." */ ; if (sess->opaque != NULL) retlen += 2 + 6 + 1 + strlen(sess->opaque); /* , opaque=... */ if (sess->qop != http_auth_qop_none) retlen += 2 + 6 + 2 + 1 + strlen(sess->unq_cnonce) + /* , cnonce="..." */ 2 + 2 + 1 + 8 + /* , nc=... */ 2 + 3 + 1 + 2 + strlen(qop_values[sess->qop]) /* , qop="..." */ ; retlen += 2; /* \r\n */ DEBUG(DEBUG_HTTPAUTH, "Calculated length of buffer: %d\n", retlen); ret = ne_calloc(retlen + 1); sprintf(ret, "Digest username=\"%s\", realm=\"%s\"" ", nonce=\"%s\", uri=\"%s\", response=\"%s\"" ", algorithm=\"%s\"", sess->username, sess->unq_realm, sess->unq_nonce, sess->uri, rdig_md5_ascii, algorithm_names[sess->alg]); if (sess->opaque != NULL) { /* We never unquote it, so it's still quoted here */ strcat(ret, ", opaque="); strcat(ret, sess->opaque); } if (sess->qop != http_auth_qop_none) { /* Add in cnonce and nc-value fields */ strcat(ret, ", cnonce=\""); strcat(ret, sess->unq_cnonce); strcat(ret, "\", nc="); strcat(ret, nc_value); strcat(ret, ", qop=\""); strcat(ret, qop_values[sess->qop]); strcat(ret, "\""); } DEBUG(DEBUG_HTTPAUTH, "Digest header field value:\n%s\n", ret); strcat(ret, "\r\n"); DEBUG(DEBUG_HTTPAUTH, "Calculated length: %d, actual length: %d\n", retlen, strlen(ret)); return ret; }
std::string Authenticity::Assay (calendar_date const& candidate ,fs::path const& data_path ) { // The cached date is valid unless it's the peremptorily-invalid // default value of JDN zero. if ( calendar_date(jdn_t(0)) != Instance().CachedDate_ && candidate == Instance().CachedDate_ ) { return "cached"; } ResetCache(); std::ostringstream oss; // Read the passkey and valid-date-range files each time // because they might change while the program is running. // They'll be validated against validated md5sums a fraction // of a second later, to guard against fraudulent manipulation. // Read saved passkey from file. std::string passkey; { fs::path passkey_path(data_path / "passkey"); fs::ifstream is(passkey_path); if(!is) { oss << "Unable to read passkey file '" << passkey_path << "'. Try reinstalling." ; return oss.str(); } is >> passkey; if(!is.eof()) { oss << "Error reading passkey file '" << passkey_path << "'. Try reinstalling." ; return oss.str(); } if(passkey.size() != chars_per_formatted_hex_byte * md5len) { oss << "Length of passkey '" << passkey << "' is " << passkey.size() << " but should be " << chars_per_formatted_hex_byte * md5len << ". Try reinstalling." ; return oss.str(); } } // Read valid date range [begin, end) from file. calendar_date begin(last_yyyy_date ()); calendar_date end (gregorian_epoch()); { fs::path expiry_path(data_path / "expiry"); fs::ifstream is(expiry_path); if(!is) { oss << "Unable to read expiry file '" << expiry_path << "'. Try reinstalling." ; return oss.str(); } is >> begin >> end; if(!is || !is.eof()) { oss << "Error reading expiry file '" << expiry_path << "'. Try reinstalling." ; return oss.str(); } } // Make sure candidate date is within valid range. if(candidate < begin) { oss << "Current date " << candidate.str() << " is invalid: this system cannot be used before " << begin.str() << ". Contact the home office." ; return oss.str(); } if(end <= candidate) { oss << "Current date " << candidate.str() << " is invalid: this system cannot be used after " << (-1 + end).str() << ". Contact the home office." ; return oss.str(); } // Validate all data files. fs::path original_path(fs::current_path()); if(0 != chdir(data_path.string().c_str())) { oss << "Unable to change directory to '" << data_path << "'. Try reinstalling." ; return oss.str(); } try { system_command("md5sum --check --status " + std::string(md5sum_file())); } catch(...) { report_exception(); oss << "At least one required file is missing, altered, or invalid." << " Try reinstalling." ; return oss.str(); } if(0 != chdir(original_path.string().c_str())) { oss << "Unable to restore directory to '" << original_path << "'. Try reinstalling." ; return oss.str(); } // The passkey must match the md5 sum of the md5 sum of the file // of md5 sums of secured files. char c_passkey[md5len]; unsigned char u_passkey[md5len]; std::FILE* md5sums_file = std::fopen ((data_path / md5sum_file()).string().c_str() ,"rb" ); md5_stream(md5sums_file, u_passkey); std::fclose(md5sums_file); std::memcpy(c_passkey, u_passkey, md5len); md5_buffer(c_passkey, md5len, u_passkey); std::memcpy(c_passkey, u_passkey, md5len); md5_buffer(c_passkey, md5len, u_passkey); std::string expected = md5_hex_string (std::vector<unsigned char>(u_passkey, u_passkey + md5len) ); if(passkey != expected) { oss << "Passkey is incorrect for this version." << " Contact the home office." ; return oss.str(); } // Cache the validated date. Instance().CachedDate_ = candidate; return "validated"; }