From 7fa3d0e1279a76643e0d3a592d496efa4109ec80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Mon, 10 May 2021 15:39:36 +0100 Subject: [PATCH 01/15] z/OS support: NetPGP Re-introducing NetPGP backend --- Makefile.conf | 2 +- src/Makefile | 7 + src/cryptotech.c | 5 +- src/openpgp_compat.h | 4 +- src/pEp_internal.h | 7 +- src/pgp_netpgp.c | 1952 +++++++++++++++++++++++++++++++++++++ src/pgp_netpgp.h | 118 +++ src/pgp_netpgp_internal.h | 11 + 8 files changed, 2097 insertions(+), 9 deletions(-) create mode 100644 src/pgp_netpgp.c create mode 100644 src/pgp_netpgp.h create mode 100644 src/pgp_netpgp_internal.h diff --git a/Makefile.conf b/Makefile.conf index a8c86bac..6eb86720 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -238,7 +238,7 @@ ETPAN_INC= ######### OpenPGP ######### # Selects OpenPGP implementation. must be `SEQUOIA` -OPENPGP=SEQUOIA +OPENPGP?=SEQUOIA # Sequoia-specific variables SEQUOIA_CFLAGS+= diff --git a/src/Makefile b/src/Makefile index 4f16ff12..a5b5568d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,6 +59,13 @@ ifeq ($(OPENPGP),SEQUOIA) CFLAGS+= $(SEQUOIA_CFLAGS) $(SEQUOIA_INC) LDFLAGS+= $(SEQUOIA_LDFLAGS) LDLIBS+= $(SEQUOIA_LIB) + NO_SOURCE+=pgp_netpgp.c +else ifeq ($(OPENPGP),NETPGP) + CPPFLAGS+= -DUSE_NETPGP + CFLAGS+= $(NETPGP_CFLAGS) $(NETPGP_INC) + LDFLAGS+= $(NETPGP_LDFLAGS) + LDLIBS+= $(NETPGP_LIB) + NO_SOURCE+=pgp_sequoia.c else $(error Unknown OpenPGP library: $(OPENPGP)) endif diff --git a/src/cryptotech.c b/src/cryptotech.c index 92cb7008..94e1983d 100644 --- a/src/cryptotech.c +++ b/src/cryptotech.c @@ -6,10 +6,11 @@ #include "pEp_internal.h" -#ifdef USE_SEQUOIA +#if defined(USE_SEQUOIA) #include "pgp_sequoia.h" +#elif defined(USE_NETPGP) +#include "pgp_netpgp.h" #endif -// #include #include diff --git a/src/openpgp_compat.h b/src/openpgp_compat.h index 9b9aabc4..d8ce0575 100644 --- a/src/openpgp_compat.h +++ b/src/openpgp_compat.h @@ -19,8 +19,10 @@ extern "C" { #include "dynamic_api.h" #include "stringpair.h" -#ifdef USE_SEQUOIA +#if defined(USE_SEQUOIA) #include "pgp_sequoia.h" +#elif defined(USE_NETPGP) +#include "pgp_netpgp.h" #endif /** diff --git a/src/pEp_internal.h b/src/pEp_internal.h index 9d1b2c46..cd7236b4 100644 --- a/src/pEp_internal.h +++ b/src/pEp_internal.h @@ -104,13 +104,10 @@ #include "keymanagement_internal.h" #include "message_api_internal.h" -// If not specified, build for Sequoia -#ifndef USE_SEQUOIA -#define USE_SEQUOIA -#endif - #if defined(USE_SEQUOIA) #include "pgp_sequoia_internal.h" +#elif defined(USE_NETPGP) +#include "pgp_netpgp_internal.h" #endif #include "../asn.1/Distribution.h" diff --git a/src/pgp_netpgp.c b/src/pgp_netpgp.c new file mode 100644 index 00000000..89205fe2 --- /dev/null +++ b/src/pgp_netpgp.c @@ -0,0 +1,1952 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "pEp_internal.h" +#include "pgp_netpgp.h" + +#include + +#include "wrappers.h" + +#include "netpgp.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static netpgp_t netpgp; +static pthread_mutex_t netpgp_mutex; + +static PEP_STATUS init_netpgp() +{ + PEP_STATUS status = PEP_STATUS_OK; + const char *home = NULL; + + if(pthread_mutex_init(&netpgp_mutex, NULL)){ + return PEP_OUT_OF_MEMORY; + } + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if (strcmp(setlocale(LC_ALL, NULL), "C") == 0) + setlocale(LC_ALL, ""); + + memset(&netpgp, 0x0, sizeof(netpgp_t)); + + // netpgp_setvar(&netpgp, "max mem alloc", "4194304"); + netpgp_setvar(&netpgp, "need seckey", "1"); + // netpgp_setvar(&netpgp, "need userid", "1"); + + if (!home) + home = getenv("HOME"); + + if (!home) + status = PEP_INIT_CRYPTO_LIB_INIT_FAILED; + + if(home){ + netpgp_set_homedir(&netpgp,(char*)home, NULL, 0); + }else{ + status = PEP_INIT_NO_CRYPTO_HOME; + goto unlock_netpgp; + } + + // pair with gpg's cert-digest-algo + netpgp_setvar(&netpgp, "hash", "SHA256"); + + // subset of gpg's personal-cipher-preferences + // here only one cipher can be selected + netpgp_setvar(&netpgp, "cipher", "CAST5"); + + if (!netpgp_init(&netpgp)) { + status = PEP_INIT_CRYPTO_LIB_INIT_FAILED; + goto unlock_netpgp; + } + + // netpgp_set_debug("packet-parse.c"); + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return status; +} + +static void release_netpgp() +{ + if(pthread_mutex_lock(&netpgp_mutex)){ + return; + } + netpgp_end(&netpgp); + memset(&netpgp, 0x0, sizeof(netpgp_t)); + + pthread_mutex_destroy(&netpgp_mutex); + + return; +} + +static PEP_STATUS init_curl( + pthread_mutex_t *curl_mutex, + bool in_first) +{ + PEP_STATUS status = PEP_STATUS_OK; + + if(pthread_mutex_init(curl_mutex, NULL)){ + return PEP_OUT_OF_MEMORY; + } + + if(pthread_mutex_lock(curl_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if(in_first){ + curl_global_init(CURL_GLOBAL_DEFAULT); + } + + pthread_mutex_unlock(curl_mutex); + return status; +} + +static void release_curl( + pthread_mutex_t *curl_mutex, + bool out_last) +{ + if(pthread_mutex_lock(curl_mutex)){ + return; + } + + if(out_last){ + curl_global_cleanup(); + } + + pthread_mutex_destroy(curl_mutex); + + return; +} + +static PEP_STATUS curl_get_ctx( + CURL **curl) +{ + PEP_STATUS status = PEP_STATUS_OK; + struct curl_slist *headers=NULL; + + if ((*curl = curl_easy_init()) == NULL) { + return PEP_OUT_OF_MEMORY; + } + + curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(*curl, CURLOPT_MAXREDIRS, 3L); + + headers=curl_slist_append(headers,"Pragma: no-cache"); + if(headers) + headers=curl_slist_append(headers,"Cache-Control: no-cache"); + + if(!headers) + { + return PEP_OUT_OF_MEMORY; + } + + curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers); + curl_slist_free_all(headers); + + // TODO curl_easy_setopt(curl,CURLOPT_PROXY,proxy); + return status; +} + +static void curl_release_ctx( + CURL **curl) +{ + if(*curl) + curl_easy_cleanup(*curl); + + *curl = NULL; + + return; +} + +PEP_STATUS pgp_init(PEP_SESSION session, bool in_first) +{ + PEP_STATUS status = PEP_STATUS_OK; + + assert(session); + if(!session) return PEP_ILLEGAL_VALUE; + + if (in_first) { + if((status = init_netpgp()) != PEP_STATUS_OK) + return status; + } + + return PEP_STATUS_OK; +} + +void pgp_release(PEP_SESSION session, bool out_last) +{ + assert(session); + if(!session) return; + + if (out_last){ + release_netpgp(); + } +} + +// return 1 if the file contains ascii-armoured text +static unsigned +_armoured(const char *buf, size_t size, const char *pattern) +{ + unsigned armoured = 0; + regex_t r; + regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB); + if (regnexec(&r, buf, size, 0, NULL, 0) == 0) { + armoured = 1; + } + regfree(&r); + return armoured; +} + +/* write key fingerprint hexdump as a string */ +static unsigned +fpr_to_str (char **str, const uint8_t *fpr, size_t length) +{ + unsigned i; + int n; + + /* 4 hexes per short + null */ + *str = malloc((length / 2) * 4 + 1); + + if(*str == NULL) + return 0; + + for (n = 0, i = 0 ; i < length; i += 2) { + n += snprintf(&((*str)[n]), 5, "%02X%02X", fpr[i], fpr[i+1]); + } + + return 1; +} + +/* write key fingerprint bytes read from hex string + * accept spaces and hexes */ +static unsigned +str_to_fpr (const char *str, uint8_t *fpr, size_t *length) +{ + unsigned i,j; + + *length = 0; + + if (str == NULL) + return 0; + + while(*str && *length < PGP_FINGERPRINT_SIZE){ + while (*str == ' ') str++; + for (j = 0; j < 2; j++) { + uint8_t *byte = &fpr[*length]; + *byte = 0; + for (i = 0; i < 2; i++) { + if (i > 0) + *byte = *byte << 4; + if (*str >= 'a' && *str <= 'f') + *byte += 10 + *str - 'a'; + else if (*str >= 'A' && *str <= 'F') + *byte += 10 + *str - 'A'; + else if (*str >= '0' && *str <= '9') + *byte += *str - '0'; + else + return 0; + str++; + } + (*length)++; + } + } + return 1; +} + +// Iterate through netpgp' reported valid signatures +// fill a list of valid figerprints +// returns PEP_STATUS_OK if all sig reported valid +// error status otherwise. +static PEP_STATUS _validation_results( + netpgp_t *netpgp, + pgp_validation_t *vresult, + stringlist_t **keylist + ) +{ + time_t now; + time_t t; + + *keylist = NULL; + + now = time(NULL); + if (now < vresult->birthtime) { + // signature is not valid yet + return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH; + } + if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) { + // signature has expired + t = vresult->duration + vresult->birthtime; + return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH; + } + if (vresult->validc && vresult->valid_sigs && + !vresult->invalidc && !vresult->unknownc ) { + + stringlist_t *_keylist; + + // caller responsible to free + _keylist = new_stringlist(NULL); + assert(_keylist); + if (_keylist == NULL) { + return PEP_OUT_OF_MEMORY; + } + + stringlist_t *k = _keylist; + unsigned c = 0; + for (unsigned n = 0; n < vresult->validc; ++n) { + unsigned from = 0; + const pgp_key_t *signer; + char *fprstr = NULL; + const uint8_t *keyid = vresult->valid_sigs[n].signer_id; + + signer = pgp_getkeybyid(netpgp->io, netpgp->pubring, + keyid, &from, NULL, NULL, + 0, 0); /* check neither revocation nor expiry + as is should be checked already */ + if(signer) + fpr_to_str(&fprstr, + signer->pubkeyfpr.fingerprint, + signer->pubkeyfpr.length); + else + continue; + + if (fprstr == NULL){ + free_stringlist(_keylist); + return PEP_OUT_OF_MEMORY; + } + + k = stringlist_add(k, fprstr); + + free(fprstr); + + if(!k){ + free_stringlist(_keylist); + return PEP_OUT_OF_MEMORY; + } + + c++; + } + if(c > 0) { + *keylist = _keylist; + return PEP_STATUS_OK; + } + + free_stringlist(_keylist); + return PEP_VERIFY_NO_KEY; + } + if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) { + // No signatures found - is this memory signed? + return PEP_VERIFY_NO_KEY; + } + + if (vresult->invalidc) { + // some invalid signatures + return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH; + } + + // only unknown sigs + return PEP_DECRYPTED; +} + +#define _ENDL "\\s*(\r\n|\r|\n)" +#define ARMOR_HEAD "^-----BEGIN PGP MESSAGE-----"_ENDL +PEP_STATUS pgp_decrypt_and_verify( + PEP_SESSION session, const char *ctext, size_t csize, + const char *dsigtext, size_t dsigsize, + char **ptext, size_t *psize, stringlist_t **keylist, + char** filename_ptr // will be ignored + ) +{ + char *_ptext = NULL; + + PEP_STATUS result; + stringlist_t *_keylist = NULL; + + assert(session); + assert(ctext); + assert(csize); + assert(ptext); + assert(psize); + assert(keylist); + + if(!session || !ctext || !csize || !ptext || !psize || !keylist) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + *ptext = NULL; + *psize = 0; + *keylist = NULL; + + pgp_validation_t *vresult = malloc(sizeof(pgp_validation_t)); + memset(vresult, 0x0, sizeof(pgp_validation_t)); + + key_id_t *recipients_key_ids = NULL; + unsigned recipients_count = 0; + + pgp_memory_t *mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize, + netpgp.secring, netpgp.pubring, + _armoured(ctext, csize, ARMOR_HEAD), + &recipients_key_ids, &recipients_count); + + if (mem == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + + const size_t _psize = pgp_mem_len(mem); + if (_psize){ + if ((_ptext = malloc(_psize + 1)) == NULL) { + result = PEP_OUT_OF_MEMORY; + goto free_pgp; + } + memcpy(_ptext, pgp_mem_data(mem), _psize); + _ptext[_psize] = '\0'; // safeguard for naive users + result = PEP_DECRYPTED; + }else{ + result = PEP_DECRYPT_NO_KEY; + goto free_pgp; + } + + if (result == PEP_DECRYPTED) { + result = _validation_results(&netpgp, vresult, &_keylist); + if (result == PEP_DECRYPTED || + result == PEP_VERIFY_NO_KEY) { + if((_keylist = new_stringlist("")) == NULL) { + result = PEP_OUT_OF_MEMORY; + goto free_ptext; + } + result = PEP_DECRYPTED; + }else if (result != PEP_STATUS_OK) { + goto free_ptext; + }else{ + result = PEP_DECRYPTED_AND_VERIFIED; + } + } + + stringlist_t *k = _keylist; + for (unsigned n = 0; n < recipients_count; ++n) { + unsigned from = 0; + const pgp_key_t *rcpt; + char *fprstr = NULL; + key_id_t *keyid = &recipients_key_ids[n]; + + rcpt = pgp_getkeybyid(netpgp.io, netpgp.pubring, + *keyid, &from, NULL, NULL, + 0, 0); /* check neither revocation nor expiry*/ + if(rcpt) + fpr_to_str(&fprstr, + rcpt->pubkeyfpr.fingerprint, + rcpt->pubkeyfpr.length); + else + // if no key found put ID instead of fpr + fpr_to_str(&fprstr, + *keyid, + sizeof(key_id_t)); + + if (fprstr == NULL){ + result = PEP_OUT_OF_MEMORY; + goto free_keylist; + } + + k = stringlist_add_unique(k, fprstr); + + free(fprstr); + + if(!k){ + result = PEP_OUT_OF_MEMORY; + goto free_keylist; + } + } + + if (result == PEP_DECRYPTED_AND_VERIFIED + || result == PEP_DECRYPTED) { + *ptext = _ptext; + *psize = _psize; + (*ptext)[*psize] = 0; // safeguard for naive users + *keylist = _keylist; + + /* _ptext and _keylist ownership transfer, don't free */ + goto free_pgp; + } + +free_keylist: + free_stringlist(_keylist); + +free_ptext: + free(_ptext); + +free_pgp: + pgp_memory_free(mem); + pgp_validate_result_free(vresult); + +unlock_netpgp: + free(recipients_key_ids); + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +#define ARMOR_SIG_HEAD "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----"_ENDL +PEP_STATUS pgp_verify_text( + PEP_SESSION session, const char *text, size_t size, + const char *signature, size_t sig_size, stringlist_t **keylist + ) +{ + pgp_memory_t *signedmem; + pgp_memory_t *sig; + pgp_validation_t *vresult; + + PEP_STATUS result; + stringlist_t *_keylist; + + assert(session); + assert(text); + assert(size); + assert(signature); + assert(sig_size); + assert(keylist); + + if(!session || !text || !size || !signature || !sig_size || !keylist) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + *keylist = NULL; + + vresult = malloc(sizeof(pgp_validation_t)); + if (vresult == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + memset(vresult, 0x0, sizeof(pgp_validation_t)); + + signedmem = pgp_memory_new(); + if (signedmem == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + pgp_memory_add(signedmem, (const uint8_t*)text, size); + + sig = pgp_memory_new(); + if (sig == NULL) { + pgp_memory_free(signedmem); + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + pgp_memory_add(sig, (const uint8_t*)signature, sig_size); + + pgp_validate_mem_detached(netpgp.io, vresult, sig, + NULL,/* output */ + _armoured(signature, sig_size, ARMOR_SIG_HEAD), + netpgp.pubring, + signedmem); + + result = _validation_results(&netpgp, vresult, &_keylist); + if (result != PEP_STATUS_OK) { + goto free_pgp; + }else{ + result = PEP_VERIFIED; + } + + if (result == PEP_VERIFIED) { + /* TODO : check trust level */ + result = PEP_VERIFIED_AND_TRUSTED; + } + + if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) { + *keylist = _keylist; + + /* _keylist ownership transfer, don't free */ + goto free_pgp; + } + + free_stringlist(_keylist); + +free_pgp: + // free done by pgp_validate_mem_detached + // pgp_memory_free(sig); + // pgp_memory_free(signedmem); + pgp_validate_result_free(vresult); + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +static PEP_STATUS _encrypt_and_sign( + PEP_SESSION session, const stringlist_t *keylist, const char *ptext, + size_t psize, char **ctext, size_t *csize, bool do_sign + ) +{ + pgp_key_t *signer = NULL; + pgp_seckey_t *seckey = NULL; + pgp_memory_t *signedmem = NULL; + pgp_memory_t *cmem; + const char *hashalg; + pgp_keyring_t *rcpts; + + PEP_STATUS result; + const stringlist_t *_keylist; + + assert(session); + assert(keylist); + assert(ptext); + assert(psize); + assert(ctext); + assert(csize); + + if(!session || !ptext || !psize || !ctext || !csize || !keylist) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + *ctext = NULL; + *csize = 0; + + if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) { + assert(_keylist->value); + + const pgp_key_t *key; + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + size_t fprlen; + unsigned from = 0; + + if (str_to_fpr(_keylist->value, fpr, &fprlen)) { + if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring, + fpr, fprlen, &from, NULL, + /* reject revoked, accept expired */ + 1,0)) == NULL) { + result = PEP_KEY_NOT_FOUND; + goto free_rcpts; + } + }else{ + result = PEP_ILLEGAL_VALUE; + goto free_rcpts; + } + + /* Signer is the first key in the list */ + if(signer == NULL){ + from = 0; + signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring, + fpr, fprlen, + &from, + NULL, + 0,0); /* accept any */ + if(signer == NULL){ + result = PEP_KEY_NOT_FOUND; + goto free_rcpts; + } + } + + // add key to recipients/signers + pgp_keyring_add(rcpts, key); + if(rcpts->keys == NULL){ + result = PEP_OUT_OF_MEMORY; + goto free_rcpts; + } + } + + /* Empty keylist ?*/ + if(rcpts->keyc == 0){ + result = PEP_ILLEGAL_VALUE; + goto free_rcpts; + } + + seckey = pgp_key_get_certkey(signer); + + /* No signig key. Revoked ? */ + if(seckey == NULL){ + result = PEP_GET_KEY_FAILED; + goto free_rcpts; + } + + hashalg = netpgp_getvar(&netpgp, "hash"); + + const char *stext; + size_t ssize; + unsigned encrypt_raw_packet; + + if (do_sign) { + // Sign data + signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey, + time(NULL), /* birthtime */ + 0 /* duration */, + hashalg, + 0 /* armored */, + 0 /* cleartext */); + + if (!signedmem) { + result = PEP_UNENCRYPTED; + goto free_rcpts; + } + stext = (char*) pgp_mem_data(signedmem); + ssize = pgp_mem_len(signedmem); + encrypt_raw_packet = 1 /* takes raw OpenPGP message */; + } else { + stext = ptext; + ssize = psize; + encrypt_raw_packet = 0 /* not a raw OpenPGP message */; + } + + // Encrypt (maybe) signed data + + cmem = pgp_encrypt_buf(netpgp.io, stext, + ssize, rcpts, 1 /* armored */, + netpgp_getvar(&netpgp, "cipher"), + encrypt_raw_packet); + + if (cmem == NULL) { + result = PEP_OUT_OF_MEMORY; + goto free_signedmem; + }else{ + + char *_buffer = NULL; + size_t length = pgp_mem_len(cmem); + + // Allocate transferable buffer + _buffer = malloc(length + 1); + assert(_buffer); + if (_buffer == NULL) { + result = PEP_OUT_OF_MEMORY; + goto free_cmem; + } + + memcpy(_buffer, pgp_mem_data(cmem), length); + + *ctext = _buffer; + *csize = length; + (*ctext)[*csize] = 0; // safeguard for naive users + result = PEP_STATUS_OK; + } + +free_cmem : + pgp_memory_free(cmem); +free_signedmem : + if (do_sign) { + pgp_memory_free(signedmem); + } +free_rcpts : + pgp_keyring_free(rcpts); +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + + +PEP_STATUS pgp_sign_only( + PEP_SESSION session, const char* fpr, const char *ptext, + size_t psize, char **stext, size_t *ssize + ) +{ + pgp_key_t *signer = NULL; + pgp_seckey_t *seckey = NULL; + pgp_memory_t *signedmem = NULL; + pgp_memory_t *text = NULL; + pgp_output_t *output; + + const char *hashalg; + pgp_keyring_t *snrs; + + pgp_create_sig_t *sig; + uint8_t keyid[PGP_KEY_ID_SIZE]; + + PEP_STATUS result; + + assert(session); + assert(fpr); + assert(ptext); + assert(psize); + assert(stext); + assert(ssize); + + if(!session || !ptext || !psize || !stext || !ssize || !fpr || !fpr[0]) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + *stext = NULL; + *ssize = 0; + + if ((snrs = calloc(1, sizeof(*snrs))) == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + + assert(fpr && fpr[0]); + + uint8_t uint_fpr[PGP_FINGERPRINT_SIZE]; + size_t fprlen; + unsigned from = 0; + + if (str_to_fpr(fpr, uint_fpr, &fprlen)) { + if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring, + uint_fpr, fprlen, &from, NULL, + /* reject revoked and expired */ + 1,1)) == NULL) { + result = PEP_KEY_NOT_FOUND; + goto free_snrs; + } + } else{ + result = PEP_ILLEGAL_VALUE; + goto free_snrs; + } + + // add key to signers + pgp_keyring_add(snrs, signer); + if(snrs->keys == NULL){ + result = PEP_OUT_OF_MEMORY; + goto free_snrs; + } + + /* Empty keylist ?*/ + if(snrs->keyc == 0){ + result = PEP_ILLEGAL_VALUE; + goto free_snrs; + } + + seckey = pgp_key_get_certkey(signer); + + /* No signing key. Revoked ? */ + if(seckey == NULL){ + result = PEP_GET_KEY_FAILED; + goto free_snrs; + } + + hashalg = netpgp_getvar(&netpgp, "hash"); + + const char *_stext; + size_t _ssize; + + text = pgp_memory_new(); + pgp_memory_add(text, (const uint8_t*)ptext, psize); + + pgp_setup_memory_write(&output, &signedmem, psize); + pgp_writer_push_armor_msg(output); + + pgp_hash_alg_t hash_alg = pgp_str_to_hash_alg(hashalg); + + sig = pgp_create_sig_new(); + pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY); + + pgp_sig_add_data(sig, pgp_mem_data(text), pgp_mem_len(text)); + pgp_memory_free(text); + + pgp_add_creation_time(sig, time(NULL)); + pgp_add_sig_expiration_time(sig, 0); + pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg); + pgp_add_issuer_keyid(sig, keyid); + pgp_end_hashed_subpkts(sig); + + pgp_write_sig(output, sig, &seckey->pubkey, seckey); + pgp_writer_close(output); + pgp_create_sig_delete(sig); + + if (!signedmem) { + result = PEP_UNENCRYPTED; + goto free_snrs; + } + _stext = (char*) pgp_mem_data(signedmem); + _ssize = pgp_mem_len(signedmem); + + // Allocate transferable buffer + char *_buffer = malloc(_ssize + 1); + + assert(_buffer); + if (_buffer == NULL) { + result = PEP_OUT_OF_MEMORY; + goto free_signedmem; + } + + memcpy(_buffer, _stext, _ssize); + *stext = _buffer; + *ssize = _ssize; + (*stext)[*ssize] = 0; // safeguard for naive users + + result = PEP_STATUS_OK; + +free_signedmem : + pgp_memory_free(signedmem); +free_snrs : + pgp_keyring_free(snrs); +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + + +PEP_STATUS pgp_encrypt_and_sign( + PEP_SESSION session, const stringlist_t *keylist, const char *ptext, + size_t psize, char **ctext, size_t *csize + ) +{ + PEP_STATUS result; + result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, + true); + return result; +} + +PEP_STATUS pgp_encrypt_only( + PEP_SESSION session, const stringlist_t *keylist, const char *ptext, + size_t psize, char **ctext, size_t *csize + ) +{ + PEP_STATUS result; + result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, + false); + return result; +} + + +PEP_STATUS pgp_generate_keypair( + PEP_SESSION session, pEp_identity *identity + ) +{ + pgp_key_t newseckey; + pgp_key_t *newpubkey; + + PEP_STATUS result; + char newid[1024]; + const char *hashalg; + const char *cipher; + + assert(session); + assert(identity); + assert(identity->address); + assert(identity->fpr == NULL); + assert(identity->username); + + if(!session || !identity || + !identity->address || identity->fpr || !identity->username) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if(snprintf(newid, sizeof(newid), + "%s <%s>", identity->username, identity->address) >= sizeof(newid)){ + result = PEP_BUFFER_TOO_SMALL; + goto unlock_netpgp; + } + + hashalg = netpgp_getvar(&netpgp, "hash"); + cipher = netpgp_getvar(&netpgp, "cipher"); + + bzero(&newseckey, sizeof(newseckey)); + + // Generate the key + if (!pgp_rsa_generate_keypair(&newseckey, 4096, 65537UL, hashalg, cipher, + (const uint8_t *) "", (const size_t) 0)) + { + result = PEP_CANNOT_CREATE_KEY; + goto free_seckey; + } + + /* make a public key out of generated secret key */ + if((newpubkey = pgp_ensure_pubkey( + netpgp.pubring, + &newseckey.key.seckey.pubkey, + newseckey.pubkeyid))==NULL) + { + result = PEP_OUT_OF_MEMORY; + goto free_seckey; + } + + // "Expire-Date: 1y\n"; + if (!pgp_add_selfsigned_userid(&newseckey, newpubkey, + (uint8_t *)newid, 365*24*3600)) + { + result = PEP_CANNOT_CREATE_KEY; + goto delete_pubkey; + } + + if (newpubkey == NULL) + { + result = PEP_OUT_OF_MEMORY; + goto delete_pubkey; + } + + // Append key to netpgp's rings (key ownership transfered) + if (!pgp_keyring_add(netpgp.secring, &newseckey)){ + result = PEP_OUT_OF_MEMORY; + goto delete_pubkey; + } + + // save rings + if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp)) + { + char *fprstr = NULL; + fpr_to_str(&fprstr, + newseckey.pubkeyfpr.fingerprint, + newseckey.pubkeyfpr.length); + + if (fprstr == NULL) { + result = PEP_OUT_OF_MEMORY; + goto pop_secring; + } + + /* keys saved, pass fingerprint back */ + identity->fpr = fprstr; + result = PEP_STATUS_OK; + + /* free nothing, everything transfered */ + goto unlock_netpgp; + } else { + /* XXX in case only pubring save succeed + * pubring file is left as-is, but backup restore + * could be attempted if such corner case matters */ + result = PEP_UNKNOWN_ERROR; + } + +pop_secring: + ((pgp_keyring_t *)netpgp.secring)->keyc--; +delete_pubkey: + pgp_deletekeybyfpr(netpgp.io, + (pgp_keyring_t *)netpgp.pubring, + newseckey.pubkeyfpr.fingerprint, + newseckey.pubkeyfpr.length); +free_seckey: + pgp_key_free(&newseckey); +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) +{ + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + size_t length; + + PEP_STATUS result; + + assert(session); + assert(fprstr); + + if (!session || !fprstr) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if (str_to_fpr(fprstr, fpr, &length)) { + unsigned insec = pgp_deletekeybyfpr(netpgp.io, + (pgp_keyring_t *)netpgp.secring, + (const uint8_t *)fpr, length); + unsigned inpub = pgp_deletekeybyfpr(netpgp.io, + (pgp_keyring_t *)netpgp.pubring, + (const uint8_t *)fpr, length); + if(!insec && !inpub){ + result = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } else { + result = PEP_STATUS_OK; + } + }else{ + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + + // save rings + if (netpgp_save_pubring(&netpgp) && + netpgp_save_secring(&netpgp)) + { + result = PEP_STATUS_OK; + }else{ + result = PEP_UNKNOWN_ERROR; + } + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +#define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----"_ENDL +PEP_STATUS pgp_import_keydata( + PEP_SESSION session, + const char *key_data, + size_t size, + identity_list **private_idents + ) +{ + pgp_memory_t *mem; + + PEP_STATUS result = PEP_STATUS_OK; + + assert(session); + assert(key_data); + + // reporting imported private keys not supported + // stub code to be reomoved + if(private_idents) + *private_idents = NULL; + + if(!session || !key_data) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + mem = pgp_memory_new(); + if (mem == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + pgp_memory_add(mem, (const uint8_t*)key_data, size); + + if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring, + _armoured(key_data, size, ARMOR_KEY_HEAD), + mem) == 0){ + result = PEP_ILLEGAL_VALUE; + } + + pgp_memory_free(mem); + + // save rings + if (netpgp_save_pubring(&netpgp) && + netpgp_save_secring(&netpgp)) + { + // we never really know if a key was imported. MEH. + result = PEP_KEY_IMPORT_STATUS_UNKNOWN; + }else{ + result = PEP_UNKNOWN_ERROR; + } + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +static PEP_STATUS _export_keydata( + pgp_key_t *key, + char **buffer, + size_t *buflen + ) +{ + PEP_STATUS result; + pgp_output_t *output; + pgp_memory_t *mem; + pgp_setup_memory_write(&output, &mem, 128); + + if (mem == NULL || output == NULL) { + return PEP_ILLEGAL_VALUE; + } + + if (!pgp_write_xfer_key(output, key, 1)) { + result = PEP_UNKNOWN_ERROR; + goto free_mem; + } + + *buffer = NULL; + *buflen = pgp_mem_len(mem); + + // Allocate transferable buffer + *buffer = malloc(*buflen + 1); + assert(*buffer); + if (*buffer == NULL) { + result = PEP_OUT_OF_MEMORY; + goto free_mem; + } + + memcpy(*buffer, pgp_mem_data(mem), *buflen); + (*buffer)[*buflen] = 0; // safeguard for naive users + + return PEP_STATUS_OK; + +free_mem : + pgp_teardown_memory_write(output, mem); + + return result; +} + +PEP_STATUS pgp_export_keydata( + PEP_SESSION session, const char *fprstr, char **key_data, size_t *size, + bool secret + ) +{ + pgp_key_t *key; + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + size_t fprlen; + + PEP_STATUS result; + char *buffer; + size_t buflen; + const pgp_keyring_t *srcring; + + assert(session); + assert(fprstr); + assert(key_data); + assert(size); + + if (secret) + srcring = netpgp.secring; + else + srcring = netpgp.pubring; + + if (!session || !fprstr || !key_data || !size) + return PEP_ILLEGAL_VALUE; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if (str_to_fpr(fprstr, fpr, &fprlen)) { + unsigned from = 0; + + if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring, + fpr, fprlen, &from, + NULL,0,0)) == NULL) { + result = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + }else{ + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + + result = _export_keydata(key, &buffer, &buflen); + + if(result == PEP_STATUS_OK) + { + *key_data = buffer; + *size = buflen; + result = PEP_STATUS_OK; + } + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +struct HKP_answer { + char *memory; + size_t size; +}; + +static size_t +HKPAnswerWriter(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct HKP_answer *mem = (struct HKP_answer *)userp; + + mem->memory = realloc(mem->memory, mem->size + realsize + 1); + if(mem->memory == NULL) { + mem->size = 0; + return 0; + } + + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + + return realsize; +} + + +PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern) +{ + assert(!"pgp_recv_key not implemented"); + return PEP_UNKNOWN_ERROR; +} + +typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *); + +static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, + const char *pattern, find_key_cb_t cb, void* cb_arg) +{ + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + size_t length; + pgp_key_t *key; + + PEP_STATUS result; + + // Try find a fingerprint in pattern + if (str_to_fpr(pattern, fpr, &length)) { + unsigned from = 0; + + + // Only one fingerprint can match + if ((key = (pgp_key_t *)pgp_getkeybyfpr( + netpgp.io, + keyring, + (const uint8_t *)fpr, length, + &from, + NULL, 0, 0)) == NULL) { + + return PEP_KEY_NOT_FOUND; + } + + result = cb(cb_arg, key); + + } else { + // Search by name for pattern. Can match many. + unsigned from = 0; + result = PEP_KEY_NOT_FOUND; + while((key = (pgp_key_t *)pgp_getnextkeybyname( + netpgp.io, + keyring, + (const char *)pattern, + &from)) != NULL) { + + result = cb(cb_arg, key); + if (result != PEP_STATUS_OK) + break; + + from++; + } + } + + return result; +} + +static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key) +{ + stringlist_t **keylist = arg; + char *newfprstr = NULL; + + fpr_to_str(&newfprstr, + key->pubkeyfpr.fingerprint, + key->pubkeyfpr.length); + + if (newfprstr == NULL) { + return PEP_OUT_OF_MEMORY; + } else { + + stringlist_add(*keylist, newfprstr); + free(newfprstr); + if (*keylist == NULL) { + return PEP_OUT_OF_MEMORY; + } + } + return PEP_STATUS_OK; +} + +static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key) +{ + if (pgp_is_key_secret(key)) { + stringlist_t **keylist = arg; + char *newfprstr = NULL; + + fpr_to_str(&newfprstr, + key->pubkeyfpr.fingerprint, + key->pubkeyfpr.length); + + if (newfprstr == NULL) { + return PEP_OUT_OF_MEMORY; + } else { + stringlist_add(*keylist, newfprstr); + free(newfprstr); + if (*keylist == NULL) { + return PEP_OUT_OF_MEMORY; + } + } + } + return PEP_STATUS_OK; +} + +static PEP_STATUS add_keyinfo_to_stringpair_list(void* arg, pgp_key_t *key) { + stringpair_list_t** keyinfo_list = (stringpair_list_t**)arg; + stringpair_t* pair = NULL; + char* id_fpr = NULL; + char* primary_userid = (char*)pgp_key_get_primary_userid(key); + +// Unused: +// bool key_revoked = false; + +// PEP_STATUS key_status = pgp_key_revoked(session, id_fpr, &key_revoked); + +// if (key_revoked || key_status == PEP_GET_KEY_FAILED) +// return PEP_STATUS_OK; // we just move on + + fpr_to_str(&id_fpr, key->pubkeyfpr.fingerprint, + key->pubkeyfpr.length); + + pair = new_stringpair(id_fpr, primary_userid); + + if (pair == NULL) + return PEP_OUT_OF_MEMORY; + + *keyinfo_list = stringpair_list_add(*keyinfo_list, pair); + free(id_fpr); + if (*keyinfo_list == NULL) + return PEP_OUT_OF_MEMORY; + return PEP_STATUS_OK; +} + +PEP_STATUS pgp_find_keys( + PEP_SESSION session, const char *pattern, stringlist_t **keylist + ) +{ + stringlist_t *_keylist, *_k; + + PEP_STATUS result; + + assert(session); + assert(pattern); + assert(keylist); + + if (!session || !pattern || !keylist ) + { + return PEP_ILLEGAL_VALUE; + } + + if (pthread_mutex_lock(&netpgp_mutex)) + { + return PEP_UNKNOWN_ERROR; + } + + *keylist = NULL; + _keylist = new_stringlist(NULL); + if (_keylist == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + _k = _keylist; + + result = find_keys_do((pgp_keyring_t *)netpgp.pubring, + pattern, &add_key_fpr_to_stringlist, &_k); + + if (result == PEP_STATUS_OK) { + *keylist = _keylist; + // Transfer ownership, no free + goto unlock_netpgp; + } + + free_stringlist(_keylist); + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +#define HKP_REQ_PREFIX "keytext=" +#define HKP_REQ_PREFIX_LEN 8 + +static PEP_STATUS send_key_cb(void *arg, pgp_key_t *key) +{ + char *buffer = NULL; + size_t buflen = 0; + PEP_STATUS result; + stringlist_t *encoded_keys; + encoded_keys = (stringlist_t*)arg; + + result = _export_keydata(key, &buffer, &buflen); + + if(result == PEP_STATUS_OK){ + char *encoded_key = curl_escape(buffer, (int)buflen); + if(!encoded_key){ + result = PEP_OUT_OF_MEMORY; + goto free_buffer; + } + size_t encoded_key_len = strlen(encoded_key); + + char *request = calloc(1, HKP_REQ_PREFIX_LEN + encoded_key_len + 1); + if(!request){ + result = PEP_OUT_OF_MEMORY; + goto free_encoded_key; + } + + memcpy(request, HKP_REQ_PREFIX, HKP_REQ_PREFIX_LEN); + memcpy(request + HKP_REQ_PREFIX_LEN, encoded_key, encoded_key_len); + request[HKP_REQ_PREFIX_LEN + encoded_key_len] = '\0'; + + if(!stringlist_add(encoded_keys, request)){ + result = PEP_OUT_OF_MEMORY; + } + free(request); + +free_encoded_key: + curl_free(encoded_key); + +free_buffer: + free(buffer); + } + + return result; +} + +PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern) +{ + assert(!"pgp_send_key not implemented"); + return PEP_UNKNOWN_ERROR; +} + + +PEP_STATUS pgp_get_key_rating( + PEP_SESSION session, + const char *fprstr, + PEP_comm_type *comm_type + ) +{ + pgp_key_t *key; + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + unsigned from = 0; + size_t length; + + + PEP_STATUS status = PEP_STATUS_OK; + + assert(session); + assert(fprstr); + assert(comm_type); + + if (!session || !fprstr || !comm_type ) + return PEP_ILLEGAL_VALUE; + + *comm_type = PEP_ct_unknown; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if (!str_to_fpr(fprstr, fpr, &length)) { + status = PEP_ILLEGAL_VALUE; + goto unlock_netpgp; + } + + key = pgp_getkeybyfpr( + netpgp.io, + netpgp.pubring, + fpr, length, &from, NULL,0,0); + + if(key == NULL) + { + status = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + + switch(pgp_key_get_rating(key)){ + case PGP_VALID: + *comm_type = PEP_ct_OpenPGP_unconfirmed; + break; + case PGP_WEAK: + *comm_type = PEP_ct_OpenPGP_weak_unconfirmed; + break; + case PGP_TOOSHORT: + *comm_type = PEP_ct_key_too_short; + break; + case PGP_INVALID: + *comm_type = PEP_ct_key_b0rken; + break; + case PGP_EXPIRED: + *comm_type = PEP_ct_key_expired; + break; + case PGP_REVOKED: + *comm_type = PEP_ct_key_revoked; + break; + default: + break; + } + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return status; +} + +PEP_STATUS pgp_renew_key( + PEP_SESSION session, + const char *fprstr, + const timestamp *ts + ) +{ + pgp_key_t *pkey; + pgp_key_t *skey; + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + size_t length; + unsigned from = 0; + time_t duration; + const uint8_t *primid; + + PEP_STATUS status = PEP_STATUS_OK; + + assert(session); + assert(fprstr); + + if (!session || !fprstr ) + return PEP_ILLEGAL_VALUE; + + if(ts) + { + time_t now, when; + now = time(NULL); + when = mktime((struct tm*)ts); + if(now && when && when > now){ + duration = when - now; + }else{ + return PEP_ILLEGAL_VALUE; + } + }else{ + /* Default 1 year from now */ + duration = 365*24*3600; + } + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + + if (!str_to_fpr(fprstr, fpr, &length)) { + status = PEP_ILLEGAL_VALUE; + goto unlock_netpgp; + } + + pkey = pgp_getkeybyfpr( + netpgp.io, + netpgp.pubring, + fpr, length, &from, NULL, + 1, 0); /* reject revoked, accept expired */ + + if(pkey == NULL) + { + status = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + + from = 0; + skey = pgp_getkeybyfpr( + netpgp.io, + netpgp.secring, + fpr, length, &from, NULL, + 1, 0); /* reject revoked, accept expired */ + + if(skey == NULL) + { + status = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + + if((primid = pgp_key_get_primary_userid(skey)) == NULL) + { + status = PEP_KEY_HAS_AMBIG_NAME; + goto unlock_netpgp; + } + + // FIXME : renew in a more gentle way + if (!pgp_add_selfsigned_userid(skey, pkey, primid, duration)) + { + status = PEP_CANNOT_CREATE_KEY; + goto unlock_netpgp; + } + + // save rings + if (netpgp_save_pubring(&netpgp) && + netpgp_save_secring(&netpgp)) + { + status = PEP_STATUS_OK; + }else{ + status = PEP_UNKNOWN_ERROR; + } + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return status; +} + +PEP_STATUS pgp_revoke_key( + PEP_SESSION session, + const char *fprstr, + const char *reason + ) +{ + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + size_t length; + unsigned from = 0; + + PEP_STATUS status = PEP_STATUS_OK; + + assert(session); + assert(fprstr); + + if (!session || !fprstr) + return PEP_UNKNOWN_ERROR; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + // FIXME : deduplicate that code w/ renew + if (!str_to_fpr(fprstr, fpr, &length)) { + status = PEP_ILLEGAL_VALUE; + goto unlock_netpgp; + } + + pgp_key_t *pkey = pgp_getkeybyfpr( + netpgp.io, + netpgp.pubring, + fpr, length, &from, NULL, + 1, 0); /* reject revoked, accept expired */ + + if(pkey == NULL) + { + status = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + + from = 0; + pgp_key_t *skey = pgp_getkeybyfpr( + netpgp.io, + netpgp.secring, + fpr, length, &from, NULL, + 1, 0); /* reject revoked, accept expired */ + + if(skey == NULL) + { + status = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + + pgp_key_revoke(skey, pkey, + 0, /* no reason code specified */ + reason); + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return status; +} + +PEP_STATUS pgp_key_expired( + PEP_SESSION session, + const char *fprstr, + const time_t when, + bool *expired + ) +{ + PEP_STATUS status = PEP_STATUS_OK; + PEP_comm_type comm_type; + + assert(session); + assert(fprstr); + assert(expired); + + if (!session || !fprstr || !expired) + return PEP_UNKNOWN_ERROR; + + // TODO : take "when" in account + + *expired = false; + + status = pgp_get_key_rating(session, fprstr, &comm_type); + + if (status != PEP_STATUS_OK) + return status; + + if (comm_type == PEP_ct_key_expired){ + *expired = true; + } + + return PEP_STATUS_OK; +} + +PEP_STATUS pgp_key_revoked( + PEP_SESSION session, + const char *fprstr, + bool *revoked + ) +{ + PEP_STATUS status = PEP_STATUS_OK; + PEP_comm_type comm_type; + + assert(session); + assert(fprstr); + assert(revoked); + + *revoked = false; + + status = pgp_get_key_rating(session, fprstr, &comm_type); + + if (status != PEP_STATUS_OK) + return status; + + if (comm_type == PEP_ct_key_revoked){ + *revoked = true; + } + + return PEP_STATUS_OK; +} + +PEP_STATUS pgp_key_created( + PEP_SESSION session, + const char *fprstr, + time_t *created + ) +{ + uint8_t fpr[PGP_FINGERPRINT_SIZE]; + pgp_key_t *key; + size_t length; + unsigned from = 0; + + PEP_STATUS status = PEP_STATUS_OK; + + assert(session); + assert(fprstr); + assert(created); + + if (!session || !fprstr || !created) + return PEP_UNKNOWN_ERROR; + + *created = 0; + + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } + + if (!str_to_fpr(fprstr, fpr, &length)) { + status = PEP_ILLEGAL_VALUE; + goto unlock_netpgp; + } + + key = pgp_getkeybyfpr( + netpgp.io, + netpgp.pubring, + fpr, length, &from, NULL,0,0); + + if (key) + { + *created = (time_t) key->key.pubkey.birthtime; + } + else + { + status = PEP_KEY_NOT_FOUND; + goto unlock_netpgp; + } + + + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return status; +} + + +PEP_STATUS pgp_list_keyinfo( + PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list) +{ + + if (!session || !keyinfo_list) + return PEP_UNKNOWN_ERROR; + + if (pthread_mutex_lock(&netpgp_mutex)) + { + return PEP_UNKNOWN_ERROR; + } + +// Unused: +// pgp_key_t *key; + + PEP_STATUS result; + + result = find_keys_do((pgp_keyring_t *)netpgp.pubring, + pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list); + + if (!keyinfo_list) + result = PEP_KEY_NOT_FOUND; + + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +/* copied from find_keys, but we need to use a callback that filters. */ +PEP_STATUS pgp_find_private_keys( + PEP_SESSION session, const char *pattern, stringlist_t **keylist) +{ + stringlist_t *_keylist, *_k; + + PEP_STATUS result; + + assert(session); + assert(keylist); + + if (!session || !keylist ) + { + return PEP_ILLEGAL_VALUE; + } + + if (pthread_mutex_lock(&netpgp_mutex)) + { + return PEP_UNKNOWN_ERROR; + } + + *keylist = NULL; + _keylist = new_stringlist(NULL); + if (_keylist == NULL) { + result = PEP_OUT_OF_MEMORY; + goto unlock_netpgp; + } + _k = _keylist; + + result = find_keys_do((pgp_keyring_t *)netpgp.secring, + pattern, &add_secret_key_fpr_to_stringlist, &_k); + + if (result == PEP_STATUS_OK) { + *keylist = _keylist; + // Transfer ownership, no free + goto unlock_netpgp; + } + + free_stringlist(_keylist); + +unlock_netpgp: + pthread_mutex_unlock(&netpgp_mutex); + + return result; +} + +PEP_STATUS pgp_contains_priv_key( + PEP_SESSION session, + const char *fpr, + bool *has_private) { + stringlist_t* keylist = NULL; + PEP_STATUS status = pgp_find_private_keys(session, fpr, &keylist); + if (status == PEP_STATUS_OK && keylist) { + free_stringlist(keylist); + *has_private = true; + } + else { + *has_private = false; + } + return status; +} + +PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) { + // Not implemented - netpgp doesn't appear to keep track of trust status in + // a meaningful way, though there is space for it in the structs. + return PEP_STATUS_OK; +} diff --git a/src/pgp_netpgp.h b/src/pgp_netpgp.h new file mode 100644 index 00000000..e8977ecb --- /dev/null +++ b/src/pgp_netpgp.h @@ -0,0 +1,118 @@ +// This file is under GNU General Public License 3.0 + +#pragma once + +#include "pEpEngine.h" + +PEP_STATUS pgp_init(PEP_SESSION session, bool in_first); +void pgp_release(PEP_SESSION session, bool out_last); + +PEP_STATUS pgp_decrypt_and_verify( + PEP_SESSION session, const char *ctext, size_t csize, + const char *dsigtext, size_t dsigsize, + char **ptext, size_t *psize, stringlist_t **keylist, + char** filename_ptr // will be ignored + ); + +PEP_STATUS pgp_encrypt_and_sign( + PEP_SESSION session, const stringlist_t *keylist, const char *ptext, + size_t psize, char **ctext, size_t *csize + ); + + +PEP_STATUS pgp_encrypt_only( + PEP_SESSION session, const stringlist_t *keylist, const char *ptext, + size_t psize, char **ctext, size_t *csize + ); + +PEP_STATUS pgp_sign_only( + PEP_SESSION session, const char* fpr, const char *ptext, + size_t psize, char **stext, size_t *ssize + ); + +PEP_STATUS pgp_verify_text( + PEP_SESSION session, const char *text, size_t size, + const char *signature, size_t sig_size, stringlist_t **keylist + ); + +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr); + +PEP_STATUS pgp_export_keydata( + PEP_SESSION session, const char *fpr, char **key_data, size_t *size, + bool secret + ); + +PEP_STATUS pgp_find_keys( + PEP_SESSION session, const char *pattern, stringlist_t **keylist + ); + +PEP_STATUS pgp_list_keyinfo( + PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list + ); + +PEP_STATUS pgp_generate_keypair( + PEP_SESSION session, pEp_identity *identity + ); + +PEP_STATUS pgp_get_key_rating( + PEP_SESSION session, + const char *fpr, + PEP_comm_type *comm_type + ); + +PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, + size_t size, identity_list **private_idents); + +PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern); +PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern); + +PEP_STATUS pgp_renew_key( + PEP_SESSION session, + const char *fpr, + const timestamp *ts + ); + +PEP_STATUS pgp_revoke_key( + PEP_SESSION session, + const char *fpr, + const char *reason + ); + +PEP_STATUS pgp_key_expired( + PEP_SESSION session, + const char *fpr, + const time_t when, + bool *expired + ); + +PEP_STATUS pgp_key_revoked( + PEP_SESSION session, + const char *fpr, + bool *revoked + ); + +PEP_STATUS pgp_key_created( + PEP_SESSION session, + const char *fprstr, + time_t *created + ); + +PEP_STATUS pgp_contains_priv_key( + PEP_SESSION session, + const char *fpr, + bool *has_private); + +PEP_STATUS pgp_find_private_keys( + PEP_SESSION session, const char *pattern, stringlist_t **keylist +); + +// Stub - just returns PEP_STATUS_OK, as netpgp isn't sufficient to do this. +PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session); + +PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite) { + if (suite == PEP_CIPHER_SUITE_DEFAULT) { + return PEP_STATUS_OK; + } else { + return PEP_CANNOT_CONFIG; + } +} diff --git a/src/pgp_netpgp_internal.h b/src/pgp_netpgp_internal.h new file mode 100644 index 00000000..afe8883e --- /dev/null +++ b/src/pgp_netpgp_internal.h @@ -0,0 +1,11 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#pragma once + +#include +#include + +typedef struct _pEpNetPGPSession { + pthread_mutex_t curl_mutex; +} pEpNetPGPSession; From 7d55688a30cf54c8b90662a8621fc4c91de8169a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Tue, 11 May 2021 12:34:24 +0100 Subject: [PATCH 02/15] z/OS support: Removing curl residue Curl is just another can of worms I just don't wanna open yet on z/OS --- src/pgp_netpgp.c | 133 ++++------------------------------------------- src/pgp_netpgp.h | 11 ++-- 2 files changed, 13 insertions(+), 131 deletions(-) diff --git a/src/pgp_netpgp.c b/src/pgp_netpgp.c index 89205fe2..537ac2bb 100644 --- a/src/pgp_netpgp.c +++ b/src/pgp_netpgp.c @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -91,85 +90,6 @@ static void release_netpgp() return; } -static PEP_STATUS init_curl( - pthread_mutex_t *curl_mutex, - bool in_first) -{ - PEP_STATUS status = PEP_STATUS_OK; - - if(pthread_mutex_init(curl_mutex, NULL)){ - return PEP_OUT_OF_MEMORY; - } - - if(pthread_mutex_lock(curl_mutex)){ - return PEP_UNKNOWN_ERROR; - } - - if(in_first){ - curl_global_init(CURL_GLOBAL_DEFAULT); - } - - pthread_mutex_unlock(curl_mutex); - return status; -} - -static void release_curl( - pthread_mutex_t *curl_mutex, - bool out_last) -{ - if(pthread_mutex_lock(curl_mutex)){ - return; - } - - if(out_last){ - curl_global_cleanup(); - } - - pthread_mutex_destroy(curl_mutex); - - return; -} - -static PEP_STATUS curl_get_ctx( - CURL **curl) -{ - PEP_STATUS status = PEP_STATUS_OK; - struct curl_slist *headers=NULL; - - if ((*curl = curl_easy_init()) == NULL) { - return PEP_OUT_OF_MEMORY; - } - - curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(*curl, CURLOPT_MAXREDIRS, 3L); - - headers=curl_slist_append(headers,"Pragma: no-cache"); - if(headers) - headers=curl_slist_append(headers,"Cache-Control: no-cache"); - - if(!headers) - { - return PEP_OUT_OF_MEMORY; - } - - curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers); - curl_slist_free_all(headers); - - // TODO curl_easy_setopt(curl,CURLOPT_PROXY,proxy); - return status; -} - -static void curl_release_ctx( - CURL **curl) -{ - if(*curl) - curl_easy_cleanup(*curl); - - *curl = NULL; - - return; -} - PEP_STATUS pgp_init(PEP_SESSION session, bool in_first) { PEP_STATUS status = PEP_STATUS_OK; @@ -202,7 +122,7 @@ _armoured(const char *buf, size_t size, const char *pattern) unsigned armoured = 0; regex_t r; regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB); - if (regnexec(&r, buf, size, 0, NULL, 0) == 0) { + if (regexec(&r, buf, size, 0, NULL) == 0) { armoured = 1; } regfree(&r); @@ -1455,49 +1375,6 @@ unlock_netpgp: #define HKP_REQ_PREFIX "keytext=" #define HKP_REQ_PREFIX_LEN 8 -static PEP_STATUS send_key_cb(void *arg, pgp_key_t *key) -{ - char *buffer = NULL; - size_t buflen = 0; - PEP_STATUS result; - stringlist_t *encoded_keys; - encoded_keys = (stringlist_t*)arg; - - result = _export_keydata(key, &buffer, &buflen); - - if(result == PEP_STATUS_OK){ - char *encoded_key = curl_escape(buffer, (int)buflen); - if(!encoded_key){ - result = PEP_OUT_OF_MEMORY; - goto free_buffer; - } - size_t encoded_key_len = strlen(encoded_key); - - char *request = calloc(1, HKP_REQ_PREFIX_LEN + encoded_key_len + 1); - if(!request){ - result = PEP_OUT_OF_MEMORY; - goto free_encoded_key; - } - - memcpy(request, HKP_REQ_PREFIX, HKP_REQ_PREFIX_LEN); - memcpy(request + HKP_REQ_PREFIX_LEN, encoded_key, encoded_key_len); - request[HKP_REQ_PREFIX_LEN + encoded_key_len] = '\0'; - - if(!stringlist_add(encoded_keys, request)){ - result = PEP_OUT_OF_MEMORY; - } - free(request); - -free_encoded_key: - curl_free(encoded_key); - -free_buffer: - free(buffer); - } - - return result; -} - PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern) { assert(!"pgp_send_key not implemented"); @@ -1950,3 +1827,11 @@ PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) { // a meaningful way, though there is space for it in the structs. return PEP_STATUS_OK; } + +PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite) { + if (suite == PEP_CIPHER_SUITE_DEFAULT) { + return PEP_STATUS_OK; + } else { + return PEP_CANNOT_CONFIG; + } +} diff --git a/src/pgp_netpgp.h b/src/pgp_netpgp.h index e8977ecb..e5f9ee38 100644 --- a/src/pgp_netpgp.h +++ b/src/pgp_netpgp.h @@ -109,10 +109,7 @@ PEP_STATUS pgp_find_private_keys( // Stub - just returns PEP_STATUS_OK, as netpgp isn't sufficient to do this. PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session); -PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite) { - if (suite == PEP_CIPHER_SUITE_DEFAULT) { - return PEP_STATUS_OK; - } else { - return PEP_CANNOT_CONFIG; - } -} +PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, + PEP_CIPHER_SUITE suite); + + From 9823de5be179d323dac7862d29e676e7c57f4eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Tue, 11 May 2021 12:35:05 +0100 Subject: [PATCH 03/15] z/OS support: Remove LD option We don't have Sequoia on z/OS --- test/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/Makefile b/test/Makefile index 8f78e2b4..a5b9fcda 100644 --- a/test/Makefile +++ b/test/Makefile @@ -89,8 +89,7 @@ all: $(CXX) -MM $(CXXFLAGS) $(CPPFLAGS) $< | sed -e 's,\($*\)\.o[ :]*,\1.o $@: ,g' > $@ $(TARGET): $(OBJS) - ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} -L${PREFIX}/lib -o $@ $^ -lpEpEngine -lgtest -lgtest_main -lsequoia_openpgp_ffi $(LDLIBS) - + ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} -L${PREFIX}/lib -o $@ $^ -lpEpEngine -lgtest -lgtest_main $(LDLIBS) test: all $(RM) -rf ./pEp_test_home/* From de2ef3057fc999858332c53fec3eefd6396e0b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Mon, 18 Jan 2021 19:34:35 +0000 Subject: [PATCH 04/15] z/OS support: Introducing OS/390 detection In case of z/OS being detected xlclang++ and xlclang should be used specifically. --- Makefile.conf | 60 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/Makefile.conf b/Makefile.conf index 6eb86720..be3518a0 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -50,7 +50,9 @@ PREFIX=$(HOME) PER_MACHINE_DIRECTORY=/usr/local/share/pEp # Filename of the pEpEngine library -ifeq ($(BUILD_FOR),Linux) +ifeq ($(BUILD_FOR),OS/390) + TARGET=libpEpEngine.so +else ifeq ($(BUILD_FOR),Linux) TARGET=libpEpEngine.so else ifeq ($(BUILD_FOR),Darwin) TARGET=libpEpEngine.dylib @@ -82,24 +84,27 @@ endif # Are we wiping this on purpose? LDLIBS= -######### C ######### -ifeq ($(BUILD_FOR),Linux) - CC=gcc +ifeq ($(BUILD_FOR),OS/390) + CC=xlclang -std=c99 +else ifeq ($(BUILD_FOR),Linux) + CC=gcc -std=c99 -pthread else ifeq ($(BUILD_FOR),Darwin) CC=clang endif -CFLAGS+=-std=c99 -pthread -CFLAGS+=-fPIC -fstrict-aliasing - -ifeq ($(BUILD_FOR),Linux) - CFLAGS+=-fdiagnostics-color=auto +ifeq ($(BUILD_FOR),OS/390) + CFLAGS+= -Wno-gnu-include-next -qnosearch -I$(HERE) -I. + CFLAGS+= -I/usr/lpp/java/J8.0_64/include -I/usr/include + CFLAGS+= -DZOS -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L -qlanglvl=NOLIBEXT +else ifeq ($(BUILD_FOR),Linux) + CFLAGS+=-fPIC -fstrict-aliasing -fdiagnostics-color=auto else ifeq ($(BUILD_FOR),Darwin) - CFLAGS+=-fcolor-diagnostics + CFLAGS+=-pthread -fPIC -fstrict-aliasing -fcolor-diagnostics endif # The flag -DNDEBUG will always be removed from CFLAGS for compiling tests. # The tests do not work properly, if compiled with -DNDEBUG +CFLAGS= ifeq ($(BUILD_FOR),Linux) ifdef WARN CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3 @@ -142,8 +147,10 @@ ifeq ($(BUILD_FOR),Linux) CXX=g++ CXXFLAGS+=-std=gnu++11 else ifeq ($(BUILD_FOR),Darwin) - CXX=clang - CXXFLAGS+=-std=c++11 + # clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX + CXX=clang -std=c++11 +else ifeq ($(BUILD_FOR),OS/390) + CXX=xlclang++ -std=c++11 endif CXXFLAGS+=-pthread @@ -151,7 +158,22 @@ CXXFLAGS+=-pthread # The flag -DNDEBUG will always be removed from CPPFLAGS for compiling tests. # # The tests do not work properly, if compiled with -DNDEBUG -ifeq ($(BUILD_FOR),Linux) +CXXFLAGS= +ifeq ($(BUILD_FOR),OS/390) + CXXFLAGS+= -fdiagnostics-color=auto -Wno-gnu-include-next + CXXFLAGS+= -qnosearch -I$(HERE) -I. -I../src -I../asn.1 $(ETPAN_INC) -I/usr/lpp/java/J8.0_64/include -I/usr/include + CXXFLAGS+= -DZOS -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L + ifdef WARN + CXXFLAGS+= + else + CXXFLAGS+= -w + endif + ifdef DEBUG + CXXFLAGS+= -g + else + CXXFLAGS+= -O3 -DNDEBUG + endif +else ifeq ($(BUILD_FOR),Linux) CXXFLAGS+=-fdiagnostics-color=auto -I../src -I../asn.1 $(ETPAN_INC) ifdef WARN CXXFLAGS+= @@ -165,7 +187,7 @@ ifeq ($(BUILD_FOR),Linux) CPPFLAGS+= -DNDEBUG endif else ifeq ($(BUILD_FOR),Darwin) - CXXFLAGS+=-fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC) + CXXFLAGS+=-pthread -fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC) ifdef WARN CXXFLAGS+= else @@ -254,6 +276,16 @@ SEQUOIA_INC= # EXTRA_MACROS=-DDEFAULT_KEYSERVER=\"default-server.org\" -DCRASHDUMP_DEFAULT_LINES=23 EXTRA_MACROS= +ifdef PER_USER_DIRECTORY + EXTRA_MACROS+= -DPER_USER_DIRECTORY=\"$(PER_USER_DIRECTORY)\" +endif + +ifdef PER_MACHINE_DIRECTORY + EXTRA_MACROS+= -DPER_MACHINE_DIRECTORY=\"$(PER_MACHINE_DIRECTORY)\" +endif + +CFLAGS+=$(EXTRA_MACROS) +CXXFLAGS+=$(EXTRA_MACROS) ######### Misc ######### # FIXME Maybe include these variables here. From 026cf763fb98552efcb0f51a90eee68b453f7084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Mon, 18 Jan 2021 21:07:23 +0000 Subject: [PATCH 05/15] z/OS support: Adding missing functions for z/OS Some functions are not provided properly by the libc provided by z/OS and need to be provided by the platform. --- src/platform_unix.c | 92 ++++++++++++++++++++++++++++++++++++++------- src/platform_unix.h | 24 ++++++++++-- 2 files changed, 98 insertions(+), 18 deletions(-) diff --git a/src/platform_unix.c b/src/platform_unix.c index 5b67774c..153bb030 100644 --- a/src/platform_unix.c +++ b/src/platform_unix.c @@ -4,7 +4,9 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt +#ifndef ZOS #define _POSIX_C_SOURCE 200809L +#endif #ifdef ANDROID #ifndef __LP64__ @@ -37,9 +39,55 @@ #endif #define SYSTEM_DB_FILENAME "system.db" -#ifdef ANDROID -#include +#ifndef strndup +char *strndup (const char *s, size_t n) +{ + char *result; + size_t len = strnlen (s, n); + + result = (char *) malloc (len + 1); + if (!result) + return 0; + result[len] = '\0'; + return (char *) memcpy (result, s, len); +} +#endif + +#ifndef strnlen +size_t strnlen (const char *s, size_t maxlen) +{ + size_t i; + + for (i = 0; i < maxlen; ++i) + if (s[i] == '\0') + break; + return i; +} +#endif + +#ifndef stpcpy +char *stpcpy(char *dst, const char *src) +{ + for (;; ++dst, ++src) { + *dst = *src; + if (*dst == 0) + break; + } + return dst; +} +#endif + +#ifndef alloca +#pragma linkage(__alloca,builtin) +void *__alloca(unsigned long x); +void *alloca(unsigned long x) +{ + return __alloca(x); +} +#endif + +#if defined(ANDROID) || defined(ZOS) /* FIXME : timegm will miss when linking for x86_64 on android, when supported */ #ifndef __LP64__ time_t timegm(struct tm* const t) { @@ -72,16 +120,6 @@ char *stpncpy(char *dst, const char *src, size_t n) return (dst); } -char *stpcpy(char *dst, const char *src) -{ - for (;; ++dst, ++src) { - *dst = *src; - if (*dst == 0) - break; - } - return dst; -} - /* long int random(void) { @@ -125,8 +163,36 @@ const char *android_system_db(void) } return buffer; } +#endif + +#ifdef ZOS +char * e2as(const char * str) +{ + char *ret = (char *)malloc(strlen(str)); + strcpy(ret, str); + __e2a_s(ret); + return ret; +} + +char * as2e(const char * str) +{ + char *ret = (char *)malloc(strlen(str)); + strcpy(ret, str); + __a2e_s(ret); + return ret; +} + +void uuid_generate_random(pEpUUID out) +{ +} + +void uuid_unparse_upper(pEpUUID uu, uuid_string_t out) +{ +} +#endif +#ifdef ANDROID void uuid_generate_random(pEpUUID out) { uuid_t *uuid; @@ -147,7 +213,6 @@ void uuid_generate_random(pEpUUID out) } } - void uuid_unparse_upper(pEpUUID uu, uuid_string_t out) { uuid_t *uuid; @@ -171,7 +236,6 @@ void uuid_unparse_upper(pEpUUID uu, uuid_string_t out) uuid_destroy(uuid); } } - #endif #if !defined(BSD) && !defined(__APPLE__) diff --git a/src/platform_unix.h b/src/platform_unix.h index 0bf9a4fc..a6932a52 100644 --- a/src/platform_unix.h +++ b/src/platform_unix.h @@ -7,7 +7,7 @@ #ifndef PLATFORM_UNIX_H #define PLATFORM_UNIX_H -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(ZOS) #define _POSIX_C_SOURCE 200809L #endif @@ -15,13 +15,30 @@ #include #include #include +#ifndef ZOS #include +#endif #include -#ifndef ANDROID +#ifdef ZOS +char * e2as(const char * str); +char * as2e(const char * str); +#endif + +#if defined(ANDROID) || defined(ZOS) +typedef unsigned char uuid_t[16]; +#else #include #endif +#ifndef MIN +#define MIN(A, B) ((A)>(B) ? (B) : (A)) +#endif + +#ifndef MAX +#define MAX(A, B) ((A)>(B) ? (A) : (B)) +#endif + // pEp files and directories #ifndef PER_USER_DIRECTORY @@ -36,7 +53,6 @@ #endif #endif - #ifdef __cplusplus extern "C" { #endif @@ -144,7 +160,7 @@ typedef char uuid_string_t[37]; // on *nix, uuid_t is an array and already implements pointer semantics #define UUID uuid_t -#ifdef ANDROID +#if defined(ANDROID) || defined(ZOS) typedef char pEpUUID[16]; void uuid_generate_random(pEpUUID out); void uuid_unparse_upper(pEpUUID uu, uuid_string_t out); From b1a6e790df72293bf61970ddf8a562282c98df2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Mon, 1 Feb 2021 00:31:07 +0000 Subject: [PATCH 06/15] z/OS: Support Well... It compiles now with the master branch. It's time for a rebase. --- Makefile.conf | 37 +++++++++++++++++++++++++++---------- src/Makefile | 30 ++++++++++++++++++------------ src/etpan_mime.c | 7 ++++++- src/pgp_netpgp_internal.h | 11 ----------- src/stdlib.h | 8 ++++++++ src/string.h | 10 ++++++++++ src/timestamp.c | 8 ++++++++ test/Makefile | 33 +++++++++++++++++++++++++++++---- 8 files changed, 106 insertions(+), 38 deletions(-) delete mode 100644 src/pgp_netpgp_internal.h create mode 100644 src/stdlib.h create mode 100644 src/string.h diff --git a/Makefile.conf b/Makefile.conf index be3518a0..0627c21c 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -32,7 +32,10 @@ BUILD_FOR=$(BUILD_ON) # Cross-compiling is currently not supported. # Maybe you can hack something with `local.conf`. ifneq ($(BUILD_ON),$(BUILD_FOR)) - $(error I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).) + ifeq ($(BUILD_FOR),OS/390) + $(warning Generating sources for z/OS) + endif + ONLY_GENERATE=true endif # Installation path prefix for libraries and binaries, except for system.db @@ -85,7 +88,7 @@ endif LDLIBS= ifeq ($(BUILD_FOR),OS/390) - CC=xlclang -std=c99 + CC=xlclang else ifeq ($(BUILD_FOR),Linux) CC=gcc -std=c99 -pthread else ifeq ($(BUILD_FOR),Darwin) @@ -93,7 +96,7 @@ else ifeq ($(BUILD_FOR),Darwin) endif ifeq ($(BUILD_FOR),OS/390) - CFLAGS+= -Wno-gnu-include-next -qnosearch -I$(HERE) -I. + CFLAGS= -Wno-gnu-include-next -qnosearch -I$(HERE) -I. CFLAGS+= -I/usr/lpp/java/J8.0_64/include -I/usr/include CFLAGS+= -DZOS -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L -qlanglvl=NOLIBEXT else ifeq ($(BUILD_FOR),Linux) @@ -104,8 +107,18 @@ endif # The flag -DNDEBUG will always be removed from CFLAGS for compiling tests. # The tests do not work properly, if compiled with -DNDEBUG -CFLAGS= -ifeq ($(BUILD_FOR),Linux) +ifeq ($(BUILD_FOR),OS/390) + ifdef WARN + CFLAGS+= -Wall -pedantic + else + CFLAGS+= -w + endif + ifdef DEBUG + CFLAGS+= -g -DDEBUG_ERRORSTACK + else + CFLAGS+= -O3 -DNDEBUG + endif +else ifeq ($(BUILD_FOR),Linux) ifdef WARN CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3 else @@ -158,7 +171,6 @@ CXXFLAGS+=-pthread # The flag -DNDEBUG will always be removed from CPPFLAGS for compiling tests. # # The tests do not work properly, if compiled with -DNDEBUG -CXXFLAGS= ifeq ($(BUILD_FOR),OS/390) CXXFLAGS+= -fdiagnostics-color=auto -Wno-gnu-include-next CXXFLAGS+= -qnosearch -I$(HERE) -I. -I../src -I../asn.1 $(ETPAN_INC) -I/usr/lpp/java/J8.0_64/include -I/usr/include @@ -203,9 +215,10 @@ endif ######### C and C++ ######### -ifeq ($(BUILD_FOR),Darwin) - CPPFLAGS+=-D_DARWIN_C_SOURCE - LDLIBS+=-liconv +ifeq ($(BUILD_FOR),OS/390) + CPPFLAGS=-W "l,xplink,dll" -W "c,float(ieee),xplink,dll,exportall" +else ifeq ($(BUILD_FOR),Darwin) + CPPFLAGS=-D_DARWIN_C_SOURCE else LDLIBS+=-luuid endif @@ -260,7 +273,11 @@ ETPAN_INC= ######### OpenPGP ######### # Selects OpenPGP implementation. must be `SEQUOIA` -OPENPGP?=SEQUOIA +ifeq ($(BUILD_FOR),OS/390) +OPENPGP=NETPGP +else +OPENPGP=SEQUOIA +endif # Sequoia-specific variables SEQUOIA_CFLAGS+= diff --git a/src/Makefile b/src/Makefile index a5b5568d..1ce2413b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,22 +5,21 @@ include ../Makefile.conf -ifdef PER_USER_DIRECTORY - EXTRA_MACROS+= -DPER_USER_DIRECTORY=$(PER_USER_DIRECTORY) +CFLAGS+= $(ETPAN_INC) $(PEP_MIME_INC) -I../asn.1 $(EXTRA_MACROS) +LDFLAGS+= $(ETPAN_LIB) $(PEP_MIME_LIB) -L../asn.1 +ifneq ($(BUILD_ON),OS/390) +LDFLAGS+= -shared endif - -ifdef PER_MACHINE_DIRECTORY - EXTRA_MACROS+= -DPER_MACHINE_DIRECTORY=\"$(PER_MACHINE_DIRECTORY)\" -endif - +LDLIBS+= -lc -lasn1 NO_SOURCE= ifndef PEP_MIME - CFLAGS+= $(ETPAN_INC) - LDFLAGS+= $(ETPAN_LIB) +ifeq ($(BUILD_ON),OS/390) + LDLIBS+= -letpan-no-mt +else LDLIBS+= -letpan +endif else - LDFLAGS+= -L../pEpMIME -shared LDLIBS+= -lpEpMIME NO_SOURCE+= etpan_mime.c endif @@ -31,7 +30,11 @@ CPPFLAGS+= -DSQLITE_THREADSAFE=1 LDFLAGS+= -L../asn.1 -shared LDLIBS+= -lc -lasn1 -ifeq ($(BUILD_ON),Darwin) + +ifeq ($(BUILD_ON),OS/390) + OPENPGP=ZOS + SQLITE3_FROM_OS=1 +else ifeq ($(BUILD_ON),Darwin) ifeq ($(BUILD_FOR),Darwin) LDLIBS+= -lz -liconv -mmacosx-version-min=10.10 else @@ -73,6 +76,9 @@ endif ALL_SOURCE=$(filter-out $(NO_SOURCE),$(wildcard *.c)) DEPENDS=$(subst .c,.d,$(ALL_SOURCE)) ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE)) +ifeq ($(BUILD_ON),OS/390) + ALL_OBJECTS+=/usr/lpp/java/J8.0_64/bin/classic/libjvm.x +endif all: $(TARGET) @@ -90,7 +96,7 @@ ifneq ($(MAKECMDGOALS),clean) endif $(TARGET): libpEpEngine.a - $(CC) $(CFLAGS) $(CPPFLAGS) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@ + $(CC) -o $@ $(CPPFLAGS) $(LDFLAGS) $(CFLAGS) $(ALL_OBJECTS) $(LDLIBS) .PHONY: objects clean install_headers install uninstall beinstall diff --git a/src/etpan_mime.c b/src/etpan_mime.c index 19b97ac9..b1e81e3e 100644 --- a/src/etpan_mime.c +++ b/src/etpan_mime.c @@ -566,7 +566,9 @@ struct mailimf_date_time * timestamp_to_etpantime(const timestamp *ts) result->dt_day = ts->tm_mday; result->dt_month = ts->tm_mon + 1; result->dt_year = ts->tm_year + 1900; +#ifndef ZOS result->dt_zone = (int) (ts->tm_gmtoff / 36L); +#endif return result; } @@ -585,13 +587,16 @@ timestamp * etpantime_to_timestamp(const struct mailimf_date_time *et) result->tm_mday = et->dt_day; result->tm_mon = et->dt_month - 1; result->tm_year = et->dt_year - 1900; +#ifndef ZOS result->tm_gmtoff = 36L * (long) et->dt_zone; +#endif // Normalize to UTC and then forget the offset. time_t t = timegm_with_gmtoff(result); gmtime_r(&t, result); +#ifndef ZOS result->tm_gmtoff = 0; - +#endif return result; } diff --git a/src/pgp_netpgp_internal.h b/src/pgp_netpgp_internal.h deleted file mode 100644 index afe8883e..00000000 --- a/src/pgp_netpgp_internal.h +++ /dev/null @@ -1,11 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#pragma once - -#include -#include - -typedef struct _pEpNetPGPSession { - pthread_mutex_t curl_mutex; -} pEpNetPGPSession; diff --git a/src/stdlib.h b/src/stdlib.h new file mode 100644 index 00000000..5370b1c7 --- /dev/null +++ b/src/stdlib.h @@ -0,0 +1,8 @@ +#ifdef ZOS +#ifdef __cplusplus +#undef _EXT +#define _NO_EXT +#endif +#endif + +#include_next diff --git a/src/string.h b/src/string.h new file mode 100644 index 00000000..ac2323f5 --- /dev/null +++ b/src/string.h @@ -0,0 +1,10 @@ +#ifdef ZOS +#ifndef __cplusplus +char * stpcpy (char *dst, const char *src); +char * strndup (const char *s, size_t n); +size_t strnlen (const char *s, size_t maxlen); +#endif +#include +#endif + +#include_next diff --git a/src/timestamp.c b/src/timestamp.c index 72702ac8..950a462b 100644 --- a/src/timestamp.c +++ b/src/timestamp.c @@ -22,13 +22,21 @@ DYNAMIC_API time_t timegm_with_gmtoff(const timestamp* ts) if (!_ts) return -1; +#if defined(ZOS) + const time_t raw_time = mktime(_ts); +#else const time_t raw_time = timegm(_ts); +#endif if(raw_time==-1) return -1; free_timestamp(_ts); +#if defined(ZOS) + return raw_time; +#else return raw_time - ts->tm_gmtoff; +#endif } diff --git a/test/Makefile b/test/Makefile index a5b9fcda..0918b8cd 100644 --- a/test/Makefile +++ b/test/Makefile @@ -16,6 +16,10 @@ SRCS:=$(wildcard src/*.cc) $(wildcard src/*/*.cc) OBJS:=$(addsuffix .o,$(basename $(SRCS))) DEPS:=$(OBJS:.o=.d) +ifeq ($(BUILD_ON),OS/390) + OBJS+=../src/libpEpEngine.x +endif + LDFLAGS+= -L../asn.1 -L../src $(ETPAN_LIB) $(GTEST_LDFLAGS) TARGET:=EngineTests @@ -34,7 +38,12 @@ else LDLIBS+= -letpan endif -LDLIBS+= -lpEpEngine -lstdc++ -lasn1 +ifeq ($(BUILD_ON),OS/390) + LDLIBS+= -letpan-no-mt +else + LDLIBS+= -letpan -lpEpEngine -lstdc++ +endif +LDLIBS+= -lasn1 ifeq ($(BUILD_FOR),Linux) LDLIBS+= -luuid @@ -52,8 +61,19 @@ ifdef SQLITE3_FROM_OS LDLIBS+= -lsqlite3 endif -CXXFLAGS:=$(filter-out -DNDEBUG,$(CXXFLAGS)) -I$(GTEST_INC_DIR) -CPPFLAGS:=$(filter-out -DNDEBUG,$(CPPFLAGS)) +ifeq ($(OPENPGP),GPG) + #LDLIBS+= -lgpgme +else ifeq ($(OPENPGP),NETPGP) + LDLIBS+= -lnetpgp + ifeq ($(BUILD_FOR),Linux) + LDLIBS+= -ltre + endif +endif + +CXXFLAGS:=$(filter-out -DNDEBUG,$(CXXFLAGS)) + +# FIXME Possibly missing incdirs: ASN1C_INC +CXXFLAGS+= -I$(GTEST_INC_DIR) -I./src -I../sync $(INC_FLAGS) -Wno-deprecated -Wno-unused-variable CXXFLAGS+= -I./src -I../src -I ../asn.1 -I../sync $(INC_FLAGS) -Wno-deprecated -Wno-unused-variable @@ -88,8 +108,13 @@ all: %.d: %.cc $(CXX) -MM $(CXXFLAGS) $(CPPFLAGS) $< | sed -e 's,\($*\)\.o[ :]*,\1.o $@: ,g' > $@ +LDLIBS+=-lgtest -lgtest_main +ifneq ($(BUILD_ON),OS/390) + LDLIBS+=-lsequoia_openpgp_ffi +endif + $(TARGET): $(OBJS) - ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} -L${PREFIX}/lib -o $@ $^ -lpEpEngine -lgtest -lgtest_main $(LDLIBS) + ${CXX} ${LDFLAGS} -L${PREFIX}/lib -o $@ $^ $(LDLIBS) test: all $(RM) -rf ./pEp_test_home/* From 15c7ec7b735ad969c3f8c4e49180c316c3a2bf24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Fri, 4 Jun 2021 18:01:56 +0100 Subject: [PATCH 07/15] z/OS support: fix isspace issue New line apparantly isn't considered a space on z/OS... Thanks IBM -.- --- src/sqlite3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c index db5678f7..ff9b0068 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -18520,7 +18520,7 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); # define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) #else # define sqlite3Toupper(x) toupper((unsigned char)(x)) -# define sqlite3Isspace(x) isspace((unsigned char)(x)) +# define sqlite3Isspace(x) (isspace((unsigned char)(x))||(x==0x15)) # define sqlite3Isalnum(x) isalnum((unsigned char)(x)) # define sqlite3Isalpha(x) isalpha((unsigned char)(x)) # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) @@ -151299,7 +151299,7 @@ static const unsigned char aiClass[] = { #ifdef SQLITE_EBCDIC /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ /* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, -/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 1x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10, From a430fdd64471a01bb82d923ad2eb495924d8c5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Sat, 5 Jun 2021 04:12:50 +0100 Subject: [PATCH 08/15] z/OS: support fix linking --- test/Makefile | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/test/Makefile b/test/Makefile index 0918b8cd..6bfac834 100644 --- a/test/Makefile +++ b/test/Makefile @@ -17,9 +17,14 @@ OBJS:=$(addsuffix .o,$(basename $(SRCS))) DEPS:=$(OBJS:.o=.d) ifeq ($(BUILD_ON),OS/390) - OBJS+=../src/libpEpEngine.x + OBJS+=../src/libpEpEngine.a + OBJS+=/usr/lib/GSKCMS64.x + OBJS+=/usr/lib/CSNPCA64.x + OBJS+=/user/lev/lib/libetpan-no-mt.a endif +#endif + LDFLAGS+= -L../asn.1 -L../src $(ETPAN_LIB) $(GTEST_LDFLAGS) TARGET:=EngineTests @@ -35,14 +40,11 @@ CPPFLAGS+= -DGTEST_SUITE_SYM=$(GTEST_SUITE_SYM) ifdef PEP_MIME LDLIBS+= -lpEpMIME else - LDLIBS+= -letpan + ifneq ($(BUILD_ON),OS/390) + LDLIBS+= -letpan -lpEpEngine -lstdc++ + endif endif -ifeq ($(BUILD_ON),OS/390) - LDLIBS+= -letpan-no-mt -else - LDLIBS+= -letpan -lpEpEngine -lstdc++ -endif LDLIBS+= -lasn1 ifeq ($(BUILD_FOR),Linux) @@ -109,7 +111,9 @@ all: $(CXX) -MM $(CXXFLAGS) $(CPPFLAGS) $< | sed -e 's,\($*\)\.o[ :]*,\1.o $@: ,g' > $@ LDLIBS+=-lgtest -lgtest_main -ifneq ($(BUILD_ON),OS/390) +ifeq ($(BUILD_ON),OS/390) + LDLIBS+=-lzz +else LDLIBS+=-lsequoia_openpgp_ffi endif From c48f1ad010162ed9a5316dd7dc5f837a5172441d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Sat, 5 Jun 2021 04:13:53 +0100 Subject: [PATCH 09/15] z/OS support: Make env Changing CFLAGS --- Makefile.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.conf b/Makefile.conf index 0627c21c..c1fadb4e 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -97,7 +97,7 @@ endif ifeq ($(BUILD_FOR),OS/390) CFLAGS= -Wno-gnu-include-next -qnosearch -I$(HERE) -I. - CFLAGS+= -I/usr/lpp/java/J8.0_64/include -I/usr/include + CFLAGS+= -I/usr/include CFLAGS+= -DZOS -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L -qlanglvl=NOLIBEXT else ifeq ($(BUILD_FOR),Linux) CFLAGS+=-fPIC -fstrict-aliasing -fdiagnostics-color=auto @@ -166,7 +166,9 @@ else ifeq ($(BUILD_FOR),OS/390) CXX=xlclang++ -std=c++11 endif +ifneq ($(BUILD_FOR),OS/390) CXXFLAGS+=-pthread +endif # The flag -DNDEBUG will always be removed from CPPFLAGS for compiling tests. # @@ -362,7 +364,9 @@ ifndef PEP_MIME_SRC $(error "Compiling with the PEP_MIME option set requires the value of PEP_MIME_SRC to be set to the source directory for libpEpMIME") else CPPFLAGS+=-DPEP_BUILTIN_MIME +ifneq ($(BUILD_ON),OS/390) LDLIBS+=-lstdc++ +endif ETPAN_LIB= ETPAN_INC= endif From d1d2f5ca33bfbc8806cd3e5d353fd42c2f607322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Sat, 5 Jun 2021 04:15:16 +0100 Subject: [PATCH 10/15] z/OS support: No threads for now Comment out mutexes for now and introduce a function to work around the encoding issue when on main frames --- src/pgp_netpgp.c | 252 +++++++++++++++++++++++++---------------------- 1 file changed, 133 insertions(+), 119 deletions(-) diff --git a/src/pgp_netpgp.c b/src/pgp_netpgp.c index 537ac2bb..de42f042 100644 --- a/src/pgp_netpgp.c +++ b/src/pgp_netpgp.c @@ -1,6 +1,16 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define NETPGP_EBCDIC 1 +#else +# define NETPGP_ASCII 1 +#endif + #include "pEp_internal.h" #include "pgp_netpgp.h" @@ -18,6 +28,17 @@ #include #include +#if defined(NETPGP_EBCDIC) +#include +#endif + +inline char A(char c) +{ +#if defined(NETPGP_EBCDIC) + __e2a_l(&c,1); +#endif + return c; +} static netpgp_t netpgp; static pthread_mutex_t netpgp_mutex; @@ -27,13 +48,13 @@ static PEP_STATUS init_netpgp() PEP_STATUS status = PEP_STATUS_OK; const char *home = NULL; - if(pthread_mutex_init(&netpgp_mutex, NULL)){ - return PEP_OUT_OF_MEMORY; - } + //if(pthread_mutex_init(&netpgp_mutex, NULL)){ + // return PEP_OUT_OF_MEMORY; + //} - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if (strcmp(setlocale(LC_ALL, NULL), "C") == 0) setlocale(LC_ALL, ""); @@ -72,20 +93,20 @@ static PEP_STATUS init_netpgp() // netpgp_set_debug("packet-parse.c"); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return status; } static void release_netpgp() { - if(pthread_mutex_lock(&netpgp_mutex)){ - return; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return; + //} netpgp_end(&netpgp); memset(&netpgp, 0x0, sizeof(netpgp_t)); - pthread_mutex_destroy(&netpgp_mutex); + //pthread_mutex_destroy(&netpgp_mutex); return; } @@ -134,7 +155,7 @@ static unsigned fpr_to_str (char **str, const uint8_t *fpr, size_t length) { unsigned i; - int n; + int n; /* 4 hexes per short + null */ *str = malloc((length / 2) * 4 + 1); @@ -169,12 +190,12 @@ str_to_fpr (const char *str, uint8_t *fpr, size_t *length) for (i = 0; i < 2; i++) { if (i > 0) *byte = *byte << 4; - if (*str >= 'a' && *str <= 'f') - *byte += 10 + *str - 'a'; - else if (*str >= 'A' && *str <= 'F') + if (A(*str) >= A('a') && A(*str) <= A('f')) + *byte += 10 + A(*str) - A('a'); + else if (A(*str) >= A('A') && A(*str) <= A('F')) *byte += 10 + *str - 'A'; else if (*str >= '0' && *str <= '9') - *byte += *str - '0'; + *byte += A(*str) - '0'; else return 0; str++; @@ -226,7 +247,7 @@ static PEP_STATUS _validation_results( unsigned c = 0; for (unsigned n = 0; n < vresult->validc; ++n) { unsigned from = 0; - const pgp_key_t *signer; + const pgp_key_t *signer; char *fprstr = NULL; const uint8_t *keyid = vresult->valid_sigs[n].signer_id; @@ -303,9 +324,9 @@ PEP_STATUS pgp_decrypt_and_verify( if(!session || !ctext || !csize || !ptext || !psize || !keylist) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} *ptext = NULL; *psize = 0; @@ -360,7 +381,7 @@ PEP_STATUS pgp_decrypt_and_verify( stringlist_t *k = _keylist; for (unsigned n = 0; n < recipients_count; ++n) { unsigned from = 0; - const pgp_key_t *rcpt; + const pgp_key_t *rcpt; char *fprstr = NULL; key_id_t *keyid = &recipients_key_ids[n]; @@ -415,7 +436,7 @@ free_pgp: unlock_netpgp: free(recipients_key_ids); - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -443,9 +464,9 @@ PEP_STATUS pgp_verify_text( if(!session || !text || !size || !signature || !sig_size || !keylist) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} *keylist = NULL; @@ -505,7 +526,7 @@ free_pgp: pgp_validate_result_free(vresult); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -535,9 +556,9 @@ static PEP_STATUS _encrypt_and_sign( if(!session || !ptext || !psize || !ctext || !csize || !keylist) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} *ctext = NULL; *csize = 0; @@ -671,7 +692,7 @@ free_signedmem : free_rcpts : pgp_keyring_free(rcpts); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -686,13 +707,13 @@ PEP_STATUS pgp_sign_only( pgp_seckey_t *seckey = NULL; pgp_memory_t *signedmem = NULL; pgp_memory_t *text = NULL; - pgp_output_t *output; + pgp_output_t *output; const char *hashalg; pgp_keyring_t *snrs; - pgp_create_sig_t *sig; - uint8_t keyid[PGP_KEY_ID_SIZE]; + pgp_create_sig_t *sig; + uint8_t keyid[PGP_KEY_ID_SIZE]; PEP_STATUS result; @@ -706,9 +727,9 @@ PEP_STATUS pgp_sign_only( if(!session || !ptext || !psize || !stext || !ssize || !fpr || !fpr[0]) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} *stext = NULL; *ssize = 0; @@ -763,29 +784,29 @@ PEP_STATUS pgp_sign_only( const char *_stext; size_t _ssize; - text = pgp_memory_new(); + text = pgp_memory_new(); pgp_memory_add(text, (const uint8_t*)ptext, psize); pgp_setup_memory_write(&output, &signedmem, psize); - pgp_writer_push_armor_msg(output); + pgp_writer_push_armor_msg(output); pgp_hash_alg_t hash_alg = pgp_str_to_hash_alg(hashalg); - sig = pgp_create_sig_new(); - pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY); + sig = pgp_create_sig_new(); + pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY); - pgp_sig_add_data(sig, pgp_mem_data(text), pgp_mem_len(text)); - pgp_memory_free(text); + pgp_sig_add_data(sig, pgp_mem_data(text), pgp_mem_len(text)); + pgp_memory_free(text); - pgp_add_creation_time(sig, time(NULL)); - pgp_add_sig_expiration_time(sig, 0); - pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg); - pgp_add_issuer_keyid(sig, keyid); - pgp_end_hashed_subpkts(sig); + pgp_add_creation_time(sig, time(NULL)); + pgp_add_sig_expiration_time(sig, 0); + pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg); + pgp_add_issuer_keyid(sig, keyid); + pgp_end_hashed_subpkts(sig); pgp_write_sig(output, sig, &seckey->pubkey, seckey); - pgp_writer_close(output); - pgp_create_sig_delete(sig); + pgp_writer_close(output); + pgp_create_sig_delete(sig); if (!signedmem) { result = PEP_UNENCRYPTED; @@ -815,7 +836,7 @@ free_signedmem : free_snrs : pgp_keyring_free(snrs); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -848,8 +869,8 @@ PEP_STATUS pgp_generate_keypair( PEP_SESSION session, pEp_identity *identity ) { - pgp_key_t newseckey; - pgp_key_t *newpubkey; + pgp_key_t newseckey; + pgp_key_t *newpubkey; PEP_STATUS result; char newid[1024]; @@ -866,9 +887,9 @@ PEP_STATUS pgp_generate_keypair( !identity->address || identity->fpr || !identity->username) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if(snprintf(newid, sizeof(newid), "%s <%s>", identity->username, identity->address) >= sizeof(newid)){ @@ -955,7 +976,7 @@ delete_pubkey: free_seckey: pgp_key_free(&newseckey); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -973,9 +994,9 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) if (!session || !fprstr) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if (str_to_fpr(fprstr, fpr, &length)) { unsigned insec = pgp_deletekeybyfpr(netpgp.io, @@ -1005,7 +1026,7 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) } unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1033,9 +1054,9 @@ PEP_STATUS pgp_import_keydata( if(!session || !key_data) return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ + /*if(pthread_mutex_lock(&netpgp_mutex)){ return PEP_UNKNOWN_ERROR; - } + }*/ mem = pgp_memory_new(); if (mem == NULL) { @@ -1044,26 +1065,22 @@ PEP_STATUS pgp_import_keydata( } pgp_memory_add(mem, (const uint8_t*)key_data, size); - if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring, - _armoured(key_data, size, ARMOR_KEY_HEAD), - mem) == 0){ + if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring, _armoured(key_data, size, ARMOR_KEY_HEAD), mem) == 0){ result = PEP_ILLEGAL_VALUE; } pgp_memory_free(mem); // save rings - if (netpgp_save_pubring(&netpgp) && - netpgp_save_secring(&netpgp)) + if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp)) { - // we never really know if a key was imported. MEH. - result = PEP_KEY_IMPORT_STATUS_UNKNOWN; - }else{ + result = PEP_KEY_IMPORTED; + } else { result = PEP_UNKNOWN_ERROR; } unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); +// pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1075,9 +1092,9 @@ static PEP_STATUS _export_keydata( ) { PEP_STATUS result; - pgp_output_t *output; + pgp_output_t *output; pgp_memory_t *mem; - pgp_setup_memory_write(&output, &mem, 128); + pgp_setup_memory_write(&output, &mem, 128); if (mem == NULL || output == NULL) { return PEP_ILLEGAL_VALUE; @@ -1105,7 +1122,7 @@ static PEP_STATUS _export_keydata( return PEP_STATUS_OK; free_mem : - pgp_teardown_memory_write(output, mem); + pgp_teardown_memory_write(output, mem); return result; } @@ -1134,19 +1151,16 @@ PEP_STATUS pgp_export_keydata( else srcring = netpgp.pubring; - if (!session || !fprstr || !key_data || !size) - return PEP_ILLEGAL_VALUE; + //if (!session || !fprstr || !key_data || !size) + // return PEP_ILLEGAL_VALUE; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if (str_to_fpr(fprstr, fpr, &fprlen)) { unsigned from = 0; - - if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring, - fpr, fprlen, &from, - NULL,0,0)) == NULL) { + if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring, fpr, fprlen, &from, NULL,0,0)) == NULL) { result = PEP_KEY_NOT_FOUND; goto unlock_netpgp; } @@ -1165,7 +1179,7 @@ PEP_STATUS pgp_export_keydata( } unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1237,7 +1251,7 @@ static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, while((key = (pgp_key_t *)pgp_getnextkeybyname( netpgp.io, keyring, - (const char *)pattern, + (const char *)pattern, &from)) != NULL) { result = cb(cb_arg, key); @@ -1342,10 +1356,10 @@ PEP_STATUS pgp_find_keys( return PEP_ILLEGAL_VALUE; } - if (pthread_mutex_lock(&netpgp_mutex)) - { - return PEP_UNKNOWN_ERROR; - } + //if (pthread_mutex_lock(&netpgp_mutex)) + //{ + // return PEP_UNKNOWN_ERROR; + //} *keylist = NULL; _keylist = new_stringlist(NULL); @@ -1367,7 +1381,7 @@ PEP_STATUS pgp_find_keys( free_stringlist(_keylist); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1405,9 +1419,9 @@ PEP_STATUS pgp_get_key_rating( *comm_type = PEP_ct_unknown; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if (!str_to_fpr(fprstr, fpr, &length)) { status = PEP_ILLEGAL_VALUE; @@ -1426,7 +1440,7 @@ PEP_STATUS pgp_get_key_rating( } switch(pgp_key_get_rating(key)){ - case PGP_VALID: + case PGP_VALID: *comm_type = PEP_ct_OpenPGP_unconfirmed; break; case PGP_WEAK: @@ -1435,10 +1449,10 @@ PEP_STATUS pgp_get_key_rating( case PGP_TOOSHORT: *comm_type = PEP_ct_key_too_short; break; - case PGP_INVALID: + case PGP_INVALID: *comm_type = PEP_ct_key_b0rken; break; - case PGP_EXPIRED: + case PGP_EXPIRED: *comm_type = PEP_ct_key_expired; break; case PGP_REVOKED: @@ -1449,7 +1463,7 @@ PEP_STATUS pgp_get_key_rating( } unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1491,9 +1505,9 @@ PEP_STATUS pgp_renew_key( duration = 365*24*3600; } - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if (!str_to_fpr(fprstr, fpr, &length)) { @@ -1549,7 +1563,7 @@ PEP_STATUS pgp_renew_key( } unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1572,9 +1586,9 @@ PEP_STATUS pgp_revoke_key( if (!session || !fprstr) return PEP_UNKNOWN_ERROR; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} // FIXME : deduplicate that code w/ renew if (!str_to_fpr(fprstr, fpr, &length)) { @@ -1612,7 +1626,7 @@ PEP_STATUS pgp_revoke_key( reason); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1699,9 +1713,9 @@ PEP_STATUS pgp_key_created( *created = 0; - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } + //if(pthread_mutex_lock(&netpgp_mutex)){ + // return PEP_UNKNOWN_ERROR; + //} if (!str_to_fpr(fprstr, fpr, &length)) { status = PEP_ILLEGAL_VALUE; @@ -1726,7 +1740,7 @@ PEP_STATUS pgp_key_created( unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1739,10 +1753,10 @@ PEP_STATUS pgp_list_keyinfo( if (!session || !keyinfo_list) return PEP_UNKNOWN_ERROR; - if (pthread_mutex_lock(&netpgp_mutex)) - { - return PEP_UNKNOWN_ERROR; - } + //if (pthread_mutex_lock(&netpgp_mutex)) + //{ + // return PEP_UNKNOWN_ERROR; + //} // Unused: // pgp_key_t *key; @@ -1755,7 +1769,7 @@ PEP_STATUS pgp_list_keyinfo( if (!keyinfo_list) result = PEP_KEY_NOT_FOUND; - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1776,10 +1790,10 @@ PEP_STATUS pgp_find_private_keys( return PEP_ILLEGAL_VALUE; } - if (pthread_mutex_lock(&netpgp_mutex)) - { - return PEP_UNKNOWN_ERROR; - } + //if (pthread_mutex_lock(&netpgp_mutex)) + //{ + // return PEP_UNKNOWN_ERROR; + //} *keylist = NULL; _keylist = new_stringlist(NULL); @@ -1801,7 +1815,7 @@ PEP_STATUS pgp_find_private_keys( free_stringlist(_keylist); unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); + //pthread_mutex_unlock(&netpgp_mutex); return result; } From c88bd9c438dc4734718a8aaea6ddc0b9e3845818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Sat, 5 Jun 2021 04:16:26 +0100 Subject: [PATCH 11/15] z/OS support: Cleaning up Getting rid of some redundancies --- src/Makefile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index 1ce2413b..476a10ca 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,7 +10,6 @@ LDFLAGS+= $(ETPAN_LIB) $(PEP_MIME_LIB) -L../asn.1 ifneq ($(BUILD_ON),OS/390) LDFLAGS+= -shared endif -LDLIBS+= -lc -lasn1 NO_SOURCE= ifndef PEP_MIME @@ -27,13 +26,16 @@ endif CFLAGS+= -I../asn.1 $(EXTRA_MACROS) CPPFLAGS+= -DSQLITE_THREADSAFE=1 -LDFLAGS+= -L../asn.1 -shared -LDLIBS+= -lc -lasn1 - +LDFLAGS+= -L../asn.1 +ifneq ($(BUILD_ON),OS/390) +LDFLAGS+= -shared +LDLIBS+= -lc +endif +LDLIBS+= -lasn1 ifeq ($(BUILD_ON),OS/390) - OPENPGP=ZOS - SQLITE3_FROM_OS=1 + OPENPGP=NETPGP + LDLIBS+= -lzz else ifeq ($(BUILD_ON),Darwin) ifeq ($(BUILD_FOR),Darwin) LDLIBS+= -lz -liconv -mmacosx-version-min=10.10 @@ -77,7 +79,8 @@ ALL_SOURCE=$(filter-out $(NO_SOURCE),$(wildcard *.c)) DEPENDS=$(subst .c,.d,$(ALL_SOURCE)) ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE)) ifeq ($(BUILD_ON),OS/390) - ALL_OBJECTS+=/usr/lpp/java/J8.0_64/bin/classic/libjvm.x + ALL_OBJECTS+=/usr/lib/GSKCMS64.x + ALL_OBJECTS+=/usr/lib/CSNPCA64.x endif all: $(TARGET) From dfb08ebcdac540ffc9157fab701716392ccc5b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Sat, 5 Jun 2021 04:17:48 +0100 Subject: [PATCH 12/15] z/OS support: Fix compilation errors This _POSIX_C_SOURCE version isn't valid on z/OS --- src/pEp_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pEp_internal.h b/src/pEp_internal.h index cd7236b4..f621f862 100644 --- a/src/pEp_internal.h +++ b/src/pEp_internal.h @@ -66,7 +66,9 @@ #define LOCAL_DB windoze_local_db() #define SYSTEM_DB windoze_system_db() #else // UNIX +#ifndef ZOS #define _POSIX_C_SOURCE 200809L +#endif #include #ifdef NDEBUG #define LOCAL_DB unix_local_db() @@ -106,8 +108,6 @@ #if defined(USE_SEQUOIA) #include "pgp_sequoia_internal.h" -#elif defined(USE_NETPGP) -#include "pgp_netpgp_internal.h" #endif #include "../asn.1/Distribution.h" From 52d1bd13a536c7e98fff23fb87c47524a118927f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Fri, 9 Jul 2021 19:32:03 +0100 Subject: [PATCH 13/15] NETPGP: Minor fixes Tracking down issues --- src/pgp_netpgp.c | 440 ++++++++++++++++++++++++++--------------------- src/pgp_netpgp.h | 4 +- test/Makefile | 8 +- 3 files changed, 254 insertions(+), 198 deletions(-) diff --git a/src/pgp_netpgp.c b/src/pgp_netpgp.c index de42f042..9f5be221 100644 --- a/src/pgp_netpgp.c +++ b/src/pgp_netpgp.c @@ -15,10 +15,12 @@ #include "pgp_netpgp.h" #include +#include #include "wrappers.h" -#include "netpgp.h" +#include + #include #include #include @@ -40,30 +42,34 @@ inline char A(char c) return c; } -static netpgp_t netpgp; +netpgp_t *netpgp; static pthread_mutex_t netpgp_mutex; static PEP_STATUS init_netpgp() { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS status = PEP_STATUS_OK; const char *home = NULL; + pgp_io_t *io; - //if(pthread_mutex_init(&netpgp_mutex, NULL)){ - // return PEP_OUT_OF_MEMORY; - //} + if(pthread_mutex_init(&netpgp_mutex, NULL)){ + return PEP_OUT_OF_MEMORY; + } - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } if (strcmp(setlocale(LC_ALL, NULL), "C") == 0) setlocale(LC_ALL, ""); - memset(&netpgp, 0x0, sizeof(netpgp_t)); + netpgp=malloc(sizeof(netpgp_t)); + memset(netpgp, 0x0, sizeof(netpgp_t)); - // netpgp_setvar(&netpgp, "max mem alloc", "4194304"); - netpgp_setvar(&netpgp, "need seckey", "1"); - // netpgp_setvar(&netpgp, "need userid", "1"); + //netpgp_setvar(netpgp, "max mem alloc", "4194304"); + //netpgp_setvar(netpgp, "need seckey", "1"); + netpgp_setvar(netpgp, "need pubkey", "1"); + //netpgp_setvar(netpgp, "need userid", "1"); if (!home) home = getenv("HOME"); @@ -72,47 +78,52 @@ static PEP_STATUS init_netpgp() status = PEP_INIT_CRYPTO_LIB_INIT_FAILED; if(home){ - netpgp_set_homedir(&netpgp,(char*)home, NULL, 0); + netpgp_set_homedir(netpgp,(char*)home, "/.netpgp", 0); }else{ status = PEP_INIT_NO_CRYPTO_HOME; goto unlock_netpgp; } // pair with gpg's cert-digest-algo - netpgp_setvar(&netpgp, "hash", "SHA256"); + netpgp_setvar(netpgp, "hash", "SHA256"); // subset of gpg's personal-cipher-preferences // here only one cipher can be selected - netpgp_setvar(&netpgp, "cipher", "CAST5"); + netpgp_setvar(netpgp, "cipher", "CAST5"); - if (!netpgp_init(&netpgp)) { + if (!netpgp_init(netpgp)) { status = PEP_INIT_CRYPTO_LIB_INIT_FAILED; + printf("%s: error, line %d\n",__FUNCTION__,__LINE__); + pgp_print_errors(stderr); + free(netpgp); + netpgp=NULL; goto unlock_netpgp; } - // netpgp_set_debug("packet-parse.c"); + //pgp_set_debug_level("packet-parse.c"); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return status; } static void release_netpgp() { - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return; - //} - netpgp_end(&netpgp); - memset(&netpgp, 0x0, sizeof(netpgp_t)); + if(pthread_mutex_lock(&netpgp_mutex)){ + return; + } + netpgp_end(netpgp); + memset(netpgp, 0x0, sizeof(netpgp_t)); - //pthread_mutex_destroy(&netpgp_mutex); + pthread_mutex_destroy(&netpgp_mutex); return; } PEP_STATUS pgp_init(PEP_SESSION session, bool in_first) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS status = PEP_STATUS_OK; assert(session); @@ -140,6 +151,7 @@ void pgp_release(PEP_SESSION session, bool out_last) static unsigned _armoured(const char *buf, size_t size, const char *pattern) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); unsigned armoured = 0; regex_t r; regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB); @@ -154,8 +166,9 @@ _armoured(const char *buf, size_t size, const char *pattern) static unsigned fpr_to_str (char **str, const uint8_t *fpr, size_t length) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); unsigned i; - int n; + int n; /* 4 hexes per short + null */ *str = malloc((length / 2) * 4 + 1); @@ -175,13 +188,15 @@ fpr_to_str (char **str, const uint8_t *fpr, size_t length) static unsigned str_to_fpr (const char *str, uint8_t *fpr, size_t *length) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); unsigned i,j; + (*length) = 0; - *length = 0; - if (str == NULL) return 0; + printf("%s\n",str); + while(*str && *length < PGP_FINGERPRINT_SIZE){ while (*str == ' ') str++; for (j = 0; j < 2; j++) { @@ -190,11 +205,11 @@ str_to_fpr (const char *str, uint8_t *fpr, size_t *length) for (i = 0; i < 2; i++) { if (i > 0) *byte = *byte << 4; - if (A(*str) >= A('a') && A(*str) <= A('f')) + if (islower(*str)) *byte += 10 + A(*str) - A('a'); - else if (A(*str) >= A('A') && A(*str) <= A('F')) + else if (isupper(*str)) *byte += 10 + *str - 'A'; - else if (*str >= '0' && *str <= '9') + else if (isdigit(*str)) *byte += A(*str) - '0'; else return 0; @@ -203,6 +218,10 @@ str_to_fpr (const char *str, uint8_t *fpr, size_t *length) (*length)++; } } + + (*length)++; + fpr[*length]=0; + return 1; } @@ -216,6 +235,7 @@ static PEP_STATUS _validation_results( stringlist_t **keylist ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); time_t now; time_t t; @@ -309,6 +329,7 @@ PEP_STATUS pgp_decrypt_and_verify( char** filename_ptr // will be ignored ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); char *_ptext = NULL; PEP_STATUS result; @@ -324,9 +345,9 @@ PEP_STATUS pgp_decrypt_and_verify( if(!session || !ctext || !csize || !ptext || !psize || !keylist) return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } *ptext = NULL; *psize = 0; @@ -338,8 +359,8 @@ PEP_STATUS pgp_decrypt_and_verify( key_id_t *recipients_key_ids = NULL; unsigned recipients_count = 0; - pgp_memory_t *mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize, - netpgp.secring, netpgp.pubring, + pgp_memory_t *mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize, + netpgp->secring, netpgp->pubring, _armoured(ctext, csize, ARMOR_HEAD), &recipients_key_ids, &recipients_count); @@ -363,7 +384,7 @@ PEP_STATUS pgp_decrypt_and_verify( } if (result == PEP_DECRYPTED) { - result = _validation_results(&netpgp, vresult, &_keylist); + result = _validation_results(netpgp, vresult, &_keylist); if (result == PEP_DECRYPTED || result == PEP_VERIFY_NO_KEY) { if((_keylist = new_stringlist("")) == NULL) { @@ -385,7 +406,7 @@ PEP_STATUS pgp_decrypt_and_verify( char *fprstr = NULL; key_id_t *keyid = &recipients_key_ids[n]; - rcpt = pgp_getkeybyid(netpgp.io, netpgp.pubring, + rcpt = pgp_getkeybyid(netpgp->io, netpgp->pubring, *keyid, &from, NULL, NULL, 0, 0); /* check neither revocation nor expiry*/ if(rcpt) @@ -436,7 +457,7 @@ free_pgp: unlock_netpgp: free(recipients_key_ids); - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -447,6 +468,7 @@ PEP_STATUS pgp_verify_text( const char *signature, size_t sig_size, stringlist_t **keylist ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); pgp_memory_t *signedmem; pgp_memory_t *sig; pgp_validation_t *vresult; @@ -464,9 +486,9 @@ PEP_STATUS pgp_verify_text( if(!session || !text || !size || !signature || !sig_size || !keylist) return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } *keylist = NULL; @@ -492,13 +514,13 @@ PEP_STATUS pgp_verify_text( } pgp_memory_add(sig, (const uint8_t*)signature, sig_size); - pgp_validate_mem_detached(netpgp.io, vresult, sig, + pgp_validate_mem_detached(netpgp->io, vresult, sig, NULL,/* output */ _armoured(signature, sig_size, ARMOR_SIG_HEAD), - netpgp.pubring, + netpgp->pubring, signedmem); - result = _validation_results(&netpgp, vresult, &_keylist); + result = _validation_results(netpgp, vresult, &_keylist); if (result != PEP_STATUS_OK) { goto free_pgp; }else{ @@ -526,7 +548,7 @@ free_pgp: pgp_validate_result_free(vresult); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -536,6 +558,7 @@ static PEP_STATUS _encrypt_and_sign( size_t psize, char **ctext, size_t *csize, bool do_sign ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); pgp_key_t *signer = NULL; pgp_seckey_t *seckey = NULL; pgp_memory_t *signedmem = NULL; @@ -556,9 +579,9 @@ static PEP_STATUS _encrypt_and_sign( if(!session || !ptext || !psize || !ctext || !csize || !keylist) return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } *ctext = NULL; *csize = 0; @@ -576,7 +599,7 @@ static PEP_STATUS _encrypt_and_sign( unsigned from = 0; if (str_to_fpr(_keylist->value, fpr, &fprlen)) { - if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring, + if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, fprlen, &from, NULL, /* reject revoked, accept expired */ 1,0)) == NULL) { @@ -591,7 +614,7 @@ static PEP_STATUS _encrypt_and_sign( /* Signer is the first key in the list */ if(signer == NULL){ from = 0; - signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring, + signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->secring, fpr, fprlen, &from, NULL, @@ -624,7 +647,7 @@ static PEP_STATUS _encrypt_and_sign( goto free_rcpts; } - hashalg = netpgp_getvar(&netpgp, "hash"); + hashalg = netpgp_getvar(netpgp, "hash"); const char *stext; size_t ssize; @@ -632,7 +655,7 @@ static PEP_STATUS _encrypt_and_sign( if (do_sign) { // Sign data - signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey, + signedmem = pgp_sign_buf(netpgp->io, ptext, psize, seckey, time(NULL), /* birthtime */ 0 /* duration */, hashalg, @@ -654,9 +677,9 @@ static PEP_STATUS _encrypt_and_sign( // Encrypt (maybe) signed data - cmem = pgp_encrypt_buf(netpgp.io, stext, + cmem = pgp_encrypt_buf(netpgp->io, stext, ssize, rcpts, 1 /* armored */, - netpgp_getvar(&netpgp, "cipher"), + netpgp_getvar(netpgp, "cipher"), encrypt_raw_packet); if (cmem == NULL) { @@ -692,7 +715,7 @@ free_signedmem : free_rcpts : pgp_keyring_free(rcpts); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -703,6 +726,7 @@ PEP_STATUS pgp_sign_only( size_t psize, char **stext, size_t *ssize ) { + printf("%s:%d\n",__FILE__,__LINE__); pgp_key_t *signer = NULL; pgp_seckey_t *seckey = NULL; pgp_memory_t *signedmem = NULL; @@ -727,9 +751,9 @@ PEP_STATUS pgp_sign_only( if(!session || !ptext || !psize || !stext || !ssize || !fpr || !fpr[0]) return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } *stext = NULL; *ssize = 0; @@ -746,10 +770,8 @@ PEP_STATUS pgp_sign_only( unsigned from = 0; if (str_to_fpr(fpr, uint_fpr, &fprlen)) { - if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring, - uint_fpr, fprlen, &from, NULL, - /* reject revoked and expired */ - 1,1)) == NULL) { + if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->secring, uint_fpr, fprlen, &from, NULL, 1,1)) == NULL) { + /* reject revoked and expired */ result = PEP_KEY_NOT_FOUND; goto free_snrs; } @@ -779,7 +801,7 @@ PEP_STATUS pgp_sign_only( goto free_snrs; } - hashalg = netpgp_getvar(&netpgp, "hash"); + hashalg = netpgp_getvar(netpgp, "hash"); const char *_stext; size_t _ssize; @@ -836,7 +858,7 @@ free_signedmem : free_snrs : pgp_keyring_free(snrs); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -847,9 +869,9 @@ PEP_STATUS pgp_encrypt_and_sign( size_t psize, char **ctext, size_t *csize ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS result; - result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, - true); + result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, true); return result; } @@ -858,9 +880,9 @@ PEP_STATUS pgp_encrypt_only( size_t psize, char **ctext, size_t *csize ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS result; - result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, - false); + result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, false); return result; } @@ -869,6 +891,7 @@ PEP_STATUS pgp_generate_keypair( PEP_SESSION session, pEp_identity *identity ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); pgp_key_t newseckey; pgp_key_t *newpubkey; @@ -887,9 +910,9 @@ PEP_STATUS pgp_generate_keypair( !identity->address || identity->fpr || !identity->username) return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } if(snprintf(newid, sizeof(newid), "%s <%s>", identity->username, identity->address) >= sizeof(newid)){ @@ -897,8 +920,8 @@ PEP_STATUS pgp_generate_keypair( goto unlock_netpgp; } - hashalg = netpgp_getvar(&netpgp, "hash"); - cipher = netpgp_getvar(&netpgp, "cipher"); + hashalg = netpgp_getvar(netpgp, "hash"); + cipher = netpgp_getvar(netpgp, "cipher"); bzero(&newseckey, sizeof(newseckey)); @@ -912,7 +935,7 @@ PEP_STATUS pgp_generate_keypair( /* make a public key out of generated secret key */ if((newpubkey = pgp_ensure_pubkey( - netpgp.pubring, + netpgp->pubring, &newseckey.key.seckey.pubkey, newseckey.pubkeyid))==NULL) { @@ -935,13 +958,13 @@ PEP_STATUS pgp_generate_keypair( } // Append key to netpgp's rings (key ownership transfered) - if (!pgp_keyring_add(netpgp.secring, &newseckey)){ + if (!pgp_keyring_add(netpgp->secring, &newseckey)){ result = PEP_OUT_OF_MEMORY; goto delete_pubkey; } // save rings - if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp)) + if (netpgp_save_pubring(netpgp) && netpgp_save_secring(netpgp)) { char *fprstr = NULL; fpr_to_str(&fprstr, @@ -967,22 +990,23 @@ PEP_STATUS pgp_generate_keypair( } pop_secring: - ((pgp_keyring_t *)netpgp.secring)->keyc--; + ((pgp_keyring_t *)netpgp->secring)->keyc--; delete_pubkey: - pgp_deletekeybyfpr(netpgp.io, - (pgp_keyring_t *)netpgp.pubring, + pgp_deletekeybyfpr(netpgp->io, + (pgp_keyring_t *)netpgp->pubring, newseckey.pubkeyfpr.fingerprint, newseckey.pubkeyfpr.length); free_seckey: pgp_key_free(&newseckey); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); uint8_t fpr[PGP_FINGERPRINT_SIZE]; size_t length; @@ -994,16 +1018,16 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) if (!session || !fprstr) return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } if (str_to_fpr(fprstr, fpr, &length)) { - unsigned insec = pgp_deletekeybyfpr(netpgp.io, - (pgp_keyring_t *)netpgp.secring, + unsigned insec = pgp_deletekeybyfpr(netpgp->io, + (pgp_keyring_t *)netpgp->secring, (const uint8_t *)fpr, length); - unsigned inpub = pgp_deletekeybyfpr(netpgp.io, - (pgp_keyring_t *)netpgp.pubring, + unsigned inpub = pgp_deletekeybyfpr(netpgp->io, + (pgp_keyring_t *)netpgp->pubring, (const uint8_t *)fpr, length); if(!insec && !inpub){ result = PEP_KEY_NOT_FOUND; @@ -1017,8 +1041,8 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) } // save rings - if (netpgp_save_pubring(&netpgp) && - netpgp_save_secring(&netpgp)) + if (netpgp_save_pubring(netpgp) && + netpgp_save_secring(netpgp)) { result = PEP_STATUS_OK; }else{ @@ -1026,53 +1050,87 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) } unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } #define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----"_ENDL -PEP_STATUS pgp_import_keydata( - PEP_SESSION session, - const char *key_data, - size_t size, - identity_list **private_idents - ) +PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, + size_t size, identity_list **private_idents, + stringlist_t** imported_keys, + uint64_t* changed_key_index) { - pgp_memory_t *mem; + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - PEP_STATUS result = PEP_STATUS_OK; + if (!imported_keys && changed_key_index) + return PEP_ILLEGAL_VALUE; + int i; + identity_list *priv_id = NULL, *priv_id_list = NULL; + pEp_identity *ident = NULL; + pgp_key_t key; + pgp_memory_t *mem = NULL; + PEP_STATUS result = PEP_STATUS_OK; + const char* pgp_begin = "-----BEGIN PGP"; + size_t prefix_len = strlen(pgp_begin); + assert(session); assert(key_data); - // reporting imported private keys not supported - // stub code to be reomoved - if(private_idents) - *private_idents = NULL; + //pgp_set_debug_level("reader.c"); if(!session || !key_data) return PEP_ILLEGAL_VALUE; - /*if(pthread_mutex_lock(&netpgp_mutex)){ + // Because we also import binary keys we have to be careful with this. + // + if (strlen(key_data + prefix_len) > prefix_len) { + const char* subtract_junk = strnstr(key_data, pgp_begin, size); + // If it's not in there, we just try to import it as is... + if (subtract_junk) { + size -= (subtract_junk - key_data); + key_data = subtract_junk; + } + } + + if(pthread_mutex_lock(&netpgp_mutex)){ return PEP_UNKNOWN_ERROR; - }*/ + } mem = pgp_memory_new(); if (mem == NULL) { result = PEP_OUT_OF_MEMORY; goto unlock_netpgp; } - pgp_memory_add(mem, (const uint8_t*)key_data, size); - if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring, _armoured(key_data, size, ARMOR_KEY_HEAD), mem) == 0){ + pgp_memory_add(mem, (const uint8_t*)key_data, size); + if (pgp_keyring_read_from_mem(netpgp->io, netpgp->pubring, netpgp->secring, _armoured(key_data, size, ARMOR_KEY_HEAD), mem) == 0){ + pgp_print_errors(stderr); result = PEP_ILLEGAL_VALUE; } - pgp_memory_free(mem); + for(i=0;isecring->keyc;i++) { + priv_id=malloc(sizeof(identity_list)); + ident=priv_id->ident=malloc(sizeof(pEp_identity)); + key=netpgp->secring->keys[i]; + fpr_to_str(&ident->fpr,key.pubkeyfpr.fingerprint,key.pubkeyfpr.length); + printf("fpr=%s\n",ident->fpr); + priv_id->next=NULL; + priv_id_list=priv_id_list?identity_list_join(priv_id_list,priv_id):priv_id; + } + +// private_idents=malloc(sizeof(private_idents)); + printf("Returning values private_idents=%p\n",private_idents); + printf("Returning values imported_keys=%p\n",imported_keys); + if(private_idents) { + printf("Returning values *private_idents=%p\n",*private_idents); + *private_idents=priv_id_list; + } + // save rings - if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp)) + if (netpgp_save_pubring(netpgp) && netpgp_save_secring(netpgp)) { result = PEP_KEY_IMPORTED; } else { @@ -1080,7 +1138,7 @@ PEP_STATUS pgp_import_keydata( } unlock_netpgp: -// pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1091,6 +1149,7 @@ static PEP_STATUS _export_keydata( size_t *buflen ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS result; pgp_output_t *output; pgp_memory_t *mem; @@ -1132,6 +1191,7 @@ PEP_STATUS pgp_export_keydata( bool secret ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); pgp_key_t *key; uint8_t fpr[PGP_FINGERPRINT_SIZE]; size_t fprlen; @@ -1147,20 +1207,20 @@ PEP_STATUS pgp_export_keydata( assert(size); if (secret) - srcring = netpgp.secring; + srcring = netpgp->secring; else - srcring = netpgp.pubring; + srcring = netpgp->pubring; - //if (!session || !fprstr || !key_data || !size) - // return PEP_ILLEGAL_VALUE; + if (!session || !fprstr || !key_data || !size) + return PEP_ILLEGAL_VALUE; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)) { + return PEP_UNKNOWN_ERROR; + } if (str_to_fpr(fprstr, fpr, &fprlen)) { unsigned from = 0; - if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring, fpr, fprlen, &from, NULL,0,0)) == NULL) { + if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, srcring, fpr, fprlen, &from, NULL,0,0)) == NULL) { result = PEP_KEY_NOT_FOUND; goto unlock_netpgp; } @@ -1179,7 +1239,7 @@ PEP_STATUS pgp_export_keydata( } unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1189,28 +1249,9 @@ struct HKP_answer { size_t size; }; -static size_t -HKPAnswerWriter(void *contents, size_t size, size_t nmemb, void *userp) -{ - size_t realsize = size * nmemb; - struct HKP_answer *mem = (struct HKP_answer *)userp; - - mem->memory = realloc(mem->memory, mem->size + realsize + 1); - if(mem->memory == NULL) { - mem->size = 0; - return 0; - } - - memcpy(&(mem->memory[mem->size]), contents, realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - - return realsize; -} - - PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); assert(!"pgp_recv_key not implemented"); return PEP_UNKNOWN_ERROR; } @@ -1220,6 +1261,7 @@ typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *); static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, const char *pattern, find_key_cb_t cb, void* cb_arg) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); uint8_t fpr[PGP_FINGERPRINT_SIZE]; size_t length; pgp_key_t *key; @@ -1230,10 +1272,9 @@ static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, if (str_to_fpr(pattern, fpr, &length)) { unsigned from = 0; - // Only one fingerprint can match if ((key = (pgp_key_t *)pgp_getkeybyfpr( - netpgp.io, + netpgp->io, keyring, (const uint8_t *)fpr, length, &from, @@ -1249,7 +1290,7 @@ static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, unsigned from = 0; result = PEP_KEY_NOT_FOUND; while((key = (pgp_key_t *)pgp_getnextkeybyname( - netpgp.io, + netpgp->io, keyring, (const char *)pattern, &from)) != NULL) { @@ -1267,6 +1308,7 @@ static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); stringlist_t **keylist = arg; char *newfprstr = NULL; @@ -1289,13 +1331,12 @@ static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key) static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); if (pgp_is_key_secret(key)) { stringlist_t **keylist = arg; char *newfprstr = NULL; - fpr_to_str(&newfprstr, - key->pubkeyfpr.fingerprint, - key->pubkeyfpr.length); + fpr_to_str(&newfprstr, key->pubkeyfpr.fingerprint, key->pubkeyfpr.length); if (newfprstr == NULL) { return PEP_OUT_OF_MEMORY; @@ -1311,6 +1352,7 @@ static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key) } static PEP_STATUS add_keyinfo_to_stringpair_list(void* arg, pgp_key_t *key) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); stringpair_list_t** keyinfo_list = (stringpair_list_t**)arg; stringpair_t* pair = NULL; char* id_fpr = NULL; @@ -1343,6 +1385,7 @@ PEP_STATUS pgp_find_keys( PEP_SESSION session, const char *pattern, stringlist_t **keylist ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); stringlist_t *_keylist, *_k; PEP_STATUS result; @@ -1356,10 +1399,10 @@ PEP_STATUS pgp_find_keys( return PEP_ILLEGAL_VALUE; } - //if (pthread_mutex_lock(&netpgp_mutex)) - //{ - // return PEP_UNKNOWN_ERROR; - //} + if (pthread_mutex_lock(&netpgp_mutex)) + { + return PEP_UNKNOWN_ERROR; + } *keylist = NULL; _keylist = new_stringlist(NULL); @@ -1369,7 +1412,7 @@ PEP_STATUS pgp_find_keys( } _k = _keylist; - result = find_keys_do((pgp_keyring_t *)netpgp.pubring, + result = find_keys_do((pgp_keyring_t *)netpgp->pubring, pattern, &add_key_fpr_to_stringlist, &_k); if (result == PEP_STATUS_OK) { @@ -1381,7 +1424,7 @@ PEP_STATUS pgp_find_keys( free_stringlist(_keylist); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1391,6 +1434,7 @@ unlock_netpgp: PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); assert(!"pgp_send_key not implemented"); return PEP_UNKNOWN_ERROR; } @@ -1402,6 +1446,7 @@ PEP_STATUS pgp_get_key_rating( PEP_comm_type *comm_type ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); pgp_key_t *key; uint8_t fpr[PGP_FINGERPRINT_SIZE]; unsigned from = 0; @@ -1419,19 +1464,16 @@ PEP_STATUS pgp_get_key_rating( *comm_type = PEP_ct_unknown; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } if (!str_to_fpr(fprstr, fpr, &length)) { status = PEP_ILLEGAL_VALUE; goto unlock_netpgp; } - key = pgp_getkeybyfpr( - netpgp.io, - netpgp.pubring, - fpr, length, &from, NULL,0,0); + key = pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, length, &from, NULL,0,0); if(key == NULL) { @@ -1463,7 +1505,7 @@ PEP_STATUS pgp_get_key_rating( } unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1474,6 +1516,7 @@ PEP_STATUS pgp_renew_key( const timestamp *ts ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); pgp_key_t *pkey; pgp_key_t *skey; uint8_t fpr[PGP_FINGERPRINT_SIZE]; @@ -1505,9 +1548,9 @@ PEP_STATUS pgp_renew_key( duration = 365*24*3600; } - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } if (!str_to_fpr(fprstr, fpr, &length)) { @@ -1516,8 +1559,8 @@ PEP_STATUS pgp_renew_key( } pkey = pgp_getkeybyfpr( - netpgp.io, - netpgp.pubring, + netpgp->io, + netpgp->pubring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ @@ -1529,8 +1572,8 @@ PEP_STATUS pgp_renew_key( from = 0; skey = pgp_getkeybyfpr( - netpgp.io, - netpgp.secring, + netpgp->io, + netpgp->secring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ @@ -1554,8 +1597,8 @@ PEP_STATUS pgp_renew_key( } // save rings - if (netpgp_save_pubring(&netpgp) && - netpgp_save_secring(&netpgp)) + if (netpgp_save_pubring(netpgp) && + netpgp_save_secring(netpgp)) { status = PEP_STATUS_OK; }else{ @@ -1563,7 +1606,7 @@ PEP_STATUS pgp_renew_key( } unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1574,6 +1617,7 @@ PEP_STATUS pgp_revoke_key( const char *reason ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); uint8_t fpr[PGP_FINGERPRINT_SIZE]; size_t length; unsigned from = 0; @@ -1586,9 +1630,9 @@ PEP_STATUS pgp_revoke_key( if (!session || !fprstr) return PEP_UNKNOWN_ERROR; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } // FIXME : deduplicate that code w/ renew if (!str_to_fpr(fprstr, fpr, &length)) { @@ -1597,8 +1641,8 @@ PEP_STATUS pgp_revoke_key( } pgp_key_t *pkey = pgp_getkeybyfpr( - netpgp.io, - netpgp.pubring, + netpgp->io, + netpgp->pubring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ @@ -1610,8 +1654,8 @@ PEP_STATUS pgp_revoke_key( from = 0; pgp_key_t *skey = pgp_getkeybyfpr( - netpgp.io, - netpgp.secring, + netpgp->io, + netpgp->secring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ @@ -1626,7 +1670,7 @@ PEP_STATUS pgp_revoke_key( reason); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1638,6 +1682,7 @@ PEP_STATUS pgp_key_expired( bool *expired ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS status = PEP_STATUS_OK; PEP_comm_type comm_type; @@ -1670,6 +1715,7 @@ PEP_STATUS pgp_key_revoked( bool *revoked ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); PEP_STATUS status = PEP_STATUS_OK; PEP_comm_type comm_type; @@ -1697,6 +1743,7 @@ PEP_STATUS pgp_key_created( time_t *created ) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); uint8_t fpr[PGP_FINGERPRINT_SIZE]; pgp_key_t *key; size_t length; @@ -1713,9 +1760,9 @@ PEP_STATUS pgp_key_created( *created = 0; - //if(pthread_mutex_lock(&netpgp_mutex)){ - // return PEP_UNKNOWN_ERROR; - //} + if(pthread_mutex_lock(&netpgp_mutex)){ + return PEP_UNKNOWN_ERROR; + } if (!str_to_fpr(fprstr, fpr, &length)) { status = PEP_ILLEGAL_VALUE; @@ -1723,8 +1770,8 @@ PEP_STATUS pgp_key_created( } key = pgp_getkeybyfpr( - netpgp.io, - netpgp.pubring, + netpgp->io, + netpgp->pubring, fpr, length, &from, NULL,0,0); if (key) @@ -1740,7 +1787,7 @@ PEP_STATUS pgp_key_created( unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return status; } @@ -1749,27 +1796,28 @@ unlock_netpgp: PEP_STATUS pgp_list_keyinfo( PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); if (!session || !keyinfo_list) return PEP_UNKNOWN_ERROR; - //if (pthread_mutex_lock(&netpgp_mutex)) - //{ - // return PEP_UNKNOWN_ERROR; - //} + if (pthread_mutex_lock(&netpgp_mutex)) + { + return PEP_UNKNOWN_ERROR; + } // Unused: // pgp_key_t *key; PEP_STATUS result; - result = find_keys_do((pgp_keyring_t *)netpgp.pubring, + result = find_keys_do((pgp_keyring_t *)netpgp->pubring, pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list); if (!keyinfo_list) result = PEP_KEY_NOT_FOUND; - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1778,6 +1826,7 @@ PEP_STATUS pgp_list_keyinfo( PEP_STATUS pgp_find_private_keys( PEP_SESSION session, const char *pattern, stringlist_t **keylist) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); stringlist_t *_keylist, *_k; PEP_STATUS result; @@ -1790,10 +1839,10 @@ PEP_STATUS pgp_find_private_keys( return PEP_ILLEGAL_VALUE; } - //if (pthread_mutex_lock(&netpgp_mutex)) - //{ - // return PEP_UNKNOWN_ERROR; - //} + if (pthread_mutex_lock(&netpgp_mutex)) + { + return PEP_UNKNOWN_ERROR; + } *keylist = NULL; _keylist = new_stringlist(NULL); @@ -1803,7 +1852,7 @@ PEP_STATUS pgp_find_private_keys( } _k = _keylist; - result = find_keys_do((pgp_keyring_t *)netpgp.secring, + result = find_keys_do((pgp_keyring_t *)netpgp->secring, pattern, &add_secret_key_fpr_to_stringlist, &_k); if (result == PEP_STATUS_OK) { @@ -1815,7 +1864,7 @@ PEP_STATUS pgp_find_private_keys( free_stringlist(_keylist); unlock_netpgp: - //pthread_mutex_unlock(&netpgp_mutex); + pthread_mutex_unlock(&netpgp_mutex); return result; } @@ -1824,6 +1873,7 @@ PEP_STATUS pgp_contains_priv_key( PEP_SESSION session, const char *fpr, bool *has_private) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); stringlist_t* keylist = NULL; PEP_STATUS status = pgp_find_private_keys(session, fpr, &keylist); if (status == PEP_STATUS_OK && keylist) { @@ -1839,10 +1889,12 @@ PEP_STATUS pgp_contains_priv_key( PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) { // Not implemented - netpgp doesn't appear to keep track of trust status in // a meaningful way, though there is space for it in the structs. + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); return PEP_STATUS_OK; } PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite) { + printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); if (suite == PEP_CIPHER_SUITE_DEFAULT) { return PEP_STATUS_OK; } else { diff --git a/src/pgp_netpgp.h b/src/pgp_netpgp.h index e5f9ee38..41bec633 100644 --- a/src/pgp_netpgp.h +++ b/src/pgp_netpgp.h @@ -61,7 +61,9 @@ PEP_STATUS pgp_get_key_rating( ); PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, - size_t size, identity_list **private_idents); + size_t size, identity_list **private_idents, + stringlist_t** imported_keys, + uint64_t* changed_key_index); PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern); PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern); diff --git a/test/Makefile b/test/Makefile index 7d786de6..c039075c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -64,9 +64,9 @@ ifdef SQLITE3_FROM_OS endif ifeq ($(OPENPGP),GPG) - #LDLIBS+= -lgpgme + LDLIBS+= -lgpgme else ifeq ($(OPENPGP),NETPGP) - LDLIBS+= -lnetpgp + LDLIBS+=$(NETPGP_LIB) ifeq ($(BUILD_FOR),Linux) LDLIBS+= -ltre endif @@ -115,7 +115,9 @@ all: LDLIBS+=-lgtest -lgtest_main ifeq ($(BUILD_ON),OS/390) LDLIBS+=-lzz -else +endif + +ifeq ($(OPENPGP),SEQUOIA) LDLIBS+=-lsequoia_openpgp_ffi endif From a279d6d2f568b2352e5292b690ecf7a442d82828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Tue, 20 Jul 2021 23:29:33 +0100 Subject: [PATCH 14/15] NetPGP support: Adding some tracing/simplifying It's easier to have NetPGP handle some of the functionality the old glue code did. Deleting some code and moving it over to NetPGP. --- src/pgp_netpgp.c | 753 ++++++++++++++++++++--------------------------- src/pgp_netpgp.h | 341 ++++++++++++++++++++- 2 files changed, 651 insertions(+), 443 deletions(-) diff --git a/src/pgp_netpgp.c b/src/pgp_netpgp.c index 9f5be221..6eab60a1 100644 --- a/src/pgp_netpgp.c +++ b/src/pgp_netpgp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -34,8 +35,17 @@ #include #endif +#if 0 +#define TRACE_FUNCS() printf("Trace fun: %s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); +#else +#define TRACE_FUNCS() +#endif + +#define _ENDL "\\s*(\r\n|\r|\n)" + inline char A(char c) { + TRACE_FUNCS() #if defined(NETPGP_EBCDIC) __e2a_l(&c,1); #endif @@ -47,7 +57,7 @@ static pthread_mutex_t netpgp_mutex; static PEP_STATUS init_netpgp() { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() PEP_STATUS status = PEP_STATUS_OK; const char *home = NULL; pgp_io_t *io; @@ -67,8 +77,11 @@ static PEP_STATUS init_netpgp() memset(netpgp, 0x0, sizeof(netpgp_t)); //netpgp_setvar(netpgp, "max mem alloc", "4194304"); - //netpgp_setvar(netpgp, "need seckey", "1"); + netpgp_setvar(netpgp, "need seckey", "1"); netpgp_setvar(netpgp, "need pubkey", "1"); + netpgp_setvar(netpgp, "batch", "1"); + + //pgp_set_debug_level("keyring.c"); //netpgp_setvar(netpgp, "need userid", "1"); if (!home) @@ -93,14 +106,14 @@ static PEP_STATUS init_netpgp() if (!netpgp_init(netpgp)) { status = PEP_INIT_CRYPTO_LIB_INIT_FAILED; - printf("%s: error, line %d\n",__FUNCTION__,__LINE__); - pgp_print_errors(stderr); free(netpgp); netpgp=NULL; goto unlock_netpgp; } //pgp_set_debug_level("packet-parse.c"); + //pgp_set_debug_level("openssl_crypto.c"); + //pgp_set_debug_level("crypto.c"); unlock_netpgp: pthread_mutex_unlock(&netpgp_mutex); @@ -110,6 +123,7 @@ unlock_netpgp: static void release_netpgp() { + TRACE_FUNCS() if(pthread_mutex_lock(&netpgp_mutex)){ return; } @@ -123,7 +137,7 @@ static void release_netpgp() PEP_STATUS pgp_init(PEP_SESSION session, bool in_first) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() PEP_STATUS status = PEP_STATUS_OK; assert(session); @@ -139,6 +153,7 @@ PEP_STATUS pgp_init(PEP_SESSION session, bool in_first) void pgp_release(PEP_SESSION session, bool out_last) { + TRACE_FUNCS() assert(session); if(!session) return; @@ -151,10 +166,10 @@ void pgp_release(PEP_SESSION session, bool out_last) static unsigned _armoured(const char *buf, size_t size, const char *pattern) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() unsigned armoured = 0; regex_t r; - regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB); + if( regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB) ) printf("_armoured error\n"); if (regexec(&r, buf, size, 0, NULL) == 0) { armoured = 1; } @@ -162,69 +177,6 @@ _armoured(const char *buf, size_t size, const char *pattern) return armoured; } -/* write key fingerprint hexdump as a string */ -static unsigned -fpr_to_str (char **str, const uint8_t *fpr, size_t length) -{ - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - unsigned i; - int n; - - /* 4 hexes per short + null */ - *str = malloc((length / 2) * 4 + 1); - - if(*str == NULL) - return 0; - - for (n = 0, i = 0 ; i < length; i += 2) { - n += snprintf(&((*str)[n]), 5, "%02X%02X", fpr[i], fpr[i+1]); - } - - return 1; -} - -/* write key fingerprint bytes read from hex string - * accept spaces and hexes */ -static unsigned -str_to_fpr (const char *str, uint8_t *fpr, size_t *length) -{ - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - unsigned i,j; - (*length) = 0; - - if (str == NULL) - return 0; - - printf("%s\n",str); - - while(*str && *length < PGP_FINGERPRINT_SIZE){ - while (*str == ' ') str++; - for (j = 0; j < 2; j++) { - uint8_t *byte = &fpr[*length]; - *byte = 0; - for (i = 0; i < 2; i++) { - if (i > 0) - *byte = *byte << 4; - if (islower(*str)) - *byte += 10 + A(*str) - A('a'); - else if (isupper(*str)) - *byte += 10 + *str - 'A'; - else if (isdigit(*str)) - *byte += A(*str) - '0'; - else - return 0; - str++; - } - (*length)++; - } - } - - (*length)++; - fpr[*length]=0; - - return 1; -} - // Iterate through netpgp' reported valid signatures // fill a list of valid figerprints // returns PEP_STATUS_OK if all sig reported valid @@ -235,7 +187,7 @@ static PEP_STATUS _validation_results( stringlist_t **keylist ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() time_t now; time_t t; @@ -276,9 +228,7 @@ static PEP_STATUS _validation_results( 0, 0); /* check neither revocation nor expiry as is should be checked already */ if(signer) - fpr_to_str(&fprstr, - signer->pubkeyfpr.fingerprint, - signer->pubkeyfpr.length); + uint_to_string(signer->pubkeyfpr.fingerprint, &fprstr, signer->pubkeyfpr.length); else continue; @@ -320,8 +270,7 @@ static PEP_STATUS _validation_results( return PEP_DECRYPTED; } -#define _ENDL "\\s*(\r\n|\r|\n)" -#define ARMOR_HEAD "^-----BEGIN PGP MESSAGE-----"_ENDL +#define ARMOR_HEAD "^-----BEGIN PGP MESSAGE-----"_ENDL PEP_STATUS pgp_decrypt_and_verify( PEP_SESSION session, const char *ctext, size_t csize, const char *dsigtext, size_t dsigsize, @@ -329,8 +278,9 @@ PEP_STATUS pgp_decrypt_and_verify( char** filename_ptr // will be ignored ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() char *_ptext = NULL; + char* passphrase = NULL; PEP_STATUS result; stringlist_t *_keylist = NULL; @@ -342,6 +292,11 @@ PEP_STATUS pgp_decrypt_and_verify( assert(psize); assert(keylist); + passphrase = session->curr_passphrase; + if(passphrase && passphrase[0]) { + netpgp_set_validation_password(passphrase); + } + if(!session || !ctext || !csize || !ptext || !psize || !keylist) return PEP_ILLEGAL_VALUE; @@ -359,10 +314,14 @@ PEP_STATUS pgp_decrypt_and_verify( key_id_t *recipients_key_ids = NULL; unsigned recipients_count = 0; - pgp_memory_t *mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize, - netpgp->secring, netpgp->pubring, - _armoured(ctext, csize, ARMOR_HEAD), - &recipients_key_ids, &recipients_count); + pgp_memory_t *mem = pgp_decrypt_and_validate_buf( + netpgp, + vresult, + ctext, csize, + netpgp->secring, netpgp->pubring, + _armoured(ctext, csize, ARMOR_HEAD), + &recipients_key_ids, &recipients_count + ); if (mem == NULL) { result = PEP_OUT_OF_MEMORY; @@ -385,8 +344,8 @@ PEP_STATUS pgp_decrypt_and_verify( if (result == PEP_DECRYPTED) { result = _validation_results(netpgp, vresult, &_keylist); - if (result == PEP_DECRYPTED || - result == PEP_VERIFY_NO_KEY) { + printf("result=%x\n",result); + if (result == PEP_DECRYPTED || result == PEP_VERIFY_NO_KEY) { if((_keylist = new_stringlist("")) == NULL) { result = PEP_OUT_OF_MEMORY; goto free_ptext; @@ -410,14 +369,10 @@ PEP_STATUS pgp_decrypt_and_verify( *keyid, &from, NULL, NULL, 0, 0); /* check neither revocation nor expiry*/ if(rcpt) - fpr_to_str(&fprstr, - rcpt->pubkeyfpr.fingerprint, - rcpt->pubkeyfpr.length); + uint_to_string(rcpt->pubkeyfpr.fingerprint, &fprstr, rcpt->pubkeyfpr.length); else // if no key found put ID instead of fpr - fpr_to_str(&fprstr, - *keyid, - sizeof(key_id_t)); + uint_to_string(*keyid, &fprstr, sizeof(key_id_t)); if (fprstr == NULL){ result = PEP_OUT_OF_MEMORY; @@ -434,8 +389,7 @@ PEP_STATUS pgp_decrypt_and_verify( } } - if (result == PEP_DECRYPTED_AND_VERIFIED - || result == PEP_DECRYPTED) { + if (result == PEP_DECRYPTED_AND_VERIFIED || result == PEP_DECRYPTED) { *ptext = _ptext; *psize = _psize; (*ptext)[*psize] = 0; // safeguard for naive users @@ -468,7 +422,7 @@ PEP_STATUS pgp_verify_text( const char *signature, size_t sig_size, stringlist_t **keylist ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() pgp_memory_t *signedmem; pgp_memory_t *sig; pgp_validation_t *vresult; @@ -553,180 +507,12 @@ unlock_netpgp: return result; } -static PEP_STATUS _encrypt_and_sign( - PEP_SESSION session, const stringlist_t *keylist, const char *ptext, - size_t psize, char **ctext, size_t *csize, bool do_sign - ) -{ - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - pgp_key_t *signer = NULL; - pgp_seckey_t *seckey = NULL; - pgp_memory_t *signedmem = NULL; - pgp_memory_t *cmem; - const char *hashalg; - pgp_keyring_t *rcpts; - - PEP_STATUS result; - const stringlist_t *_keylist; - - assert(session); - assert(keylist); - assert(ptext); - assert(psize); - assert(ctext); - assert(csize); - - if(!session || !ptext || !psize || !ctext || !csize || !keylist) - return PEP_ILLEGAL_VALUE; - - if(pthread_mutex_lock(&netpgp_mutex)){ - return PEP_UNKNOWN_ERROR; - } - - *ctext = NULL; - *csize = 0; - - if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) { - result = PEP_OUT_OF_MEMORY; - goto unlock_netpgp; - } - for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) { - assert(_keylist->value); - - const pgp_key_t *key; - uint8_t fpr[PGP_FINGERPRINT_SIZE]; - size_t fprlen; - unsigned from = 0; - - if (str_to_fpr(_keylist->value, fpr, &fprlen)) { - if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->pubring, - fpr, fprlen, &from, NULL, - /* reject revoked, accept expired */ - 1,0)) == NULL) { - result = PEP_KEY_NOT_FOUND; - goto free_rcpts; - } - }else{ - result = PEP_ILLEGAL_VALUE; - goto free_rcpts; - } - - /* Signer is the first key in the list */ - if(signer == NULL){ - from = 0; - signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->secring, - fpr, fprlen, - &from, - NULL, - 0,0); /* accept any */ - if(signer == NULL){ - result = PEP_KEY_NOT_FOUND; - goto free_rcpts; - } - } - - // add key to recipients/signers - pgp_keyring_add(rcpts, key); - if(rcpts->keys == NULL){ - result = PEP_OUT_OF_MEMORY; - goto free_rcpts; - } - } - - /* Empty keylist ?*/ - if(rcpts->keyc == 0){ - result = PEP_ILLEGAL_VALUE; - goto free_rcpts; - } - - seckey = pgp_key_get_certkey(signer); - - /* No signig key. Revoked ? */ - if(seckey == NULL){ - result = PEP_GET_KEY_FAILED; - goto free_rcpts; - } - - hashalg = netpgp_getvar(netpgp, "hash"); - - const char *stext; - size_t ssize; - unsigned encrypt_raw_packet; - - if (do_sign) { - // Sign data - signedmem = pgp_sign_buf(netpgp->io, ptext, psize, seckey, - time(NULL), /* birthtime */ - 0 /* duration */, - hashalg, - 0 /* armored */, - 0 /* cleartext */); - - if (!signedmem) { - result = PEP_UNENCRYPTED; - goto free_rcpts; - } - stext = (char*) pgp_mem_data(signedmem); - ssize = pgp_mem_len(signedmem); - encrypt_raw_packet = 1 /* takes raw OpenPGP message */; - } else { - stext = ptext; - ssize = psize; - encrypt_raw_packet = 0 /* not a raw OpenPGP message */; - } - - // Encrypt (maybe) signed data - - cmem = pgp_encrypt_buf(netpgp->io, stext, - ssize, rcpts, 1 /* armored */, - netpgp_getvar(netpgp, "cipher"), - encrypt_raw_packet); - - if (cmem == NULL) { - result = PEP_OUT_OF_MEMORY; - goto free_signedmem; - }else{ - - char *_buffer = NULL; - size_t length = pgp_mem_len(cmem); - - // Allocate transferable buffer - _buffer = malloc(length + 1); - assert(_buffer); - if (_buffer == NULL) { - result = PEP_OUT_OF_MEMORY; - goto free_cmem; - } - - memcpy(_buffer, pgp_mem_data(cmem), length); - - *ctext = _buffer; - *csize = length; - (*ctext)[*csize] = 0; // safeguard for naive users - result = PEP_STATUS_OK; - } - -free_cmem : - pgp_memory_free(cmem); -free_signedmem : - if (do_sign) { - pgp_memory_free(signedmem); - } -free_rcpts : - pgp_keyring_free(rcpts); -unlock_netpgp: - pthread_mutex_unlock(&netpgp_mutex); - - return result; -} - - PEP_STATUS pgp_sign_only( PEP_SESSION session, const char* fpr, const char *ptext, size_t psize, char **stext, size_t *ssize ) { - printf("%s:%d\n",__FILE__,__LINE__); + TRACE_FUNCS() pgp_key_t *signer = NULL; pgp_seckey_t *seckey = NULL; pgp_memory_t *signedmem = NULL; @@ -765,14 +551,16 @@ PEP_STATUS pgp_sign_only( assert(fpr && fpr[0]); - uint8_t uint_fpr[PGP_FINGERPRINT_SIZE]; + uint8_t *uint_fpr = NULL; size_t fprlen; unsigned from = 0; - if (str_to_fpr(fpr, uint_fpr, &fprlen)) { + if (string_to_uint(fpr, &uint_fpr, &fprlen)) { if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->secring, uint_fpr, fprlen, &from, NULL, 1,1)) == NULL) { /* reject revoked and expired */ result = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto free_snrs; } } else{ @@ -869,9 +657,46 @@ PEP_STATUS pgp_encrypt_and_sign( size_t psize, char **ctext, size_t *csize ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - PEP_STATUS result; - result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, true); + TRACE_FUNCS() + PEP_STATUS result = PEP_STATUS_OK; + stringlist_t *klp; + int ret; + uint8_t *fpr = NULL; + unsigned from; + size_t len = 0; + + pgp_memory_t *mem = NULL; + pgp_keyring_t *rcpts = NULL; + pgp_seckey_t *seckey = NULL; + pgp_key_t *signer = NULL; + pgp_key_t *key = NULL; + + assert(netpgp->secring); + + string_to_uint(keylist->value, &fpr, &len); + + from = 0; + signer = pgp_getkeybyfpr(netpgp->io, netpgp->secring, fpr, len, &from, NULL, 0, 0 ); + if(!signer) return PEP_KEY_NOT_FOUND; + + rcpts = malloc(sizeof(pgp_keyring_t)); + memset(rcpts,0,sizeof(pgp_keyring_t)); + + klp = keylist; + while(klp) { + string_to_uint(klp->value, &fpr, &len); + from = 0; + key = pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, len, &from, NULL, 0, 0 ); + if(key) { + pgp_keyring_add(rcpts, key); + } + klp = klp->next; + } + + mem = netpgp_encrypt_and_sign(netpgp, rcpts, seckey, ptext, psize, true, 1); + + free(rcpts); + return result; } @@ -880,9 +705,34 @@ PEP_STATUS pgp_encrypt_only( size_t psize, char **ctext, size_t *csize ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - PEP_STATUS result; - result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize, false); + TRACE_FUNCS() + PEP_STATUS result = PEP_STATUS_OK; + pgp_memory_t *mem; + pgp_keyring_t *rcpts = NULL; + unsigned from; + size_t len = 0; + uint8_t *fpr = NULL; + pgp_key_t *key = NULL; + stringlist_t *klp; + + rcpts = malloc(sizeof(pgp_keyring_t)); + memset(rcpts,0,sizeof(pgp_keyring_t)); + + klp = keylist; + while(klp) { + string_to_uint(klp->value, &fpr, &len); + from = 0; + key = pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, len, &from, NULL, 0, 0 ); + if(key) { + pgp_keyring_add(rcpts, key); + } + klp = klp->next; + } + + mem = netpgp_encrypt_and_sign(netpgp, rcpts, NULL, ptext, psize, false, 1); + + free(rcpts); + return result; } @@ -891,7 +741,7 @@ PEP_STATUS pgp_generate_keypair( PEP_SESSION session, pEp_identity *identity ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() pgp_key_t newseckey; pgp_key_t *newpubkey; @@ -967,9 +817,7 @@ PEP_STATUS pgp_generate_keypair( if (netpgp_save_pubring(netpgp) && netpgp_save_secring(netpgp)) { char *fprstr = NULL; - fpr_to_str(&fprstr, - newseckey.pubkeyfpr.fingerprint, - newseckey.pubkeyfpr.length); + uint_to_string(newseckey.pubkeyfpr.fingerprint, &fprstr, newseckey.pubkeyfpr.length); if (fprstr == NULL) { result = PEP_OUT_OF_MEMORY; @@ -1006,8 +854,8 @@ unlock_netpgp: PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - uint8_t fpr[PGP_FINGERPRINT_SIZE]; + TRACE_FUNCS() + uint8_t *fpr; size_t length; PEP_STATUS result; @@ -1022,7 +870,7 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) return PEP_UNKNOWN_ERROR; } - if (str_to_fpr(fprstr, fpr, &length)) { + if (string_to_uint(fprstr, &fpr, &length)) { unsigned insec = pgp_deletekeybyfpr(netpgp->io, (pgp_keyring_t *)netpgp->secring, (const uint8_t *)fpr, length); @@ -1031,6 +879,8 @@ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr) (const uint8_t *)fpr, length); if(!insec && !inpub){ result = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } else { result = PEP_STATUS_OK; @@ -1055,45 +905,107 @@ unlock_netpgp: return result; } -#define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----"_ENDL +void stringlist_from_keyring(pgp_keyring_t* keyring, stringlist_t **list) +{ + TRACE_FUNCS() + + int i; + char *fpr; + pgp_key_t key; + + for(i = 0; i < keyring->keyc; i++) { + key = keyring->keys[i]; + if(uint_to_string(key.pubkeyfpr.fingerprint, &fpr, PGP_FINGERPRINT_SIZE)) { + if(!*list) *list = new_stringlist(fpr); + else stringlist_add(*list, fpr); + } + } +} + +pEp_identity *ident_from_uid_fpr(char *uid, uint8_t *fpr) +{ + char *address; + char *user_id; + char *username; + + pEp_identity *ident; + ident = malloc(sizeof(pEp_identity)); + + ident->fpr = NULL; + uint_to_string(fpr, &ident->fpr, PGP_FINGERPRINT_SIZE); + printf("FPR: %s\n",ident->fpr); + + username=strtok(uid, "<"); + if(username[strlen(username)-1]==' ') username[strlen(username)-1]=0; + ident->username=malloc(strlen(username)); + strcpy(ident->username,username); + printf("User name: %s\n",ident->username); + + address=strtok(NULL, ">"); + ident->address=malloc(strlen(address)); + strcpy(ident->address,address); + printf("Address: %s\n",ident->address); + + user_id=strtok(address, "@"); + ident->user_id=malloc(strlen(user_id)); + strcpy(ident->user_id,user_id); + printf("User ID: %s\n",ident->address); + + return ident; +} + +identity_list *add_idents_from_keyring(pgp_keyring_t* keyring, identity_list *list) +{ + TRACE_FUNCS() + int i, j; + pgp_key_t key; + char *uid; + pEp_identity *ident; + + for(i = 0; i < keyring->keyc; i++ ) { + key = keyring->keys[i]; + for(j = 0; j < key.uidc; j++) { + uid = strdup(key.uids[j]); + ident = ident_from_uid_fpr(uid, key.pubkeyfpr.fingerprint); + list = identity_list_add(list, ident); + } + } + + return list; +} + +#define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----"_ENDL PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size, identity_list **private_idents, stringlist_t** imported_keys, uint64_t* changed_key_index) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() + + int ret; + PEP_STATUS result = PEP_STATUS_OK; + char* passphrase = NULL; if (!imported_keys && changed_key_index) return PEP_ILLEGAL_VALUE; - int i; - identity_list *priv_id = NULL, *priv_id_list = NULL; - pEp_identity *ident = NULL; - pgp_key_t key; + stringlist_t* key_fprs = NULL; pgp_memory_t *mem = NULL; - PEP_STATUS result = PEP_STATUS_OK; - const char* pgp_begin = "-----BEGIN PGP"; - size_t prefix_len = strlen(pgp_begin); assert(session); assert(key_data); + passphrase = session->curr_passphrase; + if(passphrase && passphrase[0]) { + netpgp_set_validation_password(passphrase); + } + + //pgp_set_debug_level("validate.c"); //pgp_set_debug_level("reader.c"); if(!session || !key_data) return PEP_ILLEGAL_VALUE; - // Because we also import binary keys we have to be careful with this. - // - if (strlen(key_data + prefix_len) > prefix_len) { - const char* subtract_junk = strnstr(key_data, pgp_begin, size); - // If it's not in there, we just try to import it as is... - if (subtract_junk) { - size -= (subtract_junk - key_data); - key_data = subtract_junk; - } - } - if(pthread_mutex_lock(&netpgp_mutex)){ return PEP_UNKNOWN_ERROR; } @@ -1105,37 +1017,51 @@ PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, } pgp_memory_add(mem, (const uint8_t*)key_data, size); - if (pgp_keyring_read_from_mem(netpgp->io, netpgp->pubring, netpgp->secring, _armoured(key_data, size, ARMOR_KEY_HEAD), mem) == 0){ - pgp_print_errors(stderr); - result = PEP_ILLEGAL_VALUE; + ret = pgp_keyring_read_from_mem(netpgp, netpgp->pubring, netpgp->secring, _armoured(key_data, size, ARMOR_KEY_HEAD), mem, 1); + switch(ret) { + case PGP_PASSWORD_REQUIRED: + printf("Password required\n"); + result=PEP_PASSPHRASE_REQUIRED; + goto unlock_netpgp; + break; + case PGP_WRONG_PASSWORD: + printf("Wrong password\n"); + result=PEP_WRONG_PASSPHRASE; + goto unlock_netpgp; + break; + default: + result=PEP_KEY_IMPORTED; + if(changed_key_index) { + (*changed_key_index)=0; + if (netpgp->pubring->keyc) { + (*changed_key_index)=pow(2,netpgp->pubring->keyc)-1; + } + //(*changed_key_index)=pow(2,netpgp->secring->keyc+netpgp->pubring->keyc)-1; + } + break; } pgp_memory_free(mem); - for(i=0;isecring->keyc;i++) { - priv_id=malloc(sizeof(identity_list)); - ident=priv_id->ident=malloc(sizeof(pEp_identity)); - key=netpgp->secring->keys[i]; - fpr_to_str(&ident->fpr,key.pubkeyfpr.fingerprint,key.pubkeyfpr.length); - printf("fpr=%s\n",ident->fpr); - priv_id->next=NULL; - priv_id_list=priv_id_list?identity_list_join(priv_id_list,priv_id):priv_id; + if(private_idents) { + printf("Return private indents\n"); + (*private_idents) = NULL; + (*private_idents) = add_idents_from_keyring(netpgp->secring, (*private_idents)); + //(*private_idents) = add_idents_from_keyring(netpgp->pubring, (*private_idents)); } -// private_idents=malloc(sizeof(private_idents)); - printf("Returning values private_idents=%p\n",private_idents); - printf("Returning values imported_keys=%p\n",imported_keys); - if(private_idents) { - printf("Returning values *private_idents=%p\n",*private_idents); - *private_idents=priv_id_list; + if(imported_keys) { + printf("Return list of imported keys\n"); + stringlist_from_keyring(netpgp->pubring, imported_keys); } + netpgp_save_pubring(netpgp); + netpgp_save_secring(netpgp); + // save rings - if (netpgp_save_pubring(netpgp) && netpgp_save_secring(netpgp)) - { - result = PEP_KEY_IMPORTED; - } else { - result = PEP_UNKNOWN_ERROR; - } + //if ( !netpgp_save_pubring(netpgp) || !netpgp_save_secring(netpgp) ) + //{ + // result = PEP_UNKNOWN_ERROR; + //} unlock_netpgp: pthread_mutex_unlock(&netpgp_mutex); @@ -1149,7 +1075,7 @@ static PEP_STATUS _export_keydata( size_t *buflen ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() PEP_STATUS result; pgp_output_t *output; pgp_memory_t *mem; @@ -1191,9 +1117,9 @@ PEP_STATUS pgp_export_keydata( bool secret ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() pgp_key_t *key; - uint8_t fpr[PGP_FINGERPRINT_SIZE]; + uint8_t *fpr = NULL; size_t fprlen; PEP_STATUS result; @@ -1218,10 +1144,12 @@ PEP_STATUS pgp_export_keydata( return PEP_UNKNOWN_ERROR; } - if (str_to_fpr(fprstr, fpr, &fprlen)) { + if (string_to_uint(fprstr, &fpr, &fprlen)) { unsigned from = 0; if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, srcring, fpr, fprlen, &from, NULL,0,0)) == NULL) { result = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } }else{ @@ -1251,7 +1179,7 @@ struct HKP_answer { PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() assert(!"pgp_recv_key not implemented"); return PEP_UNKNOWN_ERROR; } @@ -1261,44 +1189,33 @@ typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *); static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, const char *pattern, find_key_cb_t cb, void* cb_arg) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - uint8_t fpr[PGP_FINGERPRINT_SIZE]; + TRACE_FUNCS() + uint8_t *fpr = NULL; size_t length; + unsigned from; pgp_key_t *key; PEP_STATUS result; // Try find a fingerprint in pattern - if (str_to_fpr(pattern, fpr, &length)) { - unsigned from = 0; - + if (string_to_uint(pattern, &fpr, &length)) { // Only one fingerprint can match - if ((key = (pgp_key_t *)pgp_getkeybyfpr( - netpgp->io, - keyring, - (const uint8_t *)fpr, length, - &from, - NULL, 0, 0)) == NULL) { - + from = 0; + key = pgp_getkeybyfpr(netpgp->io, keyring, fpr, length, &from, NULL, 0, 0); + if ( key == NULL) { return PEP_KEY_NOT_FOUND; } - result = cb(cb_arg, key); - } else { + TRACE_FUNCS() // Search by name for pattern. Can match many. - unsigned from = 0; + from = 0; result = PEP_KEY_NOT_FOUND; - while((key = (pgp_key_t *)pgp_getnextkeybyname( - netpgp->io, - keyring, - (const char *)pattern, - &from)) != NULL) { - +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + while((key = (pgp_key_t *)pgp_getnextkeybyname(netpgp->io, keyring, (const char *)pattern, &from)) != NULL) { result = cb(cb_arg, key); if (result != PEP_STATUS_OK) break; - from++; } } @@ -1306,15 +1223,13 @@ static PEP_STATUS find_keys_do(pgp_keyring_t* keyring, return result; } -static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key) +static PEP_STATUS add_key_uint_to_stringinglist(void *arg, pgp_key_t *key) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() stringlist_t **keylist = arg; char *newfprstr = NULL; - fpr_to_str(&newfprstr, - key->pubkeyfpr.fingerprint, - key->pubkeyfpr.length); + uint_to_string(key->pubkeyfpr.fingerprint, &newfprstr, key->pubkeyfpr.length); if (newfprstr == NULL) { return PEP_OUT_OF_MEMORY; @@ -1329,15 +1244,13 @@ static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key) return PEP_STATUS_OK; } -static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key) +static PEP_STATUS add_secret_key_uint_to_stringinglist(void *arg, pgp_key_t *key) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() if (pgp_is_key_secret(key)) { stringlist_t **keylist = arg; char *newfprstr = NULL; - - fpr_to_str(&newfprstr, key->pubkeyfpr.fingerprint, key->pubkeyfpr.length); - + uint_to_string(key->pubkeyfpr.fingerprint, &newfprstr, key->pubkeyfpr.length); if (newfprstr == NULL) { return PEP_OUT_OF_MEMORY; } else { @@ -1352,7 +1265,7 @@ static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key) } static PEP_STATUS add_keyinfo_to_stringpair_list(void* arg, pgp_key_t *key) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() stringpair_list_t** keyinfo_list = (stringpair_list_t**)arg; stringpair_t* pair = NULL; char* id_fpr = NULL; @@ -1366,8 +1279,7 @@ static PEP_STATUS add_keyinfo_to_stringpair_list(void* arg, pgp_key_t *key) { // if (key_revoked || key_status == PEP_GET_KEY_FAILED) // return PEP_STATUS_OK; // we just move on - fpr_to_str(&id_fpr, key->pubkeyfpr.fingerprint, - key->pubkeyfpr.length); + uint_to_string(key->pubkeyfpr.fingerprint, &id_fpr, key->pubkeyfpr.length); pair = new_stringpair(id_fpr, primary_userid); @@ -1385,7 +1297,7 @@ PEP_STATUS pgp_find_keys( PEP_SESSION session, const char *pattern, stringlist_t **keylist ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() stringlist_t *_keylist, *_k; PEP_STATUS result; @@ -1412,8 +1324,7 @@ PEP_STATUS pgp_find_keys( } _k = _keylist; - result = find_keys_do((pgp_keyring_t *)netpgp->pubring, - pattern, &add_key_fpr_to_stringlist, &_k); + result = find_keys_do(netpgp->pubring, pattern, &add_key_uint_to_stringinglist, &_k); if (result == PEP_STATUS_OK) { *keylist = _keylist; @@ -1434,24 +1345,21 @@ unlock_netpgp: PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() assert(!"pgp_send_key not implemented"); return PEP_UNKNOWN_ERROR; } PEP_STATUS pgp_get_key_rating( - PEP_SESSION session, - const char *fprstr, - PEP_comm_type *comm_type - ) + PEP_SESSION session, const char *fprstr, PEP_comm_type *comm_type) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() pgp_key_t *key; - uint8_t fpr[PGP_FINGERPRINT_SIZE]; + uint8_t *fpr = NULL; unsigned from = 0; size_t length; - + int rating; PEP_STATUS status = PEP_STATUS_OK; @@ -1468,20 +1376,19 @@ PEP_STATUS pgp_get_key_rating( return PEP_UNKNOWN_ERROR; } - if (!str_to_fpr(fprstr, fpr, &length)) { + if (!string_to_uint(fprstr, &fpr, &length)) { status = PEP_ILLEGAL_VALUE; goto unlock_netpgp; } - key = pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, length, &from, NULL,0,0); - + key = pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, length, &from, NULL, 0, 0); if(key == NULL) { status = PEP_KEY_NOT_FOUND; goto unlock_netpgp; } - - switch(pgp_key_get_rating(key)){ + rating = pgp_key_get_rating(key); + switch(rating){ case PGP_VALID: *comm_type = PEP_ct_OpenPGP_unconfirmed; break; @@ -1516,7 +1423,7 @@ PEP_STATUS pgp_renew_key( const timestamp *ts ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() pgp_key_t *pkey; pgp_key_t *skey; uint8_t fpr[PGP_FINGERPRINT_SIZE]; @@ -1553,33 +1460,29 @@ PEP_STATUS pgp_renew_key( } - if (!str_to_fpr(fprstr, fpr, &length)) { + if (!string_to_uint(fprstr, &fpr, &length)) { status = PEP_ILLEGAL_VALUE; goto unlock_netpgp; } - pkey = pgp_getkeybyfpr( - netpgp->io, - netpgp->pubring, - fpr, length, &from, NULL, - 1, 0); /* reject revoked, accept expired */ + pkey = pgp_getkeybyfpr(netpgp->io, netpgp->pubring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ if(pkey == NULL) { status = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } from = 0; - skey = pgp_getkeybyfpr( - netpgp->io, - netpgp->secring, - fpr, length, &from, NULL, - 1, 0); /* reject revoked, accept expired */ + skey = pgp_getkeybyfpr( netpgp->io, netpgp->secring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ if(skey == NULL) { status = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } @@ -1617,8 +1520,8 @@ PEP_STATUS pgp_revoke_key( const char *reason ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - uint8_t fpr[PGP_FINGERPRINT_SIZE]; + TRACE_FUNCS() + uint8_t *fpr = NULL; size_t length; unsigned from = 0; @@ -1635,33 +1538,29 @@ PEP_STATUS pgp_revoke_key( } // FIXME : deduplicate that code w/ renew - if (!str_to_fpr(fprstr, fpr, &length)) { + if (!string_to_uint(fprstr, &fpr, &length)) { status = PEP_ILLEGAL_VALUE; goto unlock_netpgp; } - pgp_key_t *pkey = pgp_getkeybyfpr( - netpgp->io, - netpgp->pubring, - fpr, length, &from, NULL, - 1, 0); /* reject revoked, accept expired */ + pgp_key_t *pkey = pgp_getkeybyfpr( netpgp->io, netpgp->pubring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ if(pkey == NULL) { status = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } from = 0; - pgp_key_t *skey = pgp_getkeybyfpr( - netpgp->io, - netpgp->secring, - fpr, length, &from, NULL, - 1, 0); /* reject revoked, accept expired */ + pgp_key_t *skey = pgp_getkeybyfpr( netpgp->io, netpgp->secring, fpr, length, &from, NULL, 1, 0); /* reject revoked, accept expired */ if(skey == NULL) { status = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } @@ -1682,7 +1581,7 @@ PEP_STATUS pgp_key_expired( bool *expired ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() PEP_STATUS status = PEP_STATUS_OK; PEP_comm_type comm_type; @@ -1715,7 +1614,7 @@ PEP_STATUS pgp_key_revoked( bool *revoked ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() PEP_STATUS status = PEP_STATUS_OK; PEP_comm_type comm_type; @@ -1743,8 +1642,8 @@ PEP_STATUS pgp_key_created( time_t *created ) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); - uint8_t fpr[PGP_FINGERPRINT_SIZE]; + TRACE_FUNCS() + uint8_t *fpr; pgp_key_t *key; size_t length; unsigned from = 0; @@ -1764,15 +1663,12 @@ PEP_STATUS pgp_key_created( return PEP_UNKNOWN_ERROR; } - if (!str_to_fpr(fprstr, fpr, &length)) { + if (!string_to_uint(fprstr, &fpr, &length)) { status = PEP_ILLEGAL_VALUE; goto unlock_netpgp; } - key = pgp_getkeybyfpr( - netpgp->io, - netpgp->pubring, - fpr, length, &from, NULL,0,0); + key = pgp_getkeybyfpr( netpgp->io, netpgp->pubring, fpr, length, &from, NULL,0,0); if (key) { @@ -1781,6 +1677,8 @@ PEP_STATUS pgp_key_created( else { status = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + goto unlock_netpgp; } @@ -1796,7 +1694,7 @@ unlock_netpgp: PEP_STATUS pgp_list_keyinfo( PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() if (!session || !keyinfo_list) return PEP_UNKNOWN_ERROR; @@ -1811,22 +1709,23 @@ PEP_STATUS pgp_list_keyinfo( PEP_STATUS result; - result = find_keys_do((pgp_keyring_t *)netpgp->pubring, - pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list); + result = find_keys_do(netpgp->pubring, pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list); if (!keyinfo_list) result = PEP_KEY_NOT_FOUND; +printf("%s:%d, Key not found\n",__FILE__,__LINE__); + pthread_mutex_unlock(&netpgp_mutex); return result; } -/* copied from find_keys, but we need to use a callback that filters. */ PEP_STATUS pgp_find_private_keys( - PEP_SESSION session, const char *pattern, stringlist_t **keylist) + PEP_SESSION session, const char *pattern, stringlist_t **keylist +) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() stringlist_t *_keylist, *_k; PEP_STATUS result; @@ -1834,10 +1733,10 @@ PEP_STATUS pgp_find_private_keys( assert(session); assert(keylist); - if (!session || !keylist ) - { - return PEP_ILLEGAL_VALUE; - } + //if (!session || !keylist ) + //{ + // return PEP_ILLEGAL_VALUE; + //} if (pthread_mutex_lock(&netpgp_mutex)) { @@ -1852,8 +1751,7 @@ PEP_STATUS pgp_find_private_keys( } _k = _keylist; - result = find_keys_do((pgp_keyring_t *)netpgp->secring, - pattern, &add_secret_key_fpr_to_stringlist, &_k); + result = find_keys_do(netpgp->secring, pattern, &add_secret_key_uint_to_stringinglist, &_k); if (result == PEP_STATUS_OK) { *keylist = _keylist; @@ -1870,10 +1768,11 @@ unlock_netpgp: } PEP_STATUS pgp_contains_priv_key( - PEP_SESSION session, - const char *fpr, - bool *has_private) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + PEP_SESSION session, + const char *fpr, + bool *has_private) +{ + TRACE_FUNCS() stringlist_t* keylist = NULL; PEP_STATUS status = pgp_find_private_keys(session, fpr, &keylist); if (status == PEP_STATUS_OK && keylist) { @@ -1889,12 +1788,12 @@ PEP_STATUS pgp_contains_priv_key( PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) { // Not implemented - netpgp doesn't appear to keep track of trust status in // a meaningful way, though there is space for it in the structs. - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() return PEP_STATUS_OK; } PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite) { - printf("%s:%d, %s\n",__FILE__,__LINE__,__FUNCTION__); + TRACE_FUNCS() if (suite == PEP_CIPHER_SUITE_DEFAULT) { return PEP_STATUS_OK; } else { diff --git a/src/pgp_netpgp.h b/src/pgp_netpgp.h index 41bec633..c54567e9 100644 --- a/src/pgp_netpgp.h +++ b/src/pgp_netpgp.h @@ -1,85 +1,343 @@ -// This file is under GNU General Public License 3.0 +/** + * @file src/pgp_netpgp.h + * + * @brief NETPGP driver - implements required cryptotech + * functions for the engine using netpgp with SSL + * + * @license GNU General Public License 3.0 - see LICENSE.txt + */ -#pragma once +#ifndef PGP_PEP_NETPGP_H +#define PGP_PEP_NETPGP_H #include "pEpEngine.h" +/** + * + * + * @brief initialise the sequoia driver for this session + * + * @param[in] session session handle + * @param[in] in_first true if this is the first pEp session running + * after startup, else false + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_init(PEP_SESSION session, bool in_first); + +/** + * + * + * @brief release resources used by the sequoia driver in this session + * + * @param[in] session session handle + * @param[in] out_last true if this is the last extant pEp session + * running, else false + * + */ void pgp_release(PEP_SESSION session, bool out_last); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] ctext const char* + * @param[in] csize size_t + * @param[in] dsigtext const char* + * @param[in] dsigsize size_t + * @param[in] ptext char** + * @param[in] psize size_t* + * @param[in] keylist stringlist_t** + * @param[in] filename_ptr char** + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_decrypt_and_verify( PEP_SESSION session, const char *ctext, size_t csize, const char *dsigtext, size_t dsigsize, char **ptext, size_t *psize, stringlist_t **keylist, - char** filename_ptr // will be ignored + char** filename_ptr ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] keylist const stringlist_t* + * @param[in] ptext const char* + * @param[in] psize size_t + * @param[out] ctext char** + * @param[out] csize size_t* + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_encrypt_and_sign( PEP_SESSION session, const stringlist_t *keylist, const char *ptext, size_t psize, char **ctext, size_t *csize ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] ptext const char* + * @param[in] psize size_t + * @param[out] stext char** + * @param[out] ssize size_t* + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ +PEP_STATUS pgp_sign_only( + PEP_SESSION session, const char* fpr, const char *ptext, + size_t psize, char **stext, size_t *ssize + ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] keylist const stringlist_t* + * @param[in] ptext const char* + * @param[in] psize size_t + * @param[out] ctext char** + * @param[out] csize size_t* + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_encrypt_only( PEP_SESSION session, const stringlist_t *keylist, const char *ptext, size_t psize, char **ctext, size_t *csize ); -PEP_STATUS pgp_sign_only( - PEP_SESSION session, const char* fpr, const char *ptext, - size_t psize, char **stext, size_t *ssize - ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] text const char* + * @param[in] size size_t + * @param[in] signature const char* + * @param[in] sig_size size_t + * @param[in] keylist stringlist_t** + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_verify_text( PEP_SESSION session, const char *text, size_t size, const char *signature, size_t sig_size, stringlist_t **keylist ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] key_data char** + * @param[in] size size_t* + * @param[in] secret bool + * + * @retval PEP_STATUS_OK + * @retval any other value on error + */ PEP_STATUS pgp_export_keydata( PEP_SESSION session, const char *fpr, char **key_data, size_t *size, bool secret ); +/** + * + * + * @brief Find all keys (as fpr strings) which match this fpr or OpenPGP + * userid pattern + * + * @param[in] session session handle + * @param[in] pattern Pattern to search for; could be empty, + * an fpr, or a mailbox (email, URI, etc). + * @param[in,out] keylist A list of fprs containing matching keys. + * + * @note Unlike pgp_list_keyinfo, this function returns revoked keys. + * + * @see pgp_list_keyinfo() + */ PEP_STATUS pgp_find_keys( PEP_SESSION session, const char *pattern, stringlist_t **keylist ); +/** + * + * + * @brief Find all keys (returning pairs) which match this fpr + * or OpenPGP userid pattern + * + * @param[in] session session handle + * @param[in] pattern Pattern to search for; could be empty, + * an fpr, or a mailbox (email, URI, etc). + * @param[in,out] keyinfo_list A list of tuples for the + * matching keys. + * + * @note This function filters out revoked keys, but NOT expired keys. + */ PEP_STATUS pgp_list_keyinfo( - PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list + PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] identity pEp_identity* + * + */ PEP_STATUS pgp_generate_keypair( PEP_SESSION session, pEp_identity *identity ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] comm_type PEP_comm_type* + * + */ PEP_STATUS pgp_get_key_rating( PEP_SESSION session, const char *fpr, PEP_comm_type *comm_type ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] key_data const char * + * @param[in] size size_t + * @param[in] private_idents identity_list ** + * @param[in] imported_keys stringlist_t ** + * @param[in] changed_key_index uint64_t * + * + */ PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size, identity_list **private_idents, stringlist_t** imported_keys, uint64_t* changed_key_index); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] key_data const char* + * @param[in] size size_t + * @param[in] private_idents identity_list** + * + */ +PEP_STATUS pgp_import_private_keydata(PEP_SESSION session, const char *key_data, + size_t size, identity_list **private_idents); + +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] pattern const char* + * + */ PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] pattern const char* + * + */ PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] ts const timestamp* + * + */ PEP_STATUS pgp_renew_key( PEP_SESSION session, const char *fpr, const timestamp *ts ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] reason const char* + * + */ PEP_STATUS pgp_revoke_key( PEP_SESSION session, const char *fpr, const char *reason ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] when const time_t + * @param[in] expired bool* + * + */ PEP_STATUS pgp_key_expired( PEP_SESSION session, const char *fpr, @@ -87,31 +345,82 @@ PEP_STATUS pgp_key_expired( bool *expired ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[out] revoked bool* + * + */ PEP_STATUS pgp_key_revoked( PEP_SESSION session, const char *fpr, bool *revoked ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[out] created time_t* + * + */ PEP_STATUS pgp_key_created( PEP_SESSION session, - const char *fprstr, + const char *fpr, time_t *created ); +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] fpr const char* + * @param[in] has_private bool* + * + */ PEP_STATUS pgp_contains_priv_key( - PEP_SESSION session, - const char *fpr, - bool *has_private); + PEP_SESSION session, + const char *fpr, + bool *has_private); +/** + * + * + * @brief Find all keys (as fpr strings) which match this fpr or OpenPGP + * userid pattern AND contain a private key + * + * @param[in] session session handle + * @param[in] pattern Pattern to search for; could be empty, + * an fpr, or a mailbox (email, URI, etc). + * @param[in,out] keylist A list of fprs containing matching keys. + * + * @note Unlike pgp_list_keyinfo, this function returns revoked keys. + * + * @see pgp_list_keyinfo() + */ PEP_STATUS pgp_find_private_keys( PEP_SESSION session, const char *pattern, stringlist_t **keylist ); -// Stub - just returns PEP_STATUS_OK, as netpgp isn't sufficient to do this. -PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session); - +/** + * + * + * @brief TODO + * + * @param[in] session session handle + * @param[in] suite PEP_CIPHER_SUITE + * + */ PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite); - +#endif From 330ddb1949443c37288d0d3d95eacdd8d61c9a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= Date: Tue, 27 Jul 2021 19:23:14 +0100 Subject: [PATCH 15/15] z/OS support: timestamp fix Fixing the way the time stamp is calculated on z/OS --- src/timestamp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/timestamp.c b/src/timestamp.c index 96c2dd5a..d5ac322b 100644 --- a/src/timestamp.c +++ b/src/timestamp.c @@ -24,12 +24,15 @@ DYNAMIC_API time_t timegm_with_gmtoff(const timestamp* ts) if (_ts) { #if defined(ZOS) const time_t raw_time = mktime(_ts); + if (raw_time != -1) { + retval = raw_time; + } #else const time_t raw_time = timegm(_ts); -#endif if (raw_time != -1) { - retval = raw_time - ts->tm_gmtoff; + retval = raw_time - _ts->tm_gmtoff; } +#endif } }