events: Limit subscriber count
Protect against DoS by limiting the number of subscribers we allow to a total of 500, and immediately removing subscribers from our list if we encounter an error communicating with them.
This commit is contained in:
parent
14d0110fb4
commit
37346fb0a0
26
upnpevents.c
26
upnpevents.c
@ -83,18 +83,18 @@ struct subscriber {
|
|||||||
|
|
||||||
struct upnp_event_notify {
|
struct upnp_event_notify {
|
||||||
LIST_ENTRY(upnp_event_notify) entries;
|
LIST_ENTRY(upnp_event_notify) entries;
|
||||||
int s; /* socket */
|
int s; /* socket */
|
||||||
enum { ECreated=1,
|
enum { ECreated=1,
|
||||||
EConnecting,
|
EConnecting,
|
||||||
ESending,
|
ESending,
|
||||||
EWaitingForResponse,
|
EWaitingForResponse,
|
||||||
EFinished,
|
EFinished,
|
||||||
EError } state;
|
EError } state;
|
||||||
struct subscriber * sub;
|
struct subscriber * sub;
|
||||||
char * buffer;
|
char * buffer;
|
||||||
int buffersize;
|
int buffersize;
|
||||||
int tosend;
|
int tosend;
|
||||||
int sent;
|
int sent;
|
||||||
const char * path;
|
const char * path;
|
||||||
char addrstr[16];
|
char addrstr[16];
|
||||||
char portstr[8];
|
char portstr[8];
|
||||||
@ -110,6 +110,9 @@ LIST_HEAD(listhead, subscriber) subscriberlist = { NULL };
|
|||||||
/* notify list */
|
/* notify list */
|
||||||
LIST_HEAD(listheadnotif, upnp_event_notify) notifylist = { NULL };
|
LIST_HEAD(listheadnotif, upnp_event_notify) notifylist = { NULL };
|
||||||
|
|
||||||
|
#define MAX_SUBSCRIBERS 500
|
||||||
|
static uint16_t nsubscribers = 0;
|
||||||
|
|
||||||
/* create a new subscriber */
|
/* create a new subscriber */
|
||||||
static struct subscriber *
|
static struct subscriber *
|
||||||
newSubscriber(const char * eventurl, const char * callback, int callbacklen)
|
newSubscriber(const char * eventurl, const char * callback, int callbacklen)
|
||||||
@ -151,12 +154,15 @@ upnpevents_addSubscriber(const char * eventurl,
|
|||||||
struct subscriber * tmp;
|
struct subscriber * tmp;
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "addSubscriber(%s, %.*s, %d)\n",
|
DPRINTF(E_DEBUG, L_HTTP, "addSubscriber(%s, %.*s, %d)\n",
|
||||||
eventurl, callbacklen, callback, timeout);
|
eventurl, callbacklen, callback, timeout);
|
||||||
|
if (nsubscribers >= MAX_SUBSCRIBERS)
|
||||||
|
return NULL;
|
||||||
tmp = newSubscriber(eventurl, callback, callbacklen);
|
tmp = newSubscriber(eventurl, callback, callbacklen);
|
||||||
if(!tmp)
|
if(!tmp)
|
||||||
return NULL;
|
return NULL;
|
||||||
if(timeout)
|
if(timeout)
|
||||||
tmp->timeout = time(NULL) + timeout;
|
tmp->timeout = time(NULL) + timeout;
|
||||||
LIST_INSERT_HEAD(&subscriberlist, tmp, entries);
|
LIST_INSERT_HEAD(&subscriberlist, tmp, entries);
|
||||||
|
nsubscribers++;
|
||||||
upnp_event_create_notify(tmp);
|
upnp_event_create_notify(tmp);
|
||||||
return tmp->uuid;
|
return tmp->uuid;
|
||||||
}
|
}
|
||||||
@ -189,6 +195,7 @@ upnpevents_removeSubscriber(const char * sid, int sidlen)
|
|||||||
sub->notify->sub = NULL;
|
sub->notify->sub = NULL;
|
||||||
}
|
}
|
||||||
LIST_REMOVE(sub, entries);
|
LIST_REMOVE(sub, entries);
|
||||||
|
nsubscribers--;
|
||||||
free(sub);
|
free(sub);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -468,28 +475,27 @@ void upnpevents_processfds(fd_set *readset, fd_set *writeset)
|
|||||||
}
|
}
|
||||||
if(obj->sub)
|
if(obj->sub)
|
||||||
obj->sub->notify = NULL;
|
obj->sub->notify = NULL;
|
||||||
#if 0 /* Just let it time out instead of explicitly removing the subscriber */
|
|
||||||
/* remove also the subscriber from the list if there was an error */
|
/* remove also the subscriber from the list if there was an error */
|
||||||
if(obj->state == EError && obj->sub) {
|
if(obj->state == EError && obj->sub) {
|
||||||
LIST_REMOVE(obj->sub, entries);
|
LIST_REMOVE(obj->sub, entries);
|
||||||
|
nsubscribers--;
|
||||||
free(obj->sub);
|
free(obj->sub);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
free(obj->buffer);
|
free(obj->buffer);
|
||||||
LIST_REMOVE(obj, entries);
|
LIST_REMOVE(obj, entries);
|
||||||
free(obj);
|
free(obj);
|
||||||
}
|
}
|
||||||
obj = next;
|
obj = next;
|
||||||
}
|
}
|
||||||
/* remove timeouted subscribers */
|
/* remove timed-out subscribers */
|
||||||
curtime = time(NULL);
|
curtime = time(NULL);
|
||||||
for(sub = subscriberlist.lh_first; sub != NULL; ) {
|
for(sub = subscriberlist.lh_first; sub != NULL; ) {
|
||||||
subnext = sub->entries.le_next;
|
subnext = sub->entries.le_next;
|
||||||
if(sub->timeout && curtime > sub->timeout && sub->notify == NULL) {
|
if(sub->timeout && curtime > sub->timeout && sub->notify == NULL) {
|
||||||
LIST_REMOVE(sub, entries);
|
LIST_REMOVE(sub, entries);
|
||||||
|
nsubscribers--;
|
||||||
free(sub);
|
free(sub);
|
||||||
}
|
}
|
||||||
sub = subnext;
|
sub = subnext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user