authd: clean up refcounting stuff
This commit is contained in:
parent
45e6c74631
commit
4434f37513
1 changed files with 45 additions and 35 deletions
|
@ -88,7 +88,8 @@ destroy_providers(void)
|
||||||
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
|
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
|
||||||
{
|
{
|
||||||
/* TBD - is this the right thing? */
|
/* TBD - is this the right thing? */
|
||||||
reject_client(auth, -1, "destroy", "Authentication system is down... try reconnecting in a few seconds");
|
reject_client(auth, UINT32_MAX, "destroy",
|
||||||
|
"Authentication system is down... try reconnecting in a few seconds");
|
||||||
}
|
}
|
||||||
|
|
||||||
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
|
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
|
||||||
|
@ -114,7 +115,17 @@ load_provider(struct auth_provider *provider)
|
||||||
rb_dlinkDestroy(free_pids.head, &free_pids);
|
rb_dlinkDestroy(free_pids.head, &free_pids);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if(pid == UINT32_MAX)
|
||||||
|
{
|
||||||
|
/* If this happens, well, I don't know what to say. Probably a bug.
|
||||||
|
* In any case, UINT32_MAX is a special sentinel. */
|
||||||
|
warn_opers(L_WARN, "Cannot load additional provider, max reached!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
provider->id = pid++;
|
provider->id = pid++;
|
||||||
|
}
|
||||||
|
|
||||||
if(provider->opt_handlers != NULL)
|
if(provider->opt_handlers != NULL)
|
||||||
{
|
{
|
||||||
|
@ -157,21 +168,24 @@ unload_provider(struct auth_provider *provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Cancel outstanding providers for a client */
|
/* Cancel outstanding providers for a client (if any) and free the auth instance
|
||||||
|
* WARNING: do not use auth instance after calling! */
|
||||||
void
|
void
|
||||||
cancel_providers(struct auth_client *auth)
|
cancel_providers(struct auth_client *auth)
|
||||||
{
|
{
|
||||||
rb_dictionary_iter iter;
|
if(auth->refcount > 0)
|
||||||
struct auth_provider *provider;
|
|
||||||
|
|
||||||
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
|
|
||||||
{
|
{
|
||||||
if(provider->cancel != NULL && is_provider_running(auth, provider->id))
|
rb_dictionary_iter iter;
|
||||||
/* Cancel if required */
|
struct auth_provider *provider;
|
||||||
provider->cancel(auth);
|
|
||||||
|
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
|
||||||
|
{
|
||||||
|
if(provider->cancel != NULL && is_provider_running(auth, provider->id))
|
||||||
|
/* Cancel if required */
|
||||||
|
provider->cancel(auth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auth->refcount = 0;
|
|
||||||
rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid));
|
rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid));
|
||||||
rb_free(auth->data);
|
rb_free(auth->data);
|
||||||
rb_free(auth);
|
rb_free(auth);
|
||||||
|
@ -185,17 +199,19 @@ provider_done(struct auth_client *auth, uint32_t id)
|
||||||
rb_dictionary_iter iter;
|
rb_dictionary_iter iter;
|
||||||
struct auth_provider *provider;
|
struct auth_provider *provider;
|
||||||
|
|
||||||
if(auth->refcount == 1 && !auth->providers_starting)
|
lrb_assert(is_provider_running(auth, id));
|
||||||
|
lrb_assert(id != UINT32_MAX);
|
||||||
|
lrb_assert(id <= pid);
|
||||||
|
|
||||||
|
set_provider_done(auth, id);
|
||||||
|
|
||||||
|
if(auth->refcount == 0 && !auth->providers_starting)
|
||||||
{
|
{
|
||||||
/* Providers aren't being executed and refcount is 1 (last provider), accept */
|
/* All done */
|
||||||
accept_client(auth, id);
|
accept_client(auth, id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_provider_done(auth, id);
|
|
||||||
|
|
||||||
/* It's safe to use auth below, since refcount will be > 0, per above
|
|
||||||
* Thus the object will still be live */
|
|
||||||
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
|
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
|
||||||
{
|
{
|
||||||
if(provider->completed != NULL && is_provider_running(auth, provider->id))
|
if(provider->completed != NULL && is_provider_running(auth, provider->id))
|
||||||
|
@ -204,7 +220,7 @@ provider_done(struct auth_client *auth, uint32_t id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reject a client
|
/* Reject a client and cancel any outstanding providers
|
||||||
* WARNING: do not use auth instance after calling! */
|
* WARNING: do not use auth instance after calling! */
|
||||||
void
|
void
|
||||||
reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...)
|
reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...)
|
||||||
|
@ -213,9 +229,6 @@ reject_client(struct auth_client *auth, uint32_t id, const char *data, const cha
|
||||||
char buf[BUFSIZE];
|
char buf[BUFSIZE];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
if(data == NULL)
|
|
||||||
data = "*";
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
@ -227,15 +240,15 @@ reject_client(struct auth_client *auth, uint32_t id, const char *data, const cha
|
||||||
rb_helper_write(authd_helper, "R %x %c %s %s %s :%s",
|
rb_helper_write(authd_helper, "R %x %c %s %s %s :%s",
|
||||||
auth->cid, auth->data[id].provider->letter,
|
auth->cid, auth->data[id].provider->letter,
|
||||||
auth->username, auth->hostname,
|
auth->username, auth->hostname,
|
||||||
data, buf);
|
data == NULL ? "*" : data, buf);
|
||||||
|
|
||||||
set_provider_done(auth, id);
|
if(id != UINT32_MAX)
|
||||||
if(--refcount > 0)
|
set_provider_done(auth, id);
|
||||||
/* We have providers remaining, let them clean up */
|
|
||||||
cancel_providers(auth);
|
cancel_providers(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accept a client, cancel outstanding providers if any
|
/* Accept a client and cancel outstanding providers if any
|
||||||
* WARNING: do not use auth instance after calling! */
|
* WARNING: do not use auth instance after calling! */
|
||||||
void
|
void
|
||||||
accept_client(struct auth_client *auth, uint32_t id)
|
accept_client(struct auth_client *auth, uint32_t id)
|
||||||
|
@ -244,10 +257,10 @@ accept_client(struct auth_client *auth, uint32_t id)
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname);
|
rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname);
|
||||||
|
|
||||||
set_provider_done(auth, id);
|
if(id != UINT32_MAX)
|
||||||
if(--refcount > 0)
|
set_provider_done(auth, id);
|
||||||
/* We have providers remaining, let them clean up */
|
|
||||||
cancel_providers(auth);
|
cancel_providers(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Begin authenticating user */
|
/* Begin authenticating user */
|
||||||
|
@ -297,17 +310,14 @@ start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_
|
||||||
|
|
||||||
/* Execute providers */
|
/* Execute providers */
|
||||||
if(!provider->start(auth))
|
if(!provider->start(auth))
|
||||||
{
|
|
||||||
/* Rejected immediately */
|
/* Rejected immediately */
|
||||||
cancel_providers(auth);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auth->providers_starting = false;
|
auth->providers_starting = false;
|
||||||
|
|
||||||
/* If no providers are running, accept the client */
|
/* If no providers are running, accept the client */
|
||||||
if(!auth->refcount)
|
if(auth->refcount == 0)
|
||||||
accept_client(auth, -1);
|
accept_client(auth, UINT32_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for the initiation */
|
/* Callback for the initiation */
|
||||||
|
|
Loading…
Reference in a new issue