/** Generate a new certificate for our loaded or generated keys, and write it * to disk. Return 0 on success, nonzero on failure. */ static int generate_certificate(void) { char buf[8192]; time_t now = time(NULL); struct tm tm; char published[ISO_TIME_LEN+1]; char expires[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; char *ident = key_to_string(identity_key); char *signing = key_to_string(signing_key); FILE *f; size_t signed_len; char digest[DIGEST_LEN]; char signature[1024]; /* handles up to 8192-bit keys. */ int r; get_fingerprint(identity_key, fingerprint); tor_localtime_r(&now, &tm); tm.tm_mon += months_lifetime; format_iso_time(published, now); format_iso_time(expires, mktime(&tm)); tor_snprintf(buf, sizeof(buf), "dir-key-certificate-version 3" "%s%s" "\nfingerprint %s\n" "dir-key-published %s\n" "dir-key-expires %s\n" "dir-identity-key\n%s" "dir-signing-key\n%s" "dir-key-certification\n", address?"\ndir-address ":"", address?address:"", fingerprint, published, expires, ident, signing); tor_free(ident); tor_free(signing); signed_len = strlen(buf); SHA1((const unsigned char*)buf,signed_len,(unsigned char*)digest); r = RSA_private_encrypt(DIGEST_LEN, (unsigned char*)digest, (unsigned char*)signature, EVP_PKEY_get1_RSA(identity_key), RSA_PKCS1_PADDING); strlcat(buf, "-----BEGIN SIGNATURE-----\n", sizeof(buf)); signed_len = strlen(buf); base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r); strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf)); if (!(f = fopen(certificate_file, "w"))) { log_err(LD_GENERAL, "Couldn't open %s for writing: %s", certificate_file, strerror(errno)); return 1; } fputs(buf, f); fclose(f); return 0; }
/** If get_end, return the end of the accounting period that contains * the time <b>now</b>. Else, return the start of the accounting * period that contains the time <b>now</b> */ static time_t edge_of_accounting_period_containing(time_t now, int get_end) { int before; struct tm tm; tor_localtime_r(&now, &tm); /* Set 'before' to true iff the current time is before the hh:mm * changeover time for today. */ before = tm.tm_hour < cfg_start_hour || (tm.tm_hour == cfg_start_hour && tm.tm_min < cfg_start_min); /* Dispatch by unit. First, find the start day of the given period; * then, if get_end is true, increment to the end day. */ switch (cfg_unit) { case UNIT_MONTH: { /* If this is before the Nth, we want the Nth of last month. */ if (tm.tm_mday < cfg_start_day || (tm.tm_mday < cfg_start_day && before)) { --tm.tm_mon; } /* Otherwise, the month is correct. */ tm.tm_mday = cfg_start_day; if (get_end) ++tm.tm_mon; break; } case UNIT_WEEK: { /* What is the 'target' day of the week in struct tm format? (We say Sunday==7; struct tm says Sunday==0.) */ int wday = cfg_start_day % 7; /* How many days do we subtract from today to get to the right day? */ int delta = (7+tm.tm_wday-wday)%7; /* If we are on the right day, but the changeover hasn't happened yet, * then subtract a whole week. */ if (delta == 0 && before) delta = 7; tm.tm_mday -= delta; if (get_end) tm.tm_mday += 7; break; } case UNIT_DAY: if (before) --tm.tm_mday; if (get_end) ++tm.tm_mday; break; default: tor_assert(0); } tm.tm_hour = cfg_start_hour; tm.tm_min = cfg_start_min; tm.tm_sec = 0; tm.tm_isdst = -1; /* Autodetect DST */ return mktime(&tm); }
/** Helper: Write the standard prefix for log lines to a * <b>buf_len</b> character buffer in <b>buf</b>. */ static INLINE size_t _log_prefix(char *buf, size_t buf_len, int severity) { time_t t; struct timeval now; struct tm tm; size_t n; int r; tor_gettimeofday(&now); t = (time_t)now.tv_sec; n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm)); r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", (int)now.tv_usec / 1000, sev_to_string(severity)); if (r<0) return buf_len-1; else return n+r; }