ID: 45496
User updated by: develop at kristov dot de
Reported By: develop at kristov dot de
Status: Open
Bug Type: Feature/Change Request
Operating System: Gentoo Linux
PHP Version: 5.2.6
New Comment:
I forgot to mention that this patch has been successfully tested with
Cyrus 2.3.9 for months (started as a patch for PHP 5.2.5).
Previous Comments:
------------------------------------------------------------------------
[2008-07-13 06:10:20] develop at kristov dot de
Somehow I cannot add a patch file to this change request. So I include
it here:
diff -urN php-5.2.6/ext/imap/php_imap.c
php-5.2.6_p1/ext/imap/php_imap.c
--- php-5.2.6/ext/imap/php_imap.c 2008-04-17 13:04:49.000000000 +0200
+++ php-5.2.6_p1/ext/imap/php_imap.c 2008-07-12 11:42:12.000000000
+0200
@@ -229,6 +229,10 @@
efree(IMAPG(imap_password));
IMAPG(imap_password) = 0;
}
+ if (IMAPG(imap_keycert)) {
+ efree(IMAPG(imap_keycert));
+ IMAPG(imap_keycert) = 0;
+ }
efree(imap_le_struct);
}
@@ -413,6 +417,21 @@
}
/* }}} */
+#ifdef SET_SSLCLIENTCERT
+#ifdef SET_SSLCLIENTKEY
+/* {{{ mail_getkeycert
+ *
+ * Mail GET_SSLCLIENTCERT and GET_SSLCLIENTKEY callback
+ */
+char *mail_getkeycert(void)
+{
+ TSRMLS_FETCH();
+ return IMAPG(imap_keycert);
+}
+/* }}} */
+#endif
+#endif
+
#endif
@@ -422,6 +441,7 @@
{
imap_globals->imap_user = NIL;
imap_globals->imap_password = NIL;
+ imap_globals->imap_keycert = NIL;
imap_globals->imap_alertstack = NIL;
imap_globals->imap_errorstack = NIL;
@@ -469,6 +489,7 @@
mail_link(&dummydriver); /* link in the dummy driver */
#ifndef PHP_WIN32
+ auth_link(&auth_ext); /* link in the external authenticator */
auth_link(&auth_log); /* link in the log authenticator */
auth_link(&auth_md5); /* link in the cram-md5 authenticator */
#if HAVE_IMAP_KRB && defined(HAVE_IMAP_AUTH_GSS)
@@ -748,14 +769,15 @@
*/
static void php_imap_do_open(INTERNAL_FUNCTION_PARAMETERS, int
persistent)
{
- zval **mailbox, **user, **passwd, **options, **retries;
+ zval **mailbox, **user, **passwd, **options, **retries, **keycert;
MAILSTREAM *imap_stream;
pils *imap_le_struct;
long flags=NIL;
long cl_flags=NIL;
int myargc = ZEND_NUM_ARGS();
-
- if (myargc < 3 || myargc > 5 || zend_get_parameters_ex(myargc,
&mailbox, &user, &passwd, &options, &retries) == FAILURE) {
+ char *found = NULL;
+
+ if (myargc < 3 || myargc > 6 || zend_get_parameters_ex(myargc,
&mailbox, &user, &passwd, &options, &retries, &keycert) == FAILURE) {
ZEND_WRONG_PARAM_COUNT();
}
@@ -770,6 +792,9 @@
flags ^= PHP_EXPUNGE;
}
}
+ if (myargc >= 6) {
+ convert_to_string_ex(keycert);
+ }
if (IMAPG(imap_user)) {
efree(IMAPG(imap_user));
@@ -779,6 +804,10 @@
efree(IMAPG(imap_password));
}
+ if (IMAPG(imap_keycert)) {
+ efree(IMAPG(imap_keycert));
+ }
+
/* local filename, need to perform open_basedir and safe_mode checks
*/
if (Z_STRVAL_PP(mailbox)[0] != '{' &&
(php_check_open_basedir(Z_STRVAL_PP(mailbox) TSRMLS_CC)
||
@@ -789,8 +818,40 @@
IMAPG(imap_user) = estrndup(Z_STRVAL_PP(user),
Z_STRLEN_PP(user));
IMAPG(imap_password) = estrndup(Z_STRVAL_PP(passwd),
Z_STRLEN_PP(passwd));
+ found = php_memnstr(Z_STRVAL_PP(mailbox),
+ "}",
+ 1,
+ Z_STRVAL_PP(mailbox) + Z_STRLEN_PP(mailbox));
+ if (found) {
+ zval *mailboxwithuser, *tmp;
+ MAKE_STD_ZVAL(mailboxwithuser);
+ ZVAL_STRINGL(mailboxwithuser,
+ Z_STRVAL_PP(mailbox),
+ found - Z_STRVAL_PP(mailbox),
+ 1);
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_STRING(tmp, "/user=", 0);
+ add_string_to_string(mailboxwithuser, mailboxwithuser, tmp);
+ ZVAL_STRING(tmp, IMAPG(imap_user), 0);
+ add_string_to_string(mailboxwithuser, mailboxwithuser, tmp);
+ ZVAL_STRINGL(tmp,
+ found,
+ Z_STRLEN_PP(mailbox) - (found - Z_STRVAL_PP(mailbox)),
+ 0);
+ add_string_to_string(mailboxwithuser, mailboxwithuser, tmp);
+ FREE_ZVAL(tmp);
+
+ REPLACE_ZVAL_VALUE(mailbox, mailboxwithuser, 0);
+ FREE_ZVAL(mailboxwithuser);
+ }
+
+ if (myargc >= 6) {
+ IMAPG(imap_keycert) = estrndup(Z_STRVAL_PP(keycert),
Z_STRLEN_PP(keycert));
+ }
+
#ifdef SET_MAXLOGINTRIALS
- if (myargc == 5) {
+ if (myargc >= 5) {
convert_to_long_ex(retries);
if (Z_LVAL_PP(retries) < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING ,"Retries
must be
greater or equal to 0");
@@ -800,12 +861,24 @@
}
#endif
+#ifdef SET_SSLCLIENTCERT
+#ifdef SET_SSLCLIENTKEY
+ if (myargc >= 6) {
+ mail_parameters(NIL, SET_SSLCLIENTCERT, (void *)
mail_getkeycert);
+ mail_parameters(NIL, SET_SSLCLIENTKEY, (void *)
mail_getkeycert);
+ }
+#endif
+#endif
+
imap_stream = mail_open(NIL, Z_STRVAL_PP(mailbox), flags);
if (imap_stream == NIL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't open
stream
%s", Z_STRVAL_PP(mailbox));
efree(IMAPG(imap_user)); IMAPG(imap_user) = 0;
efree(IMAPG(imap_password)); IMAPG(imap_password) = 0;
+ if (myargc >= 6) {
+ efree(IMAPG(imap_keycert)); IMAPG(imap_keycert) = 0;
+ }
RETURN_FALSE;
}
diff -urN php-5.2.6/ext/imap/php_imap.h
php-5.2.6_p1/ext/imap/php_imap.h
--- php-5.2.6/ext/imap/php_imap.h 2007-12-31 08:20:07.000000000 +0100
+++ php-5.2.6_p1/ext/imap/php_imap.h 2008-07-12 11:03:40.000000000
+0200
@@ -180,6 +180,7 @@
ZEND_BEGIN_MODULE_GLOBALS(imap)
char *imap_user;
char *imap_password;
+ char *imap_keycert;
STRINGLIST *imap_alertstack;
ERRORLIST *imap_errorstack;
------------------------------------------------------------------------
[2008-07-13 06:08:32] develop at kristov dot de
Description:
------------
Currently, imap_open does not allow to specify a client certificate to
be used for a SSL/TLS-encrypted connection. Newer c-client versions do
support this (using the GET_SSLCLIENTCERT and GET_SSLCLIENTKEY
callbacks). I propose a patch which addresses this issue:
- it adds an additional parameter "keycert" to imap_open which receives
the combined client certificate and key (similar to the "local_cert"
option used e.g. by stream_socket_client/stream_context_create)
- it adds an additional IMAP global variable imap_keycert to hold the
value of this parameter until being used by the callback
- it defines and registers a callback function mail_getkeycert which
passes the combined client certificate and key to the c-client library
if supported (the existence of both of the #defines SET_SSLCLIENTCERT
and SET_SSLCLIENTKEY enables the callback)
- it links in the external authenticator auth_ext as client
certificates/keys often replace user/password combinations (the user is
identified by the CN of the client certificate and the password is
substituted by the valid client key)
One technical detail: The external authenticator of the c-client
library does not do a mm_login callback (see src/c-client/auth_ext.c,
function auth_external_client). So the user name for the connection has
to be set some other way. This is done by extending the caller's mailbox
name by a user specification "/user=<user>" which is parsed and handled
by the c-client library. The code to do this string insertion is a bit
clumsy and can probably be improved; I'm afraid I do not know Zend very
well and I was lucky to find a way for this string manipulation at all
:-)
The rest of the patch is trivial and consists mainly of memory
management and parameter checks.
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=45496&edit=1