+
+static void
+amindexd_response(
+ void *datap,
+ pkt_t *pkt,
+ security_handle_t *sech)
+{
+ int ports[NSTREAMS], *response_error = datap, i;
+ char *p;
+ char *tok;
+ char *extra = NULL;
+
+ assert(response_error != NULL);
+ assert(sech != NULL);
+
+ if (pkt == NULL) {
+ errstr = newvstralloc(errstr, "[request failed: ",
+ security_geterror(sech), "]", NULL);
+ *response_error = 1;
+ return;
+ }
+
+ if (pkt->type == P_NAK) {
+#if defined(PACKET_DEBUG)
+ fprintf(stderr, "got nak response:\n----\n%s\n----\n\n", pkt->body);
+#endif
+
+ tok = strtok(pkt->body, " ");
+ if (tok == NULL || strcmp(tok, "ERROR") != 0)
+ goto bad_nak;
+
+ tok = strtok(NULL, "\n");
+ if (tok != NULL) {
+ errstr = newvstralloc(errstr, "NAK: ", tok, NULL);
+ *response_error = 1;
+ } else {
+bad_nak:
+ errstr = newstralloc(errstr, "request NAK");
+ *response_error = 2;
+ }
+ return;
+ }
+
+ if (pkt->type != P_REP) {
+ errstr = newvstralloc(errstr, "received strange packet type ",
+ pkt_type2str(pkt->type), ": ", pkt->body, NULL);
+ *response_error = 1;
+ return;
+ }
+
+#if defined(PACKET_DEBUG)
+ fprintf(stderr, "got response:\n----\n%s\n----\n\n", pkt->body);
+#endif
+
+ for(i = 0; i < NSTREAMS; i++) {
+ ports[i] = -1;
+ streams[i].fd = NULL;
+ }
+
+ p = pkt->body;
+ while((tok = strtok(p, " \n")) != NULL) {
+ p = NULL;
+
+ /*
+ * Error response packets have "ERROR" followed by the error message
+ * followed by a newline.
+ */
+ if (strcmp(tok, "ERROR") == 0) {
+ tok = strtok(NULL, "\n");
+ if (tok == NULL)
+ tok = "[bogus error packet]";
+ errstr = newstralloc(errstr, tok);
+ *response_error = 2;
+ return;
+ }
+
+
+ /*
+ * Regular packets have CONNECT followed by three streams
+ */
+ if (strcmp(tok, "CONNECT") == 0) {
+
+ /*
+ * Parse the three stream specifiers out of the packet.
+ */
+ for (i = 0; i < NSTREAMS; i++) {
+ tok = strtok(NULL, " ");
+ if (tok == NULL || strcmp(tok, streams[i].name) != 0) {
+ extra = vstralloc("CONNECT token is \"",
+ tok ? tok : "(null)",
+ "\": expected \"",
+ streams[i].name,
+ "\"",
+ NULL);
+ goto parse_error;
+ }
+ tok = strtok(NULL, " \n");
+ if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) {
+ extra = vstralloc("CONNECT ",
+ streams[i].name,
+ " token is \"",
+ tok ? tok : "(null)",
+ "\": expected a port number",
+ NULL);
+ goto parse_error;
+ }
+ }
+ continue;
+ }
+
+ /*
+ * OPTIONS [options string] '\n'
+ */
+ if (strcmp(tok, "OPTIONS") == 0) {
+ tok = strtok(NULL, "\n");
+ if (tok == NULL) {
+ extra = stralloc("OPTIONS token is missing");
+ goto parse_error;
+ }
+/*
+ tok_end = tok + strlen(tok);
+ while((p = strchr(tok, ';')) != NULL) {
+ *p++ = '\0';
+#define sc "features="
+ if(strncmp(tok, sc, sizeof(sc)-1) == 0) {
+ tok += sizeof(sc) - 1;
+#undef sc
+ am_release_feature_set(their_features);
+ if((their_features = am_string_to_feature(tok)) == NULL) {
+ errstr = newvstralloc(errstr,
+ "OPTIONS: bad features value: ",
+ tok,
+ NULL);
+ goto parse_error;
+ }
+ }
+ tok = p;
+ }
+*/
+ continue;
+ }
+/*
+ extra = vstralloc("next token is \"",
+ tok ? tok : "(null)",
+ "\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\"",
+ NULL);
+ goto parse_error;
+*/
+ }
+
+ /*
+ * Connect the streams to their remote ports
+ */
+ for (i = 0; i < NSTREAMS; i++) {
+/*@i@*/ if (ports[i] == -1)
+ continue;
+ streams[i].fd = security_stream_client(sech, ports[i]);
+ if (streams[i].fd == NULL) {
+ errstr = newvstralloc(errstr,
+ "[could not connect ", streams[i].name, " stream: ",
+ security_geterror(sech), "]", NULL);
+ goto connect_error;
+ }
+ }
+ /*
+ * Authenticate the streams
+ */
+ for (i = 0; i < NSTREAMS; i++) {
+ if (streams[i].fd == NULL)
+ continue;
+ if (security_stream_auth(streams[i].fd) < 0) {
+ errstr = newvstralloc(errstr,
+ "[could not authenticate ", streams[i].name, " stream: ",
+ security_stream_geterror(streams[i].fd), "]", NULL);
+ goto connect_error;
+ }
+ }
+
+ /*
+ * The MESGFD and DATAFD streams are mandatory. If we didn't get
+ * them, complain.
+ */
+ if (streams[MESGFD].fd == NULL) {
+ errstr = newstralloc(errstr, "[couldn't open MESG streams]");
+ goto connect_error;
+ }
+
+ /* everything worked */
+ *response_error = 0;
+ amindexd_alive = 1;
+ return;
+
+parse_error:
+ errstr = newvstralloc(errstr,
+ "[parse of reply message failed: ",
+ extra ? extra : "(no additional information)",
+ "]",
+ NULL);
+ amfree(extra);
+ *response_error = 2;
+ return;
+
+connect_error:
+ stop_amindexd();
+ *response_error = 1;
+}
+
+/*
+ * This is called when everything needs to shut down so event_loop()
+ * will exit.
+ */
+void
+stop_amindexd(void)
+{
+ int i;
+
+ amindexd_alive = 0;
+ for (i = 0; i < NSTREAMS; i++) {
+ if (streams[i].fd != NULL) {
+ security_stream_close(streams[i].fd);
+ streams[i].fd = NULL;
+ }
+ }
+}
+
+char *
+amindexd_client_get_security_conf(
+ char * string,
+ void * arg)
+{
+ (void)arg; /* Quiet unused parameter warning */
+
+ if(!string || !*string)
+ return(NULL);
+
+ if(strcmp(string, "auth")==0) {
+ return(client_getconf_str(CLN_AUTH));
+ }
+ else if(strcmp(string, "ssh_keys")==0) {
+ return(client_getconf_str(CLN_SSH_KEYS));
+ }
+ return(NULL);
+}