+static int auth2_challenge_start(Authctxt *authctxt);
+static int send_userauth_info_request(Authctxt *authctxt);
+static void input_userauth_info_response(int type, int plen, void *ctxt);
+
+#ifdef BSD_AUTH
+extern KbdintDevice bsdauth_device;
+#else
+#ifdef SKEY
+extern KbdintDevice skey_device;
+#endif
+#endif
+
+KbdintDevice *devices[] = {
+#ifdef BSD_AUTH
+ &bsdauth_device,
+#else
+#ifdef SKEY
+ &skey_device,
+#endif
+#endif
+ NULL
+};
+
+typedef struct KbdintAuthctxt KbdintAuthctxt;
+struct KbdintAuthctxt
+{
+ char *devices;
+ void *ctxt;
+ KbdintDevice *device;
+};
+
+KbdintAuthctxt *
+kbdint_alloc(const char *devs)
+{
+ KbdintAuthctxt *kbdintctxt;
+ int i;
+ char buf[1024];
+
+ kbdintctxt = xmalloc(sizeof(KbdintAuthctxt));
+ if (strcmp(devs, "") == 0) {
+ buf[0] = '\0';
+ for (i = 0; devices[i]; i++) {
+ if (i != 0)
+ strlcat(buf, ",", sizeof(buf));
+ strlcat(buf, devices[i]->name, sizeof(buf));
+ }
+ debug("kbdint_alloc: devices '%s'", buf);
+ kbdintctxt->devices = xstrdup(buf);
+ } else {
+ kbdintctxt->devices = xstrdup(devs);
+ }
+ kbdintctxt->ctxt = NULL;
+ kbdintctxt->device = NULL;
+
+ return kbdintctxt;
+}
+void
+kbdint_reset_device(KbdintAuthctxt *kbdintctxt)
+{
+ if (kbdintctxt->ctxt) {
+ kbdintctxt->device->free_ctx(kbdintctxt->ctxt);
+ kbdintctxt->ctxt = NULL;
+ }
+ kbdintctxt->device = NULL;
+}
+void
+kbdint_free(KbdintAuthctxt *kbdintctxt)
+{
+ if (kbdintctxt->device)
+ kbdint_reset_device(kbdintctxt);
+ if (kbdintctxt->devices) {
+ xfree(kbdintctxt->devices);
+ kbdintctxt->devices = NULL;
+ }
+ xfree(kbdintctxt);
+}
+/* get next device */
+int
+kbdint_next_device(KbdintAuthctxt *kbdintctxt)
+{
+ size_t len;
+ char *t;
+ int i;
+
+ if (kbdintctxt->device)
+ kbdint_reset_device(kbdintctxt);
+ do {
+ len = kbdintctxt->devices ?
+ strcspn(kbdintctxt->devices, ",") : 0;
+
+ if (len == 0)
+ break;
+ for (i = 0; devices[i]; i++)
+ if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
+ kbdintctxt->device = devices[i];
+ t = kbdintctxt->devices;
+ kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
+ xfree(t);
+ debug2("kbdint_next_device: devices %s", kbdintctxt->devices ?
+ kbdintctxt->devices : "<empty>");
+ } while (kbdintctxt->devices && !kbdintctxt->device);
+
+ return kbdintctxt->device ? 1 : 0;
+}