diff options
Diffstat (limited to 'daemons/ipa-otpd/queue.c')
-rw-r--r-- | daemons/ipa-otpd/queue.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/daemons/ipa-otpd/queue.c b/daemons/ipa-otpd/queue.c new file mode 100644 index 00000000..730bbc40 --- /dev/null +++ b/daemons/ipa-otpd/queue.c @@ -0,0 +1,183 @@ +/* + * FreeIPA 2FA companion daemon + * + * Authors: Nathaniel McCallum <npmccallum@redhat.com> + * + * Copyright (C) 2013 Nathaniel McCallum, Red Hat + * see file 'COPYING' for use and warranty information + * + * This program is free software you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * This file contains an implementation of a queue of request/response items. + */ + +#include "internal.h" + +struct otpd_queue_iter { + struct otpd_queue_item *next; + unsigned int qindx; + const struct otpd_queue * const *queues; +}; + +krb5_error_code otpd_queue_item_new(krad_packet *req, + struct otpd_queue_item **item) +{ + *item = calloc(1, sizeof(struct otpd_queue_item)); + if (*item == NULL) + return ENOMEM; + + (*item)->req = req; + (*item)->msgid = -1; + return 0; +} + +void otpd_queue_item_free(struct otpd_queue_item *item) +{ + if (item == NULL) + return; + + ldap_memfree(item->user.dn); + free(item->user.uid); + free(item->user.ipatokenRadiusUserName); + free(item->user.ipatokenRadiusConfigLink); + free(item->user.other); + free(item->radius.ipatokenRadiusServer); + free(item->radius.ipatokenRadiusSecret); + free(item->radius.ipatokenUserMapAttribute); + free(item->error); + krad_packet_free(item->req); + krad_packet_free(item->rsp); + free(item); +} + +krb5_error_code otpd_queue_iter_new(const struct otpd_queue * const *queues, + struct otpd_queue_iter **iter) +{ + *iter = calloc(1, sizeof(struct otpd_queue_iter)); + if (*iter == NULL) + return ENOMEM; + + (*iter)->queues = queues; + return 0; +} + +/* This iterator function is used by krad to loop over all outstanding requests + * to check for duplicates. Hence, we have to iterate over all the queues to + * return all the outstanding requests as a flat list. */ +const krad_packet *otpd_queue_iter_func(void *data, krb5_boolean cancel) +{ + struct otpd_queue_iter *iter = data; + const struct otpd_queue *q; + + if (cancel) { + free(iter); + return NULL; + } + + if (iter->next != NULL) { + struct otpd_queue_item *tmp; + tmp = iter->next; + iter->next = tmp->next; + return tmp->req; + } + + q = iter->queues[iter->qindx++]; + if (q == NULL) + return otpd_queue_iter_func(data, TRUE); + + iter->next = q->head; + return otpd_queue_iter_func(data, FALSE); +} + +void otpd_queue_push(struct otpd_queue *q, struct otpd_queue_item *item) +{ + if (item == NULL) + return; + + if (q->tail == NULL) + q->head = q->tail = item; + else + q->tail = q->tail->next = item; +} + +void otpd_queue_push_head(struct otpd_queue *q, struct otpd_queue_item *item) +{ + if (item == NULL) + return; + + if (q->head == NULL) + q->tail = q->head = item; + else { + item->next = q->head; + q->head = item; + } +} + +struct otpd_queue_item *otpd_queue_peek(struct otpd_queue *q) +{ + return q->head; +} + +struct otpd_queue_item *otpd_queue_pop(struct otpd_queue *q) +{ + struct otpd_queue_item *item; + + if (q == NULL) + return NULL; + + item = q->head; + if (item != NULL) + q->head = item->next; + + if (q->head == NULL) + q->tail = NULL; + + return item; +} + +/* Remove and return an item from the queue with the given msgid. */ +struct otpd_queue_item *otpd_queue_pop_msgid(struct otpd_queue *q, int msgid) +{ + struct otpd_queue_item *item, **prev; + + for (item = q->head, prev = &q->head; + item != NULL; + item = item->next, prev = &item->next) { + if (item->msgid == msgid) { + *prev = item->next; + if (q->head == NULL) + q->tail = NULL; + return item; + } + } + + return NULL; +} + +void otpd_queue_free_items(struct otpd_queue *q) +{ + struct otpd_queue_item *item, *next; + + next = q->head; + while (next != NULL) { + item = next; + next = next->next; + otpd_queue_item_free(item); + } + + q->head = NULL; + q->tail = NULL; +} |