xp_ssl.c 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Wez Furlong <wez@thebrainroom.com> |
  16. | Daniel Lowrey <rdlowrey@php.net> |
  17. | Chris Wright <daverandom@php.net> |
  18. | Jakub Zelenka <bukka@php.net> |
  19. +----------------------------------------------------------------------+
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include "php.h"
  25. #include "ext/standard/file.h"
  26. #include "ext/standard/url.h"
  27. #include "streams/php_streams_int.h"
  28. #include "zend_smart_str.h"
  29. #include "php_openssl.h"
  30. #include "php_network.h"
  31. #include <openssl/ssl.h>
  32. #include <openssl/rsa.h>
  33. #include <openssl/x509.h>
  34. #include <openssl/x509v3.h>
  35. #include <openssl/err.h>
  36. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  37. #include <openssl/bn.h>
  38. #include <openssl/dh.h>
  39. #endif
  40. #ifdef PHP_WIN32
  41. #include "win32/winutil.h"
  42. #include "win32/time.h"
  43. #include <Wincrypt.h>
  44. /* These are from Wincrypt.h, they conflict with OpenSSL */
  45. #undef X509_NAME
  46. #undef X509_CERT_PAIR
  47. #undef X509_EXTENSIONS
  48. #endif
  49. /* Flags for determining allowed stream crypto methods */
  50. #define STREAM_CRYPTO_IS_CLIENT (1<<0)
  51. #define STREAM_CRYPTO_METHOD_SSLv2 (1<<1)
  52. #define STREAM_CRYPTO_METHOD_SSLv3 (1<<2)
  53. #define STREAM_CRYPTO_METHOD_TLSv1_0 (1<<3)
  54. #define STREAM_CRYPTO_METHOD_TLSv1_1 (1<<4)
  55. #define STREAM_CRYPTO_METHOD_TLSv1_2 (1<<5)
  56. #ifndef OPENSSL_NO_SSL3
  57. #define HAVE_SSL3 1
  58. #define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_SSLv3
  59. #else
  60. #define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_0
  61. #endif
  62. #define PHP_OPENSSL_MAX_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_2
  63. #define HAVE_TLS11 1
  64. #define HAVE_TLS12 1
  65. #ifndef OPENSSL_NO_ECDH
  66. #define HAVE_ECDH 1
  67. #endif
  68. #ifndef OPENSSL_NO_TLSEXT
  69. #define HAVE_TLS_SNI 1
  70. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  71. #define HAVE_TLS_ALPN 1
  72. #endif
  73. #endif
  74. #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  75. #define HAVE_SEC_LEVEL 1
  76. #endif
  77. /* Simplify ssl context option retrieval */
  78. #define GET_VER_OPT(name) \
  79. (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", name)) != NULL)
  80. #define GET_VER_OPT_STRING(name, str) \
  81. if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_P(val); }
  82. #define GET_VER_OPT_LONG(name, num) \
  83. if (GET_VER_OPT(name)) { num = zval_get_long(val); }
  84. /* Used for peer verification in windows */
  85. #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) \
  86. ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i)))
  87. #if PHP_OPENSSL_API_VERSION < 0x10100
  88. static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength);
  89. #endif
  90. extern php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl);
  91. extern zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw);
  92. extern int php_openssl_get_ssl_stream_data_index();
  93. extern int php_openssl_get_x509_list_id(void);
  94. static struct timeval php_openssl_subtract_timeval(struct timeval a, struct timeval b);
  95. static int php_openssl_compare_timeval(struct timeval a, struct timeval b);
  96. static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count);
  97. const php_stream_ops php_openssl_socket_ops;
  98. /* Certificate contexts used for server-side SNI selection */
  99. typedef struct _php_openssl_sni_cert_t {
  100. char *name;
  101. SSL_CTX *ctx;
  102. } php_openssl_sni_cert_t;
  103. /* Provides leaky bucket handhsake renegotiation rate-limiting */
  104. typedef struct _php_openssl_handshake_bucket_t {
  105. zend_long prev_handshake;
  106. zend_long limit;
  107. zend_long window;
  108. float tokens;
  109. unsigned should_close;
  110. } php_openssl_handshake_bucket_t;
  111. #ifdef HAVE_TLS_ALPN
  112. /* Holds the available server ALPN protocols for negotiation */
  113. typedef struct _php_openssl_alpn_ctx_t {
  114. unsigned char *data;
  115. unsigned short len;
  116. } php_openssl_alpn_ctx;
  117. #endif
  118. /* This implementation is very closely tied to the that of the native
  119. * sockets implemented in the core.
  120. * Don't try this technique in other extensions!
  121. * */
  122. typedef struct _php_openssl_netstream_data_t {
  123. php_netstream_data_t s;
  124. SSL *ssl_handle;
  125. SSL_CTX *ctx;
  126. struct timeval connect_timeout;
  127. int enable_on_connect;
  128. int is_client;
  129. int ssl_active;
  130. php_stream_xport_crypt_method_t method;
  131. php_openssl_handshake_bucket_t *reneg;
  132. php_openssl_sni_cert_t *sni_certs;
  133. unsigned sni_cert_count;
  134. #ifdef HAVE_TLS_ALPN
  135. php_openssl_alpn_ctx alpn_ctx;
  136. #endif
  137. char *url_name;
  138. unsigned state_set:1;
  139. unsigned _spare:31;
  140. } php_openssl_netstream_data_t;
  141. /* it doesn't matter that we do some hash traversal here, since it is done only
  142. * in an error condition arising from a network connection problem */
  143. static int php_openssl_is_http_stream_talking_to_iis(php_stream *stream) /* {{{ */
  144. {
  145. if (Z_TYPE(stream->wrapperdata) == IS_ARRAY &&
  146. stream->wrapper &&
  147. strcasecmp(stream->wrapper->wops->label, "HTTP") == 0
  148. ) {
  149. /* the wrapperdata is an array zval containing the headers */
  150. zval *tmp;
  151. #define SERVER_MICROSOFT_IIS "Server: Microsoft-IIS"
  152. #define SERVER_GOOGLE "Server: GFE/"
  153. ZEND_HASH_FOREACH_VAL(Z_ARRVAL(stream->wrapperdata), tmp) {
  154. if (strncasecmp(Z_STRVAL_P(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) {
  155. return 1;
  156. } else if (strncasecmp(Z_STRVAL_P(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) {
  157. return 1;
  158. }
  159. } ZEND_HASH_FOREACH_END();
  160. }
  161. return 0;
  162. }
  163. /* }}} */
  164. static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init) /* {{{ */
  165. {
  166. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  167. int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
  168. char esbuf[512];
  169. smart_str ebuf = {0};
  170. unsigned long ecode;
  171. int retry = 1;
  172. switch(err) {
  173. case SSL_ERROR_ZERO_RETURN:
  174. /* SSL terminated (but socket may still be active) */
  175. retry = 0;
  176. break;
  177. case SSL_ERROR_WANT_READ:
  178. case SSL_ERROR_WANT_WRITE:
  179. /* re-negotiation, or perhaps the SSL layer needs more
  180. * packets: retry in next iteration */
  181. errno = EAGAIN;
  182. retry = is_init ? 1 : sslsock->s.is_blocked;
  183. break;
  184. case SSL_ERROR_SYSCALL:
  185. if (ERR_peek_error() == 0) {
  186. if (nr_bytes == 0) {
  187. if (!php_openssl_is_http_stream_talking_to_iis(stream) && ERR_get_error() != 0) {
  188. php_error_docref(NULL, E_WARNING, "SSL: fatal protocol error");
  189. }
  190. SSL_set_shutdown(sslsock->ssl_handle, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
  191. stream->eof = 1;
  192. retry = 0;
  193. } else {
  194. char *estr = php_socket_strerror(php_socket_errno(), NULL, 0);
  195. php_error_docref(NULL, E_WARNING,
  196. "SSL: %s", estr);
  197. efree(estr);
  198. retry = 0;
  199. }
  200. break;
  201. }
  202. /* fall through */
  203. default:
  204. /* some other error */
  205. ecode = ERR_get_error();
  206. switch (ERR_GET_REASON(ecode)) {
  207. case SSL_R_NO_SHARED_CIPHER:
  208. php_error_docref(NULL, E_WARNING,
  209. "SSL_R_NO_SHARED_CIPHER: no suitable shared cipher could be used. "
  210. "This could be because the server is missing an SSL certificate "
  211. "(local_cert context option)");
  212. retry = 0;
  213. break;
  214. default:
  215. do {
  216. /* NULL is automatically added */
  217. ERR_error_string_n(ecode, esbuf, sizeof(esbuf));
  218. if (ebuf.s) {
  219. smart_str_appendc(&ebuf, '\n');
  220. }
  221. smart_str_appends(&ebuf, esbuf);
  222. } while ((ecode = ERR_get_error()) != 0);
  223. smart_str_0(&ebuf);
  224. php_error_docref(NULL, E_WARNING,
  225. "SSL operation failed with code %d. %s%s",
  226. err,
  227. ebuf.s ? "OpenSSL Error messages:\n" : "",
  228. ebuf.s ? ZSTR_VAL(ebuf.s) : "");
  229. if (ebuf.s) {
  230. smart_str_free(&ebuf);
  231. }
  232. }
  233. retry = 0;
  234. errno = 0;
  235. }
  236. return retry;
  237. }
  238. /* }}} */
  239. static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */
  240. {
  241. php_stream *stream;
  242. SSL *ssl;
  243. int err, depth, ret;
  244. zval *val;
  245. zend_ulong allowed_depth = OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH;
  246. ret = preverify_ok;
  247. /* determine the status for the current cert */
  248. err = X509_STORE_CTX_get_error(ctx);
  249. depth = X509_STORE_CTX_get_error_depth(ctx);
  250. /* conjure the stream & context to use */
  251. ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
  252. stream = (php_stream*)SSL_get_ex_data(ssl, php_openssl_get_ssl_stream_data_index());
  253. /* if allow_self_signed is set, make sure that verification succeeds */
  254. if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
  255. GET_VER_OPT("allow_self_signed") &&
  256. zend_is_true(val)
  257. ) {
  258. ret = 1;
  259. }
  260. /* check the depth */
  261. GET_VER_OPT_LONG("verify_depth", allowed_depth);
  262. if ((zend_ulong)depth > allowed_depth) {
  263. ret = 0;
  264. X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG);
  265. }
  266. return ret;
  267. }
  268. /* }}} */
  269. static int php_openssl_x509_fingerprint_cmp(X509 *peer, const char *method, const char *expected)
  270. {
  271. zend_string *fingerprint;
  272. int result = -1;
  273. fingerprint = php_openssl_x509_fingerprint(peer, method, 0);
  274. if (fingerprint) {
  275. result = strcasecmp(expected, ZSTR_VAL(fingerprint));
  276. zend_string_release_ex(fingerprint, 0);
  277. }
  278. return result;
  279. }
  280. static zend_bool php_openssl_x509_fingerprint_match(X509 *peer, zval *val)
  281. {
  282. if (Z_TYPE_P(val) == IS_STRING) {
  283. const char *method = NULL;
  284. switch (Z_STRLEN_P(val)) {
  285. case 32:
  286. method = "md5";
  287. break;
  288. case 40:
  289. method = "sha1";
  290. break;
  291. }
  292. return method && php_openssl_x509_fingerprint_cmp(peer, method, Z_STRVAL_P(val)) == 0;
  293. } else if (Z_TYPE_P(val) == IS_ARRAY) {
  294. zval *current;
  295. zend_string *key;
  296. if (!zend_hash_num_elements(Z_ARRVAL_P(val))) {
  297. php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint array; [algo => fingerprint] form required");
  298. return 0;
  299. }
  300. ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(val), key, current) {
  301. if (key == NULL || Z_TYPE_P(current) != IS_STRING) {
  302. php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint array; [algo => fingerprint] form required");
  303. return 0;
  304. }
  305. if (php_openssl_x509_fingerprint_cmp(peer, ZSTR_VAL(key), Z_STRVAL_P(current)) != 0) {
  306. return 0;
  307. }
  308. } ZEND_HASH_FOREACH_END();
  309. return 1;
  310. } else {
  311. php_error_docref(NULL, E_WARNING,
  312. "Invalid peer_fingerprint value; fingerprint string or array of the form [algo => fingerprint] required");
  313. }
  314. return 0;
  315. }
  316. static zend_bool php_openssl_matches_wildcard_name(const char *subjectname, const char *certname) /* {{{ */
  317. {
  318. char *wildcard = NULL;
  319. ptrdiff_t prefix_len;
  320. size_t suffix_len, subject_len;
  321. if (strcasecmp(subjectname, certname) == 0) {
  322. return 1;
  323. }
  324. /* wildcard, if present, must only be present in the left-most component */
  325. if (!(wildcard = strchr(certname, '*')) || memchr(certname, '.', wildcard - certname)) {
  326. return 0;
  327. }
  328. /* 1) prefix, if not empty, must match subject */
  329. prefix_len = wildcard - certname;
  330. if (prefix_len && strncasecmp(subjectname, certname, prefix_len) != 0) {
  331. return 0;
  332. }
  333. suffix_len = strlen(wildcard + 1);
  334. subject_len = strlen(subjectname);
  335. if (suffix_len <= subject_len) {
  336. /* 2) suffix must match
  337. * 3) no . between prefix and suffix
  338. **/
  339. return strcasecmp(wildcard + 1, subjectname + subject_len - suffix_len) == 0 &&
  340. memchr(subjectname + prefix_len, '.', subject_len - suffix_len - prefix_len) == NULL;
  341. }
  342. return 0;
  343. }
  344. /* }}} */
  345. static zend_bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /* {{{ */
  346. {
  347. int i, len;
  348. unsigned char *cert_name = NULL;
  349. char ipbuffer[64];
  350. GENERAL_NAMES *alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, 0, 0);
  351. int alt_name_count = sk_GENERAL_NAME_num(alt_names);
  352. for (i = 0; i < alt_name_count; i++) {
  353. GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
  354. if (san->type == GEN_DNS) {
  355. ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName);
  356. if ((size_t)ASN1_STRING_length(san->d.dNSName) != strlen((const char*)cert_name)) {
  357. OPENSSL_free(cert_name);
  358. /* prevent null-byte poisoning*/
  359. continue;
  360. }
  361. /* accommodate valid FQDN entries ending in "." */
  362. len = strlen((const char*)cert_name);
  363. if (len && strcmp((const char *)&cert_name[len-1], ".") == 0) {
  364. cert_name[len-1] = '\0';
  365. }
  366. if (php_openssl_matches_wildcard_name(subject_name, (const char *)cert_name)) {
  367. OPENSSL_free(cert_name);
  368. sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
  369. return 1;
  370. }
  371. OPENSSL_free(cert_name);
  372. } else if (san->type == GEN_IPADD) {
  373. if (san->d.iPAddress->length == 4) {
  374. sprintf(ipbuffer, "%d.%d.%d.%d",
  375. san->d.iPAddress->data[0],
  376. san->d.iPAddress->data[1],
  377. san->d.iPAddress->data[2],
  378. san->d.iPAddress->data[3]
  379. );
  380. if (strcasecmp(subject_name, (const char*)ipbuffer) == 0) {
  381. sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
  382. return 1;
  383. }
  384. }
  385. /* No, we aren't bothering to check IPv6 addresses. Why?
  386. * Because IP SAN names are officially deprecated and are
  387. * not allowed by CAs starting in 2015. Deal with it.
  388. */
  389. }
  390. }
  391. sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
  392. return 0;
  393. }
  394. /* }}} */
  395. static zend_bool php_openssl_matches_common_name(X509 *peer, const char *subject_name) /* {{{ */
  396. {
  397. char buf[1024];
  398. X509_NAME *cert_name;
  399. zend_bool is_match = 0;
  400. int cert_name_len;
  401. cert_name = X509_get_subject_name(peer);
  402. cert_name_len = X509_NAME_get_text_by_NID(cert_name, NID_commonName, buf, sizeof(buf));
  403. if (cert_name_len == -1) {
  404. php_error_docref(NULL, E_WARNING, "Unable to locate peer certificate CN");
  405. } else if ((size_t)cert_name_len != strlen(buf)) {
  406. php_error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' is malformed", cert_name_len, buf);
  407. } else if (php_openssl_matches_wildcard_name(subject_name, buf)) {
  408. is_match = 1;
  409. } else {
  410. php_error_docref(NULL, E_WARNING,
  411. "Peer certificate CN=`%.*s' did not match expected CN=`%s'",
  412. cert_name_len, buf, subject_name);
  413. }
  414. return is_match;
  415. }
  416. /* }}} */
  417. static int php_openssl_apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stream) /* {{{ */
  418. {
  419. zval *val = NULL;
  420. zval *peer_fingerprint;
  421. char *peer_name = NULL;
  422. int err,
  423. must_verify_peer,
  424. must_verify_peer_name,
  425. must_verify_fingerprint;
  426. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  427. must_verify_peer = GET_VER_OPT("verify_peer")
  428. ? zend_is_true(val)
  429. : sslsock->is_client;
  430. must_verify_peer_name = GET_VER_OPT("verify_peer_name")
  431. ? zend_is_true(val)
  432. : sslsock->is_client;
  433. must_verify_fingerprint = GET_VER_OPT("peer_fingerprint");
  434. peer_fingerprint = val;
  435. if ((must_verify_peer || must_verify_peer_name || must_verify_fingerprint) && peer == NULL) {
  436. php_error_docref(NULL, E_WARNING, "Could not get peer certificate");
  437. return FAILURE;
  438. }
  439. /* Verify the peer against using CA file/path settings */
  440. if (must_verify_peer) {
  441. err = SSL_get_verify_result(ssl);
  442. switch (err) {
  443. case X509_V_OK:
  444. /* fine */
  445. break;
  446. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  447. if (GET_VER_OPT("allow_self_signed") && zend_is_true(val)) {
  448. /* allowed */
  449. break;
  450. }
  451. /* not allowed, so fall through */
  452. default:
  453. php_error_docref(NULL, E_WARNING,
  454. "Could not verify peer: code:%d %s",
  455. err,
  456. X509_verify_cert_error_string(err)
  457. );
  458. return FAILURE;
  459. }
  460. }
  461. /* If a peer_fingerprint match is required this trumps peer and peer_name verification */
  462. if (must_verify_fingerprint) {
  463. if (Z_TYPE_P(peer_fingerprint) == IS_STRING || Z_TYPE_P(peer_fingerprint) == IS_ARRAY) {
  464. if (!php_openssl_x509_fingerprint_match(peer, peer_fingerprint)) {
  465. php_error_docref(NULL, E_WARNING,
  466. "peer_fingerprint match failure"
  467. );
  468. return FAILURE;
  469. }
  470. } else {
  471. php_error_docref(NULL, E_WARNING,
  472. "Expected peer fingerprint must be a string or an array"
  473. );
  474. return FAILURE;
  475. }
  476. }
  477. /* verify the host name presented in the peer certificate */
  478. if (must_verify_peer_name) {
  479. GET_VER_OPT_STRING("peer_name", peer_name);
  480. /* If no peer name was specified we use the autodetected url name in client environments */
  481. if (peer_name == NULL && sslsock->is_client) {
  482. peer_name = sslsock->url_name;
  483. }
  484. if (peer_name) {
  485. if (php_openssl_matches_san_list(peer, peer_name)) {
  486. return SUCCESS;
  487. } else if (php_openssl_matches_common_name(peer, peer_name)) {
  488. return SUCCESS;
  489. } else {
  490. return FAILURE;
  491. }
  492. } else {
  493. return FAILURE;
  494. }
  495. }
  496. return SUCCESS;
  497. }
  498. /* }}} */
  499. static int php_openssl_passwd_callback(char *buf, int num, int verify, void *data) /* {{{ */
  500. {
  501. php_stream *stream = (php_stream *)data;
  502. zval *val = NULL;
  503. char *passphrase = NULL;
  504. /* TODO: could expand this to make a callback into PHP user-space */
  505. GET_VER_OPT_STRING("passphrase", passphrase);
  506. if (passphrase) {
  507. if (Z_STRLEN_P(val) < (size_t)num - 1) {
  508. memcpy(buf, Z_STRVAL_P(val), Z_STRLEN_P(val)+1);
  509. return (int)Z_STRLEN_P(val);
  510. }
  511. }
  512. return 0;
  513. }
  514. /* }}} */
  515. #ifdef PHP_WIN32
  516. #define RETURN_CERT_VERIFY_FAILURE(code) X509_STORE_CTX_set_error(x509_store_ctx, code); return 0;
  517. static int php_openssl_win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, void *arg) /* {{{ */
  518. {
  519. PCCERT_CONTEXT cert_ctx = NULL;
  520. PCCERT_CHAIN_CONTEXT cert_chain_ctx = NULL;
  521. #if OPENSSL_VERSION_NUMBER < 0x10100000L
  522. X509 *cert = x509_store_ctx->cert;
  523. #else
  524. X509 *cert = X509_STORE_CTX_get0_cert(x509_store_ctx);
  525. #endif
  526. php_stream *stream;
  527. php_openssl_netstream_data_t *sslsock;
  528. zval *val;
  529. zend_bool is_self_signed = 0;
  530. stream = (php_stream*)arg;
  531. sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  532. { /* First convert the x509 struct back to a DER encoded buffer and let Windows decode it into a form it can work with */
  533. unsigned char *der_buf = NULL;
  534. int der_len;
  535. der_len = i2d_X509(cert, &der_buf);
  536. if (der_len < 0) {
  537. unsigned long err_code, e;
  538. char err_buf[512];
  539. while ((e = ERR_get_error()) != 0) {
  540. err_code = e;
  541. }
  542. php_error_docref(NULL, E_WARNING, "Error encoding X509 certificate: %d: %s", err_code, ERR_error_string(err_code, err_buf));
  543. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  544. }
  545. cert_ctx = CertCreateCertificateContext(X509_ASN_ENCODING, der_buf, der_len);
  546. OPENSSL_free(der_buf);
  547. if (cert_ctx == NULL) {
  548. php_error_docref(NULL, E_WARNING, "Error creating certificate context: %s", php_win_err());
  549. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  550. }
  551. }
  552. { /* Next fetch the relevant cert chain from the store */
  553. CERT_ENHKEY_USAGE enhkey_usage = {0};
  554. CERT_USAGE_MATCH cert_usage = {0};
  555. CERT_CHAIN_PARA chain_params = {sizeof(CERT_CHAIN_PARA)};
  556. LPSTR usages[] = {szOID_PKIX_KP_SERVER_AUTH, szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE};
  557. DWORD chain_flags = 0;
  558. unsigned long allowed_depth = OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH;
  559. unsigned int i;
  560. enhkey_usage.cUsageIdentifier = 3;
  561. enhkey_usage.rgpszUsageIdentifier = usages;
  562. cert_usage.dwType = USAGE_MATCH_TYPE_OR;
  563. cert_usage.Usage = enhkey_usage;
  564. chain_params.RequestedUsage = cert_usage;
  565. chain_flags = CERT_CHAIN_CACHE_END_CERT | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  566. if (!CertGetCertificateChain(NULL, cert_ctx, NULL, NULL, &chain_params, chain_flags, NULL, &cert_chain_ctx)) {
  567. php_error_docref(NULL, E_WARNING, "Error getting certificate chain: %s", php_win_err());
  568. CertFreeCertificateContext(cert_ctx);
  569. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  570. }
  571. /* check if the cert is self-signed */
  572. if (cert_chain_ctx->cChain > 0 && cert_chain_ctx->rgpChain[0]->cElement > 0
  573. && (cert_chain_ctx->rgpChain[0]->rgpElement[0]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED) != 0) {
  574. is_self_signed = 1;
  575. }
  576. /* check the depth */
  577. GET_VER_OPT_LONG("verify_depth", allowed_depth);
  578. for (i = 0; i < cert_chain_ctx->cChain; i++) {
  579. if (cert_chain_ctx->rgpChain[i]->cElement > allowed_depth) {
  580. CertFreeCertificateChain(cert_chain_ctx);
  581. CertFreeCertificateContext(cert_ctx);
  582. RETURN_CERT_VERIFY_FAILURE(X509_V_ERR_CERT_CHAIN_TOO_LONG);
  583. }
  584. }
  585. }
  586. { /* Then verify it against a policy */
  587. SSL_EXTRA_CERT_CHAIN_POLICY_PARA ssl_policy_params = {sizeof(SSL_EXTRA_CERT_CHAIN_POLICY_PARA)};
  588. CERT_CHAIN_POLICY_PARA chain_policy_params = {sizeof(CERT_CHAIN_POLICY_PARA)};
  589. CERT_CHAIN_POLICY_STATUS chain_policy_status = {sizeof(CERT_CHAIN_POLICY_STATUS)};
  590. LPWSTR server_name = NULL;
  591. BOOL verify_result;
  592. { /* This looks ridiculous and it is - but we validate the name ourselves using the peer_name
  593. ctx option, so just use the CN from the cert here */
  594. X509_NAME *cert_name;
  595. unsigned char *cert_name_utf8;
  596. int index, cert_name_utf8_len;
  597. DWORD num_wchars;
  598. cert_name = X509_get_subject_name(cert);
  599. index = X509_NAME_get_index_by_NID(cert_name, NID_commonName, -1);
  600. if (index < 0) {
  601. php_error_docref(NULL, E_WARNING, "Unable to locate certificate CN");
  602. CertFreeCertificateChain(cert_chain_ctx);
  603. CertFreeCertificateContext(cert_ctx);
  604. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  605. }
  606. cert_name_utf8_len = PHP_X509_NAME_ENTRY_TO_UTF8(cert_name, index, cert_name_utf8);
  607. num_wchars = MultiByteToWideChar(CP_UTF8, 0, (char*)cert_name_utf8, -1, NULL, 0);
  608. if (num_wchars == 0) {
  609. php_error_docref(NULL, E_WARNING, "Unable to convert %s to wide character string", cert_name_utf8);
  610. OPENSSL_free(cert_name_utf8);
  611. CertFreeCertificateChain(cert_chain_ctx);
  612. CertFreeCertificateContext(cert_ctx);
  613. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  614. }
  615. server_name = emalloc((num_wchars * sizeof(WCHAR)) + sizeof(WCHAR));
  616. num_wchars = MultiByteToWideChar(CP_UTF8, 0, (char*)cert_name_utf8, -1, server_name, num_wchars);
  617. if (num_wchars == 0) {
  618. php_error_docref(NULL, E_WARNING, "Unable to convert %s to wide character string", cert_name_utf8);
  619. efree(server_name);
  620. OPENSSL_free(cert_name_utf8);
  621. CertFreeCertificateChain(cert_chain_ctx);
  622. CertFreeCertificateContext(cert_ctx);
  623. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  624. }
  625. OPENSSL_free(cert_name_utf8);
  626. }
  627. ssl_policy_params.dwAuthType = (sslsock->is_client) ? AUTHTYPE_SERVER : AUTHTYPE_CLIENT;
  628. ssl_policy_params.pwszServerName = server_name;
  629. chain_policy_params.pvExtraPolicyPara = &ssl_policy_params;
  630. verify_result = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, cert_chain_ctx, &chain_policy_params, &chain_policy_status);
  631. efree(server_name);
  632. CertFreeCertificateChain(cert_chain_ctx);
  633. CertFreeCertificateContext(cert_ctx);
  634. if (!verify_result) {
  635. php_error_docref(NULL, E_WARNING, "Error verifying certificate chain policy: %s", php_win_err());
  636. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  637. }
  638. if (chain_policy_status.dwError != 0) {
  639. /* The chain does not match the policy */
  640. if (is_self_signed && chain_policy_status.dwError == CERT_E_UNTRUSTEDROOT
  641. && GET_VER_OPT("allow_self_signed") && zend_is_true(val)) {
  642. /* allow self-signed certs */
  643. X509_STORE_CTX_set_error(x509_store_ctx, X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
  644. } else {
  645. RETURN_CERT_VERIFY_FAILURE(SSL_R_CERTIFICATE_VERIFY_FAILED);
  646. }
  647. }
  648. }
  649. return 1;
  650. }
  651. /* }}} */
  652. #endif
  653. static long php_openssl_load_stream_cafile(X509_STORE *cert_store, const char *cafile) /* {{{ */
  654. {
  655. php_stream *stream;
  656. X509 *cert;
  657. BIO *buffer;
  658. int buffer_active = 0;
  659. char *line = NULL;
  660. size_t line_len;
  661. long certs_added = 0;
  662. stream = php_stream_open_wrapper(cafile, "rb", 0, NULL);
  663. if (stream == NULL) {
  664. php_error(E_WARNING, "failed loading cafile stream: `%s'", cafile);
  665. return 0;
  666. } else if (stream->wrapper->is_url) {
  667. php_stream_close(stream);
  668. php_error(E_WARNING, "remote cafile streams are disabled for security purposes");
  669. return 0;
  670. }
  671. cert_start: {
  672. line = php_stream_get_line(stream, NULL, 0, &line_len);
  673. if (line == NULL) {
  674. goto stream_complete;
  675. } else if (!strcmp(line, "-----BEGIN CERTIFICATE-----\n") ||
  676. !strcmp(line, "-----BEGIN CERTIFICATE-----\r\n")
  677. ) {
  678. buffer = BIO_new(BIO_s_mem());
  679. buffer_active = 1;
  680. goto cert_line;
  681. } else {
  682. efree(line);
  683. goto cert_start;
  684. }
  685. }
  686. cert_line: {
  687. BIO_puts(buffer, line);
  688. efree(line);
  689. line = php_stream_get_line(stream, NULL, 0, &line_len);
  690. if (line == NULL) {
  691. goto stream_complete;
  692. } else if (!strcmp(line, "-----END CERTIFICATE-----") ||
  693. !strcmp(line, "-----END CERTIFICATE-----\n") ||
  694. !strcmp(line, "-----END CERTIFICATE-----\r\n")
  695. ) {
  696. goto add_cert;
  697. } else {
  698. goto cert_line;
  699. }
  700. }
  701. add_cert: {
  702. BIO_puts(buffer, line);
  703. efree(line);
  704. cert = PEM_read_bio_X509(buffer, NULL, 0, NULL);
  705. BIO_free(buffer);
  706. buffer_active = 0;
  707. if (cert && X509_STORE_add_cert(cert_store, cert)) {
  708. ++certs_added;
  709. X509_free(cert);
  710. }
  711. goto cert_start;
  712. }
  713. stream_complete: {
  714. php_stream_close(stream);
  715. if (buffer_active == 1) {
  716. BIO_free(buffer);
  717. }
  718. }
  719. if (certs_added == 0) {
  720. php_error(E_WARNING, "no valid certs found cafile stream: `%s'", cafile);
  721. }
  722. return certs_added;
  723. }
  724. /* }}} */
  725. static int php_openssl_enable_peer_verification(SSL_CTX *ctx, php_stream *stream) /* {{{ */
  726. {
  727. zval *val = NULL;
  728. char *cafile = NULL;
  729. char *capath = NULL;
  730. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  731. GET_VER_OPT_STRING("cafile", cafile);
  732. GET_VER_OPT_STRING("capath", capath);
  733. if (cafile == NULL) {
  734. cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0);
  735. cafile = strlen(cafile) ? cafile : NULL;
  736. } else if (!sslsock->is_client) {
  737. /* Servers need to load and assign CA names from the cafile */
  738. STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(cafile);
  739. if (cert_names != NULL) {
  740. SSL_CTX_set_client_CA_list(ctx, cert_names);
  741. } else {
  742. php_error(E_WARNING, "SSL: failed loading CA names from cafile");
  743. return FAILURE;
  744. }
  745. }
  746. if (capath == NULL) {
  747. capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0);
  748. capath = strlen(capath) ? capath : NULL;
  749. }
  750. if (cafile || capath) {
  751. if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) {
  752. ERR_clear_error();
  753. if (cafile && !php_openssl_load_stream_cafile(SSL_CTX_get_cert_store(ctx), cafile)) {
  754. return FAILURE;
  755. }
  756. }
  757. } else {
  758. #ifdef PHP_WIN32
  759. SSL_CTX_set_cert_verify_callback(ctx, php_openssl_win_cert_verify_callback, (void *)stream);
  760. SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
  761. #else
  762. if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) {
  763. php_error_docref(NULL, E_WARNING,
  764. "Unable to set default verify locations and no CA settings specified");
  765. return FAILURE;
  766. }
  767. #endif
  768. }
  769. SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
  770. return SUCCESS;
  771. }
  772. /* }}} */
  773. static void php_openssl_disable_peer_verification(SSL_CTX *ctx, php_stream *stream) /* {{{ */
  774. {
  775. SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
  776. }
  777. /* }}} */
  778. static int php_openssl_set_local_cert(SSL_CTX *ctx, php_stream *stream) /* {{{ */
  779. {
  780. zval *val = NULL;
  781. char *certfile = NULL;
  782. GET_VER_OPT_STRING("local_cert", certfile);
  783. if (certfile) {
  784. char resolved_path_buff[MAXPATHLEN];
  785. const char *private_key = NULL;
  786. if (VCWD_REALPATH(certfile, resolved_path_buff)) {
  787. /* a certificate to use for authentication */
  788. if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) {
  789. php_error_docref(NULL, E_WARNING,
  790. "Unable to set local cert chain file `%s'; Check that your cafile/capath "
  791. "settings include details of your certificate and its issuer",
  792. certfile);
  793. return FAILURE;
  794. }
  795. GET_VER_OPT_STRING("local_pk", private_key);
  796. if (private_key) {
  797. char resolved_path_buff_pk[MAXPATHLEN];
  798. if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) {
  799. if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) {
  800. php_error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk);
  801. return FAILURE;
  802. }
  803. }
  804. } else {
  805. if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
  806. php_error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff);
  807. return FAILURE;
  808. }
  809. }
  810. if (!SSL_CTX_check_private_key(ctx)) {
  811. php_error_docref(NULL, E_WARNING, "Private key does not match certificate!");
  812. }
  813. }
  814. }
  815. return SUCCESS;
  816. }
  817. /* }}} */
  818. #define PHP_SSL_MAX_VERSION_LEN 32
  819. static char *php_openssl_cipher_get_version(const SSL_CIPHER *c, char *buffer, size_t max_len) /* {{{ */
  820. {
  821. const char *version = SSL_CIPHER_get_version(c);
  822. strncpy(buffer, version, max_len);
  823. if (max_len <= strlen(version)) {
  824. buffer[max_len - 1] = 0;
  825. }
  826. return buffer;
  827. }
  828. /* }}} */
  829. #if PHP_OPENSSL_API_VERSION < 0x10100
  830. static int php_openssl_get_crypto_method_ctx_flags(int method_flags) /* {{{ */
  831. {
  832. int ssl_ctx_options = SSL_OP_ALL;
  833. #ifdef SSL_OP_NO_SSLv2
  834. ssl_ctx_options |= SSL_OP_NO_SSLv2;
  835. #endif
  836. #ifdef HAVE_SSL3
  837. if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv3)) {
  838. ssl_ctx_options |= SSL_OP_NO_SSLv3;
  839. }
  840. #endif
  841. if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_0)) {
  842. ssl_ctx_options |= SSL_OP_NO_TLSv1;
  843. }
  844. #ifdef HAVE_TLS11
  845. if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_1)) {
  846. ssl_ctx_options |= SSL_OP_NO_TLSv1_1;
  847. }
  848. #endif
  849. #ifdef HAVE_TLS12
  850. if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_2)) {
  851. ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
  852. }
  853. #endif
  854. return ssl_ctx_options;
  855. }
  856. /* }}} */
  857. #endif
  858. static inline int php_openssl_get_min_proto_version_flag(int flags) /* {{{ */
  859. {
  860. int ver;
  861. for (ver = PHP_OPENSSL_MIN_PROTO_VERSION; ver <= PHP_OPENSSL_MAX_PROTO_VERSION; ver <<= 1) {
  862. if (flags & ver) {
  863. return ver;
  864. }
  865. }
  866. return STREAM_CRYPTO_METHOD_TLSv1_2;
  867. }
  868. /* }}} */
  869. static inline int php_openssl_get_max_proto_version_flag(int flags) /* {{{ */
  870. {
  871. int ver;
  872. for (ver = PHP_OPENSSL_MAX_PROTO_VERSION; ver >= PHP_OPENSSL_MIN_PROTO_VERSION; ver >>= 1) {
  873. if (flags & ver) {
  874. return ver;
  875. }
  876. }
  877. return STREAM_CRYPTO_METHOD_TLSv1_2;
  878. }
  879. /* }}} */
  880. #if PHP_OPENSSL_API_VERSION >= 0x10100
  881. static inline int php_openssl_map_proto_version(int flag) /* {{{ */
  882. {
  883. switch (flag) {
  884. #ifdef HAVE_SSL3
  885. case STREAM_CRYPTO_METHOD_SSLv3:
  886. return SSL3_VERSION;
  887. #endif
  888. case STREAM_CRYPTO_METHOD_TLSv1_0:
  889. return TLS1_VERSION;
  890. case STREAM_CRYPTO_METHOD_TLSv1_1:
  891. return TLS1_1_VERSION;
  892. /* case STREAM_CRYPTO_METHOD_TLSv1_2: */
  893. default:
  894. return TLS1_2_VERSION;
  895. }
  896. }
  897. /* }}} */
  898. static int php_openssl_get_min_proto_version(int flags) /* {{{ */
  899. {
  900. return php_openssl_map_proto_version(php_openssl_get_min_proto_version_flag(flags));
  901. }
  902. /* }}} */
  903. static int php_openssl_get_max_proto_version(int flags) /* {{{ */
  904. {
  905. return php_openssl_map_proto_version(php_openssl_get_max_proto_version_flag(flags));
  906. }
  907. /* }}} */
  908. #endif
  909. static int php_openssl_get_proto_version_flags(int flags, int min, int max) /* {{{ */
  910. {
  911. int ver;
  912. if (!min) {
  913. min = php_openssl_get_min_proto_version_flag(flags);
  914. }
  915. if (!max) {
  916. max = php_openssl_get_max_proto_version_flag(flags);
  917. }
  918. for (ver = PHP_OPENSSL_MIN_PROTO_VERSION; ver <= PHP_OPENSSL_MAX_PROTO_VERSION; ver <<= 1) {
  919. if (ver >= min && ver <= max) {
  920. if (!(flags & ver)) {
  921. flags |= ver;
  922. }
  923. } else if (flags & ver) {
  924. flags &= ~ver;
  925. }
  926. }
  927. return flags;
  928. }
  929. /* }}} */
  930. static void php_openssl_limit_handshake_reneg(const SSL *ssl) /* {{{ */
  931. {
  932. php_stream *stream;
  933. php_openssl_netstream_data_t *sslsock;
  934. struct timeval now;
  935. zend_long elapsed_time;
  936. stream = php_openssl_get_stream_from_ssl_handle(ssl);
  937. sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  938. gettimeofday(&now, NULL);
  939. /* The initial handshake is never rate-limited */
  940. if (sslsock->reneg->prev_handshake == 0) {
  941. sslsock->reneg->prev_handshake = now.tv_sec;
  942. return;
  943. }
  944. elapsed_time = (now.tv_sec - sslsock->reneg->prev_handshake);
  945. sslsock->reneg->prev_handshake = now.tv_sec;
  946. sslsock->reneg->tokens -= (elapsed_time * (sslsock->reneg->limit / sslsock->reneg->window));
  947. if (sslsock->reneg->tokens < 0) {
  948. sslsock->reneg->tokens = 0;
  949. }
  950. ++sslsock->reneg->tokens;
  951. /* The token level exceeds our allowed limit */
  952. if (sslsock->reneg->tokens > sslsock->reneg->limit) {
  953. zval *val;
  954. sslsock->reneg->should_close = 1;
  955. if (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
  956. "ssl", "reneg_limit_callback")) != NULL
  957. ) {
  958. zval param, retval;
  959. php_stream_to_zval(stream, &param);
  960. /* Closing the stream inside this callback would segfault! */
  961. stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
  962. if (FAILURE == call_user_function_ex(EG(function_table), NULL, val, &retval, 1, &param, 0, NULL)) {
  963. php_error(E_WARNING, "SSL: failed invoking reneg limit notification callback");
  964. }
  965. stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE;
  966. /* If the reneg_limit_callback returned true don't auto-close */
  967. if (Z_TYPE(retval) == IS_TRUE) {
  968. sslsock->reneg->should_close = 0;
  969. }
  970. zval_ptr_dtor(&retval);
  971. } else {
  972. php_error_docref(NULL, E_WARNING,
  973. "SSL: client-initiated handshake rate limit exceeded by peer");
  974. }
  975. }
  976. }
  977. /* }}} */
  978. static void php_openssl_info_callback(const SSL *ssl, int where, int ret) /* {{{ */
  979. {
  980. /* Rate-limit client-initiated handshake renegotiation to prevent DoS */
  981. if (where & SSL_CB_HANDSHAKE_START) {
  982. php_openssl_limit_handshake_reneg(ssl);
  983. }
  984. }
  985. /* }}} */
  986. static void php_openssl_init_server_reneg_limit(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
  987. {
  988. zval *val;
  989. zend_long limit = OPENSSL_DEFAULT_RENEG_LIMIT;
  990. zend_long window = OPENSSL_DEFAULT_RENEG_WINDOW;
  991. if (PHP_STREAM_CONTEXT(stream) &&
  992. NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "reneg_limit"))
  993. ) {
  994. limit = zval_get_long(val);
  995. }
  996. /* No renegotiation rate-limiting */
  997. if (limit < 0) {
  998. return;
  999. }
  1000. if (PHP_STREAM_CONTEXT(stream) &&
  1001. NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "reneg_window"))
  1002. ) {
  1003. window = zval_get_long(val);
  1004. }
  1005. sslsock->reneg = (void*)pemalloc(sizeof(php_openssl_handshake_bucket_t),
  1006. php_stream_is_persistent(stream)
  1007. );
  1008. sslsock->reneg->limit = limit;
  1009. sslsock->reneg->window = window;
  1010. sslsock->reneg->prev_handshake = 0;
  1011. sslsock->reneg->tokens = 0;
  1012. sslsock->reneg->should_close = 0;
  1013. SSL_set_info_callback(sslsock->ssl_handle, php_openssl_info_callback);
  1014. }
  1015. /* }}} */
  1016. #if PHP_OPENSSL_API_VERSION < 0x10100
  1017. static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength)
  1018. {
  1019. BIGNUM *bn = NULL;
  1020. static RSA *rsa_tmp = NULL;
  1021. if (!rsa_tmp && ((bn = BN_new()) == NULL)) {
  1022. php_error_docref(NULL, E_WARNING, "allocation error generating RSA key");
  1023. }
  1024. if (!rsa_tmp && bn) {
  1025. if (!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) ||
  1026. !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) {
  1027. if (rsa_tmp) {
  1028. RSA_free(rsa_tmp);
  1029. }
  1030. rsa_tmp = NULL;
  1031. }
  1032. BN_free(bn);
  1033. }
  1034. return (rsa_tmp);
  1035. }
  1036. #endif
  1037. static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* {{{ */
  1038. {
  1039. DH *dh;
  1040. BIO* bio;
  1041. zval *zdhpath;
  1042. zdhpath = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "dh_param");
  1043. if (zdhpath == NULL) {
  1044. #if 0
  1045. /* Coming in OpenSSL 1.1 ... eventually we'll want to enable this
  1046. * in the absence of an explicit dh_param.
  1047. */
  1048. SSL_CTX_set_dh_auto(ctx, 1);
  1049. #endif
  1050. return SUCCESS;
  1051. }
  1052. convert_to_string_ex(zdhpath);
  1053. bio = BIO_new_file(Z_STRVAL_P(zdhpath), PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
  1054. if (bio == NULL) {
  1055. php_error_docref(NULL, E_WARNING, "invalid dh_param");
  1056. return FAILURE;
  1057. }
  1058. dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  1059. BIO_free(bio);
  1060. if (dh == NULL) {
  1061. php_error_docref(NULL, E_WARNING, "failed reading DH params");
  1062. return FAILURE;
  1063. }
  1064. if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) {
  1065. php_error_docref(NULL, E_WARNING, "failed assigning DH params");
  1066. DH_free(dh);
  1067. return FAILURE;
  1068. }
  1069. DH_free(dh);
  1070. return SUCCESS;
  1071. }
  1072. /* }}} */
  1073. #if defined(HAVE_ECDH) && PHP_OPENSSL_API_VERSION < 0x10100
  1074. static int php_openssl_set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx) /* {{{ */
  1075. {
  1076. zval *zvcurve;
  1077. int curve_nid;
  1078. EC_KEY *ecdh;
  1079. zvcurve = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "ecdh_curve");
  1080. if (zvcurve == NULL) {
  1081. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  1082. SSL_CTX_set_ecdh_auto(ctx, 1);
  1083. return SUCCESS;
  1084. #else
  1085. curve_nid = NID_X9_62_prime256v1;
  1086. #endif
  1087. } else {
  1088. convert_to_string_ex(zvcurve);
  1089. curve_nid = OBJ_sn2nid(Z_STRVAL_P(zvcurve));
  1090. if (curve_nid == NID_undef) {
  1091. php_error_docref(NULL, E_WARNING, "invalid ecdh_curve specified");
  1092. return FAILURE;
  1093. }
  1094. }
  1095. ecdh = EC_KEY_new_by_curve_name(curve_nid);
  1096. if (ecdh == NULL) {
  1097. php_error_docref(NULL, E_WARNING, "failed generating ECDH curve");
  1098. return FAILURE;
  1099. }
  1100. SSL_CTX_set_tmp_ecdh(ctx, ecdh);
  1101. EC_KEY_free(ecdh);
  1102. return SUCCESS;
  1103. }
  1104. /* }}} */
  1105. #endif
  1106. static int php_openssl_set_server_specific_opts(php_stream *stream, SSL_CTX *ctx) /* {{{ */
  1107. {
  1108. zval *zv;
  1109. long ssl_ctx_options = SSL_CTX_get_options(ctx);
  1110. #if defined(HAVE_ECDH) && PHP_OPENSSL_API_VERSION < 0x10100
  1111. if (php_openssl_set_server_ecdh_curve(stream, ctx) == FAILURE) {
  1112. return FAILURE;
  1113. }
  1114. #endif
  1115. #if PHP_OPENSSL_API_VERSION < 0x10100
  1116. SSL_CTX_set_tmp_rsa_callback(ctx, php_openssl_tmp_rsa_cb);
  1117. #endif
  1118. /* We now use php_openssl_tmp_rsa_cb to generate a key of appropriate size whenever necessary */
  1119. if (php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "rsa_key_size") != NULL) {
  1120. php_error_docref(NULL, E_WARNING, "rsa_key_size context option has been removed");
  1121. }
  1122. php_openssl_set_server_dh_param(stream, ctx);
  1123. zv = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "single_dh_use");
  1124. if (zv == NULL || zend_is_true(zv)) {
  1125. ssl_ctx_options |= SSL_OP_SINGLE_DH_USE;
  1126. }
  1127. zv = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "honor_cipher_order");
  1128. if (zv == NULL || zend_is_true(zv)) {
  1129. ssl_ctx_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
  1130. }
  1131. SSL_CTX_set_options(ctx, ssl_ctx_options);
  1132. return SUCCESS;
  1133. }
  1134. /* }}} */
  1135. #ifdef HAVE_TLS_SNI
  1136. static int php_openssl_server_sni_callback(SSL *ssl_handle, int *al, void *arg) /* {{{ */
  1137. {
  1138. php_stream *stream;
  1139. php_openssl_netstream_data_t *sslsock;
  1140. unsigned i;
  1141. const char *server_name;
  1142. server_name = SSL_get_servername(ssl_handle, TLSEXT_NAMETYPE_host_name);
  1143. if (!server_name) {
  1144. return SSL_TLSEXT_ERR_NOACK;
  1145. }
  1146. stream = (php_stream*)SSL_get_ex_data(ssl_handle, php_openssl_get_ssl_stream_data_index());
  1147. sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  1148. if (!(sslsock->sni_cert_count && sslsock->sni_certs)) {
  1149. return SSL_TLSEXT_ERR_NOACK;
  1150. }
  1151. for (i=0; i < sslsock->sni_cert_count; i++) {
  1152. if (php_openssl_matches_wildcard_name(server_name, sslsock->sni_certs[i].name)) {
  1153. SSL_set_SSL_CTX(ssl_handle, sslsock->sni_certs[i].ctx);
  1154. return SSL_TLSEXT_ERR_OK;
  1155. }
  1156. }
  1157. return SSL_TLSEXT_ERR_NOACK;
  1158. }
  1159. /* }}} */
  1160. static SSL_CTX *php_openssl_create_sni_server_ctx(char *cert_path, char *key_path) /* {{{ */
  1161. {
  1162. /* The hello method is not inherited by SSL structs when assigning a new context
  1163. * inside the SNI callback, so the just use SSLv23 */
  1164. SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
  1165. if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) != 1) {
  1166. php_error_docref(NULL, E_WARNING,
  1167. "failed setting local cert chain file `%s'; " \
  1168. "check that your cafile/capath settings include " \
  1169. "details of your certificate and its issuer",
  1170. cert_path
  1171. );
  1172. SSL_CTX_free(ctx);
  1173. return NULL;
  1174. } else if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) != 1) {
  1175. php_error_docref(NULL, E_WARNING,
  1176. "failed setting private key from file `%s'",
  1177. key_path
  1178. );
  1179. SSL_CTX_free(ctx);
  1180. return NULL;
  1181. }
  1182. return ctx;
  1183. }
  1184. /* }}} */
  1185. static int php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
  1186. {
  1187. zval *val;
  1188. zval *current;
  1189. zend_string *key;
  1190. zend_ulong key_index;
  1191. int i = 0;
  1192. char resolved_path_buff[MAXPATHLEN];
  1193. SSL_CTX *ctx;
  1194. /* If the stream ctx disables SNI we're finished here */
  1195. if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val)) {
  1196. return SUCCESS;
  1197. }
  1198. /* If no SNI cert array is specified we're finished here */
  1199. if (!GET_VER_OPT("SNI_server_certs")) {
  1200. return SUCCESS;
  1201. }
  1202. if (Z_TYPE_P(val) != IS_ARRAY) {
  1203. php_error_docref(NULL, E_WARNING,
  1204. "SNI_server_certs requires an array mapping host names to cert paths"
  1205. );
  1206. return FAILURE;
  1207. }
  1208. sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_P(val));
  1209. if (sslsock->sni_cert_count == 0) {
  1210. php_error_docref(NULL, E_WARNING,
  1211. "SNI_server_certs host cert array must not be empty"
  1212. );
  1213. return FAILURE;
  1214. }
  1215. sslsock->sni_certs = (php_openssl_sni_cert_t*)safe_pemalloc(sslsock->sni_cert_count,
  1216. sizeof(php_openssl_sni_cert_t), 0, php_stream_is_persistent(stream)
  1217. );
  1218. memset(sslsock->sni_certs, 0, sslsock->sni_cert_count * sizeof(php_openssl_sni_cert_t));
  1219. ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(val), key_index, key, current) {
  1220. (void) key_index;
  1221. if (!key) {
  1222. php_error_docref(NULL, E_WARNING,
  1223. "SNI_server_certs array requires string host name keys"
  1224. );
  1225. return FAILURE;
  1226. }
  1227. if (Z_TYPE_P(current) == IS_ARRAY) {
  1228. zval *local_pk, *local_cert;
  1229. char resolved_cert_path_buff[MAXPATHLEN], resolved_pk_path_buff[MAXPATHLEN];
  1230. local_cert = zend_hash_str_find(Z_ARRVAL_P(current), "local_cert", sizeof("local_cert")-1);
  1231. if (local_cert == NULL) {
  1232. php_error_docref(NULL, E_WARNING,
  1233. "local_cert not present in the array"
  1234. );
  1235. return FAILURE;
  1236. }
  1237. convert_to_string_ex(local_cert);
  1238. if (!VCWD_REALPATH(Z_STRVAL_P(local_cert), resolved_cert_path_buff)) {
  1239. php_error_docref(NULL, E_WARNING,
  1240. "failed setting local cert chain file `%s'; file not found",
  1241. Z_STRVAL_P(local_cert)
  1242. );
  1243. return FAILURE;
  1244. }
  1245. local_pk = zend_hash_str_find(Z_ARRVAL_P(current), "local_pk", sizeof("local_pk")-1);
  1246. if (local_pk == NULL) {
  1247. php_error_docref(NULL, E_WARNING,
  1248. "local_pk not present in the array"
  1249. );
  1250. return FAILURE;
  1251. }
  1252. convert_to_string_ex(local_pk);
  1253. if (!VCWD_REALPATH(Z_STRVAL_P(local_pk), resolved_pk_path_buff)) {
  1254. php_error_docref(NULL, E_WARNING,
  1255. "failed setting local private key file `%s'; file not found",
  1256. Z_STRVAL_P(local_pk)
  1257. );
  1258. return FAILURE;
  1259. }
  1260. ctx = php_openssl_create_sni_server_ctx(resolved_cert_path_buff, resolved_pk_path_buff);
  1261. } else if (VCWD_REALPATH(Z_STRVAL_P(current), resolved_path_buff)) {
  1262. ctx = php_openssl_create_sni_server_ctx(resolved_path_buff, resolved_path_buff);
  1263. } else {
  1264. php_error_docref(NULL, E_WARNING,
  1265. "failed setting local cert chain file `%s'; file not found",
  1266. Z_STRVAL_P(current)
  1267. );
  1268. return FAILURE;
  1269. }
  1270. if (ctx == NULL) {
  1271. return FAILURE;
  1272. }
  1273. sslsock->sni_certs[i].name = pestrdup(ZSTR_VAL(key), php_stream_is_persistent(stream));
  1274. sslsock->sni_certs[i].ctx = ctx;
  1275. ++i;
  1276. } ZEND_HASH_FOREACH_END();
  1277. SSL_CTX_set_tlsext_servername_callback(sslsock->ctx, php_openssl_server_sni_callback);
  1278. return SUCCESS;
  1279. }
  1280. /* }}} */
  1281. static void php_openssl_enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
  1282. {
  1283. zval *val;
  1284. char *sni_server_name;
  1285. /* If SNI is explicitly disabled we're finished here */
  1286. if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val)) {
  1287. return;
  1288. }
  1289. sni_server_name = sslsock->url_name;
  1290. GET_VER_OPT_STRING("peer_name", sni_server_name);
  1291. if (sni_server_name) {
  1292. SSL_set_tlsext_host_name(sslsock->ssl_handle, sni_server_name);
  1293. }
  1294. }
  1295. /* }}} */
  1296. #endif
  1297. #ifdef HAVE_TLS_ALPN
  1298. /**
  1299. * Parses a comma-separated list of strings into a string suitable for SSL_CTX_set_next_protos_advertised
  1300. * outlen: (output) set to the length of the resulting buffer on success.
  1301. * err: (maybe NULL) on failure, an error message line is written to this BIO.
  1302. * in: a NULL terminated string like "abc,def,ghi"
  1303. *
  1304. * returns: an emalloced buffer or NULL on failure.
  1305. */
  1306. static unsigned char *php_openssl_alpn_protos_parse(unsigned short *outlen, const char *in) /* {{{ */
  1307. {
  1308. size_t len;
  1309. unsigned char *out;
  1310. size_t i, start = 0;
  1311. len = strlen(in);
  1312. if (len >= 65535) {
  1313. return NULL;
  1314. }
  1315. out = emalloc(strlen(in) + 1);
  1316. for (i = 0; i <= len; ++i) {
  1317. if (i == len || in[i] == ',') {
  1318. if (i - start > 255) {
  1319. efree(out);
  1320. return NULL;
  1321. }
  1322. out[start] = i - start;
  1323. start = i + 1;
  1324. } else {
  1325. out[i + 1] = in[i];
  1326. }
  1327. }
  1328. *outlen = len + 1;
  1329. return out;
  1330. }
  1331. /* }}} */
  1332. static int php_openssl_server_alpn_callback(SSL *ssl_handle,
  1333. const unsigned char **out, unsigned char *outlen,
  1334. const unsigned char *in, unsigned int inlen, void *arg) /* {{{ */
  1335. {
  1336. php_openssl_netstream_data_t *sslsock = arg;
  1337. if (SSL_select_next_proto((unsigned char **)out, outlen, sslsock->alpn_ctx.data, sslsock->alpn_ctx.len, in, inlen) != OPENSSL_NPN_NEGOTIATED) {
  1338. return SSL_TLSEXT_ERR_NOACK;
  1339. }
  1340. return SSL_TLSEXT_ERR_OK;
  1341. }
  1342. /* }}} */
  1343. #endif
  1344. int php_openssl_setup_crypto(php_stream *stream,
  1345. php_openssl_netstream_data_t *sslsock,
  1346. php_stream_xport_crypto_param *cparam) /* {{{ */
  1347. {
  1348. const SSL_METHOD *method;
  1349. int ssl_ctx_options;
  1350. int method_flags;
  1351. zend_long min_version = 0;
  1352. zend_long max_version = 0;
  1353. char *cipherlist = NULL;
  1354. char *alpn_protocols = NULL;
  1355. zval *val;
  1356. if (sslsock->ssl_handle) {
  1357. if (sslsock->s.is_blocked) {
  1358. php_error_docref(NULL, E_WARNING, "SSL/TLS already set-up for this stream");
  1359. return FAILURE;
  1360. } else {
  1361. return SUCCESS;
  1362. }
  1363. }
  1364. ERR_clear_error();
  1365. /* We need to do slightly different things based on client/server method
  1366. * so lets remember which method was selected */
  1367. sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT;
  1368. method_flags = ((cparam->inputs.method >> 1) << 1);
  1369. method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method();
  1370. sslsock->ctx = SSL_CTX_new(method);
  1371. GET_VER_OPT_LONG("min_proto_version", min_version);
  1372. GET_VER_OPT_LONG("max_proto_version", max_version);
  1373. method_flags = php_openssl_get_proto_version_flags(method_flags, min_version, max_version);
  1374. #if PHP_OPENSSL_API_VERSION < 0x10100
  1375. ssl_ctx_options = php_openssl_get_crypto_method_ctx_flags(method_flags);
  1376. #else
  1377. ssl_ctx_options = SSL_OP_ALL;
  1378. #endif
  1379. if (sslsock->ctx == NULL) {
  1380. php_error_docref(NULL, E_WARNING, "SSL context creation failure");
  1381. return FAILURE;
  1382. }
  1383. if (GET_VER_OPT("no_ticket") && zend_is_true(val)) {
  1384. ssl_ctx_options |= SSL_OP_NO_TICKET;
  1385. }
  1386. ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
  1387. if (!GET_VER_OPT("disable_compression") || zend_is_true(val)) {
  1388. ssl_ctx_options |= SSL_OP_NO_COMPRESSION;
  1389. }
  1390. if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) {
  1391. php_openssl_disable_peer_verification(sslsock->ctx, stream);
  1392. } else if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) {
  1393. return FAILURE;
  1394. }
  1395. /* callback for the passphrase (for localcert) */
  1396. if (GET_VER_OPT("passphrase")) {
  1397. SSL_CTX_set_default_passwd_cb_userdata(sslsock->ctx, stream);
  1398. SSL_CTX_set_default_passwd_cb(sslsock->ctx, php_openssl_passwd_callback);
  1399. }
  1400. GET_VER_OPT_STRING("ciphers", cipherlist);
  1401. #ifndef USE_OPENSSL_SYSTEM_CIPHERS
  1402. if (!cipherlist) {
  1403. cipherlist = OPENSSL_DEFAULT_STREAM_CIPHERS;
  1404. }
  1405. #endif
  1406. if (cipherlist) {
  1407. if (SSL_CTX_set_cipher_list(sslsock->ctx, cipherlist) != 1) {
  1408. return FAILURE;
  1409. }
  1410. }
  1411. if (GET_VER_OPT("security_level")) {
  1412. #ifdef HAVE_SEC_LEVEL
  1413. zend_long lval = zval_get_long(val);
  1414. if (lval < 0 || lval > 5) {
  1415. php_error_docref(NULL, E_WARNING, "Security level must be between 0 and 5");
  1416. }
  1417. SSL_CTX_set_security_level(sslsock->ctx, lval);
  1418. #else
  1419. php_error_docref(NULL, E_WARNING,
  1420. "security_level is not supported by the linked OpenSSL library "
  1421. "- it is supported from version 1.1.0");
  1422. #endif
  1423. }
  1424. GET_VER_OPT_STRING("alpn_protocols", alpn_protocols);
  1425. if (alpn_protocols) {
  1426. #ifdef HAVE_TLS_ALPN
  1427. {
  1428. unsigned short alpn_len;
  1429. unsigned char *alpn = php_openssl_alpn_protos_parse(&alpn_len, alpn_protocols);
  1430. if (alpn == NULL) {
  1431. php_error_docref(NULL, E_WARNING, "Failed parsing comma-separated TLS ALPN protocol string");
  1432. SSL_CTX_free(sslsock->ctx);
  1433. sslsock->ctx = NULL;
  1434. return FAILURE;
  1435. }
  1436. if (sslsock->is_client) {
  1437. SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len);
  1438. } else {
  1439. sslsock->alpn_ctx.data = (unsigned char *) pestrndup((const char*)alpn, alpn_len, php_stream_is_persistent(stream));
  1440. sslsock->alpn_ctx.len = alpn_len;
  1441. SSL_CTX_set_alpn_select_cb(sslsock->ctx, php_openssl_server_alpn_callback, sslsock);
  1442. }
  1443. efree(alpn);
  1444. }
  1445. #else
  1446. php_error_docref(NULL, E_WARNING,
  1447. "alpn_protocols support is not compiled into the OpenSSL library against which PHP is linked");
  1448. #endif
  1449. }
  1450. if (FAILURE == php_openssl_set_local_cert(sslsock->ctx, stream)) {
  1451. return FAILURE;
  1452. }
  1453. SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options);
  1454. #if PHP_OPENSSL_API_VERSION >= 0x10100
  1455. SSL_CTX_set_min_proto_version(sslsock->ctx, php_openssl_get_min_proto_version(method_flags));
  1456. SSL_CTX_set_max_proto_version(sslsock->ctx, php_openssl_get_max_proto_version(method_flags));
  1457. #endif
  1458. if (sslsock->is_client == 0 &&
  1459. PHP_STREAM_CONTEXT(stream) &&
  1460. FAILURE == php_openssl_set_server_specific_opts(stream, sslsock->ctx)
  1461. ) {
  1462. return FAILURE;
  1463. }
  1464. sslsock->ssl_handle = SSL_new(sslsock->ctx);
  1465. if (sslsock->ssl_handle == NULL) {
  1466. php_error_docref(NULL, E_WARNING, "SSL handle creation failure");
  1467. SSL_CTX_free(sslsock->ctx);
  1468. sslsock->ctx = NULL;
  1469. #ifdef HAVE_TLS_ALPN
  1470. if (sslsock->alpn_ctx.data) {
  1471. pefree(sslsock->alpn_ctx.data, php_stream_is_persistent(stream));
  1472. sslsock->alpn_ctx.data = NULL;
  1473. }
  1474. #endif
  1475. return FAILURE;
  1476. } else {
  1477. SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream);
  1478. }
  1479. if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) {
  1480. php_openssl_handle_ssl_error(stream, 0, 1);
  1481. }
  1482. #ifdef HAVE_TLS_SNI
  1483. /* Enable server-side SNI */
  1484. if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock) == FAILURE) {
  1485. return FAILURE;
  1486. }
  1487. #endif
  1488. /* Enable server-side handshake renegotiation rate-limiting */
  1489. if (!sslsock->is_client) {
  1490. php_openssl_init_server_reneg_limit(stream, sslsock);
  1491. }
  1492. #ifdef SSL_MODE_RELEASE_BUFFERS
  1493. SSL_set_mode(sslsock->ssl_handle, SSL_get_mode(sslsock->ssl_handle) | SSL_MODE_RELEASE_BUFFERS);
  1494. #endif
  1495. if (cparam->inputs.session) {
  1496. if (cparam->inputs.session->ops != &php_openssl_socket_ops) {
  1497. php_error_docref(NULL, E_WARNING, "supplied session stream must be an SSL enabled stream");
  1498. } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) {
  1499. php_error_docref(NULL, E_WARNING, "supplied SSL session stream is not initialized");
  1500. } else {
  1501. SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle);
  1502. }
  1503. }
  1504. return SUCCESS;
  1505. }
  1506. /* }}} */
  1507. static zend_array *php_openssl_capture_session_meta(SSL *ssl_handle) /* {{{ */
  1508. {
  1509. zval meta_arr;
  1510. char *proto_str;
  1511. long proto = SSL_version(ssl_handle);
  1512. const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle);
  1513. char version_str[PHP_SSL_MAX_VERSION_LEN];
  1514. switch (proto) {
  1515. #ifdef HAVE_TLS12
  1516. case TLS1_2_VERSION:
  1517. proto_str = "TLSv1.2";
  1518. break;
  1519. #endif
  1520. #ifdef HAVE_TLS11
  1521. case TLS1_1_VERSION:
  1522. proto_str = "TLSv1.1";
  1523. break;
  1524. #endif
  1525. case TLS1_VERSION:
  1526. proto_str = "TLSv1";
  1527. break;
  1528. #ifdef HAVE_SSL3
  1529. case SSL3_VERSION:
  1530. proto_str = "SSLv3";
  1531. break;
  1532. #endif
  1533. default: proto_str = "UNKNOWN";
  1534. }
  1535. array_init(&meta_arr);
  1536. add_assoc_string(&meta_arr, "protocol", proto_str);
  1537. add_assoc_string(&meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
  1538. add_assoc_long(&meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
  1539. add_assoc_string(&meta_arr, "cipher_version",
  1540. php_openssl_cipher_get_version(cipher, version_str, PHP_SSL_MAX_VERSION_LEN));
  1541. return Z_ARR(meta_arr);
  1542. }
  1543. /* }}} */
  1544. static int php_openssl_capture_peer_certs(php_stream *stream,
  1545. php_openssl_netstream_data_t *sslsock, X509 *peer_cert) /* {{{ */
  1546. {
  1547. zval *val, zcert;
  1548. int cert_captured = 0;
  1549. if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
  1550. "ssl", "capture_peer_cert")) &&
  1551. zend_is_true(val)
  1552. ) {
  1553. ZVAL_RES(&zcert, zend_register_resource(peer_cert, php_openssl_get_x509_list_id()));
  1554. php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_certificate", &zcert);
  1555. zval_ptr_dtor(&zcert);
  1556. cert_captured = 1;
  1557. }
  1558. if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
  1559. "ssl", "capture_peer_cert_chain")) &&
  1560. zend_is_true(val)
  1561. ) {
  1562. zval arr;
  1563. STACK_OF(X509) *chain;
  1564. chain = SSL_get_peer_cert_chain(sslsock->ssl_handle);
  1565. if (chain && sk_X509_num(chain) > 0) {
  1566. int i;
  1567. array_init(&arr);
  1568. for (i = 0; i < sk_X509_num(chain); i++) {
  1569. X509 *mycert = X509_dup(sk_X509_value(chain, i));
  1570. ZVAL_RES(&zcert, zend_register_resource(mycert, php_openssl_get_x509_list_id()));
  1571. add_next_index_zval(&arr, &zcert);
  1572. }
  1573. } else {
  1574. ZVAL_NULL(&arr);
  1575. }
  1576. php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_certificate_chain", &arr);
  1577. zval_ptr_dtor(&arr);
  1578. }
  1579. return cert_captured;
  1580. }
  1581. /* }}} */
  1582. static int php_openssl_enable_crypto(php_stream *stream,
  1583. php_openssl_netstream_data_t *sslsock,
  1584. php_stream_xport_crypto_param *cparam) /* {{{ */
  1585. {
  1586. int n;
  1587. int retry = 1;
  1588. int cert_captured = 0;
  1589. X509 *peer_cert;
  1590. if (cparam->inputs.activate && !sslsock->ssl_active) {
  1591. struct timeval start_time, *timeout;
  1592. int blocked = sslsock->s.is_blocked, has_timeout = 0;
  1593. #ifdef HAVE_TLS_SNI
  1594. if (sslsock->is_client) {
  1595. php_openssl_enable_client_sni(stream, sslsock);
  1596. }
  1597. #endif
  1598. if (!sslsock->state_set) {
  1599. if (sslsock->is_client) {
  1600. SSL_set_connect_state(sslsock->ssl_handle);
  1601. } else {
  1602. SSL_set_accept_state(sslsock->ssl_handle);
  1603. }
  1604. sslsock->state_set = 1;
  1605. }
  1606. if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0)) {
  1607. sslsock->s.is_blocked = 0;
  1608. /* The following mode are added only if we are able to change socket
  1609. * to non blocking mode which is also used for read and write */
  1610. SSL_set_mode(
  1611. sslsock->ssl_handle,
  1612. (
  1613. SSL_get_mode(sslsock->ssl_handle) |
  1614. SSL_MODE_ENABLE_PARTIAL_WRITE |
  1615. SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
  1616. )
  1617. );
  1618. }
  1619. timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
  1620. has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec));
  1621. /* gettimeofday is not monotonic; using it here is not strictly correct */
  1622. if (has_timeout) {
  1623. gettimeofday(&start_time, NULL);
  1624. }
  1625. do {
  1626. struct timeval cur_time, elapsed_time;
  1627. ERR_clear_error();
  1628. if (sslsock->is_client) {
  1629. n = SSL_connect(sslsock->ssl_handle);
  1630. } else {
  1631. n = SSL_accept(sslsock->ssl_handle);
  1632. }
  1633. if (has_timeout) {
  1634. gettimeofday(&cur_time, NULL);
  1635. elapsed_time = php_openssl_subtract_timeval(cur_time, start_time);
  1636. if (php_openssl_compare_timeval( elapsed_time, *timeout) > 0) {
  1637. php_error_docref(NULL, E_WARNING, "SSL: Handshake timed out");
  1638. return -1;
  1639. }
  1640. }
  1641. if (n <= 0) {
  1642. /* in case of SSL_ERROR_WANT_READ/WRITE, do not retry in non-blocking mode */
  1643. retry = php_openssl_handle_ssl_error(stream, n, blocked);
  1644. if (retry) {
  1645. /* wait until something interesting happens in the socket. It may be a
  1646. * timeout. Also consider the unlikely of possibility of a write block */
  1647. int err = SSL_get_error(sslsock->ssl_handle, n);
  1648. struct timeval left_time;
  1649. if (has_timeout) {
  1650. left_time = php_openssl_subtract_timeval(*timeout, elapsed_time);
  1651. }
  1652. php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
  1653. (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);
  1654. }
  1655. } else {
  1656. retry = 0;
  1657. }
  1658. } while (retry);
  1659. if (sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked)) {
  1660. sslsock->s.is_blocked = blocked;
  1661. }
  1662. if (n == 1) {
  1663. peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle);
  1664. if (peer_cert && PHP_STREAM_CONTEXT(stream)) {
  1665. cert_captured = php_openssl_capture_peer_certs(stream, sslsock, peer_cert);
  1666. }
  1667. if (FAILURE == php_openssl_apply_peer_verification_policy(sslsock->ssl_handle, peer_cert, stream)) {
  1668. SSL_shutdown(sslsock->ssl_handle);
  1669. n = -1;
  1670. } else {
  1671. sslsock->ssl_active = 1;
  1672. if (PHP_STREAM_CONTEXT(stream)) {
  1673. zval *val;
  1674. if (NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream),
  1675. "ssl", "capture_session_meta"))
  1676. ) {
  1677. php_error(E_DEPRECATED,
  1678. "capture_session_meta is deprecated; its information is now available via stream_get_meta_data()"
  1679. );
  1680. }
  1681. if (val && zend_is_true(val)) {
  1682. zval meta_arr;
  1683. ZVAL_ARR(&meta_arr, php_openssl_capture_session_meta(sslsock->ssl_handle));
  1684. php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "session_meta", &meta_arr);
  1685. zval_ptr_dtor(&meta_arr);
  1686. }
  1687. }
  1688. }
  1689. } else if (errno == EAGAIN) {
  1690. n = 0;
  1691. } else {
  1692. n = -1;
  1693. /* We want to capture the peer cert even if verification fails*/
  1694. peer_cert = SSL_get_peer_certificate(sslsock->ssl_handle);
  1695. if (peer_cert && PHP_STREAM_CONTEXT(stream)) {
  1696. cert_captured = php_openssl_capture_peer_certs(stream, sslsock, peer_cert);
  1697. }
  1698. }
  1699. if (n && peer_cert && cert_captured == 0) {
  1700. X509_free(peer_cert);
  1701. }
  1702. return n;
  1703. } else if (!cparam->inputs.activate && sslsock->ssl_active) {
  1704. /* deactivate - common for server/client */
  1705. SSL_shutdown(sslsock->ssl_handle);
  1706. sslsock->ssl_active = 0;
  1707. }
  1708. return -1;
  1709. }
  1710. /* }}} */
  1711. static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count) /* {{{ */
  1712. {
  1713. return php_openssl_sockop_io( 1, stream, buf, count );
  1714. }
  1715. /* }}} */
  1716. static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count) /* {{{ */
  1717. {
  1718. return php_openssl_sockop_io( 0, stream, (char*)buf, count );
  1719. }
  1720. /* }}} */
  1721. /**
  1722. * Factored out common functionality (blocking, timeout, loop management) for read and write.
  1723. * Perform IO (read or write) to an SSL socket. If we have a timeout, we switch to non-blocking mode
  1724. * for the duration of the operation, using select to do our waits. If we time out, or we have an error
  1725. * report that back to PHP
  1726. */
  1727. static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count) /* {{{ */
  1728. {
  1729. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  1730. /* Only do this if SSL is active. */
  1731. if (sslsock->ssl_active) {
  1732. int retry = 1;
  1733. struct timeval start_time;
  1734. struct timeval *timeout = NULL;
  1735. int began_blocked = sslsock->s.is_blocked;
  1736. int has_timeout = 0;
  1737. int nr_bytes = 0;
  1738. /* prevent overflow in openssl */
  1739. if (count > INT_MAX) {
  1740. count = INT_MAX;
  1741. }
  1742. /* never use a timeout with non-blocking sockets */
  1743. if (began_blocked) {
  1744. timeout = &sslsock->s.timeout;
  1745. }
  1746. if (timeout && php_set_sock_blocking(sslsock->s.socket, 0) == SUCCESS) {
  1747. sslsock->s.is_blocked = 0;
  1748. }
  1749. if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec))) {
  1750. has_timeout = 1;
  1751. /* gettimeofday is not monotonic; using it here is not strictly correct */
  1752. gettimeofday(&start_time, NULL);
  1753. }
  1754. /* Main IO loop. */
  1755. do {
  1756. struct timeval cur_time, elapsed_time, left_time;
  1757. /* If we have a timeout to check, figure out how much time has elapsed since we started. */
  1758. if (has_timeout) {
  1759. gettimeofday(&cur_time, NULL);
  1760. /* Determine how much time we've taken so far. */
  1761. elapsed_time = php_openssl_subtract_timeval(cur_time, start_time);
  1762. /* and return an error if we've taken too long. */
  1763. if (php_openssl_compare_timeval(elapsed_time, *timeout) > 0 ) {
  1764. /* If the socket was originally blocking, set it back. */
  1765. if (began_blocked) {
  1766. php_set_sock_blocking(sslsock->s.socket, 1);
  1767. sslsock->s.is_blocked = 1;
  1768. }
  1769. sslsock->s.timeout_event = 1;
  1770. return -1;
  1771. }
  1772. }
  1773. /* Now, do the IO operation. Don't block if we can't complete... */
  1774. ERR_clear_error();
  1775. if (read) {
  1776. nr_bytes = SSL_read(sslsock->ssl_handle, buf, (int)count);
  1777. if (sslsock->reneg && sslsock->reneg->should_close) {
  1778. /* renegotiation rate limiting triggered */
  1779. php_stream_xport_shutdown(stream, (stream_shutdown_t)SHUT_RDWR);
  1780. nr_bytes = 0;
  1781. stream->eof = 1;
  1782. break;
  1783. }
  1784. } else {
  1785. nr_bytes = SSL_write(sslsock->ssl_handle, buf, (int)count);
  1786. }
  1787. /* Now, how much time until we time out? */
  1788. if (has_timeout) {
  1789. left_time = php_openssl_subtract_timeval( *timeout, elapsed_time );
  1790. }
  1791. /* If we didn't do anything on the last loop (or an error) check to see if we should retry or exit. */
  1792. if (nr_bytes <= 0) {
  1793. /* Get the error code from SSL, and check to see if it's an error or not. */
  1794. int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
  1795. retry = php_openssl_handle_ssl_error(stream, nr_bytes, 0);
  1796. /* If we get this (the above doesn't check) then we'll retry as well. */
  1797. if (errno == EAGAIN && err == SSL_ERROR_WANT_READ && read) {
  1798. retry = 1;
  1799. }
  1800. if (errno == EAGAIN && err == SSL_ERROR_WANT_WRITE && read == 0) {
  1801. retry = 1;
  1802. }
  1803. /* Also, on reads, we may get this condition on an EOF. We should check properly. */
  1804. if (read) {
  1805. stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle));
  1806. }
  1807. /* Don't loop indefinitely in non-blocking mode if no data is available */
  1808. if (began_blocked == 0) {
  1809. break;
  1810. }
  1811. /* Now, if we have to wait some time, and we're supposed to be blocking, wait for the socket to become
  1812. * available. Now, php_pollfd_for uses select to wait up to our time_left value only...
  1813. */
  1814. if (retry) {
  1815. if (read) {
  1816. php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
  1817. (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
  1818. } else {
  1819. php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
  1820. (POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
  1821. }
  1822. }
  1823. } else {
  1824. /* Else, if we got bytes back, check for possible errors. */
  1825. int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
  1826. /* If we didn't get any error, then let's return it to PHP. */
  1827. if (err == SSL_ERROR_NONE) {
  1828. break;
  1829. }
  1830. /* Otherwise, we need to wait again (up to time_left or we get an error) */
  1831. if (began_blocked) {
  1832. if (read) {
  1833. php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
  1834. (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
  1835. } else {
  1836. php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
  1837. (POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
  1838. }
  1839. }
  1840. }
  1841. /* Finally, we keep going until we got data, and an SSL_ERROR_NONE, unless we had an error. */
  1842. } while (retry);
  1843. /* Tell PHP if we read / wrote bytes. */
  1844. if (nr_bytes > 0) {
  1845. php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
  1846. }
  1847. /* And if we were originally supposed to be blocking, let's reset the socket to that. */
  1848. if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1) == SUCCESS) {
  1849. sslsock->s.is_blocked = 1;
  1850. }
  1851. return 0 > nr_bytes ? 0 : nr_bytes;
  1852. } else {
  1853. size_t nr_bytes = 0;
  1854. /* This block is if we had no timeout... We will just sit and wait forever on the IO operation. */
  1855. if (read) {
  1856. nr_bytes = php_stream_socket_ops.read(stream, buf, count);
  1857. } else {
  1858. nr_bytes = php_stream_socket_ops.write(stream, buf, count);
  1859. }
  1860. return nr_bytes;
  1861. }
  1862. }
  1863. /* }}} */
  1864. static struct timeval php_openssl_subtract_timeval(struct timeval a, struct timeval b) /* {{{ */
  1865. {
  1866. struct timeval difference;
  1867. difference.tv_sec = a.tv_sec - b.tv_sec;
  1868. difference.tv_usec = a.tv_usec - b.tv_usec;
  1869. if (a.tv_usec < b.tv_usec) {
  1870. difference.tv_sec -= 1L;
  1871. difference.tv_usec += 1000000L;
  1872. }
  1873. return difference;
  1874. }
  1875. /* }}} */
  1876. static int php_openssl_compare_timeval( struct timeval a, struct timeval b )
  1877. {
  1878. if (a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec) ) {
  1879. return 1;
  1880. } else if( a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec ) {
  1881. return 0;
  1882. } else {
  1883. return -1;
  1884. }
  1885. }
  1886. static int php_openssl_sockop_close(php_stream *stream, int close_handle) /* {{{ */
  1887. {
  1888. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  1889. #ifdef PHP_WIN32
  1890. int n;
  1891. #endif
  1892. unsigned i;
  1893. if (close_handle) {
  1894. if (sslsock->ssl_active) {
  1895. SSL_shutdown(sslsock->ssl_handle);
  1896. sslsock->ssl_active = 0;
  1897. }
  1898. if (sslsock->ssl_handle) {
  1899. SSL_free(sslsock->ssl_handle);
  1900. sslsock->ssl_handle = NULL;
  1901. }
  1902. if (sslsock->ctx) {
  1903. SSL_CTX_free(sslsock->ctx);
  1904. sslsock->ctx = NULL;
  1905. }
  1906. #ifdef HAVE_TLS_ALPN
  1907. if (sslsock->alpn_ctx.data) {
  1908. pefree(sslsock->alpn_ctx.data, php_stream_is_persistent(stream));
  1909. }
  1910. #endif
  1911. #ifdef PHP_WIN32
  1912. if (sslsock->s.socket == -1)
  1913. sslsock->s.socket = SOCK_ERR;
  1914. #endif
  1915. if (sslsock->s.socket != SOCK_ERR) {
  1916. #ifdef PHP_WIN32
  1917. /* prevent more data from coming in */
  1918. shutdown(sslsock->s.socket, SHUT_RD);
  1919. /* try to make sure that the OS sends all data before we close the connection.
  1920. * Essentially, we are waiting for the socket to become writeable, which means
  1921. * that all pending data has been sent.
  1922. * We use a small timeout which should encourage the OS to send the data,
  1923. * but at the same time avoid hanging indefinitely.
  1924. * */
  1925. do {
  1926. n = php_pollfd_for_ms(sslsock->s.socket, POLLOUT, 500);
  1927. } while (n == -1 && php_socket_errno() == EINTR);
  1928. #endif
  1929. closesocket(sslsock->s.socket);
  1930. sslsock->s.socket = SOCK_ERR;
  1931. }
  1932. }
  1933. if (sslsock->sni_certs) {
  1934. for (i = 0; i < sslsock->sni_cert_count; i++) {
  1935. if (sslsock->sni_certs[i].ctx) {
  1936. SSL_CTX_free(sslsock->sni_certs[i].ctx);
  1937. pefree(sslsock->sni_certs[i].name, php_stream_is_persistent(stream));
  1938. }
  1939. }
  1940. pefree(sslsock->sni_certs, php_stream_is_persistent(stream));
  1941. sslsock->sni_certs = NULL;
  1942. }
  1943. if (sslsock->url_name) {
  1944. pefree(sslsock->url_name, php_stream_is_persistent(stream));
  1945. }
  1946. if (sslsock->reneg) {
  1947. pefree(sslsock->reneg, php_stream_is_persistent(stream));
  1948. }
  1949. pefree(sslsock, php_stream_is_persistent(stream));
  1950. return 0;
  1951. }
  1952. /* }}} */
  1953. static int php_openssl_sockop_flush(php_stream *stream) /* {{{ */
  1954. {
  1955. return php_stream_socket_ops.flush(stream);
  1956. }
  1957. /* }}} */
  1958. static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ */
  1959. {
  1960. return php_stream_socket_ops.stat(stream, ssb);
  1961. }
  1962. /* }}} */
  1963. static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_netstream_data_t *sock,
  1964. php_stream_xport_param *xparam STREAMS_DC) /* {{{ */
  1965. {
  1966. int clisock;
  1967. zend_bool nodelay = 0;
  1968. zval *tmpzval = NULL;
  1969. xparam->outputs.client = NULL;
  1970. if (PHP_STREAM_CONTEXT(stream) &&
  1971. (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL &&
  1972. zend_is_true(tmpzval)) {
  1973. nodelay = 1;
  1974. }
  1975. clisock = php_network_accept_incoming(sock->s.socket,
  1976. xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
  1977. xparam->want_addr ? &xparam->outputs.addr : NULL,
  1978. xparam->want_addr ? &xparam->outputs.addrlen : NULL,
  1979. xparam->inputs.timeout,
  1980. xparam->want_errortext ? &xparam->outputs.error_text : NULL,
  1981. &xparam->outputs.error_code,
  1982. nodelay);
  1983. if (clisock >= 0) {
  1984. php_openssl_netstream_data_t *clisockdata = (php_openssl_netstream_data_t*) emalloc(sizeof(*clisockdata));
  1985. /* copy underlying tcp fields */
  1986. memset(clisockdata, 0, sizeof(*clisockdata));
  1987. memcpy(clisockdata, sock, sizeof(clisockdata->s));
  1988. clisockdata->s.socket = clisock;
  1989. xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+");
  1990. if (xparam->outputs.client) {
  1991. xparam->outputs.client->ctx = stream->ctx;
  1992. if (stream->ctx) {
  1993. GC_ADDREF(stream->ctx);
  1994. }
  1995. }
  1996. if (xparam->outputs.client && sock->enable_on_connect) {
  1997. /* remove the client bit */
  1998. if (sock->method & STREAM_CRYPTO_IS_CLIENT) {
  1999. sock->method = ((sock->method >> 1) << 1);
  2000. }
  2001. clisockdata->method = sock->method;
  2002. if (php_stream_xport_crypto_setup(xparam->outputs.client, clisockdata->method,
  2003. NULL) < 0 || php_stream_xport_crypto_enable(
  2004. xparam->outputs.client, 1) < 0) {
  2005. php_error_docref(NULL, E_WARNING, "Failed to enable crypto");
  2006. php_stream_close(xparam->outputs.client);
  2007. xparam->outputs.client = NULL;
  2008. xparam->outputs.returncode = -1;
  2009. }
  2010. }
  2011. }
  2012. return xparam->outputs.client == NULL ? -1 : 0;
  2013. }
  2014. /* }}} */
  2015. static int php_openssl_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam) /* {{{ */
  2016. {
  2017. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  2018. php_stream_xport_crypto_param *cparam = (php_stream_xport_crypto_param *)ptrparam;
  2019. php_stream_xport_param *xparam = (php_stream_xport_param *)ptrparam;
  2020. switch (option) {
  2021. case PHP_STREAM_OPTION_META_DATA_API:
  2022. if (sslsock->ssl_active) {
  2023. zval tmp;
  2024. char *proto_str;
  2025. char version_str[PHP_SSL_MAX_VERSION_LEN];
  2026. const SSL_CIPHER *cipher;
  2027. array_init(&tmp);
  2028. switch (SSL_version(sslsock->ssl_handle)) {
  2029. #ifdef HAVE_TLS12
  2030. case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
  2031. #endif
  2032. #ifdef HAVE_TLS11
  2033. case TLS1_1_VERSION: proto_str = "TLSv1.1"; break;
  2034. #endif
  2035. case TLS1_VERSION: proto_str = "TLSv1"; break;
  2036. #ifdef HAVE_SSL3
  2037. case SSL3_VERSION: proto_str = "SSLv3"; break;
  2038. #endif
  2039. default: proto_str = "UNKNOWN";
  2040. }
  2041. cipher = SSL_get_current_cipher(sslsock->ssl_handle);
  2042. add_assoc_string(&tmp, "protocol", proto_str);
  2043. add_assoc_string(&tmp, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
  2044. add_assoc_long(&tmp, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
  2045. add_assoc_string(&tmp, "cipher_version",
  2046. php_openssl_cipher_get_version(cipher, version_str, PHP_SSL_MAX_VERSION_LEN));
  2047. #ifdef HAVE_TLS_ALPN
  2048. {
  2049. const unsigned char *alpn_proto = NULL;
  2050. unsigned int alpn_proto_len = 0;
  2051. SSL_get0_alpn_selected(sslsock->ssl_handle, &alpn_proto, &alpn_proto_len);
  2052. if (alpn_proto) {
  2053. add_assoc_stringl(&tmp, "alpn_protocol", (char *)alpn_proto, alpn_proto_len);
  2054. }
  2055. }
  2056. #endif
  2057. add_assoc_zval((zval *)ptrparam, "crypto", &tmp);
  2058. }
  2059. add_assoc_bool((zval *)ptrparam, "timed_out", sslsock->s.timeout_event);
  2060. add_assoc_bool((zval *)ptrparam, "blocked", sslsock->s.is_blocked);
  2061. add_assoc_bool((zval *)ptrparam, "eof", stream->eof);
  2062. return PHP_STREAM_OPTION_RETURN_OK;
  2063. case PHP_STREAM_OPTION_CHECK_LIVENESS:
  2064. {
  2065. struct timeval tv;
  2066. char buf;
  2067. int alive = 1;
  2068. if (value == -1) {
  2069. if (sslsock->s.timeout.tv_sec == -1) {
  2070. #ifdef _WIN32
  2071. tv.tv_sec = (long)FG(default_socket_timeout);
  2072. #else
  2073. tv.tv_sec = (time_t)FG(default_socket_timeout);
  2074. #endif
  2075. tv.tv_usec = 0;
  2076. } else {
  2077. tv = sslsock->connect_timeout;
  2078. }
  2079. } else {
  2080. tv.tv_sec = value;
  2081. tv.tv_usec = 0;
  2082. }
  2083. if (sslsock->s.socket == -1) {
  2084. alive = 0;
  2085. } else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
  2086. if (sslsock->ssl_active) {
  2087. int n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf));
  2088. if (n <= 0) {
  2089. int err = SSL_get_error(sslsock->ssl_handle, n);
  2090. switch (err) {
  2091. case SSL_ERROR_SYSCALL:
  2092. alive = php_socket_errno() == EAGAIN;
  2093. break;
  2094. case SSL_ERROR_WANT_READ:
  2095. case SSL_ERROR_WANT_WRITE:
  2096. alive = 1;
  2097. break;
  2098. default:
  2099. /* any other problem is a fatal error */
  2100. alive = 0;
  2101. }
  2102. }
  2103. } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) {
  2104. alive = 0;
  2105. }
  2106. }
  2107. return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
  2108. }
  2109. case PHP_STREAM_OPTION_CRYPTO_API:
  2110. switch(cparam->op) {
  2111. case STREAM_XPORT_CRYPTO_OP_SETUP:
  2112. cparam->outputs.returncode = php_openssl_setup_crypto(stream, sslsock, cparam);
  2113. return PHP_STREAM_OPTION_RETURN_OK;
  2114. break;
  2115. case STREAM_XPORT_CRYPTO_OP_ENABLE:
  2116. cparam->outputs.returncode = php_openssl_enable_crypto(stream, sslsock, cparam);
  2117. return PHP_STREAM_OPTION_RETURN_OK;
  2118. break;
  2119. default:
  2120. /* fall through */
  2121. break;
  2122. }
  2123. break;
  2124. case PHP_STREAM_OPTION_XPORT_API:
  2125. switch(xparam->op) {
  2126. case STREAM_XPORT_OP_CONNECT:
  2127. case STREAM_XPORT_OP_CONNECT_ASYNC:
  2128. /* TODO: Async connects need to check the enable_on_connect option when
  2129. * we notice that the connect has actually been established */
  2130. php_stream_socket_ops.set_option(stream, option, value, ptrparam);
  2131. if ((sslsock->enable_on_connect) &&
  2132. ((xparam->outputs.returncode == 0) ||
  2133. (xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC &&
  2134. xparam->outputs.returncode == 1 && xparam->outputs.error_code == EINPROGRESS)))
  2135. {
  2136. if (php_stream_xport_crypto_setup(stream, sslsock->method, NULL) < 0 ||
  2137. php_stream_xport_crypto_enable(stream, 1) < 0) {
  2138. php_error_docref(NULL, E_WARNING, "Failed to enable crypto");
  2139. xparam->outputs.returncode = -1;
  2140. }
  2141. }
  2142. return PHP_STREAM_OPTION_RETURN_OK;
  2143. case STREAM_XPORT_OP_ACCEPT:
  2144. /* we need to copy the additional fields that the underlying tcp transport
  2145. * doesn't know about */
  2146. xparam->outputs.returncode = php_openssl_tcp_sockop_accept(stream, sslsock, xparam STREAMS_CC);
  2147. return PHP_STREAM_OPTION_RETURN_OK;
  2148. default:
  2149. /* fall through */
  2150. break;
  2151. }
  2152. }
  2153. return php_stream_socket_ops.set_option(stream, option, value, ptrparam);
  2154. }
  2155. /* }}} */
  2156. static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret) /* {{{ */
  2157. {
  2158. php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
  2159. switch(castas) {
  2160. case PHP_STREAM_AS_STDIO:
  2161. if (sslsock->ssl_active) {
  2162. return FAILURE;
  2163. }
  2164. if (ret) {
  2165. *ret = fdopen(sslsock->s.socket, stream->mode);
  2166. if (*ret) {
  2167. return SUCCESS;
  2168. }
  2169. return FAILURE;
  2170. }
  2171. return SUCCESS;
  2172. case PHP_STREAM_AS_FD_FOR_SELECT:
  2173. if (ret) {
  2174. size_t pending;
  2175. if (stream->writepos == stream->readpos
  2176. && sslsock->ssl_active
  2177. && (pending = (size_t)SSL_pending(sslsock->ssl_handle)) > 0) {
  2178. php_stream_fill_read_buffer(stream, pending < stream->chunk_size
  2179. ? pending
  2180. : stream->chunk_size);
  2181. }
  2182. *(php_socket_t *)ret = sslsock->s.socket;
  2183. }
  2184. return SUCCESS;
  2185. case PHP_STREAM_AS_FD:
  2186. case PHP_STREAM_AS_SOCKETD:
  2187. if (sslsock->ssl_active) {
  2188. return FAILURE;
  2189. }
  2190. if (ret) {
  2191. *(php_socket_t *)ret = sslsock->s.socket;
  2192. }
  2193. return SUCCESS;
  2194. default:
  2195. return FAILURE;
  2196. }
  2197. }
  2198. /* }}} */
  2199. const php_stream_ops php_openssl_socket_ops = {
  2200. php_openssl_sockop_write, php_openssl_sockop_read,
  2201. php_openssl_sockop_close, php_openssl_sockop_flush,
  2202. "tcp_socket/ssl",
  2203. NULL, /* seek */
  2204. php_openssl_sockop_cast,
  2205. php_openssl_sockop_stat,
  2206. php_openssl_sockop_set_option,
  2207. };
  2208. static zend_long php_openssl_get_crypto_method(
  2209. php_stream_context *ctx, zend_long crypto_method) /* {{{ */
  2210. {
  2211. zval *val;
  2212. if (ctx && (val = php_stream_context_get_option(ctx, "ssl", "crypto_method")) != NULL) {
  2213. crypto_method = zval_get_long(val);
  2214. crypto_method |= STREAM_CRYPTO_IS_CLIENT;
  2215. }
  2216. return crypto_method;
  2217. }
  2218. /* }}} */
  2219. static char *php_openssl_get_url_name(const char *resourcename,
  2220. size_t resourcenamelen, int is_persistent) /* {{{ */
  2221. {
  2222. php_url *url;
  2223. if (!resourcename) {
  2224. return NULL;
  2225. }
  2226. url = php_url_parse_ex(resourcename, resourcenamelen);
  2227. if (!url) {
  2228. return NULL;
  2229. }
  2230. if (url->host) {
  2231. const char * host = ZSTR_VAL(url->host);
  2232. char * url_name = NULL;
  2233. size_t len = ZSTR_LEN(url->host);
  2234. /* skip trailing dots */
  2235. while (len && host[len-1] == '.') {
  2236. --len;
  2237. }
  2238. if (len) {
  2239. url_name = pestrndup(host, len, is_persistent);
  2240. }
  2241. php_url_free(url);
  2242. return url_name;
  2243. }
  2244. php_url_free(url);
  2245. return NULL;
  2246. }
  2247. /* }}} */
  2248. php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen,
  2249. const char *resourcename, size_t resourcenamelen,
  2250. const char *persistent_id, int options, int flags,
  2251. struct timeval *timeout,
  2252. php_stream_context *context STREAMS_DC) /* {{{ */
  2253. {
  2254. php_stream *stream = NULL;
  2255. php_openssl_netstream_data_t *sslsock = NULL;
  2256. sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0);
  2257. memset(sslsock, 0, sizeof(*sslsock));
  2258. sslsock->s.is_blocked = 1;
  2259. /* this timeout is used by standard stream funcs, therefor it should use the default value */
  2260. #ifdef _WIN32
  2261. sslsock->s.timeout.tv_sec = (long)FG(default_socket_timeout);
  2262. #else
  2263. sslsock->s.timeout.tv_sec = (time_t)FG(default_socket_timeout);
  2264. #endif
  2265. sslsock->s.timeout.tv_usec = 0;
  2266. /* use separate timeout for our private funcs */
  2267. sslsock->connect_timeout.tv_sec = timeout->tv_sec;
  2268. sslsock->connect_timeout.tv_usec = timeout->tv_usec;
  2269. /* we don't know the socket until we have determined if we are binding or
  2270. * connecting */
  2271. sslsock->s.socket = -1;
  2272. /* Initialize context as NULL */
  2273. sslsock->ctx = NULL;
  2274. stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+");
  2275. if (stream == NULL) {
  2276. pefree(sslsock, persistent_id ? 1 : 0);
  2277. return NULL;
  2278. }
  2279. if (strncmp(proto, "ssl", protolen) == 0) {
  2280. sslsock->enable_on_connect = 1;
  2281. sslsock->method = php_openssl_get_crypto_method(context, STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT);
  2282. } else if (strncmp(proto, "sslv2", protolen) == 0) {
  2283. php_error_docref(NULL, E_WARNING, "SSLv2 unavailable in this PHP version");
  2284. php_stream_close(stream);
  2285. return NULL;
  2286. } else if (strncmp(proto, "sslv3", protolen) == 0) {
  2287. #ifdef HAVE_SSL3
  2288. sslsock->enable_on_connect = 1;
  2289. sslsock->method = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
  2290. #else
  2291. php_error_docref(NULL, E_WARNING,
  2292. "SSLv3 support is not compiled into the OpenSSL library against which PHP is linked");
  2293. php_stream_close(stream);
  2294. return NULL;
  2295. #endif
  2296. } else if (strncmp(proto, "tls", protolen) == 0) {
  2297. sslsock->enable_on_connect = 1;
  2298. sslsock->method = php_openssl_get_crypto_method(context, STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT);
  2299. } else if (strncmp(proto, "tlsv1.0", protolen) == 0) {
  2300. sslsock->enable_on_connect = 1;
  2301. sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
  2302. } else if (strncmp(proto, "tlsv1.1", protolen) == 0) {
  2303. #ifdef HAVE_TLS11
  2304. sslsock->enable_on_connect = 1;
  2305. sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
  2306. #else
  2307. php_error_docref(NULL, E_WARNING,
  2308. "TLSv1.1 support is not compiled into the OpenSSL library against which PHP is linked");
  2309. php_stream_close(stream);
  2310. return NULL;
  2311. #endif
  2312. } else if (strncmp(proto, "tlsv1.2", protolen) == 0) {
  2313. #ifdef HAVE_TLS12
  2314. sslsock->enable_on_connect = 1;
  2315. sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
  2316. #else
  2317. php_error_docref(NULL, E_WARNING,
  2318. "TLSv1.2 support is not compiled into the OpenSSL library against which PHP is linked");
  2319. php_stream_close(stream);
  2320. return NULL;
  2321. #endif
  2322. }
  2323. sslsock->url_name = php_openssl_get_url_name(resourcename, resourcenamelen, !!persistent_id);
  2324. return stream;
  2325. }
  2326. /* }}} */
  2327. /*
  2328. * Local variables:
  2329. * tab-width: 4
  2330. * c-basic-offset: 4
  2331. * End:
  2332. * vim600: noet sw=4 ts=4 fdm=marker
  2333. * vim<600: noet sw=4 ts=4
  2334. */