1df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt/* 2df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * Hotspot 2.0 SPP server - standalone version 3df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. 4df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * 5df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * See README for more details. 7df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt */ 8df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 9df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "includes.h" 10df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <time.h> 11df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <sqlite3.h> 12df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 13df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "common.h" 14df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "xml-utils.h" 15df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "spp_server.h" 16df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 17df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 18df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic void write_timestamp(FILE *f) 19df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 20df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt time_t t; 21df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt struct tm *tm; 22df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 23df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt time(&t); 24df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt tm = localtime(&t); 25df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 26df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ", 27df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 28df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt tm->tm_hour, tm->tm_min, tm->tm_sec); 29df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 30df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 31df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 32df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtvoid debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...) 33df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 34df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt va_list ap; 35df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 36df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx->debug_log == NULL) 37df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return; 38df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 39df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt write_timestamp(ctx->debug_log); 40df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt va_start(ap, fmt); 41df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt vfprintf(ctx->debug_log, fmt, ap); 42df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt va_end(ap); 43df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 44df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt fprintf(ctx->debug_log, "\n"); 45df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 46df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 47df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 48df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtvoid debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node) 49df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 50df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt char *str; 51df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 52df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx->debug_log == NULL) 53df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return; 54df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt str = xml_node_to_str(ctx->xml, node); 55df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (str == NULL) 56df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return; 57df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 58df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt write_timestamp(ctx->debug_log); 59df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt fprintf(ctx->debug_log, "%s: '%s'\n", title, str); 60df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt os_free(str); 61df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 62df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 63df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 64df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic int process(struct hs20_svc *ctx) 65df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 66df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt int dmacc = 0; 67df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt xml_node_t *soap, *spp, *resp; 68df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt char *user, *realm, *post, *str; 69df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 70df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ctx->addr = getenv("HS20ADDR"); 71df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx->addr) 72df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "Connection from %s", ctx->addr); 73df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 74df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt user = getenv("HS20USER"); 75df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (user && strlen(user) == 0) 76df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt user = NULL; 77df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt realm = getenv("HS20REALM"); 78df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (realm == NULL) { 79df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "HS20REALM not set"); 80df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 81df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 82df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt post = getenv("HS20POST"); 83df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (post == NULL) { 84df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "HS20POST not set"); 85df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 86df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 87df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 88df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt soap = xml_node_from_buf(ctx->xml, post); 89df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (soap == NULL) { 90df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "Could not parse SOAP data"); 91df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 92df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 93df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_dump_node(ctx, "Received SOAP message", soap); 94df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt spp = soap_get_body(ctx->xml, soap); 95df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (spp == NULL) { 96df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "Could not get SPP message"); 97df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt xml_node_free(ctx->xml, soap); 98df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 99df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 100df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_dump_node(ctx, "Received SPP message", spp); 101df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 102df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc); 103df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt xml_node_free(ctx->xml, soap); 104df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (resp == NULL && user == NULL) { 105df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "Request HTTP authentication"); 106df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return 2; /* Request authentication */ 107df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 108df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (resp == NULL) { 109df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "No response"); 110df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 111df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 112df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 113df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt soap = soap_build_envelope(ctx->xml, resp); 114df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (soap == NULL) { 115df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "SOAP envelope building failed"); 116df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 117df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 118df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt str = xml_node_to_str(ctx->xml, soap); 119df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt xml_node_free(ctx->xml, soap); 120df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (str == NULL) { 121df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(ctx, 1, "Could not get node string"); 122df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 123df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 124df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt printf("%s", str); 125df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt free(str); 126df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 127df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return 0; 128df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 129df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 130df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 131df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic void usage(void) 132df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 133df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt printf("usage:\n" 134df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt "hs20_spp_server -r<root directory> [-f<debug log>]\n"); 135df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 136df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 137df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 138df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtint main(int argc, char *argv[]) 139df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 140df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt struct hs20_svc ctx; 141df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt int ret; 142df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 143df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt os_memset(&ctx, 0, sizeof(ctx)); 144df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt for (;;) { 145df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt int c = getopt(argc, argv, "f:r:"); 146df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (c < 0) 147df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt break; 148df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt switch (c) { 149df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt case 'f': 150df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx.debug_log) 151df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt break; 152df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ctx.debug_log = fopen(optarg, "a"); 153df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx.debug_log == NULL) { 154df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt printf("Could not write to %s\n", optarg); 155df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 156df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 157df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt break; 158df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt case 'r': 159df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ctx.root_dir = optarg; 160df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt break; 161df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt default: 162df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt usage(); 163df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 164df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 165df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 166df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx.root_dir == NULL) { 167df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt usage(); 168df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 169df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 170df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ctx.xml = xml_node_init_ctx(&ctx, NULL); 171df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx.xml == NULL) 172df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 173df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (hs20_spp_server_init(&ctx) < 0) { 174df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt xml_node_deinit_ctx(ctx.xml); 175df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 176df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 177df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 178df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ret = process(&ctx); 179df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt debug_print(&ctx, 1, "process() --> %d", ret); 180df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 181df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt xml_node_deinit_ctx(ctx.xml); 182df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt hs20_spp_server_deinit(&ctx); 183df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (ctx.debug_log) 184df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt fclose(ctx.debug_log); 185df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 186df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return ret; 187df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 188