Mercurial > openid
comparison src/c/openid.c @ 26:ee97bc0e08fa
Some default OPs, along with some tweaks to keep them happy
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Sun, 23 Jan 2011 14:57:49 -0500 |
parents | 6b2a44da71b0 |
children | f129ddee75f3 |
comparison
equal
deleted
inserted
replaced
25:c560ec5bf514 | 26:ee97bc0e08fa |
---|---|
8 #include <openssl/hmac.h> | 8 #include <openssl/hmac.h> |
9 #include <openssl/dh.h> | 9 #include <openssl/dh.h> |
10 #include <curl/curl.h> | 10 #include <curl/curl.h> |
11 #include <expat.h> | 11 #include <expat.h> |
12 | 12 |
13 #include <pthread.h> | |
14 | |
13 #include <openid.h> | 15 #include <openid.h> |
14 | 16 |
15 #define BUF_MAX 10240 | 17 #define BUF_MAX 10240 |
16 #define BUF_INIT 1024 | 18 #define BUF_INIT 1024 |
17 | 19 |
18 #define PRIME_LEN 64 | 20 #define DEFAULT_PRIME "DCF93A0B883972EC0E19989AC5A2CE310E1D37717E8D9571BB7623731866E61EF75A2E27898B057F9891C2E27A639C3F29B60814581CD3B2CA3986D2683705577D45C2E7E52DC81C7A171876E5CEA74B1448BFDFAF18828EFD2519F14E45E3826634AF1949E5B535CC829A483B8A76223E5D490A257F05BDFF16F2FB22C583AB" |
19 #define GENERATOR DH_GENERATOR_5 | 21 #define DEFAULT_GENERATOR "2" |
22 | |
23 static BIGNUM *default_prime, *default_generator; | |
20 | 24 |
21 uw_Basis_string uw_OpenidFfi_endpoint(uw_context ctx, uw_OpenidFfi_discovery d) { | 25 uw_Basis_string uw_OpenidFfi_endpoint(uw_context ctx, uw_OpenidFfi_discovery d) { |
22 return d.endpoint; | 26 return d.endpoint; |
23 } | 27 } |
24 | 28 |
25 uw_Basis_string uw_OpenidFfi_localId(uw_context ctx, uw_OpenidFfi_discovery d) { | 29 uw_Basis_string uw_OpenidFfi_localId(uw_context ctx, uw_OpenidFfi_discovery d) { |
26 return d.localId; | 30 return d.localId; |
27 } | 31 } |
28 | 32 |
33 static pthread_mutex_t *locks; | |
34 | |
35 static void locking_function(int mode, int n, const char *file, int line) { | |
36 if (mode & CRYPTO_LOCK) | |
37 pthread_mutex_lock(&locks[n]); | |
38 else | |
39 pthread_mutex_unlock(&locks[n]); | |
40 } | |
41 | |
42 static unsigned long id_function() { | |
43 return pthread_self(); | |
44 } | |
45 | |
29 uw_unit uw_OpenidFfi_init(uw_context ctx) { | 46 uw_unit uw_OpenidFfi_init(uw_context ctx) { |
47 int nl = CRYPTO_num_locks(), i; | |
48 locks = malloc(sizeof(pthread_mutex_t) * nl); | |
49 for (i = 0; i < nl; ++i) | |
50 pthread_mutex_init(&locks[i], NULL); | |
51 | |
52 CRYPTO_set_locking_callback(locking_function); | |
53 CRYPTO_set_id_callback(id_function); | |
30 curl_global_init(CURL_GLOBAL_ALL); | 54 curl_global_init(CURL_GLOBAL_ALL); |
55 | |
56 BN_hex2bn(&default_prime, DEFAULT_PRIME); | |
57 BN_dec2bn(&default_generator, DEFAULT_GENERATOR); | |
31 | 58 |
32 return uw_unit_v; | 59 return uw_unit_v; |
33 } | 60 } |
34 | 61 |
35 static CURL *curl(uw_context ctx) { | 62 static CURL *curl(uw_context ctx) { |
42 } | 69 } |
43 | 70 |
44 return r; | 71 return r; |
45 } | 72 } |
46 | 73 |
74 typedef enum { NONE, SERVICE, TYPE, MATCHED, URI } xrds_mode; | |
75 | |
47 typedef struct { | 76 typedef struct { |
48 uw_context ctx; | 77 uw_context ctx; |
49 uw_OpenidFfi_discovery *d; | 78 uw_OpenidFfi_discovery *d; |
79 xrds_mode mode; | |
50 } endpoint; | 80 } endpoint; |
51 | 81 |
52 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) { | 82 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) { |
53 endpoint *ep = userData; | 83 endpoint *ep = userData; |
84 | |
85 if (!strncmp(name, "xrd:", 4)) | |
86 name += 4; | |
54 | 87 |
55 if (!strcmp(name, "link")) { | 88 if (!strcmp(name, "link")) { |
56 const XML_Char **attp; | 89 const XML_Char **attp; |
57 int found = 0; | 90 int found = 0; |
58 | 91 |
70 return; | 103 return; |
71 } | 104 } |
72 } | 105 } |
73 } | 106 } |
74 } | 107 } |
108 else if (!strcmp(name, "Service")) | |
109 ep->mode = SERVICE; | |
110 else if (!strcmp(name, "Type")) { | |
111 if (ep->mode == SERVICE) | |
112 ep->mode = TYPE; | |
113 } | |
114 else if (!strcmp(name, "URI")) { | |
115 if (ep->mode == MATCHED) | |
116 ep->mode = URI; | |
117 } | |
118 } | |
119 | |
120 static char server[] = "http://specs.openid.net/auth/2.0/server"; | |
121 static char signon[] = "http://specs.openid.net/auth/2.0/signon"; | |
122 | |
123 static void XMLCALL cdata(void *userData, const XML_Char *s, int len) { | |
124 endpoint *ep = userData; | |
125 | |
126 switch (ep->mode) { | |
127 case TYPE: | |
128 if ((len == sizeof(server)-1 && !memcmp(server, s, sizeof(server)-1)) | |
129 || (len == sizeof(signon)-1 && !memcmp(signon, s, sizeof(signon)-1))) | |
130 ep->mode = MATCHED; | |
131 break; | |
132 case URI: | |
133 ep->d->endpoint = uw_malloc(ep->ctx, len+1); | |
134 memcpy(ep->d->endpoint, s, len); | |
135 ep->d->endpoint[len] = 0; | |
136 break; | |
137 default: | |
138 break; | |
139 } | |
140 } | |
141 | |
142 static void XMLCALL endElement(void *userData, const XML_Char *name) { | |
143 endpoint *ep = userData; | |
144 | |
145 if (!strncmp(name, "xrd:", 4)) | |
146 name += 4; | |
147 | |
148 if (!strcmp(name, "Service")) | |
149 ep->mode = NONE; | |
150 else if (!strcmp(name, "Type")) { | |
151 if (ep->mode != MATCHED) | |
152 ep->mode = SERVICE; | |
153 } | |
154 else if (!strcmp(name, "URI")) | |
155 ep->mode = MATCHED; | |
75 } | 156 } |
76 | 157 |
77 typedef struct { | 158 typedef struct { |
78 XML_Parser parser; | 159 XML_Parser parser; |
79 int any_errors; | 160 int any_errors; |
91 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) { | 172 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) { |
92 char *s; | 173 char *s; |
93 CURL *c = curl(ctx); | 174 CURL *c = curl(ctx); |
94 curl_discovery_data cd = {}; | 175 curl_discovery_data cd = {}; |
95 uw_OpenidFfi_discovery *dy = uw_malloc(ctx, sizeof(uw_OpenidFfi_discovery)); | 176 uw_OpenidFfi_discovery *dy = uw_malloc(ctx, sizeof(uw_OpenidFfi_discovery)); |
96 endpoint ep = {ctx, dy}; | 177 endpoint ep = {ctx, dy, NONE}; |
97 CURLcode code; | 178 CURLcode code; |
98 | 179 |
99 dy->endpoint = dy->localId = NULL; | 180 dy->endpoint = dy->localId = NULL; |
100 | 181 |
101 if (!strchr(id, ':')) { | 182 if (!strchr(id, ':')) { |
110 } | 191 } |
111 | 192 |
112 cd.parser = XML_ParserCreate(NULL); | 193 cd.parser = XML_ParserCreate(NULL); |
113 XML_SetUserData(cd.parser, &ep); | 194 XML_SetUserData(cd.parser, &ep); |
114 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser); | 195 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser); |
115 XML_SetStartElementHandler(cd.parser, startElement); | 196 XML_SetElementHandler(cd.parser, startElement, endElement); |
116 | 197 XML_SetCharacterDataHandler(cd.parser, cdata); |
198 | |
199 curl_easy_reset(c); | |
117 curl_easy_setopt(c, CURLOPT_URL, id); | 200 curl_easy_setopt(c, CURLOPT_URL, id); |
118 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_discovery_data); | 201 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_discovery_data); |
119 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd); | 202 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd); |
120 | 203 |
121 code = curl_easy_perform(c); | 204 code = curl_easy_perform(c); |
141 uw_buffer_append(buf, s, 1); | 224 uw_buffer_append(buf, s, 1); |
142 else { | 225 else { |
143 sprintf(hex, "%%%02X", (unsigned char)*s); | 226 sprintf(hex, "%%%02X", (unsigned char)*s); |
144 uw_buffer_append(buf, hex, 3); | 227 uw_buffer_append(buf, hex, 3); |
145 } | 228 } |
146 | |
147 /*switch (*s) { | |
148 case '=': | |
149 uw_buffer_append(buf, "%3D", 3); | |
150 break; | |
151 case '&': | |
152 uw_buffer_append(buf, "%26", 3); | |
153 break; | |
154 case '%': | |
155 uw_buffer_append(buf, "%25", 3); | |
156 break; | |
157 default: | |
158 uw_buffer_append(buf, s, 1); | |
159 }*/ | |
160 } | 229 } |
161 } | 230 } |
162 | 231 |
163 uw_unit uw_OpenidFfi_addInput(uw_context ctx, uw_OpenidFfi_inputs buf, uw_Basis_string key, uw_Basis_string value) { | 232 uw_unit uw_OpenidFfi_addInput(uw_context ctx, uw_OpenidFfi_inputs buf, uw_Basis_string key, uw_Basis_string value) { |
164 if (uw_buffer_used(buf) > 0) | 233 if (uw_buffer_used(buf) > 0) |
198 | 267 |
199 uw_buffer_init(BUF_MAX, buf, BUF_INIT); | 268 uw_buffer_init(BUF_MAX, buf, BUF_INIT); |
200 | 269 |
201 uw_buffer_append(inps, "", 1); | 270 uw_buffer_append(inps, "", 1); |
202 | 271 |
272 curl_easy_reset(c); | |
203 curl_easy_setopt(c, CURLOPT_URL, url); | 273 curl_easy_setopt(c, CURLOPT_URL, url); |
204 curl_easy_setopt(c, CURLOPT_POSTFIELDS, inps->start); | 274 curl_easy_setopt(c, CURLOPT_POSTFIELDS, inps->start); |
205 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_buffer_data); | 275 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_buffer_data); |
206 curl_easy_setopt(c, CURLOPT_WRITEDATA, buf); | 276 curl_easy_setopt(c, CURLOPT_WRITEDATA, buf); |
207 | 277 |
208 code = curl_easy_perform(c); | 278 code = curl_easy_perform(c); |
209 | |
210 uw_buffer_append(buf, "", 1); | 279 uw_buffer_append(buf, "", 1); |
211 | 280 |
212 if (code) { | 281 if (code) { |
213 uw_buffer_reset(buf); | 282 uw_buffer_reset(buf); |
214 uw_buffer_append(buf, curl_failure, sizeof curl_failure); | 283 uw_buffer_append(buf, curl_failure, sizeof curl_failure); |
386 return btwoc(ctx, dh->pub_key); | 455 return btwoc(ctx, dh->pub_key); |
387 } | 456 } |
388 | 457 |
389 static void free_DH(void *data, int will_retry) { | 458 static void free_DH(void *data, int will_retry) { |
390 DH *dh = data; | 459 DH *dh = data; |
460 dh->p = NULL; | |
461 dh->g = NULL; | |
391 DH_free(dh); | 462 DH_free(dh); |
392 } | 463 } |
393 | 464 |
394 uw_OpenidFfi_dh uw_OpenidFfi_generate(uw_context ctx) { | 465 uw_OpenidFfi_dh uw_OpenidFfi_generate(uw_context ctx) { |
395 DH *dh = DH_new(); | 466 DH *dh = DH_new(); |
396 | 467 |
468 dh->p = default_prime; | |
469 dh->g = default_generator; | |
397 uw_register_transactional(ctx, dh, NULL, NULL, free_DH); | 470 uw_register_transactional(ctx, dh, NULL, NULL, free_DH); |
398 | |
399 DH_generate_parameters_ex(dh, PRIME_LEN, GENERATOR, NULL); | |
400 | 471 |
401 if (DH_generate_key(dh) != 1) | 472 if (DH_generate_key(dh) != 1) |
402 uw_error(ctx, FATAL, "Diffie-Hellman key generation failed"); | 473 uw_error(ctx, FATAL, "Diffie-Hellman key generation failed"); |
403 | 474 |
404 return dh; | 475 return dh; |