1 /*
2 +----------------------------------------------------------------------+
3 | See LICENSE file for further copyright information |
4 +----------------------------------------------------------------------+
5 | Authors: John Jawed <jawed@php.net> |
6 | Felipe Pena <felipe@php.net> |
7 | Rasmus Lerdorf <rasmus@php.net> |
8 +----------------------------------------------------------------------+
9 */
10
11 #ifndef PHP_OAUTH_H
12 #define PHP_OAUTH_H
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include "php.h"
19
20 #ifdef PHP_WIN32
21 #include "win32/time.h"
22 #endif
23
24 #include "SAPI.h"
25 #include "zend_API.h"
26 #include "zend_variables.h"
27 #include "ext/standard/head.h"
28 #include "php_globals.h"
29 #include "php_main.h"
30 #include "php_ini.h"
31 #include "ext/standard/php_string.h"
32 #include "ext/standard/php_rand.h"
33 #include "ext/standard/php_smart_string.h"
34 #include "ext/standard/info.h"
35 #include "ext/standard/php_string.h"
36 #include "ext/standard/php_versioning.h"
37 #include "ext/standard/url.h"
38 #include "php_variables.h"
39 #include "zend_exceptions.h"
40 #include "zend_interfaces.h"
41 #include "php_globals.h"
42 #include "ext/standard/file.h"
43 #include "ext/standard/base64.h"
44 #include "ext/standard/php_lcg.h"
45 #include "ext/pcre/php_pcre.h"
46 #include "php_network.h"
47
48 #if OAUTH_USE_CURL
49 #include <curl/curl.h>
50 #define CLEANUP_CURL_AND_FORM(f,h) \
51 curl_easy_cleanup(h); \
52 curl_formfree(f);
53 #endif
54
55 #define PHP_OAUTH_VERSION 2.0.7
56
57 #define __stringify_1(x) #x
58 #define __stringify(x) __stringify_1(x)
59 #define __OAUTH_EXT_VER PHP_OAUTH_VERSION
60 #define OAUTH_EXT_VER __stringify(__OAUTH_EXT_VER)
61 #define OAUTH_USER_AGENT "PECL-OAuth/" __stringify(__OAUTH_EXT_VER)
62 #define OAUTH_HTTP_PORT 80
63 #define OAUTH_HTTPS_PORT 443
64 #define OAUTH_MAX_REDIRS 4L
65 #define OAUTH_MAX_HEADER_LEN 512L
66 #define OAUTH_AUTH_TYPE_URI 0x01
67 #define OAUTH_AUTH_TYPE_FORM 0x02
68 #define OAUTH_AUTH_TYPE_AUTHORIZATION 0x03
69 #define OAUTH_AUTH_TYPE_NONE 0x04
70
71 #define OAUTH_SIG_METHOD_HMACSHA1 "HMAC-SHA1"
72 #define OAUTH_SIG_METHOD_HMACSHA256 "HMAC-SHA256"
73 #define OAUTH_SIG_METHOD_RSASHA1 "RSA-SHA1"
74 #define OAUTH_SIG_METHOD_PLAINTEXT "PLAINTEXT"
75
76 extern zend_module_entry oauth_module_entry;
77
78 #define phpext_oauth_ptr &oauth_module_entry
79
80 #define PHP_OAUTH_API
81
82 #define OAUTH_ATTR_CONSUMER_KEY "oauth_consumer_key"
83 #define OAUTH_ATTR_CONSUMER_SECRET "oauth_consumer_secret"
84 #define OAUTH_ATTR_ACCESS_TOKEN "oauth_access_token"
85 #define OAUTH_RAW_LAST_RES "oauth_last_response_raw"
86 #define OAUTH_ATTR_LAST_RES_INFO "oauth_last_response_info"
87 #define OAUTH_ATTR_SIGMETHOD "oauth_sig_method"
88 #define OAUTH_ATTR_TOKEN "oauth_token"
89 #define OAUTH_ATTR_TOKEN_SECRET "oauth_token_secret"
90 #define OAUTH_ATTR_AUTHMETHOD "oauth_auth_method"
91 #define OAUTH_ATTR_OAUTH_VERSION "oauth_version"
92 #define OAUTH_ATTR_OAUTH_NONCE "oauth_nonce"
93 #define OAUTH_ATTR_OAUTH_USER_NONCE "oauth_user_nonce"
94 #define OAUTH_ATTR_CA_PATH "oauth_ssl_ca_path"
95 #define OAUTH_ATTR_CA_INFO "oauth_ssl_ca_info"
96
97 #define OAUTH_HTTP_METHOD_GET "GET"
98 #define OAUTH_HTTP_METHOD_POST "POST"
99 #define OAUTH_HTTP_METHOD_PUT "PUT"
100 #define OAUTH_HTTP_METHOD_HEAD "HEAD"
101 #define OAUTH_HTTP_METHOD_DELETE "DELETE"
102
103 #define OAUTH_REQENGINE_STREAMS 1
104 #define OAUTH_REQENGINE_CURL 2
105
106 #define OAUTH_FETCH_USETOKEN 1
107 #define OAUTH_FETCH_SIGONLY 2
108 #define OAUTH_FETCH_HEADONLY 4
109 #define OAUTH_OVERRIDE_HTTP_METHOD 8
110
111 #define OAUTH_SSLCHECK_NONE 0
112 #define OAUTH_SSLCHECK_HOST 1
113 #define OAUTH_SSLCHECK_PEER 2
114 #define OAUTH_SSLCHECK_BOTH (OAUTH_SSLCHECK_HOST | OAUTH_SSLCHECK_PEER)
115
116 #define OAUTH_DEFAULT_VERSION "1.0"
117
118 /* errors */
119 #define OAUTH_ERR_CONTENT_TYPE "invalidcontentttype"
120 #define OAUTH_ERR_BAD_REQUEST 400
121 #define OAUTH_ERR_BAD_AUTH 401
122 #define OAUTH_ERR_INTERNAL_ERROR 503
123
124 /* params */
125 #define OAUTH_PARAM_CONSUMER_KEY "oauth_consumer_key"
126 #define OAUTH_PARAM_SIGNATURE "oauth_signature"
127 #define OAUTH_PARAM_SIGNATURE_METHOD "oauth_signature_method"
128 #define OAUTH_PARAM_TIMESTAMP "oauth_timestamp"
129 #define OAUTH_PARAM_NONCE "oauth_nonce"
130 #define OAUTH_PARAM_VERSION "oauth_version"
131 #define OAUTH_PARAM_TOKEN "oauth_token"
132 #define OAUTH_PARAM_ASH "oauth_session_handle"
133 #define OAUTH_PARAM_VERIFIER "oauth_verifier"
134 #define OAUTH_PARAM_CALLBACK "oauth_callback"
135
136 /* values */
137 #define OAUTH_CALLBACK_OOB "oob"
138
139 #define OAUTH_PARAM_PREFIX "oauth_"
140 #define OAUTH_PARAM_PREFIX_LEN 6
141
142 #ifdef ZTS
143 #include "TSRM.h"
144 #endif
145
146 PHP_MINIT_FUNCTION(oauth);
147 PHP_MSHUTDOWN_FUNCTION(oauth);
148 PHP_MINFO_FUNCTION(oauth);
149
150 #ifdef ZTS
151 #define OAUTH(v) TSRMG(oauth_globals_id, zend_oauth_globals *, v)
152 #else
153 #define OAUTH(v) (oauth_globals.v)
154 #endif
155
156 typedef enum { OAUTH_SIGCTX_TYPE_NONE, OAUTH_SIGCTX_TYPE_HMAC, OAUTH_SIGCTX_TYPE_RSA, OAUTH_SIGCTX_TYPE_PLAIN } oauth_sigctx_type;
157
158 typedef struct {
159 oauth_sigctx_type type;
160 char *hash_algo;
161 zval privatekey;
162 } oauth_sig_context;
163
164 #define OAUTH_SIGCTX_INIT(ctx) { \
165 (ctx) = emalloc(sizeof(*(ctx))); \
166 (ctx)->type = OAUTH_SIGCTX_TYPE_NONE; \
167 (ctx)->hash_algo = NULL; \
168 ZVAL_UNDEF(&ctx->privatekey); \
169 }
170
171 #define OAUTH_SIGCTX_HMAC(ctx, algo) { \
172 (ctx)->type = OAUTH_SIGCTX_TYPE_HMAC; \
173 (ctx)->hash_algo = algo; \
174 }
175
176 #define OAUTH_SIGCTX_PLAIN(ctx) { \
177 (ctx)->type = OAUTH_SIGCTX_TYPE_PLAIN; \
178 }
179
180 #define OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) { \
181 if (Z_TYPE(ctx->privatekey) != IS_UNDEF) { \
182 oauth_free_privatekey(&ctx->privatekey); \
183 ZVAL_UNDEF(&ctx->privatekey); \
184 } \
185 }
186
187 #define OAUTH_SIGCTX_SET_PRIVATEKEY(ctx, privkey) { \
188 OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) \
189 ZVAL_DUP(&ctx->privatekey, &privkey); \
190 }
191
192 #define OAUTH_SIGCTX_RSA(ctx, algo) { \
193 (ctx)->type = OAUTH_SIGCTX_TYPE_RSA; \
194 (ctx)->hash_algo = algo; \
195 }
196
197 #define OAUTH_SIGCTX_FREE(ctx) { \
198 if (ctx) { \
199 OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) \
200 efree((ctx)); \
201 } \
202 }
203
204 typedef struct {
205 zend_string *sbs;
206 smart_string headers_in;
207 smart_string headers_out;
208 smart_string body_in;
209 smart_string body_out;
210 smart_string curl_info;
211 } php_so_debug;
212
213 typedef struct {
214 HashTable *properties;
215 smart_string lastresponse;
216 smart_string headers_in;
217 smart_string headers_out;
218 char last_location_header[OAUTH_MAX_HEADER_LEN];
219 uint32_t redirects;
220 uint32_t multipart_files_num;
221 uint32_t sslcheck; /* whether we check for SSL verification or not */
222 uint32_t debug; /* verbose output */
223 uint32_t follow_redirects; /* follow and sign redirects? */
224 uint32_t reqengine; /* streams or curl */
225 long timeout; /* timeout in milliseconds */
226 char *nonce;
227 char *timestamp;
228 zend_string *signature;
229 zval *this_ptr;
230 zval debugArr;
231 oauth_sig_context *sig_ctx;
232 php_so_debug *debug_info;
233 char **multipart_files;
234 char **multipart_params;
235 uint32_t is_multipart;
236 void ***thread_ctx;
237 zend_object zo;
238 } php_so_object;
239
so_object_from_obj(zend_object * obj)240 static inline php_so_object *so_object_from_obj(zend_object *obj) /* {{{ */ {
241 return (php_so_object*)((char*)(obj) - XtOffsetOf(php_so_object, zo));
242 }
243 /* }}} */
244
Z_SOO_P(zval * zv)245 static inline php_so_object *Z_SOO_P(zval *zv) /* {{{ */ {
246 php_so_object *soo = so_object_from_obj(Z_OBJ_P((zv)));
247 soo->this_ptr = zv;
248 return soo;
249 }
250 /* }}} */
251
252 #ifndef zend_parse_parameters_none
253 #define zend_parse_parameters_none() \
254 zend_parse_parameters(ZEND_NUM_ARGS(), "")
255 #endif
256
257 void soo_handle_error(php_so_object *soo, long errorCode, char *msg, char *response, char *additional_info);
258 zend_string *oauth_generate_sig_base(php_so_object *soo, const char *http_method, const char *uri, HashTable *post_args, HashTable *extra_args);
259
260 #ifndef zend_hash_quick_del
261 #define HASH_DEL_KEY_QUICK 2
262 #define zend_hash_quick_del(ht, arKey, nKeyLength, h) \
263 zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK)
264 #endif
265
266 #define SO_ME(func, arg_info, flags) PHP_ME(oauth, func, arg_info, flags)
267 #define SO_MALIAS(func, alias, arg_info, flags) PHP_MALIAS(oauth, func, alias, arg_info, flags)
268 #define SO_METHOD(func) PHP_METHOD(oauth, func)
269 #define FREE_ARGS_HASH(a) \
270 if (a) { \
271 zend_hash_destroy(a); \
272 FREE_HASHTABLE(a); \
273 }
274
275 #define INIT_smart_string(a) \
276 (a).len = 0; \
277 (a).c = NULL;
278
279 #define HTTP_IS_REDIRECT(http_response_code) \
280 (http_response_code > 300 && http_response_code < 304)
281
282 #define INIT_DEBUG_INFO(a) \
283 INIT_smart_string((a)->headers_out); \
284 INIT_smart_string((a)->body_in); \
285 INIT_smart_string((a)->body_out); \
286 INIT_smart_string((a)->curl_info);
287
288 #define FREE_DEBUG_INFO(a) \
289 smart_string_free(&(a)->headers_out); \
290 smart_string_free(&(a)->body_in); \
291 smart_string_free(&(a)->body_out); \
292 smart_string_free(&(a)->curl_info);
293
294 /* this and code that uses it is from ext/curl/interface.c */
295 #define CAAL(s, v) add_assoc_long_ex(&info, s, sizeof(s) - 1, (long) v);
296 #define CAAD(s, v) add_assoc_double_ex(&info, s, sizeof(s) - 1, (double) v);
297 #define CAAS(s, v) add_assoc_string_ex(&info, s, sizeof(s) - 1, (char *) (v ? v : ""));
298
299 #define ADD_DEBUG_INFO(a, k, s, t) \
300 if(s.len) { \
301 smart_string_0(&(s)); \
302 if(t) { \
303 zend_string *tmp, *s_zstr = zend_string_init((s).c, (s).len, 0); \
304 tmp = php_trim(s_zstr, NULL, 0, 3); \
305 add_assoc_string((a), k, ZSTR_VAL(tmp)); \
306 zend_string_release(tmp); \
307 zend_string_release(s_zstr); \
308 } else { \
309 add_assoc_string((a), k, (s).c); \
310 } \
311 }
312
313 #ifndef TRUE
314 #define TRUE 1
315 #define FALSE 0
316 #endif
317
318 #define OAUTH_OK SUCCESS
319
320 #if OAUTH_USE_CURL
321 long make_req_curl(php_so_object *soo, const char *url, const smart_string *payload, const char *http_method, HashTable *request_headers);
322 #if LIBCURL_VERSION_NUM >= 0x071304
323 #define OAUTH_PROTOCOLS_ALLOWED CURLPROTO_HTTP | CURLPROTO_HTTPS
324 #endif
325 #endif
326
327
328 void oauth_free_privatekey(zval *privatekey);
329 zend_string *soo_sign(php_so_object *soo, char *message, zval *cs, zval *ts, const oauth_sig_context *ctx);
330 oauth_sig_context *oauth_create_sig_context(const char *sigmethod);
331 zend_string *oauth_url_encode(char *url, int url_len);
332
333
334 // Compatibility macros
335 #if PHP_VERSION_ID < 70300
336 #define OAUTH_URL_STR(a) (a)
337 #define OAUTH_URL_LEN(a) strlen(a)
338 #else
339 #define OAUTH_URL_STR(a) ZSTR_VAL(a)
340 #define OAUTH_URL_LEN(a) ZSTR_LEN(a)
341 #endif
342
343 #if PHP_VERSION_ID < 80000
344 #define OBJ_FOR_PROP(zv) (zv)
345 #else
346 #define OBJ_FOR_PROP(zv) Z_OBJ_P(zv)
347 #endif
348
349 #endif
350
351 /**
352 * Local Variables:
353 * c-basic-offset: 4
354 * tab-width: 4
355 * indent-tabs-mode: t
356 * End:
357 * vim600: fdm=marker
358 * vim: noet sw=4 ts=4 noexpandtab
359 */
360