scheduler: changes to allow the code signing key to be changed.

Aargh!  My checkin of 31 Aug 2011 causes the client to strip the trailing \n
from the code-signing key; this change affects 7.0+ clients.
This broke the documented protocol for changing code-signing keys,
since signatures for the new key with the trailing \n won't work.

Solution: when you change code-signing key,
you have to sign both the stripped and non-stripped versions
of the new public key.
See http://boinc.berkeley.edu/trac/wiki/CodeSigning

This required a change to the scheduler so that it sends
one signature or the other based on client version
(stripped for 7.0+, else unstripped).
This change is entirely within send_code_sign_key(),
in case you want to update just that.
This commit is contained in:
David Anderson 2014-08-29 13:35:51 -07:00
parent e7b4910213
commit a7c6b32ca2
1 changed files with 68 additions and 59 deletions

View File

@ -834,7 +834,7 @@ int handle_global_prefs() {
// if the client has an old code sign public key,
// send it the new one, with a signature based on the old one.
// If they don't have a code sign key, send them one.
// Return false if they have a key we recognize
// Return false if they have a key we don't recognize
// (in which case we won't send them work).
//
bool send_code_sign_key(char* code_sign_key) {
@ -842,70 +842,79 @@ bool send_code_sign_key(char* code_sign_key) {
int i, retval;
char path[MAXPATHLEN];
if (strlen(g_request->code_sign_key)) {
if (strcmp(g_request->code_sign_key, code_sign_key)) {
log_messages.printf(MSG_NORMAL, "received old code sign key\n");
if (!strlen(g_request->code_sign_key)) {
safe_strcpy(g_reply->code_sign_key, code_sign_key);
return true;
}
if (!strcmp(g_request->code_sign_key, code_sign_key)) {
return true;
}
// look for a signature file for the key the client has.
// these are in pairs of files (N = 0, 1, ...)
// old_key_N: contains an old key
// signature_N: contains a signature for new key,
// based on the old key
// A project can have several of these pairs if it wants,
// e.g. if it changes keys a lot.
log_messages.printf(MSG_NORMAL, "received old code sign key\n");
// look for a signature file for the client's key.
// These are in pairs of files (N = 0, 1, ...)
// old_key_N: contains an old key
// signature_N: contains a signature for new key,
// based on the old key
// signature_stripped_N: signature for new key w/ trailing \n removed
// (needed for 7.0+ clients, which strip trailing whitespace)
//
// A project can have several of these if it wants,
// e.g. if it changes keys a lot.
//
for (i=0; ; i++) {
sprintf(path, "%s/old_key_%d", config.key_dir, i);
retval = read_file_malloc(path, oldkey);
if (retval) {
// we've scanned all the signature files and
// didn't find one that worked.
// User must reattach.
//
for (i=0; ; i++) {
sprintf(path, "%s/old_key_%d", config.key_dir, i);
retval = read_file_malloc(path, oldkey);
if (retval) {
// we've scanned all the signature files and
// didn't find one that worked.
// User must reattach.
//
g_reply->insert_message(
_("Invalid code signing key. To fix, remove and add this project."),
"notice"
);
return false;
}
strip_whitespace(oldkey);
if (!strcmp(oldkey, g_request->code_sign_key)) {
// We've found the client's key.
// Get the signature for the new key.
//
sprintf(path, "%s/signature_%d", config.key_dir, i);
retval = read_file_malloc(path, signature);
if (retval) {
// project is missing the signature file.
// Tell the user to reattach.
//
g_reply->insert_message(
_("The project has changed its security key. Please remove and add this project."),
"notice"
);
log_messages.printf(MSG_CRITICAL,
"Missing signature file for old key %d\n", i
);
free(oldkey);
return false;
} else {
log_messages.printf(MSG_NORMAL,
"sending new code sign key and signature\n"
);
safe_strcpy(g_reply->code_sign_key, code_sign_key);
safe_strcpy(g_reply->code_sign_key_signature, signature);
free(signature);
free(oldkey);
return true;
}
}
log_messages.printf(MSG_CRITICAL,
"scanned old_key_i files, can find client's key\n"
);
break;
}
strip_whitespace(oldkey);
if (!strcmp(oldkey, g_request->code_sign_key)) {
// We've found the client's key.
// Get the signature for the new key.
//
if (g_request->core_client_major_version < 7) {
sprintf(path, "%s/signature_%d", config.key_dir, i);
} else {
sprintf(path, "%s/signature_stripped_%d", config.key_dir, i);
}
retval = read_file_malloc(path, signature);
if (retval) {
// project is missing the signature file.
// Tell the user to reattach.
//
log_messages.printf(MSG_CRITICAL,
"Missing signature file for old key %d\n", i
);
free(oldkey);
break;
} else {
log_messages.printf(MSG_NORMAL,
"sending new code sign key and signature\n"
);
safe_strcpy(g_reply->code_sign_key, code_sign_key);
safe_strcpy(g_reply->code_sign_key_signature, signature);
free(signature);
free(oldkey);
return true;
}
}
} else {
safe_strcpy(g_reply->code_sign_key, code_sign_key);
free(oldkey);
}
return true;
g_reply->insert_message(
_("The project has changed its security key. Please remove and add this project."),
"notice"
);
return false;
}
// If <min_core_client_version_announced> is set,