adam@1
|
1 #include <string.h>
|
adam@1
|
2
|
adam@0
|
3 #include <openssl/sha.h>
|
adam@0
|
4 #include <curl/curl.h>
|
adam@1
|
5 #include <expat.h>
|
adam@0
|
6
|
adam@1
|
7 #include <openid.h>
|
adam@0
|
8
|
adam@2
|
9 struct uw_OpenidFfi_discovery {
|
adam@2
|
10 uw_Basis_string endpoint, localId;
|
adam@2
|
11 };
|
adam@2
|
12
|
adam@2
|
13 uw_Basis_string uw_OpenidFfi_endpoint(uw_context ctx, uw_OpenidFfi_discovery d) {
|
adam@2
|
14 return d->endpoint;
|
adam@2
|
15 }
|
adam@2
|
16
|
adam@2
|
17 uw_Basis_string uw_OpenidFfi_localId(uw_context ctx, uw_OpenidFfi_discovery d) {
|
adam@2
|
18 return d->localId;
|
adam@2
|
19 }
|
adam@2
|
20
|
adam@0
|
21 uw_unit uw_OpenidFfi_init(uw_context ctx) {
|
adam@0
|
22 curl_global_init(CURL_GLOBAL_ALL);
|
adam@0
|
23
|
adam@0
|
24 return uw_unit_v;
|
adam@0
|
25 }
|
adam@1
|
26
|
adam@1
|
27 static CURL *curl(uw_context ctx) {
|
adam@1
|
28 CURL *r;
|
adam@1
|
29
|
adam@1
|
30 if (!(r = uw_get_global(ctx, "curl"))) {
|
adam@1
|
31 r = curl_easy_init();
|
adam@1
|
32 if (r)
|
adam@1
|
33 uw_set_global(ctx, "curl", r, curl_easy_cleanup);
|
adam@1
|
34 }
|
adam@1
|
35
|
adam@1
|
36 return r;
|
adam@1
|
37 }
|
adam@1
|
38
|
adam@1
|
39 typedef struct {
|
adam@1
|
40 uw_context ctx;
|
adam@2
|
41 uw_OpenidFfi_discovery d;
|
adam@1
|
42 } endpoint;
|
adam@1
|
43
|
adam@1
|
44 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
|
adam@1
|
45 endpoint *ep = userData;
|
adam@1
|
46
|
adam@1
|
47 if (!strcmp(name, "link")) {
|
adam@1
|
48 const XML_Char **attp;
|
adam@1
|
49 int found = 0;
|
adam@1
|
50
|
adam@1
|
51 for (attp = atts; *attp; attp += 2) {
|
adam@1
|
52 if (!strcmp(attp[0], "rel") && !strcmp(attp[1], "openid2.provider")) {
|
adam@1
|
53 found = 1;
|
adam@1
|
54 break;
|
adam@1
|
55 }
|
adam@1
|
56 }
|
adam@1
|
57
|
adam@1
|
58 if (found) {
|
adam@1
|
59 for (attp = atts; *attp; attp += 2) {
|
adam@1
|
60 if (!strcmp(attp[0], "href")) {
|
adam@2
|
61 ep->d->endpoint = uw_strdup(ep->ctx, attp[1]);
|
adam@1
|
62 return;
|
adam@1
|
63 }
|
adam@1
|
64 }
|
adam@1
|
65 }
|
adam@1
|
66 }
|
adam@1
|
67 }
|
adam@1
|
68
|
adam@1
|
69 static void XMLCALL endElement(void *userData, const XML_Char *name) {
|
adam@1
|
70 }
|
adam@1
|
71
|
adam@1
|
72 typedef struct {
|
adam@1
|
73 XML_Parser parser;
|
adam@1
|
74 int any_errors;
|
adam@1
|
75 } curl_data;
|
adam@1
|
76
|
adam@1
|
77 static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
|
adam@1
|
78 curl_data *d = userp;
|
adam@1
|
79
|
adam@1
|
80 if (!XML_Parse(d->parser, buffer, size * nmemb, 0))
|
adam@1
|
81 d->any_errors = 1;
|
adam@1
|
82
|
adam@1
|
83 return size * nmemb;
|
adam@1
|
84 }
|
adam@1
|
85
|
adam@2
|
86 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) {
|
adam@1
|
87 char *s;
|
adam@1
|
88 CURL *c = curl(ctx);
|
adam@1
|
89 curl_data cd = {};
|
adam@2
|
90 uw_OpenidFfi_discovery dy = uw_malloc(ctx, sizeof(struct uw_OpenidFfi_discovery));
|
adam@2
|
91 endpoint ep = {ctx, dy};
|
adam@1
|
92 CURLcode code;
|
adam@1
|
93
|
adam@2
|
94 dy->endpoint = dy->localId = NULL;
|
adam@2
|
95
|
adam@1
|
96 if (!strchr(id, ':')) {
|
adam@1
|
97 id = uw_Basis_strcat(ctx, "http://", id);
|
adam@1
|
98 if ((s = strchr(id, '#')) != NULL)
|
adam@1
|
99 *s = 0;
|
adam@1
|
100 } else if ((s = strchr(id, '#')) != NULL) {
|
adam@1
|
101 char *id2 = uw_malloc(ctx, s - id + 1);
|
adam@1
|
102 memcpy(id2, s, s - id);
|
adam@1
|
103 id2[s - id] = 0;
|
adam@1
|
104 id = id2;
|
adam@1
|
105 }
|
adam@1
|
106
|
adam@1
|
107 cd.parser = XML_ParserCreate(NULL);
|
adam@1
|
108 XML_SetUserData(cd.parser, &ep);
|
adam@1
|
109 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser);
|
adam@1
|
110 XML_SetElementHandler(cd.parser, startElement, endElement);
|
adam@1
|
111
|
adam@1
|
112 curl_easy_setopt(c, CURLOPT_URL, id);
|
adam@1
|
113 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data);
|
adam@1
|
114 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd);
|
adam@1
|
115
|
adam@1
|
116 code = curl_easy_perform(c);
|
adam@1
|
117 uw_pop_cleanup(ctx);
|
adam@1
|
118
|
adam@2
|
119 if (code || !ep.d->endpoint)
|
adam@1
|
120 return NULL;
|
adam@2
|
121 else {
|
adam@2
|
122 uw_OpenidFfi_discovery *dyp = malloc(sizeof(uw_OpenidFfi_discovery));
|
adam@2
|
123 *dyp = ep.d;
|
adam@2
|
124 return dyp;
|
adam@2
|
125 }
|
adam@1
|
126 }
|