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;