| |
1 /* |
| |
2 * (C) Copyright 2008 Wojtek Kaniewski <wojtekka@irc.pl> |
| |
3 * |
| |
4 * This program is free software; you can redistribute it and/or modify |
| |
5 * it under the terms of the GNU Lesser General Public License Version |
| |
6 * 2.1 as published by the Free Software Foundation. |
| |
7 * |
| |
8 * This program is distributed in the hope that it will be useful, |
| |
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| |
11 * GNU Lesser General Public License for more details. |
| |
12 * |
| |
13 * You should have received a copy of the GNU Lesser General Public |
| |
14 * License along with this program; if not, write to the Free Software |
| |
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, |
| |
16 * USA. |
| |
17 */ |
| |
18 |
| |
19 // source: http://toxygen.net/libgadu/ |
| |
20 |
| |
21 #include "oauth.h" |
| |
22 |
| |
23 #include "oauth-parameter.h" |
| |
24 #include <cipher.h> |
| |
25 |
| |
26 char *gg_oauth_static_nonce; /* dla unit testów */ |
| |
27 char *gg_oauth_static_timestamp; /* dla unit testów */ |
| |
28 |
| |
29 static void gg_oauth_generate_nonce(char *buf, int len) |
| |
30 { |
| |
31 const char charset[] = "0123456789"; |
| |
32 |
| |
33 if (buf == NULL || len < 1) |
| |
34 return; |
| |
35 |
| |
36 while (len > 1) { |
| |
37 *buf++ = charset[(unsigned) (((float) sizeof(charset) - 1.0) * rand() / (RAND_MAX + 1.0))]; |
| |
38 len--; |
| |
39 } |
| |
40 |
| |
41 *buf = 0; |
| |
42 } |
| |
43 |
| |
44 static gchar *gg_hmac_sha1(const char *key, const char *message) |
| |
45 { |
| |
46 PurpleCipherContext *context; |
| |
47 guchar digest[20]; |
| |
48 |
| |
49 context = purple_cipher_context_new_by_name("hmac", NULL); |
| |
50 purple_cipher_context_set_option(context, "hash", "sha1"); |
| |
51 purple_cipher_context_set_key(context, (guchar *)key); |
| |
52 purple_cipher_context_append(context, (guchar *)message, strlen(message)); |
| |
53 purple_cipher_context_digest(context, sizeof(digest), digest, NULL); |
| |
54 purple_cipher_context_destroy(context); |
| |
55 |
| |
56 return purple_base64_encode(digest, sizeof(digest)); |
| |
57 } |
| |
58 |
| |
59 static char *gg_oauth_generate_signature(const char *method, const char *url, const char *request, const char *consumer_secret, const char *token_secret) |
| |
60 { |
| |
61 char *text, *key, *res; |
| |
62 gchar *url_e, *request_e, *consumer_secret_e, *token_secret_e; |
| |
63 |
| |
64 url_e = g_uri_escape_string(url, NULL, FALSE); |
| |
65 request_e = g_uri_escape_string(request, NULL, FALSE); |
| |
66 text = g_strdup_printf("%s&%s&%s", method, url_e, request_e); |
| |
67 g_free(url_e); |
| |
68 g_free(request_e); |
| |
69 |
| |
70 consumer_secret_e = g_uri_escape_string(consumer_secret, NULL, FALSE); |
| |
71 token_secret_e = g_uri_escape_string(token_secret, NULL, FALSE); |
| |
72 key = g_strdup_printf("%s&%s", consumer_secret, token_secret ? token_secret : ""); |
| |
73 g_free(consumer_secret_e); |
| |
74 g_free(token_secret_e); |
| |
75 |
| |
76 res = gg_hmac_sha1(key, text); |
| |
77 |
| |
78 free(key); |
| |
79 free(text); |
| |
80 |
| |
81 return res; |
| |
82 } |
| |
83 |
| |
84 char *gg_oauth_generate_header(const char *method, const char *url, const const char *consumer_key, const char *consumer_secret, const char *token, const char *token_secret) |
| |
85 { |
| |
86 char *request, *signature, *res; |
| |
87 char nonce[80], timestamp[16]; |
| |
88 gg_oauth_parameter_t *params = NULL; |
| |
89 |
| |
90 if (gg_oauth_static_nonce == NULL) |
| |
91 gg_oauth_generate_nonce(nonce, sizeof(nonce)); |
| |
92 else { |
| |
93 strncpy(nonce, gg_oauth_static_nonce, sizeof(nonce) - 1); |
| |
94 nonce[sizeof(nonce) - 1] = 0; |
| |
95 } |
| |
96 |
| |
97 if (gg_oauth_static_timestamp == NULL) |
| |
98 snprintf(timestamp, sizeof(timestamp), "%ld", time(NULL)); |
| |
99 else { |
| |
100 strncpy(timestamp, gg_oauth_static_timestamp, sizeof(timestamp) - 1); |
| |
101 timestamp[sizeof(timestamp) - 1] = 0; |
| |
102 } |
| |
103 |
| |
104 gg_oauth_parameter_set(¶ms, "oauth_consumer_key", consumer_key); |
| |
105 gg_oauth_parameter_set(¶ms, "oauth_nonce", nonce); |
| |
106 gg_oauth_parameter_set(¶ms, "oauth_signature_method", "HMAC-SHA1"); |
| |
107 gg_oauth_parameter_set(¶ms, "oauth_timestamp", timestamp); |
| |
108 gg_oauth_parameter_set(¶ms, "oauth_token", token); |
| |
109 gg_oauth_parameter_set(¶ms, "oauth_version", "1.0"); |
| |
110 |
| |
111 request = gg_oauth_parameter_join(params, 0); |
| |
112 |
| |
113 signature = gg_oauth_generate_signature(method, url, request, consumer_secret, token_secret); |
| |
114 |
| |
115 free(request); |
| |
116 |
| |
117 gg_oauth_parameter_free(params); |
| |
118 params = NULL; |
| |
119 |
| |
120 if (signature == NULL) |
| |
121 return NULL; |
| |
122 |
| |
123 gg_oauth_parameter_set(¶ms, "oauth_version", "1.0"); |
| |
124 gg_oauth_parameter_set(¶ms, "oauth_nonce", nonce); |
| |
125 gg_oauth_parameter_set(¶ms, "oauth_timestamp", timestamp); |
| |
126 gg_oauth_parameter_set(¶ms, "oauth_consumer_key", consumer_key); |
| |
127 gg_oauth_parameter_set(¶ms, "oauth_token", token); |
| |
128 gg_oauth_parameter_set(¶ms, "oauth_signature_method", "HMAC-SHA1"); |
| |
129 gg_oauth_parameter_set(¶ms, "oauth_signature", signature); |
| |
130 |
| |
131 free(signature); |
| |
132 |
| |
133 res = gg_oauth_parameter_join(params, 1); |
| |
134 |
| |
135 gg_oauth_parameter_free(params); |
| |
136 |
| |
137 return res; |
| |
138 } |
| |
139 |