Merged the hostap_2.6 updates, and the Leap of Faith work, from the hostap_update...
[mech_eap.git] / libeap / hs20 / server / hs20_spp_server.c
diff --git a/libeap/hs20/server/hs20_spp_server.c b/libeap/hs20/server/hs20_spp_server.c
new file mode 100644 (file)
index 0000000..591f66b
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Hotspot 2.0 SPP server - standalone version
+ * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+#include <time.h>
+#include <sqlite3.h>
+
+#include "common.h"
+#include "xml-utils.h"
+#include "spp_server.h"
+
+
+static void write_timestamp(FILE *f)
+{
+       time_t t;
+       struct tm *tm;
+
+       time(&t);
+       tm = localtime(&t);
+
+       fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ",
+               tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+
+void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...)
+{
+       va_list ap;
+
+       if (ctx->debug_log == NULL)
+               return;
+
+       write_timestamp(ctx->debug_log);
+       va_start(ap, fmt);
+       vfprintf(ctx->debug_log, fmt, ap);
+       va_end(ap);
+
+       fprintf(ctx->debug_log, "\n");
+}
+
+
+void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node)
+{
+       char *str;
+
+       if (ctx->debug_log == NULL)
+               return;
+       str = xml_node_to_str(ctx->xml, node);
+       if (str == NULL)
+               return;
+
+       write_timestamp(ctx->debug_log);
+       fprintf(ctx->debug_log, "%s: '%s'\n", title, str);
+       os_free(str);
+}
+
+
+static int process(struct hs20_svc *ctx)
+{
+       int dmacc = 0;
+       xml_node_t *soap, *spp, *resp;
+       char *user, *realm, *post, *str;
+
+       ctx->addr = getenv("HS20ADDR");
+       if (ctx->addr)
+               debug_print(ctx, 1, "Connection from %s", ctx->addr);
+
+       user = getenv("HS20USER");
+       if (user && strlen(user) == 0)
+               user = NULL;
+       realm = getenv("HS20REALM");
+       if (realm == NULL) {
+               debug_print(ctx, 1, "HS20REALM not set");
+               return -1;
+       }
+       post = getenv("HS20POST");
+       if (post == NULL) {
+               debug_print(ctx, 1, "HS20POST not set");
+               return -1;
+       }
+
+       soap = xml_node_from_buf(ctx->xml, post);
+       if (soap == NULL) {
+               debug_print(ctx, 1, "Could not parse SOAP data");
+               return -1;
+       }
+       debug_dump_node(ctx, "Received SOAP message", soap);
+       spp = soap_get_body(ctx->xml, soap);
+       if (spp == NULL) {
+               debug_print(ctx, 1, "Could not get SPP message");
+               xml_node_free(ctx->xml, soap);
+               return -1;
+       }
+       debug_dump_node(ctx, "Received SPP message", spp);
+
+       resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc);
+       xml_node_free(ctx->xml, soap);
+       if (resp == NULL && user == NULL) {
+               debug_print(ctx, 1, "Request HTTP authentication");
+               return 2; /* Request authentication */
+       }
+       if (resp == NULL) {
+               debug_print(ctx, 1, "No response");
+               return -1;
+       }
+
+       soap = soap_build_envelope(ctx->xml, resp);
+       if (soap == NULL) {
+               debug_print(ctx, 1, "SOAP envelope building failed");
+               return -1;
+       }
+       str = xml_node_to_str(ctx->xml, soap);
+       xml_node_free(ctx->xml, soap);
+       if (str == NULL) {
+               debug_print(ctx, 1, "Could not get node string");
+               return -1;
+       }
+       printf("%s", str);
+       free(str);
+
+       return 0;
+}
+
+
+static void usage(void)
+{
+       printf("usage:\n"
+              "hs20_spp_server -r<root directory> [-f<debug log>]\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+       struct hs20_svc ctx;
+       int ret;
+
+       os_memset(&ctx, 0, sizeof(ctx));
+       for (;;) {
+               int c = getopt(argc, argv, "f:r:");
+               if (c < 0)
+                       break;
+               switch (c) {
+               case 'f':
+                       if (ctx.debug_log)
+                               break;
+                       ctx.debug_log = fopen(optarg, "a");
+                       if (ctx.debug_log == NULL) {
+                               printf("Could not write to %s\n", optarg);
+                               return -1;
+                       }
+                       break;
+               case 'r':
+                       ctx.root_dir = optarg;
+                       break;
+               default:
+                       usage();
+                       return -1;
+               }
+       }
+       if (ctx.root_dir == NULL) {
+               usage();
+               return -1;
+       }
+       ctx.xml = xml_node_init_ctx(&ctx, NULL);
+       if (ctx.xml == NULL)
+               return -1;
+       if (hs20_spp_server_init(&ctx) < 0) {
+               xml_node_deinit_ctx(ctx.xml);
+               return -1;
+       }
+
+       ret = process(&ctx);
+       debug_print(&ctx, 1, "process() --> %d", ret);
+
+       xml_node_deinit_ctx(ctx.xml);
+       hs20_spp_server_deinit(&ctx);
+       if (ctx.debug_log)
+               fclose(ctx.debug_log);
+
+       return ret;
+}