authd/providers/blacklist: fix use after free

After calling provider_done, you must *always* assume your auth instance
is freed.
This commit is contained in:
Elizabeth Myers 2016-03-26 23:15:28 -05:00
parent f681e277eb
commit e43e61f7a7

View file

@ -73,7 +73,7 @@ struct blacklist_lookup
struct blacklist *bl; /* Blacklist we're checking */ struct blacklist *bl; /* Blacklist we're checking */
struct auth_client *auth; /* Client */ struct auth_client *auth; /* Client */
struct dns_query *query; /* DNS query pointer */ struct dns_query *query; /* DNS query pointer */
rb_dlink_node node; rb_dlink_node node;
}; };
@ -230,11 +230,13 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d
{ {
struct blacklist_lookup *bllookup = (struct blacklist_lookup *)data; struct blacklist_lookup *bllookup = (struct blacklist_lookup *)data;
struct blacklist_user *bluser; struct blacklist_user *bluser;
struct blacklist *bl;
struct auth_client *auth; struct auth_client *auth;
if (bllookup == NULL || bllookup->auth == NULL) if (bllookup == NULL || bllookup->auth == NULL)
return; return;
bl = bllookup->bl;
auth = bllookup->auth; auth = bllookup->auth;
bluser = auth->data[PROVIDER_BLACKLIST]; bluser = auth->data[PROVIDER_BLACKLIST];
if(bluser == NULL) if(bluser == NULL)
@ -244,20 +246,21 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d
{ {
/* Match found, so proceed no further */ /* Match found, so proceed no further */
blacklists_cancel(auth); blacklists_cancel(auth);
reject_client(auth, PROVIDER_BLACKLIST, bllookup->bl->reason); reject_client(auth, PROVIDER_BLACKLIST, bl->reason);
return; return;
} }
unref_blacklist(bllookup->bl); unref_blacklist(bl);
cancel_query(bllookup->query); /* Ignore future responses */
rb_dlinkDelete(&bllookup->node, &bluser->queries); rb_dlinkDelete(&bllookup->node, &bluser->queries);
rb_free(bllookup); rb_free(bllookup);
if(!rb_dlink_list_length(&bluser->queries)) if(!rb_dlink_list_length(&bluser->queries))
{ {
/* Done here */ /* Done here */
provider_done(auth, PROVIDER_BLACKLIST);
rb_free(bluser); rb_free(bluser);
auth->data[PROVIDER_BLACKLIST] = NULL; auth->data[PROVIDER_BLACKLIST] = NULL;
provider_done(auth, PROVIDER_BLACKLIST);
} }
} }
@ -398,9 +401,11 @@ blacklists_cancel(struct auth_client *auth)
RB_DLINK_FOREACH_SAFE(ptr, nptr, bluser->queries.head) RB_DLINK_FOREACH_SAFE(ptr, nptr, bluser->queries.head)
{ {
struct blacklist_lookup *bllookup = ptr->data; struct blacklist_lookup *bllookup = ptr->data;
rb_dlinkDelete(&bllookup->node, &bluser->queries);
unref_blacklist(bllookup->bl);
cancel_query(bllookup->query); cancel_query(bllookup->query);
unref_blacklist(bllookup->bl);
rb_dlinkDelete(&bllookup->node, &bluser->queries);
rb_free(bllookup); rb_free(bllookup);
} }