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

Implement auto attach #2250

Merged
merged 17 commits into from
Dec 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
5c4fea1
Client: make autologin work for account managers as well as projects.
davidpanderson Nov 16, 2017
3bd4dd0
Merge branch 'dpa_autologin_client' of https://github.com/BOINC/boinc…
davidpanderson Nov 16, 2017
a48b853
login_token_lookup RPC: make it work for account managers too
davidpanderson Nov 16, 2017
0d1c8f8
Win installer: don't overwrite project list file.
davidpanderson Nov 16, 2017
fbdb9ea
Merge branch 'dpa_autologin_client' of https://github.com/BOINC/boinc…
davidpanderson Nov 16, 2017
051f9e6
Manager: if client is auto-attaching to a project, increase the delay…
Nov 16, 2017
b8467bb
Merge branch 'dpa_autologin_client' of https://github.com/BOINC/boinc…
Nov 16, 2017
ca920a4
Manager: remove obsolete comment
Nov 16, 2017
7eec5f3
Mac installer: correctly determine package name and branding if insta…
Nov 16, 2017
3980f20
client: if autologin project ID not in project list, get new list
davidpanderson Nov 17, 2017
45868c1
client: change name of autologin file
davidpanderson Nov 17, 2017
32307b3
client: don't start two project-list fetches at once.
davidpanderson Nov 17, 2017
a8f8908
Manager: don't bother checking for autologin file before showing atta…
davidpanderson Nov 17, 2017
29183cf
client: fix autologin logic
davidpanderson Nov 17, 2017
c912d17
client: keep track of whether project list fetch was triggered by aut…
davidpanderson Nov 17, 2017
dcf5653
client: show no-projects-attached message only if not doing autologin.
Dec 1, 2017
038d274
Merge branch 'master' into dpa_autologin_client
CharlieFenton Dec 1, 2017
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
3 changes: 3 additions & 0 deletions client/acct_mgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct ACCT_MGR_INFO : PROJ_AM {
// in AM RPCs (used for "farm management")
bool no_project_notices;
// if set, don't show notices from projects

// TODO: get rid of the following
bool cookie_required;
// use of cookies are required during initial signup
// NOTE: This bool gets dropped after the client has
Expand All @@ -60,6 +62,7 @@ struct ACCT_MGR_INFO : PROJ_AM {
// if the cookies could not be detected, provide a
// link to a website to go to so the user can find
// what login name and password they have been assigned

bool password_error;
bool send_rec;
// send REC in AM RPCs
Expand Down
139 changes: 101 additions & 38 deletions client/acct_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ int GET_PROJECT_LIST_OP::do_rpc() {

void GET_PROJECT_LIST_OP::handle_reply(int http_op_retval) {
bool error = false;
error_num = 0;
if (http_op_retval) {
error_num = http_op_retval;
error = true;
Expand All @@ -232,6 +233,7 @@ void GET_PROJECT_LIST_OP::handle_reply(int http_op_retval) {
);
gstate.all_projects_list_check_time = gstate.now;
} else {
error_num = ERR_XML_PARSE;
error = true;
}
}
Expand All @@ -241,10 +243,17 @@ void GET_PROJECT_LIST_OP::handle_reply(int http_op_retval) {
gstate.all_projects_list_check_time =
gstate.now - ALL_PROJECTS_LIST_CHECK_PERIOD + SECONDS_PER_DAY;
}

// were we initiated by autologin?
//
if (gstate.autologin_fetching_project_list) {
gstate.process_autologin(false);
}
}

void CLIENT_STATE::all_projects_list_check() {
if (cc_config.dont_contact_ref_site) return;
if (get_project_list_op.gui_http->gui_http_state == GUI_HTTP_STATE_BUSY) return;
if (all_projects_list_check_time) {
if (now - all_projects_list_check_time < ALL_PROJECTS_LIST_CHECK_PERIOD) {
return;
Expand All @@ -253,36 +262,55 @@ void CLIENT_STATE::all_projects_list_check() {
get_project_list_op.do_rpc();
}

// called at startup.
// called at startup (first=true)
// or on completion of get project list RPC (first=false).
// check for installer filename file.
// If present, parse project ID and login token,
// and initiate RPC to look up token.
//
void CLIENT_STATE::process_autologin() {
int project_id, user_id, n, retval;
char buf[256], login_token[256], *p;
void CLIENT_STATE::process_autologin(bool first) {
static int project_id, user_id;
static char login_token[256];

// read and parse installer filename
//
FILE* f = boinc_fopen(ACCOUNT_DATA_FILENAME, "r");
if (!f) return;
fgets(buf, 256, f);
fclose(f);
p = strstr(buf, "__");
if (!p) {
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
msg_printf(NULL, MSG_INFO, "Read installer filename file");
p += 2;
n = sscanf(p, "%d_%d_%[^. ]", &project_id, &user_id, login_token);
// don't include the ".exe" or the " (1)"
if (n != 3) {
msg_printf(NULL, MSG_INFO, "bad account data: %s", buf);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
int n, retval;
char buf[256], *p;

if (first) {
// read and parse autologin file
//
FILE* f = boinc_fopen(ACCOUNT_DATA_FILENAME, "r");
if (!f) return;
fgets(buf, 256, f);
fclose(f);
p = strstr(buf, "__");
if (!p) {
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
msg_printf(NULL, MSG_INFO, "Read account data file");
p += 2;
n = sscanf(p, "%d_%d_%[^. ]", &project_id, &user_id, login_token);
// don't include the ".exe" or the " (1)"
if (n != 3) {
msg_printf(NULL, MSG_INFO, "bad account data: %s", buf);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
strip_whitespace(login_token);
} else {
// here the get project list RPC finished.
// check whether it failed.
//
autologin_in_progress = false;
if (get_project_list_op.error_num) {
msg_printf(NULL, MSG_INFO,
"get project list RPC failed: %s",
boincerror(get_project_list_op.error_num)
);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
}
strip_whitespace(login_token);

// check that project ID is valid, get URL
//
Expand All @@ -296,9 +324,29 @@ void CLIENT_STATE::process_autologin() {
}
PROJECT_LIST_ITEM *pli = project_list.lookup(project_id);
if (!pli) {
msg_printf(NULL, MSG_INFO, "Unknown project ID: %d", project_id);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
if (first) {
// we may have an outdated project list.
// Initiate RPC to get newest version
//
retval = get_project_list_op.do_rpc();
if (retval) {
msg_printf(NULL, MSG_INFO,
"Get project list RPC failed: %s",
boincerror(retval)
);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
autologin_in_progress = true;
// defer GUI RPCs
autologin_fetching_project_list = true;
// tell RPC handler to call us when done
return;
} else {
msg_printf(NULL, MSG_INFO, "Unknown project ID: %d", project_id);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
}

if (!pli->is_account_manager) {
Expand All @@ -320,14 +368,14 @@ void CLIENT_STATE::process_autologin() {
retval = lookup_login_token_op.do_rpc(pli, user_id, login_token);
if (retval) {
msg_printf(NULL, MSG_INFO,
"lookup token RPC failed: %s", boincerror(retval)
"token lookup RPC failed: %s", boincerror(retval)
);
boinc_delete_file(ACCOUNT_DATA_FILENAME);
}

// disable GUI RPCs until we get an RPC reply
//
gstate.enable_gui_rpcs = false;
gstate.autologin_in_progress = true;
}

int LOOKUP_LOGIN_TOKEN_OP::do_rpc(
Expand All @@ -345,16 +393,19 @@ int LOOKUP_LOGIN_TOKEN_OP::do_rpc(
// If everything checks out, attach to account manager or project.
//
void LOOKUP_LOGIN_TOKEN_OP::handle_reply(int http_op_retval) {
string user_name, team_name, weak_auth;
string user_name;
string team_name, weak_auth; // returned by projects
string login_name, passwd_hash; // returned by AMs

gstate.enable_gui_rpcs = true;
gstate.autologin_in_progress = false;

if (http_op_retval) {
msg_printf(NULL, MSG_INFO, "token lookup RPC failed: %s", boincerror(http_op_retval));
return;
}
FILE* f = boinc_fopen(LOGIN_TOKEN_LOOKUP_REPLY, "r");
if (!f) {
msg_printf(NULL, MSG_INFO, "lookup token: no reply file");
msg_printf(NULL, MSG_INFO, "token lookup RPC: no reply file");
boinc_delete_file(ACCOUNT_DATA_FILENAME);
return;
}
Expand All @@ -368,21 +419,33 @@ void LOOKUP_LOGIN_TOKEN_OP::handle_reply(int http_op_retval) {
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)) {
continue;
}
}
fclose(f);

if (!user_name.size() || !weak_auth.size()) {
msg_printf(NULL, MSG_INFO, "lookup token: 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, weak_auth.c_str());
strcpy(gstate.acct_mgr_info.password_hash, passwd_hash.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
);
Expand Down
20 changes: 10 additions & 10 deletions client/client_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ CLIENT_STATE::CLIENT_STATE()
must_check_work_fetch = true;
retry_shmem_time = 0;
no_gui_rpc = false;
enable_gui_rpcs = true;
autologin_in_progress = false;
autologin_fetching_project_list = false;
gui_rpc_unix_domain = false;
new_version_check_time = 0;
all_projects_list_check_time = 0;
Expand Down Expand Up @@ -731,7 +732,7 @@ int CLIENT_STATE::init() {

// check for initialization files
//
process_autologin();
process_autologin(true);
acct_mgr_info.init();
project_init.init();

Expand Down Expand Up @@ -787,13 +788,12 @@ int CLIENT_STATE::init() {
//
proxy_info_startup();

if (gstate.projects.size() == 0) {
msg_printf(NULL, MSG_INFO,
"This computer is not attached to any projects"
);
msg_printf(NULL, MSG_INFO,
"Visit https://boinc.berkeley.edu for instructions"
);
if (!autologin_in_progress) {
if (gstate.projects.size() == 0) {
msg_printf(NULL, MSG_INFO,
"This computer is not attached to any projects"
);
}
}

// get list of BOINC projects occasionally,
Expand Down Expand Up @@ -843,7 +843,7 @@ void CLIENT_STATE::do_io_or_sleep(double max_time) {
gui_rpc_fds.zero();
http_ops->get_fdset(curl_fds);
all_fds = curl_fds;
if (enable_gui_rpcs) {
if (!autologin_in_progress) {
gui_rpcs.get_fdset(gui_rpc_fds, all_fds);
}

Expand Down
5 changes: 3 additions & 2 deletions client/client_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ struct CLIENT_STATE {
FILE_XFER_SET* file_xfers;
#ifndef SIM
GUI_RPC_CONN_SET gui_rpcs;
bool enable_gui_rpcs;
#endif
GUI_HTTP gui_http;
#ifdef ENABLE_AUTO_UPDATE
Expand Down Expand Up @@ -247,8 +246,10 @@ struct CLIENT_STATE {
double all_projects_list_check_time;
// the time we last successfully fetched the project list
string newer_version;
bool autologin_in_progress;
bool autologin_fetching_project_list;
PROJECT_LIST project_list;
void process_autologin();
void process_autologin(bool first);

// --------------- client_state.cpp:
CLIENT_STATE();
Expand Down
2 changes: 2 additions & 0 deletions client/project_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ int PROJECT_LIST_ITEM::parse(XML_PARSER& xp, bool is_am) {
}

int PROJECT_LIST::read_file() {
items.clear();
FILE* f = fopen(ALL_PROJECTS_LIST_FILENAME, "r");
if (!f) return ERR_FOPEN;
MIOFILE mf;
Expand All @@ -56,6 +57,7 @@ int PROJECT_LIST::read_file() {
msg_printf(NULL, MSG_INTERNAL_ERROR,
"missing start tag in project list file"
);
fclose(f);
return ERR_XML_PARSE;
}
while (!xp.get_tag()) {
Expand Down
2 changes: 1 addition & 1 deletion clientgui/AdvancedFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1884,7 +1884,7 @@ void CAdvancedFrame::OnConnect(CFrameEvent& WXUNUSED(event)) {
//
m_pNotebook->SetSelection(ID_ADVNOTICESVIEW - ID_ADVVIEWBASE);
}
} else if ((0 >= pDoc->GetProjectCount()) && !status.disallow_attach && !autoattach_in_progress()) {
} else if ((0 >= pDoc->GetProjectCount()) && !status.disallow_attach) {
// client isn't attached to any projects.
// Look for an account to attach to, either in project_init.xml
// or in browser cookies
Expand Down
Loading