Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / hs20 / server / hs20_spp_server.c
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
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
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
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
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
131 static void usage(void)
132 {
133         printf("usage:\n"
134                "hs20_spp_server -r<root directory> [-f<debug log>]\n");
135 }
136
137
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 }