php-gnupg/gnupg.c

1536 lines
49 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
+--------------------------------------------------------------------+
| PECL :: gnupg |
+--------------------------------------------------------------------+
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
| Copyright (c) 2006, Thilo Raufeisen <traufeisen@php.net> |
| Copyright (c) 2013, Jim Jagielski <jimjag@php.net> |
+--------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "zend_exceptions.h"
#include "ext/standard/info.h"
#include "php_gnupg.h"
#include "php_gnupg_keylistiterator.h"
static int le_gnupg;
static zend_object_handlers gnupg_object_handlers;
/* {{{ defs */
#define GNUPG_GETOBJ() \
zval *this = getThis(); \
gnupg_object *intern; \
zval *res; \
if(this){ \
intern = Z_GNUPGO_P(this); \
if(!intern){ \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized gnupg object"); \
RETURN_FALSE; \
} \
}
#define GNUPG_ERR(error) \
if(intern){ \
switch (intern->errormode) { \
case 1: \
php_error_docref(NULL TSRMLS_CC, E_WARNING, (char*)error); \
break; \
case 2: \
zend_throw_exception(zend_exception_get_default(TSRMLS_C), (char*) error, 0 TSRMLS_CC); \
break; \
default: \
intern->errortxt = (char*)error; \
} \
}else{ \
php_error_docref(NULL TSRMLS_CC, E_WARNING, (char*)error); \
} \
if(return_value){ \
RETVAL_FALSE; \
}
/* }}} */
/* {{{ free encryptkeys */
static void gnupg_free_encryptkeys(gnupg_object *intern TSRMLS_DC){
if(intern){
int idx;
/* loop through all encryptkeys and unref them in the gpgme-lib */
for(idx=0;idx<intern->encrypt_size;idx++){
gpgme_key_unref (intern->encryptkeys[idx]);
}
/* it´s an odd-thing, but other solutions makes problems :
* erealloc(x,0) gives a segfault with PHP 4 and debug enabled
* efree(x) alone ends in a segfault
*/
efree(erealloc(intern->encryptkeys,0));
intern->encryptkeys = NULL;
intern->encrypt_size = 0;
}
}
/* }}} */
/* {{{ free_resource */
static void gnupg_free_resource_ptr(gnupg_object *intern TSRMLS_DC){
if(intern){
if(intern->ctx){
/* clear all signers from the gpgme-lib and finally release it */
gpgme_signers_clear (intern->ctx);
gpgme_release (intern->ctx);
intern->ctx = NULL;
}
/* basic cleanup */
gnupg_free_encryptkeys(intern TSRMLS_CC);
zend_hash_destroy(intern->signkeys);
FREE_HASHTABLE(intern->signkeys);
zend_hash_destroy(intern->decryptkeys);
FREE_HASHTABLE(intern->decryptkeys);
}
}
/* }}} */
/* {{{ gnupg_res_dtor */
ZEND_RSRC_DTOR_FUNC(gnupg_res_dtor) {
gnupg_object *intern = res->ptr;
gnupg_free_resource_ptr(intern);
efree(intern);
}
/* }}} */
/* {{{ gnupg_res_init */
static void gnupg_res_init(gnupg_object *intern TSRMLS_DC){
/* init the gpgme-lib and set the default values */
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_check_version (NULL);
err = gpgme_new(&ctx);
if(err == GPG_ERR_NO_ERROR) {
#ifdef GNUPG_PATH
gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, GNUPG_PATH, NULL);
#endif
gpgme_set_armor (ctx,1);
}
intern->ctx = ctx;
intern->encryptkeys = NULL;
intern->encrypt_size = 0;
intern->signmode = GPGME_SIG_MODE_CLEAR;
intern->errortxt = NULL;
intern->errormode = 3;
ALLOC_HASHTABLE (intern->signkeys);
zend_hash_init (intern->signkeys, 0, NULL, NULL, 0);
ALLOC_HASHTABLE (intern->decryptkeys);
zend_hash_init (intern->decryptkeys, 0, NULL, NULL, 0);
return;
}
/* }}} */
/* {{{ free_storage */
static void gnupg_obj_dtor(zend_object *intern TSRMLS_DC){
gnupg_object *gnupg_o;
gnupg_o = gnupg_object_from_obj(intern);
gnupg_free_resource_ptr(gnupg_o);
zend_object_std_dtor(&gnupg_o->zo);
}
/* }}} */
/* {{{ objects_new */
static zend_object* gnupg_obj_new(zend_class_entry *class_type TSRMLS_DC){
gnupg_object *intern;
intern = ecalloc(1, sizeof(gnupg_object) + zend_object_properties_size(class_type));
zend_object_std_init(&intern->zo, class_type);
object_properties_init(&intern->zo, class_type);
intern->zo.handlers = &gnupg_object_handlers;
gnupg_res_init (intern TSRMLS_CC);
return &intern->zo;
}
/* }}} */
/* {{{ arginfo gnupg_verify_method */
ZEND_BEGIN_ARG_INFO_EX(arginfo_gnupg_verify_method, 0, 0, 2)
ZEND_ARG_INFO(0, text)
ZEND_ARG_INFO(0, signature)
ZEND_ARG_INFO(1, plaintext)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ arginfo gnupg_decryptverify_method */
ZEND_BEGIN_ARG_INFO_EX(arginfo_gnupg_decryptverify_method, 0, 0, 2)
ZEND_ARG_INFO(0, enctext)
ZEND_ARG_INFO(1, plaintext)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ methodlist gnupg */
static zend_function_entry gnupg_methods[] = {
PHP_FALIAS(keyinfo, gnupg_keyinfo, NULL)
PHP_FALIAS(verify, gnupg_verify, arginfo_gnupg_verify_method)
PHP_FALIAS(geterror, gnupg_geterror, NULL)
PHP_FALIAS(clearsignkeys, gnupg_clearsignkeys, NULL)
PHP_FALIAS(clearencryptkeys, gnupg_clearencryptkeys, NULL)
PHP_FALIAS(cleardecryptkeys, gnupg_cleardecryptkeys, NULL)
PHP_FALIAS(setarmor, gnupg_setarmor, NULL)
PHP_FALIAS(encrypt, gnupg_encrypt, NULL)
PHP_FALIAS(decrypt, gnupg_decrypt, NULL)
PHP_FALIAS(export, gnupg_export, NULL)
PHP_FALIAS(import, gnupg_import, NULL)
PHP_FALIAS(getprotocol, gnupg_getprotocol, NULL)
PHP_FALIAS(setsignmode, gnupg_setsignmode, NULL)
PHP_FALIAS(sign, gnupg_sign, NULL)
PHP_FALIAS(encryptsign, gnupg_encryptsign, NULL)
PHP_FALIAS(decryptverify, gnupg_decryptverify, arginfo_gnupg_decryptverify_method)
PHP_FALIAS(addsignkey, gnupg_addsignkey, NULL)
PHP_FALIAS(addencryptkey, gnupg_addencryptkey, NULL)
PHP_FALIAS(adddecryptkey, gnupg_adddecryptkey, NULL)
PHP_FALIAS(deletekey, gnupg_deletekey, NULL)
PHP_FALIAS(gettrustlist, gnupg_gettrustlist, NULL)
PHP_FALIAS(listsignatures, gnupg_listsignatures, NULL)
PHP_FALIAS(seterrormode, gnupg_seterrormode, NULL)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ class constants */
static void gnupg_declare_long_constant(const char *const_name, long value TSRMLS_DC){
zend_declare_class_constant_long(gnupg_class_entry, (char*)const_name, strlen(const_name), value TSRMLS_CC);
}
/* }}} */
/* {{{ arginfo gnupg_verify_method */
ZEND_BEGIN_ARG_INFO_EX(arginfo_gnupg_verify_function, 0, 0, 3)
ZEND_ARG_INFO(0, res)
ZEND_ARG_INFO(0, text)
ZEND_ARG_INFO(0, signature)
ZEND_ARG_INFO(1, plaintext)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ arginfo gnupg_decryptverify_method */
ZEND_BEGIN_ARG_INFO_EX(arginfo_gnupg_decryptverify_function, 0, 0, 3)
ZEND_ARG_INFO(0, res)
ZEND_ARG_INFO(0, enctext)
ZEND_ARG_INFO(1, plaintext)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ functionlist gnupg */
static zend_function_entry gnupg_functions[] = {
PHP_FE(gnupg_init, NULL)
PHP_FE(gnupg_keyinfo, NULL)
PHP_FE(gnupg_sign, NULL)
PHP_FE(gnupg_verify, arginfo_gnupg_verify_function)
PHP_FE(gnupg_clearsignkeys, NULL)
PHP_FE(gnupg_clearencryptkeys, NULL)
PHP_FE(gnupg_cleardecryptkeys, NULL)
PHP_FE(gnupg_setarmor, NULL)
PHP_FE(gnupg_encrypt, NULL)
PHP_FE(gnupg_decrypt, NULL)
PHP_FE(gnupg_export, NULL)
PHP_FE(gnupg_import, NULL)
PHP_FE(gnupg_getprotocol, NULL)
PHP_FE(gnupg_setsignmode, NULL)
PHP_FE(gnupg_encryptsign, NULL)
PHP_FE(gnupg_decryptverify, arginfo_gnupg_decryptverify_function)
PHP_FE(gnupg_geterror, NULL)
PHP_FE(gnupg_addsignkey, NULL)
PHP_FE(gnupg_addencryptkey, NULL)
PHP_FE(gnupg_adddecryptkey, NULL)
PHP_FE(gnupg_deletekey, NULL)
PHP_FE(gnupg_gettrustlist, NULL)
PHP_FE(gnupg_listsignatures, NULL)
PHP_FE(gnupg_seterrormode, NULL)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ gnupg_module_entry
*/
zend_module_entry gnupg_module_entry = {
STANDARD_MODULE_HEADER,
"gnupg",
gnupg_functions,
PHP_MINIT(gnupg),
PHP_MSHUTDOWN(gnupg),
NULL,
NULL,
PHP_MINFO(gnupg),
PHP_GNUPG_VERSION,
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_GNUPG
ZEND_GET_MODULE(gnupg)
#endif
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(gnupg)
{
le_gnupg = zend_register_list_destructors_ex(gnupg_res_dtor, NULL, "ctx", module_number);
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "gnupg", gnupg_methods);
ce.create_object = gnupg_obj_new;
gnupg_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
memcpy(&gnupg_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
gnupg_object_handlers.offset = XtOffsetOf(gnupg_object, zo);
gnupg_object_handlers.free_obj = gnupg_obj_dtor;
if (SUCCESS != gnupg_keylistiterator_init()){
return FAILURE;
}
gnupg_declare_long_constant("SIG_MODE_NORMAL", GPGME_SIG_MODE_NORMAL TSRMLS_CC);
gnupg_declare_long_constant("SIG_MODE_DETACH", GPGME_SIG_MODE_DETACH TSRMLS_CC);
gnupg_declare_long_constant("SIG_MODE_CLEAR", GPGME_SIG_MODE_CLEAR TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_UNKNOWN", GPGME_VALIDITY_UNKNOWN TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_UNDEFINED", GPGME_VALIDITY_UNDEFINED TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_NEVER", GPGME_VALIDITY_NEVER TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_MARGINAL", GPGME_VALIDITY_MARGINAL TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_FULL", GPGME_VALIDITY_FULL TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_ULTIMATE", GPGME_VALIDITY_ULTIMATE TSRMLS_CC);
gnupg_declare_long_constant("PROTOCOL_OpenPGP", GPGME_PROTOCOL_OpenPGP TSRMLS_CC);
gnupg_declare_long_constant("PROTOCOL_CMS", GPGME_PROTOCOL_CMS TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_VALID", GPGME_SIGSUM_VALID TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_GREEN", GPGME_SIGSUM_GREEN TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_RED", GPGME_SIGSUM_RED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_KEY_REVOKED", GPGME_SIGSUM_KEY_REVOKED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_KEY_EXPIRED", GPGME_SIGSUM_KEY_EXPIRED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_SIG_EXPIRED", GPGME_SIGSUM_SIG_EXPIRED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_KEY_MISSING", GPGME_SIGSUM_KEY_MISSING TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_CRL_MISSING", GPGME_SIGSUM_CRL_MISSING TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_CRL_TOO_OLD", GPGME_SIGSUM_CRL_TOO_OLD TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_BAD_POLICY", GPGME_SIGSUM_BAD_POLICY TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_SYS_ERROR", GPGME_SIGSUM_SYS_ERROR TSRMLS_CC);
gnupg_declare_long_constant("ERROR_WARNING", 1 TSRMLS_CC);
gnupg_declare_long_constant("ERROR_EXCEPTION", 2 TSRMLS_CC);
gnupg_declare_long_constant("ERROR_SILENT", 3 TSRMLS_CC);
REGISTER_LONG_CONSTANT("GNUPG_SIG_MODE_NORMAL", GPGME_SIG_MODE_NORMAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIG_MODE_DETACH", GPGME_SIG_MODE_DETACH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIG_MODE_CLEAR", GPGME_SIG_MODE_CLEAR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_UNKNOWN", GPGME_VALIDITY_UNKNOWN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_UNDEFINED", GPGME_VALIDITY_UNDEFINED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_NEVER", GPGME_VALIDITY_NEVER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_MARGINAL", GPGME_VALIDITY_MARGINAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_FULL", GPGME_VALIDITY_FULL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_ULTIMATE", GPGME_VALIDITY_ULTIMATE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_PROTOCOL_OpenPGP", GPGME_PROTOCOL_OpenPGP, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_PROTOCOL_CMS", GPGME_PROTOCOL_CMS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_VALID", GPGME_SIGSUM_VALID, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_GREEN", GPGME_SIGSUM_GREEN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_RED", GPGME_SIGSUM_RED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_KEY_REVOKED", GPGME_SIGSUM_KEY_REVOKED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_KEY_EXPIRED", GPGME_SIGSUM_KEY_EXPIRED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_SIG_EXPIRED", GPGME_SIGSUM_SIG_EXPIRED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_KEY_MISSING", GPGME_SIGSUM_KEY_MISSING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_CRL_MISSING", GPGME_SIGSUM_CRL_MISSING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_CRL_TOO_OLD", GPGME_SIGSUM_CRL_TOO_OLD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_BAD_POLICY", GPGME_SIGSUM_BAD_POLICY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_SYS_ERROR", GPGME_SIGSUM_SYS_ERROR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_ERROR_WARNING", 1, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_ERROR_EXCEPTION", 2, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_ERROR_SILENT", 3, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(gnupg)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(gnupg)
{
php_info_print_table_start();
php_info_print_table_header(2, "gnupg support", "enabled");
php_info_print_table_row(2,"GPGme Version",gpgme_check_version(NULL));
php_info_print_table_row(2,"Extension Version",PHP_GNUPG_VERSION);
php_info_print_table_end();
}
/* }}} */
/* {{{ callback func for setting the passphrase */
gpgme_error_t passphrase_cb (gnupg_object *intern, const char *uid_hint, const char *passphrase_info,int last_was_bad, int fd TSRMLS_DC){
char uid[17];
int idx;
char *passphrase = NULL;
zval *return_value = NULL;
if(last_was_bad){
GNUPG_ERR("Incorrent passphrase");
return 1;
}
for(idx=0;idx<16;idx++){
uid[idx] = uid_hint[idx];
}
uid[16] = '\0';
if((passphrase = zend_hash_str_find_ptr(intern->signkeys,(char *) uid, 16)) == NULL){
GNUPG_ERR("no passphrase set");
return 1;
}
if(!passphrase){
GNUPG_ERR("no passphrase set");
return 1;
}
if (write (fd, passphrase, strlen(passphrase))==strlen(passphrase)
&& write (fd, "\n", 1)==1) {
return 0;
}
GNUPG_ERR("write failed");
return 1;
}
gpgme_error_t passphrase_decrypt_cb (gnupg_object *intern, const char *uid_hint, const char *passphrase_info,int last_was_bad, int fd TSRMLS_DC){
char uid[17];
int idx;
char *passphrase = NULL;
zval *return_value = NULL;
if(last_was_bad){
GNUPG_ERR("Incorrent passphrase");
return 1;
}
for(idx=0;idx<16;idx++){
uid[idx] = uid_hint[idx];
}
uid[16] = '\0';
if((passphrase = zend_hash_str_find_ptr(intern->decryptkeys,(char *) uid, 16)) == NULL){
GNUPG_ERR("no passphrase set");
return 1;
}
if(!passphrase){
GNUPG_ERR("no passphrase set");
return 1;
}
if (write (fd, passphrase, strlen(passphrase))==strlen(passphrase)
&& write (fd, "\n", 1)==1) {
return 0;
}
GNUPG_ERR("write failed");
return 1;
}
/* }}} */
/* {{{ gnupg_fetchsignatures */
int gnupg_fetchsignatures(gpgme_signature_t gpgme_signatures, zval *main_arr){
zval sig_arr;
array_init (main_arr);
while(gpgme_signatures){
array_init (&sig_arr);
add_assoc_string (&sig_arr, "fingerprint", gpgme_signatures->fpr );
add_assoc_long (&sig_arr, "validity", gpgme_signatures->validity );
add_assoc_long (&sig_arr, "timestamp", gpgme_signatures->timestamp );
add_assoc_long (&sig_arr, "status", gpgme_signatures->status );
add_assoc_long (&sig_arr, "summary", gpgme_signatures->summary );
add_next_index_zval (main_arr, &sig_arr);
gpgme_signatures = gpgme_signatures->next;
}
return 1;
}
/* }}} */
/* {{{ proto resource gnupg_init()
* inits gnupg and returns a resource
*/
PHP_FUNCTION(gnupg_init){
gnupg_object *intern;
intern = emalloc(sizeof(gnupg_object));
gnupg_res_init(intern TSRMLS_CC);
RETURN_RES(zend_register_resource(intern,le_gnupg));
}
/* }}} */
/* {{{ proto bool gnupg_setarmor(int armor)
* turn on/off armor mode
* 0 = off
* >0 = on
* */
PHP_FUNCTION(gnupg_setarmor){
zend_long armor;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &armor) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &armor) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if(armor > 1){
armor = 1; /*just to make sure */
}
gpgme_set_armor (intern->ctx,armor);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_seterrormode(int errormde) */
PHP_FUNCTION(gnupg_seterrormode){
zend_long errormode;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &errormode) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &errormode) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
switch(errormode){
case 1: /* warning */
case 3: /* silent */
intern->errormode = errormode;
break;
case 2: /* exception */
intern->errormode = errormode;
break;
default:
GNUPG_ERR("invalid errormode");
}
}
/* }}} */
/* {{{ proto bool gnupg_setsignmode(int signmode)
* sets the mode for signing operations
*/
PHP_FUNCTION(gnupg_setsignmode){
zend_long signmode;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &signmode) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &signmode) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
switch(signmode){
case GPGME_SIG_MODE_NORMAL:
case GPGME_SIG_MODE_DETACH:
case GPGME_SIG_MODE_CLEAR:
intern->signmode = signmode;
RETVAL_TRUE;
break;
default:
GNUPG_ERR("invalid signmode");
RETVAL_FALSE;
break;
}
}
/* }}} */
/* {{{ proto string gnupg_geterror(void)
* returns the last errormessage
*/
PHP_FUNCTION(gnupg_geterror){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if(!intern->errortxt){
RETURN_FALSE;
}else{
RETURN_STRINGL(intern->errortxt, strlen(intern->errortxt));
}
}
/* }}} */
/* {{{ proto int gnupg_getprotocol(void)
* returns the currently used pgp-protocol.
* atm only OpenPGP is supported
*/
PHP_FUNCTION(gnupg_getprotocol){
RETURN_LONG(GPGME_PROTOCOL_OpenPGP);
}
/* }}} */
/* {{{ proto array gnupg_keyinfo(string pattern)
* returns an array with informations about all keys, that matches the given pattern
*/
PHP_FUNCTION(gnupg_keyinfo)
{
char *searchkey = NULL;
size_t searchkey_len;
zval subarr;
zval userid;
zval userids;
zval subkey;
zval subkeys;
gpgme_key_t gpgme_key;
gpgme_subkey_t gpgme_subkey;
gpgme_user_id_t gpgme_userid;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &searchkey, &searchkey_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &searchkey, &searchkey_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_op_keylist_start(intern->ctx, searchkey, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("could not init keylist");
return;
}
array_init(return_value);
while(!(intern->err = gpgme_op_keylist_next(intern->ctx, &gpgme_key))){
array_init (&subarr);
array_init (&subkeys);
array_init (&userids);
add_assoc_bool (&subarr, "disabled", gpgme_key->disabled );
add_assoc_bool (&subarr, "expired", gpgme_key->expired );
add_assoc_bool (&subarr, "revoked", gpgme_key->revoked );
add_assoc_bool (&subarr, "is_secret", gpgme_key->secret );
add_assoc_bool (&subarr, "can_sign", gpgme_key->can_sign );
add_assoc_bool (&subarr, "can_encrypt", gpgme_key->can_encrypt );
gpgme_userid = gpgme_key->uids;
while(gpgme_userid){
array_init (&userid);
add_assoc_string (&userid, "name", gpgme_userid->name );
add_assoc_string (&userid, "comment", gpgme_userid->comment );
add_assoc_string (&userid, "email", gpgme_userid->email );
add_assoc_string (&userid, "uid", gpgme_userid->uid );
add_assoc_bool (&userid, "revoked", gpgme_userid->revoked );
add_assoc_bool (&userid, "invalid", gpgme_userid->invalid );
add_next_index_zval (&userids, &userid);
gpgme_userid = gpgme_userid->next;
}
add_assoc_zval (&subarr, "uids", &userids);
gpgme_subkey = gpgme_key->subkeys;
while(gpgme_subkey){
array_init (&subkey);
if(gpgme_subkey->fpr){
add_assoc_string (&subkey, "fingerprint", gpgme_subkey->fpr );
}
add_assoc_string (&subkey, "keyid", gpgme_subkey->keyid );
add_assoc_long (&subkey, "timestamp", gpgme_subkey->timestamp );
add_assoc_long (&subkey, "expires", gpgme_subkey->expires );
add_assoc_bool (&subkey, "is_secret", gpgme_subkey->secret );
add_assoc_bool (&subkey, "invalid", gpgme_subkey->invalid );
add_assoc_bool (&subkey, "can_encrypt", gpgme_subkey->can_encrypt );
add_assoc_bool (&subkey, "can_sign", gpgme_subkey->can_sign );
add_assoc_bool (&subkey, "disabled", gpgme_subkey->disabled );
add_assoc_bool (&subkey, "expired", gpgme_subkey->expired );
add_assoc_bool (&subkey, "revoked", gpgme_subkey->revoked );
add_next_index_zval (&subkeys, &subkey);
gpgme_subkey = gpgme_subkey->next;
}
add_assoc_zval (&subarr, "subkeys", &subkeys);
add_next_index_zval (return_value, &subarr);
gpgme_key_unref (gpgme_key);
}
return;
}
/* }}} */
/* {{{ proto bool gnupg_addsignkey(string key) */
PHP_FUNCTION(gnupg_addsignkey){
char *key_id = NULL;
size_t key_id_len;
char *passphrase = NULL;
size_t passphrase_len;
gpgme_key_t gpgme_key;
gpgme_subkey_t gpgme_subkey;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &res, &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key_id, &gpgme_key, 1)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
if(passphrase){
gpgme_subkey = gpgme_key->subkeys;
while(gpgme_subkey){
if(gpgme_subkey->can_sign == 1){
zend_hash_str_add_ptr(intern->signkeys, (char *) gpgme_subkey->keyid, (uint) strlen(gpgme_subkey->keyid), passphrase);
}
gpgme_subkey = gpgme_subkey->next;
}
}
if((intern->err = gpgme_signers_add(intern->ctx, gpgme_key))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not add signer");
}else{
RETVAL_TRUE;
}
gpgme_key_unref(gpgme_key);
}
/* }}} */
/* {{{ proto bool gnupg_adddecryptkey(string key) */
PHP_FUNCTION(gnupg_adddecryptkey){
char *key_id = NULL;
size_t key_id_len;
char *passphrase = NULL;
size_t passphrase_len;
gpgme_key_t gpgme_key;
gpgme_subkey_t gpgme_subkey;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &res, &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key_id, &gpgme_key, 1)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
gpgme_subkey = gpgme_key->subkeys;
while(gpgme_subkey){
if(gpgme_subkey->secret == 1){
zend_hash_str_add_ptr(intern->decryptkeys, (char *) gpgme_subkey->keyid, strlen(gpgme_subkey->keyid), passphrase);
}
gpgme_subkey = gpgme_subkey->next;
}
gpgme_key_unref(gpgme_key);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_addencryptkey(string key) */
PHP_FUNCTION(gnupg_addencryptkey){
char *key_id = NULL;
size_t key_id_len;
gpgme_key_t gpgme_key = NULL;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key_id, &key_id_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &key_id, &key_id_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key_id, &gpgme_key, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
intern->encryptkeys = erealloc(intern->encryptkeys, sizeof(intern->encryptkeys) * (intern->encrypt_size + 2));
intern->encryptkeys[intern->encrypt_size] = gpgme_key;
intern->encrypt_size++;
intern->encryptkeys[intern->encrypt_size] = NULL;
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_clearsignerkeys(void)
* removes all keys which are set for signing
*/
PHP_FUNCTION(gnupg_clearsignkeys){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
gpgme_signers_clear (intern->ctx);
zend_hash_clean(intern->signkeys);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_clearencryptkeys(void)
* removes all keys which are set for encryption
*/
PHP_FUNCTION(gnupg_clearencryptkeys){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
gnupg_free_encryptkeys(intern TSRMLS_CC);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_clearsignerkeys(void)
* removes all keys which are set for signing
*/
PHP_FUNCTION(gnupg_cleardecryptkeys){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
zend_hash_clean(intern->decryptkeys);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string gnupg_sign(string text)
* signs the given test with the key, which was set with setsignerkey before
* and returns the signed text
* the signmode depends on gnupg_setsignmode
*/
PHP_FUNCTION(gnupg_sign){
char *value = NULL;
size_t value_len;
char *userret;
size_t ret_size;
gpgme_data_t in, out;
gpgme_sign_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &value, &value_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, value, value_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
return;
}
if((intern->err = gpgme_data_new(&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_sign(intern->ctx, in, out, intern->signmode))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("data signing failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
result = gpgme_op_sign_result (intern->ctx);
if(result->invalid_signers){
GNUPG_ERR("invalid signers found");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
if(!result->signatures){
GNUPG_ERR("no signature in result");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
if(ret_size < 1){
RETVAL_FALSE;
}else{
RETVAL_STRINGL (userret,ret_size);
}
gpgme_data_release (in);
free (userret);
}
/* }}} */
/* {{{ proto string gnupg_encrypt(string text)
* encrypts the given text with the key, which was set with setencryptkey before
* and returns the encrypted text
*/
PHP_FUNCTION(gnupg_encrypt){
char *value = NULL;
size_t value_len;
char *userret = NULL;
size_t ret_size;
gpgme_data_t in, out;
gpgme_encrypt_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &value, &value_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if(!intern->encryptkeys){
GNUPG_ERR("no key for encryption set");
return;
}
if((intern->err = gpgme_data_new_from_mem (&in, value, value_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could no create in-data buffer");
return;
}
if((intern->err = gpgme_data_new(&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_encrypt(intern->ctx, intern->encryptkeys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("encrypt failed");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
result = gpgme_op_encrypt_result (intern->ctx);
if (result->invalid_recipients){
GNUPG_ERR("Invalid recipient encountered");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
gpgme_data_release (in);
RETVAL_STRINGL (userret,ret_size);
free (userret);
if(ret_size < 1){
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto string gnupg_encrypt_sign(string text)
* encrypts and signs the given text with the keys, which weres set with setencryptkey and setsignkey before
* and returns the encrypted text
*/
PHP_FUNCTION(gnupg_encryptsign){
char *value = NULL;
size_t value_len;
char *userret = NULL;
size_t ret_size;
gpgme_data_t in, out;
gpgme_encrypt_result_t result;
gpgme_sign_result_t sign_result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &value, &value_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if(!intern->encryptkeys){
GNUPG_ERR("no key for encryption set");
return;
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, value, value_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
return;
}
if((intern->err = gpgme_data_new(&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_encrypt_sign(intern->ctx, intern->encryptkeys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("encrypt-sign failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
result = gpgme_op_encrypt_result (intern->ctx);
if (result->invalid_recipients){
GNUPG_ERR("Invalid recipient encountered");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
sign_result = gpgme_op_sign_result (intern->ctx);
if(sign_result->invalid_signers){
GNUPG_ERR("invalid signers found");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
if(!sign_result->signatures){
GNUPG_ERR("could not find a signature");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
gpgme_data_release (in);
RETVAL_STRINGL (userret,ret_size);
free (userret);
if(ret_size < 1){
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto array gnupg_verify(string text, string signature [, string &plaintext])
* verifies the given clearsigned text and returns information about the result in an array
*/
PHP_FUNCTION(gnupg_verify){
gpgme_data_t gpgme_text, gpgme_sig;
gpgme_verify_result_t gpgme_result;
zval *signed_text = NULL; /* text without the signature, if its a detached one, or the text incl the sig */
zval *signature = NULL; /* signature, if its a detached one */
zval *plain_text = NULL; /* signed_text without the signature if its not a detached sig */
char *gpg_plain;
size_t gpg_plain_len;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z", &signed_text, &signature, &plain_text) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz|z", &res, &signed_text, &signature, &plain_text) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if(Z_TYPE_P(signature) == IS_STRING){ /* detached signature */
/* setup signature-databuffer for gpgme */
if((intern->err = gpgme_data_new_from_mem (&gpgme_sig, Z_STRVAL_P(signature), Z_STRLEN_P(signature), 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create signature-databuffer");
return;
}
/* and the text */
if((intern->err = gpgme_data_new_from_mem (&gpgme_text, Z_STRVAL_P(signed_text), Z_STRLEN_P(signed_text), 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create text-databuffer");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
/* now verify sig + text */
if((intern->err = gpgme_op_verify (intern->ctx, gpgme_sig, gpgme_text, NULL))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("verify failed");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
}else{ /* clearsign or normal signature */
if((intern->err = gpgme_data_new_from_mem (&gpgme_sig, Z_STRVAL_P(signed_text), Z_STRLEN_P(signed_text), 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create signature-databuffer");
return;
}
/* set a NULL databuffer for gpgme */
if((intern->err = gpgme_data_new_from_mem (&gpgme_text, NULL, 0, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create text-databuffer");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
/* and verify the 'signature' */
if((intern->err = gpgme_op_verify (intern->ctx, gpgme_sig, NULL, gpgme_text))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("verify failed");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
}
/* now get the result */
gpgme_result = gpgme_op_verify_result (intern->ctx);
if(!gpgme_result->signatures){
GNUPG_ERR ("no signature found");
}else{
/* fetch all signatures in an array */
gnupg_fetchsignatures (gpgme_result->signatures, return_value);
/* get a 'plain' version of the text without a signature */
gpg_plain = gpgme_data_release_and_get_mem(gpgme_text,&gpg_plain_len);
if(gpg_plain && gpg_plain_len > 0 && plain_text){
ZVAL_DEREF (plain_text);
ZVAL_STRINGL (plain_text, gpg_plain,gpg_plain_len);
}
free (gpg_plain);
}
gpgme_data_release (gpgme_sig);
}
/* }}} */
/* {{{ proto string gnupg_decrypt(string enctext)
* decrypts the given enctext
*/
PHP_FUNCTION(gnupg_decrypt){
char *enctxt;
size_t enctxt_len;
char *userret;
size_t ret_size;
gpgme_data_t in, out;
gpgme_decrypt_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &enctxt, &enctxt_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &enctxt, &enctxt_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_decrypt_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, enctxt, enctxt_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
}
if((intern->err = gpgme_data_new (&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_decrypt (intern->ctx, in, out))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("decrypt failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
result = gpgme_op_decrypt_result (intern->ctx);
if (result->unsupported_algorithm){
GNUPG_ERR("unsupported algorithm");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
gpgme_data_release (in);
RETVAL_STRINGL (userret,ret_size);
free (userret);
if(ret_size < 1){
RETVAL_FALSE;
}
}
/* }}} */
/* {{{ proto string gnupg_decryptverify(string enctext, string &plaintext)
* decrypts the given enctext
*/
PHP_FUNCTION(gnupg_decryptverify){
char *enctxt;
size_t enctxt_len;
zval *plaintext;
char *userret;
size_t ret_size;
gpgme_data_t in, out;
gpgme_decrypt_result_t decrypt_result;
gpgme_verify_result_t verify_result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &enctxt, &enctxt_len, &plaintext) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz", &res, &enctxt, &enctxt_len, &plaintext) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
ZVAL_DEREF(plaintext);
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_decrypt_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, enctxt, enctxt_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
}
if((intern->err = gpgme_data_new (&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_decrypt_verify (intern->ctx, in, out))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("decrypt-verify failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
ZVAL_STRINGL (plaintext,userret,ret_size);
free (userret);
decrypt_result = gpgme_op_decrypt_result (intern->ctx);
if (decrypt_result->unsupported_algorithm){
GNUPG_ERR ("unsupported algorithm");
gpgme_data_release(in);
return;
}
verify_result = gpgme_op_verify_result (intern->ctx);
if(!verify_result->signatures){
GNUPG_ERR ("no signature found");
gpgme_data_release(in);
return;
}
gnupg_fetchsignatures (verify_result->signatures, return_value);
gpgme_data_release (in);
}
/* }}} */
/* {{{ proto string gnupg_export(string pattern)
* exports the first public key which matches against the given pattern
*/
PHP_FUNCTION(gnupg_export){
char *searchkey = NULL;
size_t searchkey_len;
char *userret;
size_t ret_size;
gpgme_data_t out;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &searchkey, &searchkey_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &searchkey, &searchkey_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_data_new (&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create data buffer");
return;
}
if((intern->err = gpgme_op_export (intern->ctx, searchkey, 0, out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("export failed");
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
RETVAL_STRINGL (userret,ret_size);
if(ret_size < 1){
RETVAL_FALSE;
}
free(userret);
}
/* }}} */
/* {{{ proto array gnupg_import(string key)
* imports the given key and returns a status-array
*/
PHP_FUNCTION(gnupg_import){
char *importkey = NULL;
size_t importkey_len;
gpgme_data_t in;
gpgme_import_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &importkey, &importkey_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &importkey, &importkey_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_data_new_from_mem (&in, importkey, importkey_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
return;
}
if((intern->err = gpgme_op_import(intern->ctx,in)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("import failed");
gpgme_data_release(in);
return;
}
gpgme_data_release(in);
result = gpgme_op_import_result (intern->ctx);
if(!result || !result->imports || result->imports->result != GPG_ERR_NO_ERROR){
RETURN_FALSE;
}
array_init (return_value);
add_assoc_long (return_value, "imported", result->imported);
add_assoc_long (return_value, "unchanged", result->unchanged);
add_assoc_long (return_value, "newuserids", result->new_user_ids);
add_assoc_long (return_value, "newsubkeys", result->new_sub_keys);
add_assoc_long (return_value, "secretimported", result->secret_imported);
add_assoc_long (return_value, "secretunchanged", result->secret_unchanged);
add_assoc_long (return_value, "newsignatures", result->new_signatures);
add_assoc_long (return_value, "skippedkeys", result->skipped_new_keys);
if(result->imports && result->imports->fpr){
add_assoc_string (return_value, "fingerprint", result->imports->fpr);
}
}
/* }}} */
/* {{{ proto book gnupg_deletekey(string key)
* deletes a key from the keyring
*/
PHP_FUNCTION(gnupg_deletekey){
char *key;
size_t key_len;
zend_long allow_secret = 0;
gpgme_key_t gpgme_key;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &allow_secret) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &res, &key, &key_len, &allow_secret) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key, &gpgme_key, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
if((intern->err = gpgme_op_delete(intern->ctx,gpgme_key,allow_secret))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("delete failed");
RETVAL_FALSE;
}else{
RETVAL_TRUE;
}
gpgme_key_unref(gpgme_key);
}
/* }}} */
/* {{{ proto array gnupg_gettrustlist(string pattern)
* searching for trust items which match PATTERN
*/
PHP_FUNCTION(gnupg_gettrustlist){
char *pattern;
size_t pattern_len;
zval sub_arr;
gpgme_trust_item_t item;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pattern, &pattern_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &pattern, &pattern_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_op_trustlist_start (intern->ctx, pattern, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not start trustlist");
return;
}
array_init(return_value);
while (!(intern->err = gpgme_op_trustlist_next (intern->ctx, &item))){
array_init (&sub_arr);
add_assoc_long (&sub_arr, "level", item->level );
add_assoc_long (&sub_arr, "type", item->type );
add_assoc_string (&sub_arr, "keyid", item->keyid );
add_assoc_string (&sub_arr, "ownertrust", item->owner_trust );
add_assoc_string (&sub_arr, "validity", item->validity );
add_assoc_string (&sub_arr, "name", item->name );
gpgme_trust_item_unref (item);
add_next_index_zval (return_value, &sub_arr);
}
}
/* }}} */
/* {{{ proto array gnupg_listsignatures(string keyid) */
PHP_FUNCTION(gnupg_listsignatures){
char *keyid;
size_t keyid_len;
zval sub_arr;
zval sig_arr;
gpgme_key_t gpgme_key;
gpgme_user_id_t gpgme_userid;
gpgme_key_sig_t gpgme_signature;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &keyid, &keyid_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &keyid, &keyid_len) == FAILURE){
return;
}
intern = (gnupg_object *) zend_fetch_resource(Z_RES_P(res), "ctx", le_gnupg);
}
if((intern->err = gpgme_set_keylist_mode(intern->ctx,GPGME_KEYLIST_MODE_SIGS))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not switch to sigmode");
return;
}
if((intern->err = gpgme_get_key(intern->ctx, keyid, &gpgme_key, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed. given key not unique?");
return;
}
if(!gpgme_key->uids){
GNUPG_ERR("no uids found");
gpgme_key_unref(gpgme_key);
return;
}
array_init(return_value);
gpgme_userid = gpgme_key->uids;
while(gpgme_userid){
array_init (&sub_arr);
gpgme_signature = gpgme_userid->signatures;
while(gpgme_signature){
array_init (&sig_arr);
add_assoc_string (&sig_arr, "uid", gpgme_signature->uid );
add_assoc_string (&sig_arr, "name", gpgme_signature->name );
add_assoc_string (&sig_arr, "email", gpgme_signature->email );
add_assoc_string (&sig_arr, "comment", gpgme_signature->comment );
add_assoc_long (&sig_arr, "expires", gpgme_signature->expires );
add_assoc_bool (&sig_arr, "revoked", gpgme_signature->revoked );
add_assoc_bool (&sig_arr, "expired", gpgme_signature->expired );
add_assoc_bool (&sig_arr, "invalid", gpgme_signature->invalid );
add_assoc_zval (&sub_arr, gpgme_signature->keyid, &sig_arr);
gpgme_signature = gpgme_signature->next;
}
add_assoc_zval (return_value,gpgme_userid->uid, &sub_arr);
gpgme_userid = gpgme_userid->next;
}
gpgme_key_unref(gpgme_key);
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/