summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-otpd/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/ipa-otpd/queue.c')
-rw-r--r--daemons/ipa-otpd/queue.c183
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;
+}