fragattacks/hs20/server/hs20_spp_server.c
Jouni Malinen 0f27c20d8d HS 2.0R2: Add example OSU SPP server implementation
This is meant mainly for testing purposes and as a reference
implementation showing how OSU SPP server could be implemented. This is
not suitable for any real production use in its current form.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2014-03-31 12:25:17 +03:00

188 lines
3.7 KiB
C

/*
* 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;
}