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

Reply via email to