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