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