Index: Makefile.in =================================================================== --- Makefile.in (.../tags/RELEASE_0_1_0) +++ Makefile.in (.../trunk) @@ -1,8 +0,0 @@ -# $Id$ - -LTLIBRARY_NAME = libsasl.la -LTLIBRARY_SOURCES = sasl.c -LTLIBRARY_SHARED_NAME = sasl.la -LTLIBRARY_SHARED_LIBADD = $(SASL_SHARED_LIBADD) - -include $(top_srcdir)/build/dynlib.mk Index: sasl.c =================================================================== --- sasl.c (.../tags/RELEASE_0_1_0) +++ sasl.c (.../trunk) @@ -41,13 +41,493 @@ #define le_conn_name "SASL Connection Context" static int le_conn; -/* {{{ sasl_callbacks[] - Global callbacks. These have no per-session context. */ -static sasl_callback_t sasl_callbacks[] = { - { SASL_CB_LIST_END, 0, 0 } -}; -/* }}}*/ +PHPAPI ZEND_DECLARE_MODULE_GLOBALS(sasl); +/* SASL Callback Functions */ +/* {{{ php_sasl_cb_getopt + */ +static int php_sasl_cb_getopt(void *context, const char *plugin_name, + const char *option, const char **result, + unsigned *len) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_FAIL; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_STRING(args[0], (plugin_name) ? (char *)plugin_name : "", 1); + ZVAL_STRING(args[1], (char *)option, 1); + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + ret = Z_LVAL_P(retval); + *result = estrdup(Z_STRVAL_P(retval)); + *len = Z_STRLEN_P(retval); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_log + */ +static int php_sasl_cb_log(void *context, int level, const char *message) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_FAIL; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], level); + ZVAL_STRING(args[1], (char *)message, 1); + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + ret = Z_LVAL_P(retval); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_getpath + */ +static int php_sasl_cb_getpath(void *context, const char **path) +{ + zval *function = context; + zval *retval; + int ret = SASL_FAIL; + + MAKE_STD_ZVAL(retval); + + if (call_user_function(CG(function_table), NULL, function, retval, + 0, NULL TSRMLS_CC) == SUCCESS) { + ret = Z_LVAL_P(retval); + *path = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&retval); + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_verifyfile + */ +static int php_sasl_cb_verifyfile(void *context, const char *file, + sasl_verify_type_t type) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_FAIL; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_STRING(args[0], (char *)file, 1); + ZVAL_LONG(args[1], type); + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + ret = Z_LVAL_P(retval); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_getconfpath + */ +static int php_sasl_cb_getconfpath(void *context, char **path) +{ + zval *function = context; + zval *retval; + int ret = SASL_FAIL; + + MAKE_STD_ZVAL(retval); + + if (call_user_function(CG(function_table), NULL, function, retval, + 0, NULL TSRMLS_CC) == SUCCESS) { + ret = Z_LVAL_P(retval); + *path = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&retval); + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_getsimple + */ +static int php_sasl_cb_getsimple(void *context, int id, const char **result, + unsigned *len) +{ + zval *function = context; + zval *args[1]; + zval *retval; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + + if (call_user_function(CG(function_table), NULL, function, retval, + 1, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + *len = Z_STRLEN_P(retval); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&retval); + + return SASL_OK; +} +/* }}} */ +/* {{{ php_sasl_cb_getsecret + */ +static int php_sasl_cb_getsecret(sasl_conn_t *conn, void *context, int id, + sasl_secret_t **psecret) +{ + zval *function = context; + zval *args[2]; + zval *retval; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_NULL(args[0]); + //ZVAL_RESOURCE(args[0], r); + ZVAL_LONG(args[1], id); + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + int len = Z_STRLEN_P(retval); + *psecret = (sasl_secret_t *)emalloc(sizeof(sasl_secret_t) + + (len * sizeof(char))); + if (*psecret) { + (*psecret)->len = len; + memcpy((*psecret)->data, Z_STRVAL_P(retval), len); + } + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); + + return SASL_OK; +} +/* }}} */ +/* {{{ php_sasl_cb_chalprompt + */ +static int php_sasl_cb_chalprompt(void *context, int id, const char *challenge, + const char *prompt, const char *defresult, + const char **result, unsigned *len) +{ + zval *function = context; + zval *args[4]; + zval *retval; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(args[2]); + MAKE_STD_ZVAL(args[3]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + ZVAL_STRING(args[1], (char *)challenge, 1); + ZVAL_STRING(args[2], (char *)prompt, 1); + ZVAL_STRING(args[3], (char *)defresult, 1); + + if (call_user_function(CG(function_table), NULL, function, retval, + 4, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + *len = Z_STRLEN_P(retval); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&args[2]); + zval_ptr_dtor(&args[3]); + zval_ptr_dtor(&retval); + + return SASL_OK; +} +/* }}} */ +/* {{{ php_sasl_cb_getrealm + */ +static int php_sasl_cb_getrealm(void *context, int id, + const char **availrealms, const char **result) +{ + zval *function = context; + zval *args[2]; + zval *retval; + + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + ZVAL_NULL(args[1]); // TODO: Make an array of available realms + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); + + return SASL_OK; +} +/* }}} */ +/* {{{ php_sasl_cb_authorize + */ +static int php_sasl_cb_authorize(sasl_conn_t *conn, void *context, + const char *requested_user, unsigned rlen, + const char *auth_identity, unsigned alen, + const char *def_realm, unsigned urlen, + struct propctx *propctx) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_NOAUTHZ; + +#if 0 + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + ZVAL_NULL(args[1]); // TODO: Make an array of available realms + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); +#endif + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_userdb_checkpass + */ +static int php_sasl_cb_userdb_checkpass(sasl_conn_t *conn, void *context, + const char *user, const char *pass, + unsigned passlen, + struct propctx *propctx) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_FAIL; + +#if 0 + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + ZVAL_NULL(args[1]); // TODO: Make an array of available realms + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); +#endif + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_userdb_setpass + */ +static int php_sasl_cb_userdb_setpass(sasl_conn_t *conn, void *context, + const char *user, const char *pass, + unsigned passlen, + struct propctx *propctx, unsigned flags) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_FAIL; + +#if 0 + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + ZVAL_NULL(args[1]); // TODO: Make an array of available realms + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); +#endif + + return ret; +} +/* }}} */ +/* {{{ php_sasl_cb_canon_user + */ +static int php_sasl_cb_canon_user(sasl_conn_t *conn, void *context, + const char *in, unsigned inlen, + unsigned flags, const char *user_realm, + char *out, unsigned out_max, + unsigned *out_len) +{ + zval *function = context; + zval *args[2]; + zval *retval; + int ret = SASL_FAIL; + +#if 0 + MAKE_STD_ZVAL(args[0]); + MAKE_STD_ZVAL(args[1]); + MAKE_STD_ZVAL(retval); + + ZVAL_LONG(args[0], id); + ZVAL_NULL(args[1]); // TODO: Make an array of available realms + + if (call_user_function(CG(function_table), NULL, function, retval, + 2, args TSRMLS_CC) == SUCCESS) { + *result = estrdup(Z_STRVAL_P(retval)); + } + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&retval); +#endif + + return ret; +} +/* }}} */ + +/* {{{ sasl_callback_function_t php_sasl_get_callback_function(unsigned long id) + */ +typedef int (*sasl_callback_function_t)(); +static sasl_callback_function_t php_sasl_get_callback_function(unsigned long id) +{ + switch (id) { + case SASL_CB_GETOPT: return php_sasl_cb_getopt; + case SASL_CB_LOG: return php_sasl_cb_log; + case SASL_CB_GETPATH: return php_sasl_cb_getpath; + case SASL_CB_VERIFYFILE: return php_sasl_cb_verifyfile; + case SASL_CB_GETCONFPATH: return php_sasl_cb_getconfpath; + case SASL_CB_USER: return php_sasl_cb_getsimple; + case SASL_CB_AUTHNAME: return php_sasl_cb_getsimple; + case SASL_CB_LANGUAGE: return php_sasl_cb_getsimple; + case SASL_CB_CNONCE: return php_sasl_cb_getsimple; + case SASL_CB_PASS: return php_sasl_cb_getsecret; + case SASL_CB_ECHOPROMPT: return php_sasl_cb_chalprompt; + case SASL_CB_NOECHOPROMPT: return php_sasl_cb_chalprompt; + case SASL_CB_GETREALM: return php_sasl_cb_getrealm; + case SASL_CB_PROXY_POLICY: return php_sasl_cb_authorize; + case SASL_CB_SERVER_USERDB_CHECKPASS: return php_sasl_cb_userdb_checkpass; + case SASL_CB_SERVER_USERDB_SETPASS: return php_sasl_cb_userdb_setpass; + case SASL_CB_CANON_USER: return php_sasl_cb_canon_user; + } + + return NULL; +} +/* }}} */ +/* {{{ php_sasl_create_callbacks(HashTable *ht) + */ +static int php_sasl_create_callbacks(HashTable *ht, sasl_callback_t *callbacks) +{ + int n = 0; + zval **entry; + char *string_key; + long num_key; + + /* + * Start by counting the number of legitimate callbacks that exist in + * the array. This allows us to appropriately size our callback array. + */ + zend_hash_internal_pointer_reset(ht); + while (zend_hash_get_current_data(ht, (void **)&entry) == SUCCESS) { + switch (zend_hash_get_current_key(ht, &string_key, &num_key, 0)) { + case HASH_KEY_IS_LONG: + if (php_sasl_get_callback_function(num_key)) { + n++; + } + break; + } + zend_hash_move_forward(ht); + } + + /* + * Now that we know how many callbacks we have, allocate the array. We + * include an additional entry for the final SASL_CB_LIST_END sentinel. + */ + callbacks = (sasl_callback_t *)emalloc(sizeof(sasl_callback_t) * (n + 1)); + + if (callbacks) { + /* Assign the sentinel to the last entry in the callback array. */ + callbacks[n].id = SASL_CB_LIST_END; + + /* + * Now we iterate through the array again, except this time we will + * actually create the callback entries. + */ + n = 0; + + zend_hash_internal_pointer_reset(ht); + while (zend_hash_get_current_data(ht, (void **)&entry) == SUCCESS) { + sasl_callback_t *cb = &callbacks[n]; + + switch (zend_hash_get_current_key(ht, &string_key, &num_key, 0)) { + case HASH_KEY_IS_LONG: + { + cb->proc = php_sasl_get_callback_function(num_key); + if (cb->proc) { + cb->id = num_key; + cb->context = *entry; + n++; + } + } + break; + } + zend_hash_move_forward(ht); + } + } + + return n; +} +/* }}} */ + /* {{{ php_sasl_error(int level, int reason) */ static void php_sasl_error(int level, int code TSRMLS_DC) @@ -56,6 +536,29 @@ "%s", sasl_errstring(code, NULL, NULL)); } /* }}} */ +/* {{{ php_sasl_rinit_globals(TSRMLS_D) + */ +static void php_sasl_rinit_globals(TSRMLS_D) +{ + SASLG(client_callbacks) = NULL; + SASLG(server_callbacks) = NULL; +} +/* }}} */ +/* {{{ php_sasl_rshutdown_globals(TSRMLS_D) + */ +static void php_sasl_rshutdown_globals(TSRMLS_D) +{ + if (SASLG(client_callbacks)) { + efree(SASLG(client_callbacks)); + SASLG(client_callbacks) = NULL; + } + + if (SASLG(server_callbacks)) { + efree(SASLG(server_callbacks)); + SASLG(server_callbacks) = NULL; + } +} +/* }}} */ /* {{{ php_sasl_destroy_conn(zend_rsrc_list_entry *rsrc TSRMLS_DC) */ static void php_sasl_destroy_conn(zend_rsrc_list_entry *rsrc TSRMLS_DC) @@ -67,29 +570,30 @@ /* {{{ sasl_functions[] */ -function_entry sasl_functions[] = { +zend_function_entry sasl_functions[] = { /* Common Functions */ - PHP_FE(sasl_version, NULL) - PHP_FE(sasl_errstring, NULL) + PHP_FE(sasl_version, NULL) + PHP_FE(sasl_errstring, NULL) #if SASL_VERSION_MAJOR >= 2 - PHP_FE(sasl_errdetail, NULL) + PHP_FE(sasl_errdetail, NULL) + PHP_FE(sasl_seterror, NULL) #endif - PHP_FE(sasl_encode, NULL) - PHP_FE(sasl_decode, NULL) + PHP_FE(sasl_encode, NULL) + PHP_FE(sasl_decode, NULL) /* Client Functions */ - PHP_FE(sasl_client_init, NULL) - PHP_FE(sasl_client_new, NULL) - PHP_FE(sasl_client_start, NULL) - PHP_FE(sasl_client_step, NULL) + PHP_FE(sasl_client_init, NULL) + PHP_FE(sasl_client_new, NULL) + PHP_FE(sasl_client_start, NULL) + PHP_FE(sasl_client_step, NULL) /* Server Functions */ - PHP_FE(sasl_server_init, NULL) - PHP_FE(sasl_server_new, NULL) - PHP_FE(sasl_server_start, NULL) - PHP_FE(sasl_server_step, NULL) - PHP_FE(sasl_listmech, NULL) - PHP_FE(sasl_checkpass, NULL) + PHP_FE(sasl_server_init, NULL) + PHP_FE(sasl_server_new, NULL) + PHP_FE(sasl_server_start, NULL) + PHP_FE(sasl_server_step, NULL) + PHP_FE(sasl_listmech, NULL) + PHP_FE(sasl_checkpass, NULL) {NULL, NULL, NULL} }; @@ -102,10 +606,10 @@ sasl_functions, PHP_MINIT(sasl), PHP_MSHUTDOWN(sasl), - NULL, - NULL, + PHP_RINIT(sasl), + PHP_RSHUTDOWN(sasl), PHP_MINFO(sasl), - NO_VERSION_YET, + PHP_SASL_VERSION, STANDARD_MODULE_PROPERTIES }; @@ -173,6 +677,31 @@ SASL_CONSTANT(SASL_SEC_MAXIMUM); #endif + /* SASL callback identifiers */ + SASL_CONSTANT(SASL_CB_GETOPT); + SASL_CONSTANT(SASL_CB_LOG); + SASL_CONSTANT(SASL_CB_GETPATH); + SASL_CONSTANT(SASL_CB_VERIFYFILE); + SASL_CONSTANT(SASL_CB_GETCONFPATH); + SASL_CONSTANT(SASL_CB_USER); + SASL_CONSTANT(SASL_CB_AUTHNAME); + SASL_CONSTANT(SASL_CB_LANGUAGE); + SASL_CONSTANT(SASL_CB_CNONCE); + SASL_CONSTANT(SASL_CB_PASS); + SASL_CONSTANT(SASL_CB_ECHOPROMPT); + SASL_CONSTANT(SASL_CB_NOECHOPROMPT); + SASL_CONSTANT(SASL_CB_GETREALM); + SASL_CONSTANT(SASL_CB_PROXY_POLICY); + SASL_CONSTANT(SASL_CB_SERVER_USERDB_CHECKPASS); + SASL_CONSTANT(SASL_CB_SERVER_USERDB_SETPASS); + SASL_CONSTANT(SASL_CB_CANON_USER); + + /* SASL_CB_VERIFYFILE flags */ + SASL_CONSTANT(SASL_VRFY_PLUGIN); + SASL_CONSTANT(SASL_VRFY_CONF); + SASL_CONSTANT(SASL_VRFY_PASSWD); + SASL_CONSTANT(SASL_VRFY_OTHER); + return SUCCESS; } /* }}} */ @@ -185,6 +714,22 @@ return SUCCESS; } /* }}} */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(sasl) +{ + php_sasl_rinit_globals(TSRMLS_C); + return SUCCESS; +} +/* }}} */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(sasl) +{ + php_sasl_rshutdown_globals(TSRMLS_C); + return SUCCESS; +} +/* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(sasl) @@ -214,7 +759,8 @@ php_info_print_table_row(2, "SASL Support", "enabled"); php_info_print_table_row(2, "SASL API Version", api_version); php_info_print_table_row(2, "SASL Library Version", lib_version); - php_info_print_table_row(2, "Extension Version", "$Revision$"); + php_info_print_table_row(2, "Extension Version", PHP_SASL_VERSION); + php_info_print_table_row(2, "CVS Revision", "$Revision$"); php_info_print_table_end(); } /* }}} */ @@ -239,7 +785,7 @@ libsasl_step = libsasl_version & 0xFFFF; #endif - snprintf(version, 64, "%u.%u.%u (%s)", + snprintf(version, sizeof(version), "%u.%u.%u (%s)", libsasl_major, libsasl_minor, libsasl_step, sasl_implementation); RETURN_STRING(version, 1); @@ -267,7 +813,7 @@ Returns the string translation of the given error code. */ PHP_FUNCTION(sasl_errstring) { - long code; + long code; char *languages = NULL; int languages_len; @@ -279,6 +825,27 @@ RETURN_STRING((char *)sasl_errstring(code, languages, NULL), 1); } /* }}} */ +/* {{{ proto void sasl_seterror(resource conn, string message) + Set the error string which will be returned by sasl_errdetail. */ +#if SASL_VERSION_MAJOR >= 2 +PHP_FUNCTION(sasl_seterror) +{ + zval *rsrc; + sasl_conn_t *conn; + char *message; + int message_len; + + if (zend_parse_parameters(2 TSRMLS_CC, "rs", + &rsrc, &message, &message_len) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(conn, sasl_conn_t *, &rsrc, -1, le_conn_name, le_conn); + + sasl_seterror(conn, 0, message); +} +#endif +/* }}} */ /* {{{ proto string sasl_encode(resource conn, string input) Encodes a block of data for tranmission using the security layer. */ PHP_FUNCTION(sasl_encode) @@ -345,10 +912,25 @@ Initializes the SASL client drivers. */ PHP_FUNCTION(sasl_client_init) { - if (sasl_client_init(NULL) != SASL_OK) { + zval *array; + + if (zend_parse_parameters(1 TSRMLS_CC, "a", &array) == FAILURE) { + return; + } + + /* + * Convert the supplied array into a set of callback functions. We + * don't bother spending any time validating its contents because the + * sasl_client_init() function will do that for us (and return an error + * if it encounters something that it doesn't like). + */ + php_sasl_create_callbacks(Z_ARRVAL_P(array), SASLG(client_callbacks)); + + if (sasl_client_init(SASLG(client_callbacks)) != SASL_OK) { + /* XXX: Free the callbacks? */ RETURN_FALSE; } - + RETURN_TRUE; } /* }}} */ @@ -384,7 +966,7 @@ ZEND_REGISTER_RESOURCE(return_value, conn, le_conn); } /* }}} */ -/* {{{ proto bool sasl_client_start(resource conn, string mechlist [, string &$output [, string &$mech]]) +/* {{{ proto int sasl_client_start(resource conn, string mechlist [, string &$output [, string &$mech]]) Starts an authentication session. */ PHP_FUNCTION(sasl_client_start) { @@ -421,10 +1003,13 @@ r = sasl_client_start(conn, mechlist, NULL, &data, &data_len, &chosenmech); #endif - /* Print a warning and return false if we receive an unexpected result. */ + /* + * Issue a warning and return the error code if we receive an unexpected + * result code. + */ if ((r != SASL_OK) && (r != SASL_CONTINUE)) { php_sasl_error(E_WARNING, r TSRMLS_CC); - RETURN_FALSE; + RETURN_LONG(r); } /* Store the output in the "output" parameter (by reference). */ @@ -434,7 +1019,7 @@ /* Store the chosen mechanism in the "mech" parameter (by reference). */ ZVAL_STRING(mech, (char *)chosenmech, 1); - RETURN_TRUE; + RETURN_LONG(r); } /* }}} */ /* {{{ proto int sasl_client_step(resource conn, string input, string &$output) @@ -483,14 +1068,25 @@ Initializes the session and loads the shared authentication mechanisms. */ PHP_FUNCTION(sasl_server_init) { + zval *array; char *name; int name_len; - if (zend_parse_parameters(1 TSRMLS_CC, "s", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "as", + &array, &name, &name_len) == FAILURE) { return; } - if (sasl_server_init(NULL, name) != SASL_OK) { + /* + * Convert the supplied array into a set of callback functions. We + * don't bother spending any time validating its contents because the + * sasl_client_init() function will do that for us (and return an error + * if it encounters something that it doesn't like). + */ + php_sasl_create_callbacks(Z_ARRVAL_P(array), SASLG(server_callbacks)); + + if (sasl_server_init(SASLG(server_callbacks), name) != SASL_OK) { + /* XXX: Free the callbacks? */ RETURN_FALSE; } Property changes on: sasl.c ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.3 \ No newline at end of property +1.6 \ No newline at end of property Index: config.m4 =================================================================== --- config.m4 (.../tags/RELEASE_0_1_0) +++ config.m4 (.../trunk) @@ -6,7 +6,7 @@ if test "$PHP_SASL" != "no"; then SEARCH_DIRS="/usr/local /usr" - SEARCH_SUBS="sasl sasl1 sasl2" + SEARCH_SUBS="sasl2 sasl sasl1" SEARCH_LIBS="sasl2 sasl" if test -r $PHP_SASL; then @@ -19,6 +19,7 @@ SASL_DIR=$i SASL_SUB=$j AC_MSG_RESULT(found in $i) + break fi done done @@ -31,9 +32,10 @@ AC_MSG_CHECKING(for SASL library in $SASL_DIR/lib) for i in $SEARCH_LIBS; do - if test -r $SASL_DIR/lib/lib$i.a; then + if test -r $SASL_DIR/lib/lib$i.a -o -r $SASL_DIR/lib/lib$i.$SHLIB_SUFFIX_NAME; then SASL_LIB=$i AC_MSG_RESULT(found -l$i) + break fi done Property changes on: config.m4 ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.2 \ No newline at end of property +1.4 \ No newline at end of property Index: docs/guide.txt =================================================================== --- docs/guide.txt (.../tags/RELEASE_0_1_0) +++ docs/guide.txt (.../trunk) @@ -0,0 +1,50 @@ +============================ + The SASL Extension for PHP +============================ + +-------------------- + User Documentation +-------------------- + +:Author: Jon Parise +:Contact: jon@php.net +:Date: $Date$ +:Revision: $Revision$ + +.. contents:: Contents +.. section-numbering:: + +Frequently Asked Questions +-------------------------- + +How does the SASL extension relate to the Auth_SASL PEAR package? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The `Auth_SASL`_ PEAR package provides native PHP implementations of many of +the SASL authentication mechanisms. In theory, those methods could call out +to the SASL extension to compute those strings using the native C library, but +I'm not sure the effort is worth it. I wouldn't object to the idea if someone +did the work, though. + +.. _Auth_SASL: http://pear.php.net/Auth_SASL + +Does saslauthd need to be running locally? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``saslauthd`` needs to be running on the same machine as the SASL client (the +PHP process, in your case). The libsasl library (that the SASL extension +wraps) will communicate with the ``saslauthd`` process via a local Unix domain +socket. + +Can saslauthd be used to authenticate against a remote server? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``saslauthd`` process loads the SASL authentication modules and performs +the actual authentication. This may involve contacting a foreign machine +(such as a remote Kerberos or LDAP server). + +To complicate things even further, ``saslauthd`` can use `PAM`_ as its +authentication backend, which opens up even more authentication possibilities +(many of which may involve other hosts). + +.. _PAM: http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pam/ + +.. vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab textwidth=78 ft=rst: Property changes on: docs/guide.txt ___________________________________________________________________ Added: cvs2svn:cvs-rev ## -0,0 +1 ## +1.1 \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: package.xml =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/xml Index: package.xml =================================================================== --- package.xml (.../tags/RELEASE_0_1_0) +++ package.xml (.../trunk) Property changes on: package.xml ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.3 \ No newline at end of property +1.5 \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/xml \ No newline at end of property Index: php_sasl.h =================================================================== --- php_sasl.h (.../tags/RELEASE_0_1_0) +++ php_sasl.h (.../trunk) @@ -26,6 +26,8 @@ extern zend_module_entry sasl_module_entry; #define phpext_sasl_ptr &sasl_module_entry +#define PHP_SASL_VERSION "0.2.0-dev" + #ifdef PHP_WIN32 #define PHP_SASL_API __declspec(dllexport) #else @@ -38,6 +40,8 @@ PHP_MINIT_FUNCTION(sasl); PHP_MSHUTDOWN_FUNCTION(sasl); +PHP_RINIT_FUNCTION(sasl); +PHP_RSHUTDOWN_FUNCTION(sasl); PHP_MINFO_FUNCTION(sasl); /* Common Functions */ @@ -45,6 +49,7 @@ PHP_FUNCTION(sasl_errstring); #if SASL_VERSION_MAJOR >= 2 PHP_FUNCTION(sasl_errdetail); +PHP_FUNCTION(sasl_seterror); #endif PHP_FUNCTION(sasl_encode); PHP_FUNCTION(sasl_decode); @@ -63,12 +68,16 @@ PHP_FUNCTION(sasl_listmech); PHP_FUNCTION(sasl_checkpass); -#if 0 +/* Global Variables */ +ZEND_BEGIN_MODULE_GLOBALS(sasl) + sasl_callback_t *client_callbacks; + sasl_callback_t *server_callbacks; +ZEND_END_MODULE_GLOBALS(sasl) + #ifdef ZTS #define SASLG(v) TSRMG(sasl_globals_id, zend_sasl_globals *, v) #else #define SASLG(v) (sasl_globals.v) #endif -#endif #endif /* PHP_SASL_H */ Property changes on: php_sasl.h ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.2 \ No newline at end of property +1.4 \ No newline at end of property Index: package.php =================================================================== --- package.php (.../tags/RELEASE_0_1_0) +++ package.php (.../trunk) @@ -0,0 +1,67 @@ +setOptions(array( + 'filelistgenerator' => 'svn', + 'changelogoldtonew' => false, + 'simpleoutput' => true, + 'baseinstalldir' => '/', + 'packagefile' => 'package.xml', + 'packagedirectory' => '.', + 'clearcontents' => true, + 'ignore' => array('package.php', 'package.xml'), + 'dir_roles' => array( + 'docs' => 'doc', + 'tests' => 'test', + ), +)); + +if (PEAR::isError($result)) { + echo $result->getMessage(); + die(); +} + +$package->clearDeps(); +$package->setPackage('sasl'); +$package->setPackageType('extsrc'); +$package->setSummary('Cyrus SASL Extensions'); +$package->setDescription($desc); +$package->setChannel('pecl.php.net'); +$package->setLicense('PHP License'); +$package->addMaintainer('lead', 'jon', 'Jon Parise', 'jon@php.net'); + +$package->addRelease(); +$package->setProvidesExtension('sasl'); +$package->setAPIVersion('0.6.0'); +$package->setAPIStability('alpha'); +$package->setReleaseVersion($version); +$package->setReleaseStability('alpha'); +$package->setNotes($notes); +$package->setPhpDep('5.3.0'); +$package->setPearInstallerDep('1.4.3'); + +$package->generateContents(); + +if (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'commit') { + $result = $package->writePackageFile(); +} else { + $result = $package->debugPackageFile(); +} + +if (PEAR::isError($result)) { + echo $result->getMessage(); + die(); +} Property changes on: package.php ___________________________________________________________________ Added: cvs2svn:cvs-rev ## -0,0 +1 ## +1.3 \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: tests/sasl_version.phpt =================================================================== --- tests/sasl_version.phpt (.../tags/RELEASE_0_1_0) +++ tests/sasl_version.phpt (.../trunk) @@ -4,11 +4,7 @@ --FILE-- 0) { - echo "OK"; -} - ---EXPECT-- -OK +--EXPECTREGEX-- +\d+\.\d+\.\d+ \(.*\) Property changes on: tests/sasl_version.phpt ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.2 \ No newline at end of property +1.3 \ No newline at end of property Index: tests =================================================================== --- tests (.../tags/RELEASE_0_1_0) +++ tests (.../trunk) Property changes on: tests ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,4 ## +*.diff +*.exp +*.log +*.out Index: . =================================================================== --- . (.../tags/RELEASE_0_1_0) +++ . (.../trunk) Property changes on: . ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,32 ## +.deps +Makefile +*.lo +*.la +.libs +libs.mk +Makefile.fragments +Makefile.global +Makefile.objects +autom4te.cache +acinclude.m4 +aclocal.m4 +build +config.cache +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +modules +scan_makefile_in.awk +conftest* +*.tgz