Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry Picks to Client Release 7.10 branch #2429

Merged
merged 5 commits into from
Apr 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 52 additions & 32 deletions client/acct_mgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,12 @@ static const char *run_mode_name[] = {"", "always", "auto", "never"};
// do an account manager RPC;
// if URL is null, detach from current account manager
//
int ACCT_MGR_OP::do_rpc(
string _url, string name, string password_hash, bool _via_gui
) {
int ACCT_MGR_OP::do_rpc(ACCT_MGR_INFO& _ami, bool _via_gui) {
int retval;
unsigned int i;
char url[256], password[256], buf[256];
FILE *pwdf;
char buf[256];

strlcpy(url, _url.c_str(), sizeof(url));
ami = _ami;

error_num = ERR_IN_PROGRESS;
error_str = "";
Expand All @@ -70,7 +67,7 @@ int ACCT_MGR_OP::do_rpc(

// if null URL, detach from current AMS
//
if (!strlen(url) && strlen(gstate.acct_mgr_info.master_url)) {
if (!strlen(ami.master_url) && strlen(gstate.acct_mgr_info.master_url)) {
msg_printf(NULL, MSG_INFO, "Removing account manager info");
gstate.acct_mgr_info.clear();
boinc_delete_file(ACCT_MGR_URL_FILENAME);
Expand All @@ -84,29 +81,35 @@ int ACCT_MGR_OP::do_rpc(
return 0;
}

canonicalize_master_url(url, sizeof(url));
if (!valid_master_url(url)) {
canonicalize_master_url(ami.master_url, sizeof(ami.master_url));
if (!valid_master_url(ami.master_url)) {
error_num = ERR_INVALID_URL;
return 0;
}

strlcpy(ami.master_url, url, sizeof(ami.master_url));
strlcpy(ami.project_name, "", sizeof(ami.project_name));
strlcpy(ami.login_name, name.c_str(), sizeof(ami.login_name));
strlcpy(ami.password_hash, password_hash.c_str(), sizeof(ami.password_hash));

FILE* f = boinc_fopen(ACCT_MGR_REQUEST_FILENAME, "w");
if (!f) return ERR_FOPEN;
fprintf(f,
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
"<acct_mgr_request>\n"
" <name>%s</name>\n"
" <password_hash>%s</password_hash>\n"
);
if (strlen(ami.authenticator)) {
fprintf(f,
" <authenticator>%s</authenticator>\n",
ami.authenticator
);
} else {
fprintf(f,
" <name>%s</name>\n"
" <password_hash>%s</password_hash>\n",
ami.login_name, ami.password_hash
);
}
fprintf(f,
" <host_cpid>%s</host_cpid>\n"
" <domain_name>%s</domain_name>\n"
" <client_version>%d.%d.%d</client_version>\n"
" <run_mode>%s</run_mode>\n",
name.c_str(), password_hash.c_str(),
gstate.host_info.host_cpid,
gstate.host_info.domain_name,
gstate.core_client_version.major,
Expand All @@ -122,7 +125,7 @@ int ACCT_MGR_OP::do_rpc(
);
}

// If the AMS requested it, send GUI RPC port and password hash.
// If the AMS requested it, send GUI RPC port and password.
// This is for the "farm" account manager so it
// can know where to send GUI RPC requests to
// without having to configure each host
Expand All @@ -134,15 +137,19 @@ int ACCT_MGR_OP::do_rpc(
fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", GUI_RPC_PORT);
}
if (boinc_file_exists(GUI_RPC_PASSWD_FILE)) {
safe_strcpy(password, "");
pwdf = fopen(GUI_RPC_PASSWD_FILE, "r");
char gui_rpc_password[256];
safe_strcpy(gui_rpc_password, "");
FILE* pwdf = fopen(GUI_RPC_PASSWD_FILE, "r");
if (pwdf) {
if (fgets(password, 256, pwdf)) {
strip_whitespace(password);
if (fgets(gui_rpc_password, 256, pwdf)) {
strip_whitespace(gui_rpc_password);
}
fclose(pwdf);
}
fprintf(f," <gui_rpc_password>%s</gui_rpc_password>\n", password);
fprintf(f,
" <gui_rpc_password>%s</gui_rpc_password>\n",
gui_rpc_password
);
}
}
for (i=0; i<gstate.projects.size(); i++) {
Expand Down Expand Up @@ -228,15 +235,15 @@ int ACCT_MGR_OP::do_rpc(
gstate.net_stats.write(mf);
fprintf(f, "</acct_mgr_request>\n");
fclose(f);
snprintf(buf, sizeof(buf), "%srpc.php", url);
snprintf(buf, sizeof(buf), "%srpc.php", ami.master_url);
retval = gui_http->do_rpc_post(
this, buf, ACCT_MGR_REQUEST_FILENAME, ACCT_MGR_REPLY_FILENAME, true
);
if (retval) {
error_num = retval;
return retval;
}
msg_printf(NULL, MSG_INFO, "Contacting account manager at %s", url);
msg_printf(NULL, MSG_INFO, "Contacting account manager at %s", ami.master_url);

return 0;
}
Expand Down Expand Up @@ -376,6 +383,7 @@ int ACCT_MGR_OP::parse(FILE* f) {
}
if (xp.match_tag("/acct_mgr_reply")) return 0;
if (xp.parse_str("name", ami.project_name, 256)) continue;
if (xp.parse_str("authenticator", ami.authenticator, 256)) continue;
if (xp.parse_int("error_num", error_num)) continue;
if (xp.parse_string("error", error_str)) continue;
if (xp.parse_string("error_msg", error_str)) continue;
Expand Down Expand Up @@ -585,6 +593,7 @@ void ACCT_MGR_OP::handle_reply(int http_op_retval) {
safe_strcpy(gstate.acct_mgr_info.master_url, ami.master_url);
safe_strcpy(gstate.acct_mgr_info.login_name, ami.login_name);
safe_strcpy(gstate.acct_mgr_info.password_hash, ami.password_hash);
safe_strcpy(gstate.acct_mgr_info.authenticator, ami.authenticator);
gstate.acct_mgr_info.no_project_notices = ami.no_project_notices;

// process projects
Expand Down Expand Up @@ -824,15 +833,26 @@ int ACCT_MGR_INFO::write_info() {
}
fprintf(f,
"<acct_mgr_login>\n"
" <login>%s</login>\n"
" <password_hash>%s</password_hash>\n"
);
if (strlen(authenticator)) {
fprintf(f,
" <authenticator>%s</authenticator>\n",
authenticator
);
} else {
fprintf(f,
" <login>%s</login>\n"
" <password_hash>%s</password_hash>\n",
login_name,
password_hash
);
}
fprintf(f,
" <previous_host_cpid>%s</previous_host_cpid>\n"
" <next_rpc_time>%f</next_rpc_time>\n"
" <opaque>\n%s\n"
" </opaque>\n"
" <no_project_notices>%d</no_project_notices>\n",
login_name,
password_hash,
previous_host_cpid,
next_rpc_time,
opaque,
Expand All @@ -853,6 +873,7 @@ void ACCT_MGR_INFO::clear() {
safe_strcpy(login_name, "");
safe_strcpy(user_name, "");
safe_strcpy(password_hash, "");
safe_strcpy(authenticator, "");
safe_strcpy(signing_key, "");
safe_strcpy(previous_host_cpid, "");
safe_strcpy(opaque, "");
Expand Down Expand Up @@ -889,6 +910,7 @@ int ACCT_MGR_INFO::parse_login_file(FILE* p) {
if (xp.match_tag("/acct_mgr_login")) break;
else if (xp.parse_str("login", login_name, 256)) continue;
else if (xp.parse_str("password_hash", password_hash, 256)) continue;
else if (xp.parse_str("authenticator", authenticator, 256)) continue;
else if (xp.parse_str("previous_host_cpid", previous_host_cpid, sizeof(previous_host_cpid))) continue;
else if (xp.parse_double("next_rpc_time", next_rpc_time)) continue;
else if (xp.match_tag("opaque")) {
Expand Down Expand Up @@ -1002,9 +1024,7 @@ bool ACCT_MGR_INFO::poll() {
// default synch period is 1 day
//
next_rpc_time = gstate.now + 86400;
gstate.acct_mgr_op.do_rpc(
master_url, login_name, password_hash, false
);
gstate.acct_mgr_op.do_rpc(*this, false);
return true;
}
return false;
Expand Down
17 changes: 12 additions & 5 deletions client/acct_mgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,18 @@ struct ACCT_MGR_INFO : PROJ_AM {
// the following used to be std::string but there
// were mysterious bugs where setting it to "" didn't work
//

// Account managers originally authenticated with name/password;
// e.g. BAM!, Gridrepublic.
// This has drawbacks, e.g. no way to change password.
// So we added the option of using a random-string authenticator.
// If this is present, use it rather than name/passwd.
//
char login_name[256]; // unique name (could be email addr)
char user_name[256]; // non-unique name
char password_hash[256];
// md5 of password.lowercase(login_name)
char authenticator[256];
char opaque[256];
// opaque data, from the AM, to be included in future AM requests
char signing_key[MAX_KEY_LEN];
Expand Down Expand Up @@ -70,12 +78,14 @@ struct ACCT_MGR_INFO : PROJ_AM {

inline bool using_am() {
if (!strlen(master_url)) return false;
if (strlen(authenticator)) return true;
if (!strlen(login_name)) return false;
if (!strlen(password_hash)) return false;
return true;
}
inline bool same_am(const char* mu, const char* ln, const char* ph) {
inline bool same_am(const char* mu, const char* ln, const char* ph, const char* auth) {
if (strcmp(mu, master_url)) return false;
if (!strcmp(auth, authenticator)) return true;
if (strcmp(ln, login_name)) return false;
if (strcmp(ph, password_hash)) return false;
return true;
Expand Down Expand Up @@ -155,10 +165,7 @@ struct ACCT_MGR_OP: public GUI_HTTP_OP {
bool got_rss_feeds;
std::vector<RSS_FEED>rss_feeds;

int do_rpc(
std::string url, std::string name, std::string password,
bool via_gui
);
int do_rpc(ACCT_MGR_INFO&, bool via_gui);
int parse(FILE*);
virtual void handle_reply(int http_op_retval);

Expand Down
29 changes: 9 additions & 20 deletions client/acct_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,7 @@ int LOOKUP_LOGIN_TOKEN_OP::do_rpc(
//
void LOOKUP_LOGIN_TOKEN_OP::handle_reply(int http_op_retval) {
string user_name;
string team_name, weak_auth; // returned by projects
string login_name, passwd_hash; // returned by AMs
string team_name, authenticator;

gstate.autologin_in_progress = false;

Expand All @@ -417,37 +416,27 @@ void LOOKUP_LOGIN_TOKEN_OP::handle_reply(int http_op_retval) {
continue;
} else if (xp.parse_string("team_name", team_name)) {
continue;
} else if (xp.parse_string("weak_auth", weak_auth)) {
continue;
} else if (xp.parse_string("login_name", login_name)) {
continue;
} else if (xp.parse_string("passwd_hash", passwd_hash)) {
} else if (xp.parse_string("authenticator", authenticator)) {
continue;
}
}
fclose(f);

if (!user_name.size() || !authenticator.size()) {
msg_printf(NULL, MSG_INFO, "token lookup RPC: missing info");
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}

if (pli->is_account_manager) {
if (!login_name.size() || !passwd_hash.size()) {
msg_printf(NULL, MSG_INFO, "token lookup RPC: missing info");
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
msg_printf(NULL, MSG_INFO, "Using account manager %s", pli->name.c_str());
strcpy(gstate.acct_mgr_info.master_url, pli->master_url.c_str());
strcpy(gstate.acct_mgr_info.login_name, login_name.c_str());
strcpy(gstate.acct_mgr_info.user_name, user_name.c_str());
strcpy(gstate.acct_mgr_info.password_hash, passwd_hash.c_str());
strcpy(gstate.acct_mgr_info.authenticator, authenticator.c_str());
} else {
if (!user_name.size() || !weak_auth.size()) {
msg_printf(NULL, MSG_INFO, "token lookup RPC: missing info");
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
msg_printf(NULL, MSG_INFO, "Attaching to project %s", pli->name.c_str());
gstate.add_project(
pli->master_url.c_str(), weak_auth.c_str(), pli->name.c_str(), false
pli->master_url.c_str(), authenticator.c_str(), pli->name.c_str(), false
);
PROJECT *p = gstate.lookup_project(pli->master_url.c_str());
if (p) {
Expand Down
16 changes: 12 additions & 4 deletions client/gui_rpc_server_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,9 @@ static void handle_acct_mgr_info(GUI_RPC_CONN& grc) {
gstate.acct_mgr_info.project_name
);

if (strlen(gstate.acct_mgr_info.login_name)) {
if (strlen(gstate.acct_mgr_info.login_name)
|| strlen(gstate.acct_mgr_info.authenticator)
) {
grc.mfout.printf(" <have_credentials/>\n");
}

Expand Down Expand Up @@ -938,7 +940,7 @@ static void handle_project_attach_poll(GUI_RPC_CONN& grc) {
// url/name/passwd args are null
//
static void handle_acct_mgr_rpc(GUI_RPC_CONN& grc) {
string url, name, password;
string url, name, password, authenticator;
string password_hash, name_lc;
bool use_config_file = false;
bool bad_arg = false;
Expand Down Expand Up @@ -971,6 +973,7 @@ static void handle_acct_mgr_rpc(GUI_RPC_CONN& grc) {
url = gstate.acct_mgr_info.master_url;
name = gstate.acct_mgr_info.login_name;
password_hash = gstate.acct_mgr_info.password_hash;
authenticator = gstate.acct_mgr_info.authenticator;
}
} else {
bad_arg = !url_found || !name_found || !password_found;
Expand All @@ -990,11 +993,16 @@ static void handle_acct_mgr_rpc(GUI_RPC_CONN& grc) {
grc.mfout.printf("<error>bad arg</error>\n");
} else if (gstate.acct_mgr_info.using_am()
&& !url.empty()
&& !gstate.acct_mgr_info.same_am(url.c_str(), name.c_str(), password_hash.c_str())
&& !gstate.acct_mgr_info.same_am(url.c_str(), name.c_str(), password_hash.c_str(), authenticator.c_str())
){
grc.mfout.printf("<error>attached to a different AM - detach first</error>\n");
} else {
gstate.acct_mgr_op.do_rpc(url, name, password_hash, true);
ACCT_MGR_INFO ami;
safe_strcpy(ami.master_url, url.c_str());
safe_strcpy(ami.login_name, name.c_str());
safe_strcpy(ami.password_hash, password_hash.c_str());
safe_strcpy(ami.authenticator, authenticator.c_str());
gstate.acct_mgr_op.do_rpc(ami, true);
grc.mfout.printf("<success/>\n");
}
}
Expand Down
2 changes: 1 addition & 1 deletion client/scripts/boinc-client.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ProtectHome=true
Type=simple
Nice=10
User=boinc
WorkingDirectory=~
WorkingDirectory=/var/lib/boinc
ExecStart=@exec_prefix@/bin/boinc
ExecStop=@exec_prefix@/bin/boinccmd --quit
ExecReload=@exec_prefix@/bin/boinccmd --read_cc_config
Expand Down
Loading