Author | SHA1 | Message | Date |
---|---|---|---|
|
cddafe4c76 | implement toggle() which was missing for whatever reason. :-O | 7 months ago |
|
2e3dd04af6 | add reference to unittest_logger.cc to document usage of the Logger. | 7 months ago |
|
3408d6f436 | make the unittest much more comprehensive and show the different usages of the Logger, and add some comments to explain things. :-) | 7 months ago |
|
ac2d89b641 | make README.md Logger-specific | 7 months ago |
|
587932a19f | strip down Makefile. | 7 months ago |
|
002fb754a5 | remove non-logger stuff from html directory. | 7 months ago |
|
efeed4abd7 | renamed 'server' into 'src' | 7 months ago |
|
6775938b17 | remove non-logger unittests. | 7 months ago |
|
5efa414e59 | delete all non-logger stuff. | 7 months ago |
@ -1,747 +0,0 @@ | |||
### Detailed Function reference for the p≡p JSON Server Adapter. Version “(38) Frankenberg”, API version 0.15.0 ### | |||
Output parameters are denoted by a **⇑** , InOut parameters are denoted by a **⇕** after the parameter type. | |||
Nota bene: This list was created manually from the "authorative API description" and might be outdated. | |||
#### Message API #### | |||
##### MIME_encrypt_message( String mimetext, Integer size, StringList extra, String⇑ mime_ciphertext, PEP_enc_format env_format, Integer flags) ##### | |||
encrypt a MIME message, with MIME output | |||
``` | |||
parameters: | |||
mimetext (in) MIME encoded text to encrypt | |||
size (in) size of input mime text | |||
extra (in) extra keys for encryption | |||
mime_ciphertext (out) encrypted, encoded message | |||
enc_format (in) encrypted format | |||
flags (in) flags to set special encryption features | |||
return value: | |||
PEP_STATUS_OK if everything worked | |||
PEP_BUFFER_TOO_SMALL if encoded message size is too big to handle | |||
PEP_CANNOT_CREATE_TEMP_FILE | |||
if there are issues with temp files; in | |||
this case errno will contain the underlying | |||
error | |||
PEP_OUT_OF_MEMORY if not enough memory could be allocated | |||
``` | |||
*Caveat:* the encrypted, encoded mime text will go to the ownership of the caller; mimetext | |||
will remain in the ownership of the caller | |||
##### MIME_encrypt_message_for_self( Identity target_id, String mimetext, Integer size, StringList extra, String⇑ mime_ciphertext, PEP_enc_format enc_format, Integer flags) ##### | |||
encrypt MIME message for user's identity only, ignoring recipients and other identities from | |||
the message, with MIME output | |||
``` | |||
parameters: | |||
target_id (in) self identity this message should be encrypted for | |||
mimetext (in) MIME encoded text to encrypt | |||
size (in) size of input mime text | |||
extra (in) extra keys for encryption | |||
mime_ciphertext (out) encrypted, encoded message | |||
enc_format (in) encrypted format | |||
flags (in) flags to set special encryption features | |||
return value: | |||
PEP_STATUS_OK if everything worked | |||
PEP_BUFFER_TOO_SMALL if encoded message size is too big to handle | |||
PEP_CANNOT_CREATE_TEMP_FILE | |||
if there are issues with temp files; in | |||
this case errno will contain the underlying | |||
error | |||
PEP_OUT_OF_MEMORY if not enough memory could be allocated | |||
caveat: | |||
the encrypted, encoded mime text will go to the ownership of the caller; mimetext | |||
will remain in the ownership of the caller | |||
``` | |||
##### MIME_decrypt_message(String mimetext, Integer size, String⇑ mime_plaintext, StringList⇑ keylist, PEP_rating⇑ rating, Integer⇕ flags, String⇑ modified_src) | |||
decrypt a MIME message, with MIME output | |||
``` | |||
parameters: | |||
mimetext (in) MIME encoded text to decrypt | |||
size (in) size of mime text to decode (in order to decrypt) | |||
mime_plaintext (out) decrypted, encoded message | |||
keylist (out) stringlist with keyids | |||
rating (out) rating for the message | |||
flags (inout) flags to signal special decryption features | |||
modified_src (out) modified source string, if decrypt had reason to change it | |||
return value: | |||
decrypt status if everything worked with MIME encode/decode, | |||
the status of the decryption is returned | |||
(PEP_STATUS_OK or decryption error status) | |||
PEP_BUFFER_TOO_SMALL if encoded message size is too big to handle | |||
PEP_CANNOT_CREATE_TEMP_FILE | |||
if there are issues with temp files; in | |||
this case errno will contain the underlying | |||
error | |||
PEP_OUT_OF_MEMORY if not enough memory could be allocated | |||
flag values: | |||
in: | |||
PEP_decrypt_flag_untrusted_server | |||
used to signal that decrypt function should engage in behaviour | |||
specified for when the server storing the source is untrusted. | |||
out: | |||
PEP_decrypt_flag_own_private_key | |||
private key was imported for one of our addresses (NOT trusted | |||
or set to be used - handshake/trust is required for that) | |||
PEP_decrypt_flag_src_modified | |||
indicates that the modified_src field should contain a modified | |||
version of the source, at the moment always as a result of the | |||
input flags. | |||
PEP_decrypt_flag_consume | |||
used by sync | |||
PEP_decrypt_flag_ignore | |||
used by sync | |||
caveat: | |||
the decrypted, encoded mime text will go to the ownership of the caller; mimetext | |||
will remain in the ownership of the caller | |||
``` | |||
##### startKeySync() | |||
Start Key Synchronization for the current session. | |||
##### stopKeySync() | |||
Stop Key Synchronization for the current session. | |||
##### encrypt_message(Message src, StringList extra_keys, Message⇑ dst, PEP_enc_format enc_format, Integer flags) | |||
encrypt message in memory | |||
``` | |||
parameters: | |||
src (in) message to encrypt | |||
extra_keys (in) extra keys for encryption | |||
dst (out) pointer to new encrypted message or NULL on failure | |||
enc_format (in) encrypted format | |||
flags (in) flags to set special encryption features | |||
return value: | |||
PEP_STATUS_OK on success | |||
PEP_KEY_NOT_FOUND at least one of the receipient keys | |||
could not be found | |||
PEP_KEY_HAS_AMBIG_NAME at least one of the receipient keys has | |||
an ambiguous name | |||
PEP_GET_KEY_FAILED cannot retrieve key | |||
PEP_UNENCRYPTED no recipients with usable key, | |||
message is left unencrypted, | |||
and key is attached to it | |||
``` | |||
##### encrypt_message_and_add_priv_key( Message src, Message⇑ dst, String to_fingerprint, PEP_enc_format enc_format, Integer flags) | |||
encrypt message in memory, adding an encrypted private key (encrypted separately and sent within the inner message) | |||
``` | |||
parameters: | |||
session (in) session handle | |||
src (in) message to encrypt | |||
dst (out) pointer to new encrypted message or NULL if no | |||
encryption could take place | |||
to_fpr fingerprint of the recipient key to which the private key | |||
should be encrypted | |||
enc_format (in) encrypted format | |||
flags (in) flags to set special encryption features | |||
return value: | |||
PEP_STATUS_OK on success | |||
PEP_KEY_HAS_AMBIG_NAME at least one of the receipient keys has | |||
an ambiguous name | |||
PEP_UNENCRYPTED on demand or no recipients with usable | |||
key, is left unencrypted, and key is | |||
attached to it | |||
caveat: | |||
the ownershop of src remains with the caller | |||
the ownership of dst goes to the caller | |||
``` | |||
##### encrypt_message_for_self(Identity target_id, Message src, Message⇑ dst, PEP_enc_format enc_format, Integer flags) | |||
encrypt message in memory for user's identity only, | |||
ignoring recipients and other identities from | |||
the message. | |||
``` | |||
parameters: | |||
target_id (in) self identity this message should be encrypted for | |||
src (in) message to encrypt | |||
dst (out) pointer to new encrypted message or NULL on failure | |||
enc_format (in) encrypted format | |||
flags (in) flags to set special encryption features | |||
return value: (FIXME: This may not be correct or complete) | |||
PEP_STATUS_OK on success | |||
PEP_KEY_NOT_FOUND at least one of the receipient keys | |||
could not be found | |||
PEP_KEY_HAS_AMBIG_NAME at least one of the receipient keys has | |||
an ambiguous name | |||
PEP_GET_KEY_FAILED cannot retrieve key | |||
``` | |||
*Caveat:* message is NOT encrypted for identities other than the target_id (and then, | |||
only if the target_id refers to self!) | |||
##### decrypt_message(Message⇕ src, Message⇑ dst, StringList⇑ keylist, PEP_rating⇑ rating, Integer⇕ flags) | |||
decrypt message in memory | |||
``` | |||
parameters: | |||
src (inout) message to decrypt | |||
dst (out) pointer to new decrypted message or NULL on failure | |||
keylist (out) stringlist with keyids | |||
rating (out) rating for the message | |||
flags (inout) flags to signal special decryption features | |||
return value: | |||
error status | |||
or PEP_DECRYPTED if message decrypted but not verified | |||
or PEP_CANNOT_REENCRYPT if message was decrypted (and possibly | |||
verified) but a reencryption operation is expected by the caller | |||
and failed | |||
or PEP_STATUS_OK on success | |||
flag values: | |||
in: | |||
PEP_decrypt_flag_untrusted_server | |||
used to signal that decrypt function should engage in behaviour | |||
specified for when the server storing the source is untrusted | |||
out: | |||
PEP_decrypt_flag_own_private_key | |||
private key was imported for one of our addresses (NOT trusted | |||
or set to be used - handshake/trust is required for that) | |||
PEP_decrypt_flag_src_modified | |||
indicates that the src object has been modified. At the moment, | |||
this is always as a direct result of the behaviour driven | |||
by the input flags. This flag is the ONLY value that should be | |||
relied upon to see if such changes have taken place. | |||
PEP_decrypt_flag_consume | |||
used by sync | |||
PEP_decrypt_flag_ignore | |||
used by sync | |||
caveat: | |||
the ownership of src remains with the caller - however, the contents | |||
might be modified (strings freed and allocated anew or set to NULL, | |||
etc) intentionally; when this happens, PEP_decrypt_flag_src_modified | |||
is set. | |||
the ownership of dst goes to the caller | |||
the ownership of keylist goes to the caller | |||
if src is unencrypted this function returns PEP_UNENCRYPTED and sets | |||
dst to NULL | |||
``` | |||
##### outgoing_message_rating(Message msg, PEP_rating⇑ rating) | |||
get rating for an outgoing message | |||
``` | |||
parameters: | |||
msg (in) message to get the rating for | |||
rating (out) rating for the message | |||
return value: | |||
error status or PEP_STATUS_OK on success | |||
caveat: | |||
msg->from must point to a valid pEp_identity | |||
msg->dir must be PEP_dir_outgoing | |||
``` | |||
##### re_evaluate_message_rating(Message msg, StringList keylist, PEP_rating enc_status, PEP_rating⇑ rating) | |||
re-evaluate already decrypted message rating | |||
``` | |||
parameters: | |||
msg (in) message to get the rating for | |||
keylist (in) decrypted message recipients keys fpr | |||
enc_status (in) original rating for the decrypted message | |||
rating (out) rating for the message | |||
return value: | |||
PEP_ILLEGAL_VALUE if decrypted message doesn't contain | |||
X-EncStatus optional field and x_enc_status is | |||
pEp_rating_udefined | |||
or if decrypted message doesn't contain | |||
X-Keylist optional field and x_keylist is NULL | |||
PEP_OUT_OF_MEMORY if not enough memory could be allocated | |||
caveat: | |||
msg->from must point to a valid pEp_identity | |||
``` | |||
##### identity_rating(Identity ident, PEP_rating⇑ rating) | |||
get rating for a single identity | |||
``` | |||
parameters: | |||
ident (in) identity to get the rating for | |||
rating (out) rating for the identity | |||
return value: | |||
error status or PEP_STATUS_OK on success | |||
``` | |||
##### get_gpg_path(String⇑) | |||
get path of gpg binary. | |||
#### MIME message handling #### | |||
##### mime_decode_message(String mime_message, Integer message_lenght, Message msg) | |||
#### pEp Engine Core API #### | |||
##### get_trustwords(Identity id1, Identity id2, Language lang, String⇑ words, Integer⇑ wsize, Bool full) | |||
get full trustwords string for a *pair* of identities | |||
``` | |||
parameters: | |||
id1 (in) identity of first party in communication - fpr can't be NULL | |||
id2 (in) identity of second party in communication - fpr can't be NULL | |||
lang (in) C string with ISO 639-1 language code | |||
words (out) pointer to C string with all trustwords UTF-8 encoded, | |||
separated by a blank each | |||
NULL if language is not supported or trustword | |||
wordlist is damaged or unavailable | |||
wsize (out) length of full trustwords string | |||
full (in) if true, generate ALL trustwords for these identities. | |||
else, generate a fixed-size subset. (TODO: fixed-minimum-entropy | |||
subset in next version) | |||
return value: | |||
PEP_STATUS_OK trustwords retrieved | |||
PEP_OUT_OF_MEMORY out of memory | |||
PEP_TRUSTWORD_NOT_FOUND at least one trustword not found | |||
``` | |||
##### get_languagelist(String⇑ languages) | |||
get the list of languages | |||
``` | |||
parameters: | |||
languages (out) languages as string in double quoted CSV format | |||
column 1 is the ISO 639-1 language code | |||
column 2 is the name of the language | |||
``` | |||
##### is_pep_user(Identity id, Bool⇑ ia_pwp) | |||
returns true if the USER corresponding to this identity has been listed in the *person* table as a pEp user | |||
``` | |||
parameters: | |||
identity (in) - identity containing the user_id to check (this is | |||
the only part of the struct we require to be set) | |||
is_pep (out) - boolean pointer - will return true or false by | |||
reference with respect to whether or not user is | |||
a known pep user | |||
``` | |||
##### config_passive_mode(Bool enable) | |||
enable passive mode | |||
* parameters: enable (in) flag if enabled or disabled | |||
##### config_unencrypted_subject(Bool enable) | |||
disable subject encryption | |||
* parameters: enable (in) flag if enabled or disabled | |||
#### Identity Management API #### | |||
##### get_identity(String address, String user_id, Identity⇑ identity) | |||
get identity information | |||
``` | |||
parameters: | |||
address (in) string with communication address, UTF-8 encoded | |||
user_id (in) unique string to identify person that identity is refering to | |||
identity (out) pEp_identity structure with results or NULL if failure | |||
``` | |||
##### set_identity(Identity) | |||
set identity information | |||
``` | |||
parameters: | |||
identity (in) pEp_identity structure | |||
return value: | |||
PEP_STATUS_OK = 0 encryption and signing succeeded | |||
PEP_CANNOT_SET_PERSON writing to table person failed | |||
PEP_CANNOT_SET_PGP_KEYPAIR writing to table pgp_keypair failed | |||
PEP_CANNOT_SET_IDENTITY writing to table identity failed | |||
PEP_COMMIT_FAILED SQL commit failed | |||
PEP_KEY_BLACKLISTED Key blacklisted, cannot set identity | |||
caveat: | |||
address, fpr, user_id and username must be given | |||
``` | |||
##### mark_as_comprimized(String fpr) | |||
mark key in trust db as compromized | |||
* parameters: fpr (in) fingerprint of key to mark | |||
##### identity_rating(Identity ident, PEP_rating⇑ rating) | |||
get rating for a single identity | |||
``` | |||
parameters: | |||
ident (in) identity to get the rating for | |||
rating (out) rating for the identity | |||
return value: | |||
error status or PEP_STATUS_OK on success | |||
``` | |||
##### outgoing_message_rating(Message msg, PEP_rating⇑ rating) | |||
get rating for an outgoing message | |||
``` | |||
parameters: | |||
msg (in) message to get the rating for | |||
rating (out) rating for the message | |||
return value: | |||
error status or PEP_STATUS_OK on success | |||
caveat: | |||
msg->from must point to a valid pEp_identity | |||
msg->dir must be PEP_dir_outgoing | |||
``` | |||
##### set_identity_flags(Identity⇕ identity, Integer flags) | |||
update identity flags on existing identity | |||
``` | |||
parameters: | |||
identity (in,out) pointer to pEp_identity structure | |||
flags (in) new value for flags | |||
return value: | |||
PEP_STATUS_OK = 0 encryption and signing succeeded | |||
PEP_CANNOT_SET_IDENTITY update of identity failed | |||
caveat: | |||
address and user_id must be given in identity | |||
``` | |||
##### unset_identity_flags(Identity⇕ identity, Integer flags) | |||
update identity flags on existing identity | |||
``` | |||
parameters: | |||
identity (in,out) pointer to pEp_identity structure | |||
flags (in) new value for flags | |||
return value: | |||
PEP_STATUS_OK = 0 encryption and signing succeeded | |||
PEP_CANNOT_SET_IDENTITY update of identity failed | |||
caveat: | |||
address and user_id must be given in identity | |||
``` | |||
#### Low level Key Management API #### | |||
##### generate_keypair(Identity⇕ identity) | |||
generate a new key pair and add it to the key ring | |||
``` | |||
parameters: | |||
identity (inout) pEp_identity structure | |||
return value: | |||
PEP_STATUS_OK = 0 encryption and signing succeeded | |||
PEP_ILLEGAL_VALUE illegal values for identity fields given | |||
PEP_CANNOT_CREATE_KEY key engine is on strike | |||
caveat: | |||
address and username fields must be set to UTF-8 strings | |||
the fpr field must be set to NULL | |||
``` | |||
##### delete_keypair(String fpr) | |||
delete a public key or a key pair from the key ring | |||
``` | |||
parameters: | |||
fpr (in) string with key id or fingerprint of the public key | |||
return value: | |||
PEP_STATUS_OK = 0 key was successfully deleted | |||
PEP_KEY_NOT_FOUND key not found | |||
PEP_ILLEGAL_VALUE not a valid key id or fingerprint | |||
PEP_KEY_HAS_AMBIG_NAME fpr does not uniquely identify a key | |||
PEP_OUT_OF_MEMORY out of memory | |||
``` | |||
##### import_key(String key_data, Integer size, IdentityList⇑ private_keys) | |||
import key from data | |||
``` | |||
parameters: | |||
key_data (in) key data, i.e. ASCII armored OpenPGP key | |||
size (in) amount of data to handle | |||
private_keys (out) list of private keys that have been imported | |||
return value: | |||
PEP_STATUS_OK = 0 key was successfully imported | |||
PEP_OUT_OF_MEMORY out of memory | |||
PEP_ILLEGAL_VALUE there is no key data to import | |||
``` | |||
##### export_key(String fpr, String⇑ key_data, Integer⇑ size) | |||
export ascii armored key | |||
``` | |||
parameters: | |||
fpr (in) key id or fingerprint of key | |||
key_data (out) ASCII armored OpenPGP key | |||
size (out) amount of data to handle | |||
return value: | |||
PEP_STATUS_OK = 0 key was successfully exported | |||
PEP_OUT_OF_MEMORY out of memory | |||
PEP_KEY_NOT_FOUND key not found | |||
``` | |||
##### find_keys(String pattern, StringList⇑ keylist) | |||
find keys in keyring | |||
``` | |||
parameters: | |||
pattern (in) key id, user id or address to search for as UTF-8 string | |||
keylist (out) list of fingerprints found or NULL on error | |||
``` | |||
##### get_trust(Identity⇕ identity) | |||
get the trust level a key has for a person | |||
``` | |||
parameters: | |||
identity (inout) user_id and fpr to check as UTF-8 strings (in) | |||
user_id and comm_type as result (out) | |||
``` | |||
This function modifies the given identity struct; the struct remains in | |||
the ownership of the caller. | |||
If the trust level cannot be determined identity->comm_type is set | |||
to PEP_ct_unknown. | |||
##### own_key_is_listed(String fpr, Bool⇑ listed) | |||
returns true id key is listed as own key | |||
``` | |||
parameters: | |||
fpr (in) fingerprint of key to test | |||
listed (out) flags if key is own | |||
``` | |||
##### own_identities_retrieve(IdentityList⇑ own_identities) | |||
retrieve all own identities | |||
``` | |||
parameters: | |||
own_identities (out) list of own identities | |||
``` | |||
##### set_own_key( Identity⇕ id, String fpr) | |||
mark key as own key | |||
``` | |||
parameters: | |||
me (inout) own identity this key is used for | |||
fpr (in) fingerprint of the key to mark as own key | |||
``` | |||
##### undo_last_mistrust() | |||
reset identity and trust status for the last`identity in this session marked | |||
as mistrusted to their cached values from the time of mistrust | |||
``` | |||
parameters: | |||
(none) | |||
return value: | |||
PEP_STATUS_OK if identity and trust were successfully restored. | |||
Otherwise, error status from attempts to set. | |||
caveat: | |||
only works for this session, and only once. cache is invalidated | |||
upon use. | |||
WILL NOT WORK ON MISTRUSTED OWN KEY | |||
``` | |||
##### myself(Identity⇕ identity) | |||
ensures that the own identity is being complete | |||
``` | |||
parameters: | |||
identity (inout) identity of local user. At least .address, .username, .user_id must be set. | |||
return value: | |||
PEP_STATUS_OK if identity could be completed or was already complete, any other value on error | |||
caveat: | |||
This function generates a keypair on demand; because it's synchronous | |||
it can need a decent amount of time to return. | |||
If you need to do this asynchronous, you need to return an identity | |||
with retrieve_next_identity() where pEp_identity.me is true. | |||
``` | |||
##### update_identity(Identity⇕) | |||
update identity information | |||
``` | |||
parameters: | |||
identity (inout) identity information of communication partner | |||
(identity->fpr is OUT ONLY) | |||
return value: | |||
PEP_STATUS_OK if identity could be updated, | |||
PEP_GET_KEY_FAILED for own identity that must be completed (myself()) | |||
any other value on error | |||
caveat: | |||
if this function returns PEP_ct_unknown or PEP_ct_key_expired in | |||
identity->comm_type, the caller must insert the identity into the | |||
asynchronous management implementation, so retrieve_next_identity() | |||
will return this identity later | |||
at least identity->address must be a non-empty UTF-8 string as input | |||
update_identity() never writes flags; use set_identity_flags() for | |||
writing | |||
this function NEVER reads the incoming fpr, only writes to it. | |||
``` | |||
##### trust_personal_key(Identity) | |||
mark a key as trusted with a person | |||
``` | |||
parameters: | |||
ident (in) person and key to trust in | |||
caveat: | |||
the fields user_id, address and fpr must be supplied | |||
``` | |||
##### key_mistrusted(Identity) | |||
mark key as being compromized | |||
``` | |||
parameters: | |||
ident (in) person and key which was compromized | |||
``` | |||
##### key_reset_trust(Identity) | |||
undo trust_personal_key and key_mistrusted() for keys we don't own | |||
``` | |||
parameters: | |||
ident (in) person and key which was compromized | |||
``` | |||
##### least_trust(String fpr, PEP_comm_type⇑ comm_type) | |||
get the least known trust level for a key in the database | |||
``` | |||
parameters: | |||
fpr (in) fingerprint of key to check | |||
comm_type (out) least comm_type as result (out) | |||
``` | |||
If the trust level cannot be determined comm_type is set to PEP_ct_unknown. | |||
##### get_key_rating(String fpr, PEP_comm_type⇑ comm_type) | |||
get the rating a bare key has | |||
``` | |||
parameters: | |||
fpr (in) unique identifyer for key as UTF-8 string | |||
comm_type (out) key rating | |||
``` | |||
Iif an error occurs, *comm_type is set to PEP_ct_unknown and an error is returned | |||
##### renew_key(String fpr, Timestamp ts) | |||
renew an expired key | |||
``` | |||
parameters: | |||
fpr (in) ID of key to renew as UTF-8 string | |||
ts (in) timestamp when key should expire or NULL for default | |||
``` | |||
##### revoke(String fpr, String reason) | |||
revoke a key | |||
``` | |||
parameters: | |||
fpr (in) ID of key to revoke as UTF-8 string | |||
reason (in) text with reason for revoke as UTF-8 string | |||
or NULL if reason unknown | |||
caveat: | |||
reason text must not include empty lines | |||
this function is meant for internal use only; better use | |||
key_mistrusted() of keymanagement API | |||
``` | |||
##### key_expired(String fpr, Integer when, Bool⇑ expired) | |||
flags if a key is already expired | |||
``` | |||
parameters: | |||
fpr (in) ID of key to check as UTF-8 string | |||
when (in) UTC time of when should expiry be considered | |||
expired (out) flag if key expired | |||
``` | |||
#### from blacklist.h & OpenPGP_compat.h #### | |||
##### blacklist_add(String fpr) | |||
add to blacklist | |||
* parameters: fpr (in) fingerprint of key to blacklist | |||
##### blacklist_delete(String fpr) | |||
delete from blacklist | |||
* parameters: fpr (in) fingerprint of key to blacklist | |||
##### blacklist_is_listed(String fpr, Bool⇑ listed) | |||
is_listed in blacklist | |||
``` | |||
parameters: | |||
session (in) session to use | |||
fpr (in) fingerprint of key to blacklist | |||
listted (out) | |||
``` | |||
##### blacklist_retrieve(StringList⇑ blacklist) | |||
retrieve full blacklist of key fingerprints | |||
* parameters: blacklist (out) copy of blacklist | |||
##### OpenPGP_list_keyinfo(String search_pattern, StringPairList⇑ keyinfo_list) | |||
get a key/UID list for pattern matches in keyring ("" to return entire keyring), filtering out revoked keys in the results | |||
``` | |||
parameters: | |||
search_pattern (in) search pattern - either an fpr, or something within the UID, or "" for all keys | |||
keyinfo_list (out) a key/value pair list for each key / UID combination | |||
``` | |||
#### Event Listener & Results #### | |||
##### registerEventListener(String address, Integer port, String security_context) | |||
Register an address/port pair where a JSON-RPC call shall be made to, when the Engine wants to call the client application. | |||
These RPC calls are authenticated with a security_context parameter that is given to all calls (and can be different from the security_context | |||
that is used for calls from the client to the JSON Server Adapter). | |||
Currently there are two functions that can be called: | |||
* messageToSend( Message ) | |||
* notifyHandshake( Identity self, Identity partner, sync_handshake_signal sig ) | |||
##### unregisterEventListener(String address, Integer port, String security_context) | |||
Unregister a previous registered JSON-RPC listener. | |||
##### deliverHandshakeResult(Identity partner, PEP_sync_handshake_result result) | |||
give the result of the handshake dialog back to the Engine | |||
``` | |||
parameters: | |||
partner (in) the parther of the handshake | |||
result (in) handshake result | |||
``` | |||
#### Other #### | |||
##### serverVersion() | |||
Returns a struct with SemVer-compatible ABI version, the codename of the | |||
JSON Adapter version etc. | |||
##### version() | |||
Returns a codename for the current JSON Server Adapter's version. | |||
##### shutdown() | |||
shutdown the JSON Adapter |
@ -1,96 +0,0 @@ | |||
### Function reference for the p≡p JSON Server Adapter. Version “(38) Frankenberg”, API version 0.15.0 ### | |||
Output parameters are denoted by a **⇑** , InOut parameters are denoted by a **⇕** after the parameter type. | |||
#### Message API #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| MIME_encrypt_message | PEP_STATUS | String, Integer, StringList, String⇑, PEP_enc_format, Integer | | |||
| MIME_encrypt_message_for_self | PEP_STATUS | Identity, String, Integer, StringList, String⇑, PEP_enc_format, Integer | | |||
| MIME_decrypt_message | PEP_STATUS | String, Integer, String⇑, StringList⇑, PEP_rating⇑, Integer⇕, String⇑ | | |||
| startKeySync | Void | | | |||
| stopKeySync | Void | | | |||
| startKeyserverLookup | Void | | | |||
| stopKeyserverLookup | Void | | | |||
| encrypt_message | PEP_STATUS | Message, StringList, Message⇑, PEP_enc_format, Integer | | |||
| encrypt_message_and_add_priv_key | PEP_STATUS | Message, Message⇑, String, , PEP_enc_format, Integer | | |||
| encrypt_message_for_self | PEP_STATUS | Identity, Message, StringList, Message⇑, PEP_enc_format, Integer | | |||
| decrypt_message | PEP_STATUS | Message⇕, Message⇑, StringList⇑, PEP_rating⇑, Integer⇕ | | |||
| outgoing_message_rating | PEP_STATUS | Message, PEP_rating⇑ | | |||
| identity_rating | PEP_STATUS | Identity, PEP_rating⇑ | | |||
#### MIME message handling #### | |||
| mime_decode_message | PEP_STATUS | String, Integer, Message⇑ | | |||
#### pEp Engine Core API #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| get_trustwords | PEP_STATUS | Identity, Identity, Language, String⇑, Integer⇑, Bool | | |||
| get_languagelist | PEP_STATUS | String⇑ | | |||
| is_pep_user | PEP_STATUS | Identity, Bool⇑ | | |||
| config_passive_mode | Void | Bool | | |||
| config_unencrypted_subject | Void | Bool | | |||
#### Identity Management API #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| get_identity | PEP_STATUS | String, String, Identity⇑ | | |||
| set_identity | PEP_STATUS | Identity | | |||
| mark_as_comprimized | PEP_STATUS | String | | |||
| identity_rating | PEP_STATUS | Identity, PEP_rating⇑ | | |||
| outgoing_message_rating | PEP_STATUS | Message, PEP_rating⇑ | | |||
| set_identity_flags | PEP_STATUS | Identity⇕, Integer | | |||
| unset_identity_flags | PEP_STATUS | Identity⇕, Integer | | |||
#### Low level Key Management API #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| generate_keypair | PEP_STATUS | Identity⇕ | | |||
| delete_keypair | PEP_STATUS | String | | |||
| import_key | PEP_STATUS | String, Integer, IdentityList⇑ | | |||
| export_key | PEP_STATUS | String, String⇑, Integer⇑ | | |||
| find_keys | PEP_STATUS | String, StringList⇑ | | |||
| get_trust | PEP_STATUS | Identity⇕ | | |||
| own_key_is_listed | PEP_STATUS | String, Bool⇑ | | |||
| own_identities_retrieve | PEP_STATUS | IdentityList⇑ | | |||
| set_own_key | PEP_STATUS | Identity⇕, String | | |||
| undo_last_mistrust | PEP_STATUS | | | |||
| myself | PEP_STATUS | Identity⇕ | | |||
| update_identity | PEP_STATUS | Identity⇕ | | |||
| trust_personal_key | PEP_STATUS | Identity | | |||
| key_mistrusted | PEP_STATUS | Identity | | |||
| key_reset_trust | PEP_STATUS | Identity | | |||
| least_trust | PEP_STATUS | String, PEP_comm_type⇑ | | |||
| get_key_rating | PEP_STATUS | String, PEP_comm_type⇑ | | |||
| renew_key | PEP_STATUS | String, Timestamp | | |||
| revoke | PEP_STATUS | String, String | | |||
| key_expired | PEP_STATUS | String, Integer, Bool⇑ | | |||
#### from blacklist.h & OpenPGP_compat.h #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| blacklist_add | PEP_STATUS | String | | |||
| blacklist_delete | PEP_STATUS | String | | |||
| blacklist_is_listed | PEP_STATUS | String, Bool⇑ | | |||
| blacklist_retrieve | PEP_STATUS | StringList⇑ | | |||
| OpenPGP_list_keyinfo | PEP_STATUS | String, StringPairList⇑ | | |||
#### Event Listener & Results #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| registerEventListener | Void | String, Integer, String | | |||
| unregisterEventListener | Void | String, Integer, String | | |||
| deliverHandshakeResult | PEP_STATUS | Identity, PEP_sync_handshake_result | | |||
#### Other #### | |||
| Function name | Return Type | Parameters | | |||
|---------------|-------------|------------| | |||
| serverVersion | ServerVersion | | | |||
| version | String | | | |||
| getGpgEnvironment | GpgEnvironment | | | |||
| shutdown | Void | | | |||
@ -1,718 +1,64 @@ | |||
# p≡p JSON Server Adapter | |||
# p≡p Logger | |||
## Introduction | |||
The p≡p JSON Server Adapter provides a REST-like jQuery-compatible API to | |||
connect with the p≡p engine. It is language-independent and can be used by | |||
any client. | |||
The p≡p Logger is a fork of the Logger module of the p≡p JSON Server Adapter. | |||
## Requirements | |||
In order to use the p≡p JSON Server Adapter, you need to build and run it. | |||
Currently, Linux (Debian 9, Ubuntu 16.04) and MacOS (10.11, 10.12) are | |||
supported, Windows is about to follow. Newer versions should also work | |||
(file a bug report if not) but are not in our main focus, yet. | |||
## Dependencies | |||
* C++ compiler: tested with g++ 4.8, 4.9, 8.3 and clang++ 2.8. Newer versions should work, too. | |||
* GNU make | |||
* libboost-thread-dev (tested with 1.58, 1.62, 1.67, 1.70 and 1.74) | |||
* libboost-program-options-dev | |||
* libboost-filesystem-dev | |||
* [p≡p Engine](https://gitea.pep.foundation/pEp.foundation/pEpEngine/) | |||
(which needs sequoia, a patched libetpan, libboost-system-dev) | |||
* [libpEpAdapter](https://gitea.pep.foundation/pEp.foundation/libpEpAdapter/) | |||
* [webserver](https://gitea.pep.foundation/fdik/webserver) | |||
* OSSP libuuid | |||
## Building/Installing (Linux and macOS) | |||
### Install the dependencies | |||
Debian 9/10: | |||
~~~~~ | |||
apt install -y build-essential libboost-dev libboost-system-dev \ | |||
libboost-filesystem-dev libboost-program-options-dev \ | |||
libboost-thread-dev libgpgme-dev uuid-dev googletest \ | |||
libevent-dev libevhtp-dev | |||
~~~~~ | |||
macOS 10.12, 10.13, 10.14: | |||
Use homebrew or macports to install the required libraries. | |||
For more explicit instructions on how to do this with macports, see the | |||
section below. | |||
Build and install the pEp Engine. Instructions can be found here: | |||
[the Engine's Readme](https://gitea.pep.foundation/pEp.foundation/pEpEngineREADME.md) | |||
### Build and install the 'webserver' project | |||
~~~~~ | |||
cd ~/code | |||
git clone https://gitea.pep.foundation/fdik/webserver | |||
cd webserver | |||
(edit the Makefile for your $PREFIX etc.) | |||
make | |||
make install | |||
~~~~~ | |||
### Build and install the JSON server | |||
~~~~~ | |||
cd ~/code/json-ad/server | |||
~~~~~ | |||
| :warning: FIXME: The following instructions refer to the old Makefile system that built a dynamically linked binary. This old Makefile was replaced by a hack to create a static binary. Unfortunately the config flexibility of the old Makefile system was removed in this change. | | |||
| ------ | | |||
| There is now also an ad-hoc created `Makefile.Linux`, which also can only be configured directly by editing the file. :-( | | |||
| ------ | | |||
| TODO: Re-create a more flexible build system with a `Makefile` (which is under revision control) and a `local.conf` (which is not, but contains your local-only config settings) | | |||
| ------ | | |||
Edit the build configuration to your needs in `./Makefile.conf`, or create a | |||
`./local.conf` that sets any of the make variables documented in | |||
`./Makefile.conf`. | |||
### Features | |||
If a dependency is not found in your system's default include or library | |||
paths, you will have to specify the according paths in a make variable. | |||
Typically, this has to be done at least for the pEp Engine, libetpan and | |||
libevent. | |||
* compile-time configurable via `logger_config.hh`, run-time configuable via | |||
API functions | |||
Below are two sample `./local.conf` files, for orientation. | |||
* supports logging to syslog (UN*X only), to a file and to the console (stderr). | |||
* supports log levels ("severities" in syslog terminology) and run-time filtering | |||
of log entries lower than given "log level" | |||
* API for both printf()-like ("C") style and C++ outputstream-like style | |||
macOS 10.12, 10.13: | |||
* compile-time disabling of debug messages via `-D DEBUG_ENABLED` (if done via macros, see below) | |||
~~~~~ | |||
PREFIX=$(HOME)/code/json-ad/build | |||
HTML_DIRECTORY=$(PREFIX)/share/pEp/json-adapter/html | |||
GTEST_DIR=$(HOME)/code/gtest/googletest | |||
* hierarchical Logger instances that inherit their "name" and their log level from their | |||
parent Logger instance | |||
* multi-line log messages, visualized via big square brackets | |||
BOOST_INC=-I$(HOME)/Cellar/boost/1.65.1/include | |||
BOOST_LIB=-L$(HOME)/Cellar/boost/1.65.1/lib | |||
* auto wrapping of long log lines, visualized via "↩" and "↪" | |||
(configurable at run-time via `Logger::setMaxLineLength()` ) | |||
ENGINE_INC=-I$(HOME)/code/engine/build/include | |||
ENGINE_LIB=-L$(HOME)/code/engine/build/lib | |||
* log GMT / UTC timestamp and easily greppable thread IDs. | |||
The thread IDh have the form `¶XYZ` where 'XYZ' is a hash of `std::this_thread::get_id()`, | |||
truncated to three base-37 digits, to make collisions of thread IDs unlikely. | |||
ETPAN_INC=-I$(HOME)/code/libetpan/build/include | |||
ETPAN_LIB=-L$(HOME)/code/libetpan/build/lib | |||
* logfile analyzer (e.g. for filtering log of different threads) via HTML & Javascript, | |||
see `html/logview.html` | |||
GPGME_INC=-I$(HOME)/Cellar/gpgme/1.9.0_1/include | |||
GPGME_LIB=-L$(HOME)/Cellar/gpgme/1.9.0_1/lib | |||
UUID_INC=-I$(HOME)/Cellar/ossp-uuid/1.6.2_2/include | |||
UUID_LIB=-L$(HOME)/Cellar/ossp-uuid/1.6.2_2/lib | |||
~~~~~ | |||
### TODOs | |||
Debian 9/10: | |||
* truncating of pathologically long log messages, visualized via "▒ (%u octets clipped)" | |||
(configurable at run-time via `Logger::setMaxMessageLength()` ) | |||
~~~~~ | |||
PREFIX=$(HOME)/code/json-ad/build | |||
HTML_DIRECTORY=$(PREFIX)/share/pEp/json-adapter/html | |||
GTEST_DIR=/usr/src/googletest/googletest/ | |||
* escaping of non-printing control characters, illegal Unicode codepoints and illegal UTF-8 sequences | |||
ENGINE_INC=-I$(HOME)/code/engine/build/include | |||
ENGINE_LIB=-L$(HOME)/code/engine/build/lib | |||
ETPAN_INC=-I$(HOME)/code/libetpan/build/include | |||
ETPAN_LIB=-L$(HOME)/code/libetpan/build/lib | |||
## Building | |||
### Dependencies | |||
* C++14 compiler: tested with clang++ 10, g++ 11. Newer versions should work, too. | |||
* GNU make | |||
~~~~~ | |||
### Building/Installing (Linux and macOS) | |||
Now, build and install the server: | |||
It is so simple. This should do out of the box: | |||
~~~~~ | |||
make all | |||
make install | |||
make test | |||
~~~~~ | |||
If you only want to build the JsonAdapter library, run `make lib` and you'll get | |||
a libjson-adapter.a | |||
With `make test` you can execute the server's tests. | |||
### Macports | |||
[Install MacPorts](https://www.macports.org/install.php) for your version of macOS. | |||
If MacPorts is already installed on your machine, but was installed by a | |||
different user, make sure your `PATH` variable is set as follows in | |||
`~/.profile`: | |||
``` | |||
export PATH="/opt/local/bin:/opt/local/sbin:$PATH" | |||
``` | |||
Install dependencies packaged with MacPorts as follows. | |||
``` | |||
sudo port install gpgme boost ossp-uuid | |||
``` | |||
## Building/Installing (Windows) | |||
Clone the repository from https://pep.foundation/dev/repos/pEpJSONServerAdapter and add the | |||
following projects to your MS Visual Studio solution: | |||
pEpJSONServerAdapter\build-windows\pEpJSONServerAdapter\pEpJSONServerAdapter.vcxproj | |||
pEpJSONServerAdapter\build-windows\pEpJSONServerAdapter\pEpJSONServerAdapterLibrary.vcxproj | |||
pEpJSONServerAdapter\build-windows\libevent\libevent.vcxproj | |||
In order to build, the MS VS solution also needs to build the following dependent projects: | |||
- pEpEngine (note that this requires further dependent projects) | |||
- libpEpAdapter | |||
- libevent | |||
The resulting executable is called pEpJSONServerAdapter.exe and will be placed into | |||
the `Debug` or `Release` directory of the solution. | |||
## Running the pEp JSON Adapter | |||
You can use `make run` to start the server. | |||
1. Run `./pEp-mini-json-adapter`. This creates a file that is readable only by the | |||
current user (`~/.pEp/json-token`) and contains the address and | |||
port the JSON adapter is listening on, normally 127.0.0.1:4223 and a | |||
"security-token" that must be given in each function call to authenticate | |||
you as the valid user. | |||
``` | |||
./pEp-mini-json-adapter | |||
``` | |||
2. Visit that address (normally `http://127.0.0.1:4223/`) in your | |||
JavaScript-enabled web browser to see the "JavaScript test client". | |||
3. Call any function (`version()` or `get_gpg_path()` should work just | |||
fine) with the correct security token. | |||
## Using the p≡p JSON Adapter | |||
In the following section, you'll find background information on how to use | |||
the adapter and its functions. | |||
### Server startup and shutdown | |||
The JSON Server Adapter can be started on demand. | |||
It checks automatically whether an instance for the same user on the machine | |||
is already running and if yes it ends itself gracefully. (TODO!) | |||
If there is no running server found the newly started server creates the | |||
server token file and forks itself into background (if not prevented via | |||
"-d" commandline switch). | |||
### Multi-Client handling | |||
The p≡p JSON server adapter supports multiple clients, communicating with the | |||
server at the same time. Each client instance is identified by a client ID, | |||
that the clients put into each JSON RPC request in the field "clientid". | |||
The client ID is a UUID Version 4, created by the client at startup and has to | |||
be stable while the client application runs. When the client restarts, a new | |||
client ID should be created to avoid interferene with data from the old client | |||
session. | |||
The p≡p JSON server adapter stores data (e.g., a so called "config cache", see | |||
next section) associated with each client ID. After a timeout period with no | |||
JSON RPC calls and no open client connections these data are removed | |||
automatically. Run the mini adapter with -h to see the compiled-in default | |||
timeout value. | |||
### PEP_SESSION handling | |||
When using the p≡p engine, a `PEP_SESSION` is needed as parameter to many API | |||
functions. The p≡p JSON Server Adapter automatically creates one session per | |||
HTTP client connection (and also closes that session automatically when the | |||
client connections is closed). Therefore, the client does not need to take | |||
care of the session management. However, the client should set up a [HTTP | |||
persistent | |||
connection](https://en.wikipedia.org/wiki/HTTP_persistent_connection) to | |||
minify session creation and destruction. | |||
There is a configuration cache, that stores all `config_*()` calls and its | |||
configured values. Whenever a new PEP_SESSION is needed for this client | |||
(identified via its client ID, see previous section), all config values | |||
are applied to this new session, too, before the session is used. | |||
### API Principles | |||
All C data types are mapped the same way, so some day the JSON wrapper can | |||
be generated from the p≡p Engine header files (or the JSON wrapper and the | |||
p≡p engine header are both generated from a common interface description | |||
file). | |||
| C type | JSON mapping | | |||
|--|--| | |||
| `bool` | JSON boolean | | |||
| `int` | JSON decimal number | | |||
| `size_t` | JSON decimal number | | |||
| `char*` (representing a UTF-8-encoded NULL-terminated string | JSON string | | |||
| `char*` (representing a binary string | base64-encoded JSON string | | |||
| `enum` | either JSON decimal number or JSON object containing one decimal number as member | | |||
| `struct` | JSON object | | |||
| linked lists (e.g. `bloblist_t`, `stringlist_t`, `identity_list` etc.) | JSON array of their member data type (without the `next` pointer) | | |||
The parameter type PEP_SESSION is handled automatically by the JSON Server | |||
Adapter and the PEP_SESSION parameter is omitted from the JSON API. | |||
#### enum types | |||
Enum types are represented as JSON objects with one member, whose name is | |||
derived from the enum type name, holding the numeric value of the enum. | |||
Some enum types are still represented directly as JSON decimal number. It | |||
shall be changed in a future version of the JSON Adapter. | |||
#### String types | |||
The JSON Server Adapter does automatic memory management for string | |||
parameters. The current p≡p Engine's API distinguish between `const char*` | |||
parameters and `char*` parameters. `const char*` normally means: the | |||
"ownership" of the string remains at the caller, so the JSON Adapter frees | |||
the string automatically after the call. `char*` normally means: the | |||
"ownership" of the string goes to the Engine, so the JSON Adapter does _not_ | |||
free string. | |||
If there are functions that have a different semantics the behavior of the | |||
JSON wrapper has to be changed. | |||
#### Parameter (value) restrictions | |||
Some API functions have restrictions on their parameter values. The JSON | |||
Adapter does not know these restrictions (because it does not know the | |||
semantics of the wrapped functions at all). So it is the client's | |||
responsibility to fulfill these parameter restrictions! Especially when | |||
there are restrictions that are checked with assert() within the p≡p Engine, | |||
it is impossible for the JSON Adapter to catch failed assertions - the | |||
Engine and the Adapter process will be terminated immediatetely when the | |||
Engine is compiled in debug mode (= with enabled assert() checking). | |||
Currently there are no range checks for numerical parameter types (e.g. a | |||
JSON decimal number can hold a bigger value than the `int` parameter type of | |||
a certain C function). | |||
### JSON RPC Requests | |||
The JSON Server Adapter offers its services via HTTP on the address and port | |||
specified on command line. It offers a simple test HTML page on the root | |||
URL. | |||
The JSON RPC functions are POST requests to the path /ja/0.1/callFunction | |||
and the JSON RPC data comes, as usual for POST requests, in the request body and | |||
must be in UTF-8 without any BOM. The `Content-Type` of the request is not relevant. | |||
Here is the body of an example request: | |||
``` | |||
{ | |||
"id": 1001, | |||
"jsonrpc": "2.0", | |||
"security_token": "YSxxkNga0YUlkmdpUL6_qJuioicGK1wOC5sjGVG", | |||
"method": "import_key", | |||
"params": [ | |||
"4oW5PKhgY8XdvIYQiu+KaKnZYyP5UseHD1Sfjb8HpO75m/QT/FxFI………", | |||
4444, | |||
[ | |||
"OP" | |||
] | |||
] | |||
} | |||
``` | |||
another example: | |||
``` | |||
{ | |||
"id": 1002, | |||
"jsonrpc": "2.0", | |||
"security_token": "YSxxkNga0YUlkmdpUL6_qJuioicGK1wOC5sjGVG", | |||
"method": "myself", | |||
"params": [ | |||
{ | |||
"user_id": "alice", | |||
"username": "Alice in pEp land", | |||
"address": "alice@pEp.lol", | |||
"fpr": "4ABE3AAF59AC32CFE4F86500A9411D176FF00E97" | |||
} | |||
] | |||
} | |||
``` | |||
Output parameters must be given, but their value is not relevant. The | |||
JavaScript example test client fills the output values with a dummy array, | |||
containing one string element "OP", just to ease debugging. | |||
The result contains the return value and the values of the output parameters, | |||
in reverse order: | |||
Request: | |||
``` | |||
{ | |||
"id": 1003, | |||
"jsonrpc": "2.0", | |||
"security_token": "YSxxkNga0YUlkmdpUL6_qJuioicGK1wOC5sjGVG", | |||
"method": "get_languagelist", | |||
"params": [ | |||
[ | |||
"OP" | |||
] | |||
] | |||
} | |||
``` | |||
Result: | |||
``` | |||
{ | |||
"outParams": [ | |||
"\"en\",\"English\",\"I want to display the trustwords in English language\"……" | |||
], | |||
"return": { | |||
"status": 0, | |||
"hex": "0 \"PEP_STATUS_OK\"" | |||
} | |||
} | |||
``` | |||
### API Reference | |||
An complete overview with all functions that are callable from the client | |||
can be found in the [API Reference](pEp JSON Server Adapter/API Reference). | |||
That API reference is a generated file (at irregular intervals) that shows the current API briefly. | |||
There is also a (currently manually written) file that holts a copy of the | |||
documentation from the Engine's header files: [API reference detail.md] | |||
BEWARE: Because this file is not auto-generated, yet, it might be even more outdated! | |||
Most of the callable functions are functions from the C API of the p≡p | |||
Engine. They are described in detail, incl. pre- and post-conditions in | |||
the appropriate C header files of the Engine, which are the authoritative source | |||
of documentation in cases of doubt. | |||
### Authentication | |||
The JSON Server Adapter and the client have to authenticate to each other. | |||
"Authentication" in this case means "run with the same user rights". This is | |||
done by proving that each communication partner is able to read a certain | |||
file that has user-only read permissions. | |||
0. There is a common (between client & server) algorithm to create the path | |||
and filename of the "server token file", for a given user name. | |||
The token file and its directory MUST be owned by the user and MUST be | |||
readable and writable only by the user, nobody else. Client and server | |||
check for the right ownership and access rights of the token file and its | |||
directory. (TODO: What shall be done if that check fails?) | |||
1. The server creates a "server token file" containing a "server token" (a | |||
random-generated string of printable ASCII characters) and the IP address | |||
and port where the server listens on. This file can only be read by | |||
client programs that run with the same user rights. | |||
2. The client checks the path, reads the "server token" from the file and | |||
authenticates itself to the server in each JSON RPC call with that "server | |||
token". | |||
### Callbacks / Event delivery | |||
p≡p applications must register callback handlers at the Engine. At the moment | |||
there are these callbacks: | |||
* `PEP_STATUS messageToSend(message* msg)` | |||
* `PEP_STATUS notifyHandshake(pEp_identity* self, pEp_identity* partner, sync_handshake_signal signal)` | |||
The JSON adapter register its own functions at the Engine which propagate these | |||
events to all connected clients. | |||
The event propagation to the clients are done via long polling: Clients | |||
call the function `pollForEvents()` that blocks until an event | |||
from the Engine arrives. TODO: remove create_session(), use client ID instead? | |||
It is planned to switch to use WebSockets: In fact this is also a type of | |||
"long polling" and an open TCP connection, opened by the Client. | |||
See: https://pep.foundation/jira/browse/JSON-128 | |||
## Extending / customizing | |||
If you want to extend or customize the p≡p JSON Adapter, there are several | |||
rules and definitions to take into account. | |||
### API Functions | |||
* The `FunctionMap function` in `ev_server.cc` defines which functions | |||
are callable via the JSON-RPC interface. The existing entries show the | |||
syntax of that map. | |||
Non-static member functions can be called, too. Thanks to `std::function<>` | |||
a member function `Foo::func(Params...)` is handled like a free-standing | |||
function `func(Foo* f, Params...)`. | |||
* For each type there must exist specializations of the template classes | |||
"In" (for input parameters) and "Out" (for output parameters). | |||
The linker will tell you, which specializations are needed. | |||
* The specializations for "generic types" are in `function_map.cc`. | |||
* The specializations for "p≡p-specific types" are in `pep-types.cc`. | |||
#### Parameter directions (In, Out, InOut) | |||
The p≡p JSON Server Adapter supports Input, Output and two ways of "In/Out" | |||
parameters. You have to annotate the direction in the FunctionMap with | |||
`In<>` for input, `Out<>` for output and `InOut<>` or `InOutP<>` for in/out | |||
parameters. These wrapper classes have an optional second template | |||
parameter (parameter type flag) that is explained below. | |||
Return values are always "output" parameters, so they don't have to be | |||
wrapped with `Out<>`, but this wrapper is necessary when you need | |||
non-default wrapper semantics, see below. | |||
Input parameters of fundamental or simple struct types are | |||
usually by-value parameters. Complex structs (or structs that are only | |||
forward-declared in the public API) are usually pointer | |||
parameters. Both ways are supported. You have to specialize `In<T>` or | |||
`In<T*>`, depending how your type is used. | |||
Output parameters of fundamental or simple struct types `T` are usually | |||
declared as a paremeter of type `T*`. The p≡p JSON Server Adapter manages | |||
the memory allocated by the called C function automatically and calls the | |||
appropriate de-allocating function after use. | |||
Calling a function with output parameters requires a dummy value (`null` or | |||
empty string is fine) at the JSON side for each output parameter to keep the | |||
number of parameters at the JSON side the same with the C side. | |||
For In/Out parameters there exist two calling conventions for | |||
call-by-pointer types: | |||
1. caller allocates object and fills with input values, callee can only *change members*. | |||
The C type of the parameter is usually `struct T*`. Use the wrapper `InOut<T*>` | |||
for these parameters. | |||
2. caller allocates object and fills with input values, callee might | |||
change/reallocate the *whole object*. The C type of the parameter is | |||
`struct T**`. Use the wrapper `InOutP<T*>` in these cases. | |||
`InOutP<T>` is also the right wrapper for in/out parameters of fundamental or | |||
enum types due to the additional indirection in the C function call | |||
signature. | |||
#### Parameter type flags | |||
The wrapper classes might be instantiated with special "parameter type | |||
flags". If no flag is given the `DefaultFlag` is used with means the | |||
semantics described already above. | |||
At the moment there exist two parameter type flags which are interpreted as | |||
bitfield, so they can be combined: | |||
* NoInput : This denotes a parameter at the C side that shall *not be exposed* | |||
at the JSON side. So the value cannot be specified by the client, it is | |||
provided by the JSON Server Adapter internally (e.g. for PEP_SESSION) | |||
* DontOwn : Used for pointer types who don't "own" the referred ressource, | |||
so it is not released automatically by the JSON Server Adapter after the | |||
call. | |||
More flags will be added when different semantics will be needed. | |||
#### Automatic parameter value generation | |||
For some parameters or parameter combinations the JSON Server Adapter is | |||
able to generate the values automatically either from the environment or | |||
from other parameters. | |||
These automatic parameter value generators are supported at the moment: | |||
##### In<c_string> and InLength | |||
For functions that have a string parameter of type `const char*` followed by | |||
a `size_t` that specifies the length of the string, the JSON Adapter can | |||
calculate the value of that length parameter automatically, because in the | |||
JSON API the lengths of strings are always known. | |||
Moreover, the "length" that has to be given here means the length of the | |||
string seen by the C API side after processing of all JSON escaping | |||
mechanisms as raw UTF-8 NFC string, so it might be difficult to calculate | |||
that value at client side. | |||
The "magic" is done inside the In<c_string> constructor that stores the string | |||
length in its "Context", and the InLength<> constructore retrieves the value | |||
from its "Context". | |||
Example: | |||
``` | |||
// C function declaration: | |||
char* tohex(const char* input, size_t length); | |||
// API definition: | |||
// with implicit length parameter, with dummy JSON parameter | |||
FP( "tohex", new Func<char*, In<c_string>, InLength<>>( &tohex )) | |||
``` | |||
To be compatible with previous API versions the `InLength` parameter still | |||
needs a dummy placeholder in the JSON interface, but its value is no longer | |||
relevant: | |||
``` | |||
{"jsonrpc":"2.0", "id":28, | |||
"method":"tohex", "params":["some string","dummy_parameter"] | |||
} | |||
``` | |||
It is possible to specifiy `InLength<ParamFlag::NoInput>` so no | |||
parameter is exposed to the JSON API anymore: | |||
``` | |||
FP( "tohex", new Func<char*, In<c_string>, InLength<ParamFlag::NoInput>>( &tohex )) | |||
``` | |||
Now the 2nd parameter is omitted: | |||
``` | |||
{"jsonrpc":"2.0", "id":28, | |||
"method":"tohex", "params":["some string"] | |||
} | |||
``` | |||
### Embedding in other (desktop) adapters | |||
The JSON Adapter can run as a stand-alone program (called the "mini-adapter") or | |||
as part of another desktop adapter to enhance that adapter with a JSON-RPC interface. | |||
For this the JSON Adapter has to co-operate with the desktop adapter in several ways: | |||
* Startup, configuration and shutdown is managed by the desktop adapter. | |||
* Handshake events and sync messages created by the pEpEngine have to be dispatched | |||
to *all* connected clients, no matter whether they are JSON clients or "native" | |||
clients of the desktop adapter. See "messageToSend" and "notifyHandshake" callbacks. | |||
* The sync thread loop has to be managed by the desktop adapter. The libpEpAdapter | |||
contains an example implementation for that. | |||
* (something else?) | |||
## TODOs | |||
The following issues are planned but not yet implemented. | |||
* More sensible unit tests | |||
* Generate all the tedious boiler plate code | |||
* the content of pep-types.cc | |||
* perhaps the FunctionMap 'function' in mt-server.cc | |||
* perhaps the JavaScript side of the HTML test page to ensure to be | |||
consistent with the server side in pep-types.cc | |||
* Adapt the "p≡p Transport API", when it is final. (either manually or by | |||
code generator, if ready) | |||
## Appendix A: Attack scenarios on the authentication | |||
Let's discuss different attack / threat scenarios. I don't know which are | |||
realistic or possible, yet. | |||
### General ideas / improvements | |||
Currently the JSON Server Adapter writes its server token file in a | |||
directory that is only readable & writable by the user itself. | |||
The server token file is written in $HOME/.pEp/json-token on | |||
UNIX/Linux/MacOS and %LOCALAPPDATA%/pEp/json-token on MS Windows. | |||
The JSON Server Adapter also checks whether .pEp has 0700 access rights | |||
on unixoid systems. | |||
### Attacker with the same user rights | |||
If the attacker is able to run his malicious code with the same user | |||
rights as the JSON Server Adapter and his legitimate client, it is (and | |||
always will be) *impossible* to prevent this attack. Such an attacker also | |||
can just start a legitimate client that is under his control. | |||
The same applies to an attacker who gains root / admin access rights. | |||
### Fake Server with different user rights | |||
``` | |||
,----------. ,--------. | |||
| Attacker | <==> | Client | | |||
`----------' `--------' | |||
``` | |||
If no real JSON Adapter runs an attacker can create a fake server that | |||
pretends to be a legitimate JSON Adapter. It creates its own server token | |||
file, with different and conspicuous access rights, but a limited | |||
JavaScript client might be unable to detect the file permissions. | |||
This fake server cannot access the private key of the user but it might | |||
get sensitive plaintext data the client wants to encrypt. The fake server | |||
cannot sign the encrypted data so the fake would be conspicuous, too. But | |||
that would be too late, because the sensitive plaintext data could | |||
already be leaked by the fake server. | |||
This attack needs a user's home directory that is writable by someone else | |||
(to create a ~/.pEp/ directory) or a foreign-writable ~/.pEp/ directory. | |||
The pEpEngine creates a ~/.pEp/ directory (if not yet exists) and sets the | |||
permissions to 0700 explicitly. | |||
### Man-in-the-middle with different user rights | |||
### Building/Installing (Windows) | |||
``` | |||
,---------------------. ,----------. ,--------. | |||
| JSON Server Adapter | <==> | Attacker | <==> | Client | | |||
`---------------------' `----------' `--------' | |||
``` | |||
TODO. | |||
* The attacker cannot read "client token file" nor "server token file". | |||
* The server cannot check "who" connects to it, until the client | |||
authenticates itself, which might be relayed by the attacker from the | |||
original client. | |||
* The attacker has to convince the client that it is a legitimate server. It | |||
has to create a fake "server token file" to divert the client to the | |||
attacker's port. But that fake file cannot contain the right server token | |||
because the attacker does not know it. | |||
* if the server started before the attacker the "server token file"'s | |||
access rights should prevent this (no write access for the attacker, no | |||
"delete" right in common TEMP dir (sticky bit on the directory) | |||
* if the attacker starts before the server it can write a fake toke file. | |||
The server could detect it but is unable to notice the legitimate | |||
client. The client could detect it when it can check the file access | |||
rights. | |||
There might be race conditons... | |||
## Using the Logger in your own code | |||
* Is it possible for the attacker to let the client send the right server | |||
token to him, at least temporarily (e.g. within a race condition)? | |||
* As long as the server runs, the attacker cannot bind to the same address | |||
& port. Finding and binding of the port is done by the server before the | |||
server token file is created and filled. | |||
* When the server that created the "server token file" dies, its port | |||
becomes available for the attacker, but the server token is no longer | |||
valid and no longer useful for the attacker. | |||
* there _might_ be a very _small_ chance for a race condition: | |||
1. The attacker opens a connection to the running server but does not | |||
use it. To find the server it cannot read the server configuration | |||
file, but it can ask the OS for ports that are open in "listen" mode. | |||
Normally the JSON Adapter listens on 4223 or some port numbers above | |||
that. That means: guessing the server's address is quite easy. | |||
2. when the server shuts down, the attacker immediately binds itself to | |||
that port. If a client connects just in this moment it sends the server | |||
token to the attacker, not to the server. But the attacker can use that | |||
token now to the server via the already opened TCP connection. | |||
3. To prevent this the server should call shutdown(2) on its listening | |||
socket to block any new client connection, but still block the port. | |||
(is that the case on all platforms?) Than close(2) all TCP connections | |||
to the clients (if any) and than also delete the server token file. | |||
Finally call close(2) on the listening socket. | |||
See examples in `src/unittest_logger.cc` |
@ -1,172 +0,0 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<ItemGroup Label="ProjectConfigurations"> | |||
<ProjectConfiguration Include="Debug|Win32"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>Win32</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|Win32"> | |||
<Configuration>Release</Configuration> | |||
<Platform>Win32</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|x64"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>x64</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|x64"> | |||
<Configuration>Release</Configuration> | |||
<Platform>x64</Platform> | |||
</ProjectConfiguration> | |||
</ItemGroup> | |||
<PropertyGroup Label="Globals"> | |||
<VCProjectVersion>16.0</VCProjectVersion> | |||
<Keyword>Win32Proj</Keyword> | |||
<ProjectGuid>{0d25734e-a71b-4536-8dc4-60e945382fc5}</ProjectGuid> | |||
<RootNamespace>libpEpwebserver</RootNamespace> | |||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> | |||
<ProjectName>libpEpWebserver</ProjectName> | |||
</PropertyGroup> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | |||
<ConfigurationType>StaticLibrary</ConfigurationType> | |||
<UseDebugLibraries>true</UseDebugLibraries> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<CharacterSet>Unicode</CharacterSet> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | |||
<ConfigurationType>StaticLibrary</ConfigurationType> | |||
<UseDebugLibraries>false</UseDebugLibraries> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<WholeProgramOptimization>true</WholeProgramOptimization> | |||
<CharacterSet>Unicode</CharacterSet> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<UseDebugLibraries>true</UseDebugLibraries> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<CharacterSet>Unicode</CharacterSet> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<UseDebugLibraries>false</UseDebugLibraries> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<WholeProgramOptimization>true</WholeProgramOptimization> | |||
<CharacterSet>Unicode</CharacterSet> | |||
</PropertyGroup> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |||
<ImportGroup Label="ExtensionSettings"> | |||
</ImportGroup> | |||
<ImportGroup Label="Shared"> | |||
</ImportGroup> | |||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||
</ImportGroup> | |||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||
</ImportGroup> | |||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||
</ImportGroup> | |||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||
</ImportGroup> | |||
<PropertyGroup Label="UserMacros" /> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |||
<LinkIncremental>true</LinkIncremental> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |||
<LinkIncremental>false</LinkIncremental> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
<LinkIncremental>true</LinkIncremental> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||
<LinkIncremental>false</LinkIncremental> | |||
</PropertyGroup> | |||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |||
<ClCompile> | |||
<WarningLevel>Level3</WarningLevel> | |||
<SDLCheck>true</SDLCheck> | |||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<ConformanceMode>true</ConformanceMode> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||
</Link> | |||
</ItemDefinitionGroup> | |||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |||
<ClCompile> | |||
<WarningLevel>Level3</WarningLevel> | |||
<FunctionLevelLinking>true</FunctionLevelLinking> | |||
<IntrinsicFunctions>true</IntrinsicFunctions> | |||
<SDLCheck>true</SDLCheck> | |||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<ConformanceMode>true</ConformanceMode> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
<EnableCOMDATFolding>true</EnableCOMDATFolding> | |||
<OptimizeReferences>true</OptimizeReferences> | |||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||
</Link> | |||
</ItemDefinitionGroup> | |||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
<ClCompile> | |||
<WarningLevel>Level3</WarningLevel> | |||
<SDLCheck>true</SDLCheck> | |||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<ConformanceMode>true</ConformanceMode> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||
</Link> | |||
</ItemDefinitionGroup> | |||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||
<ClCompile> | |||
<WarningLevel>Level3</WarningLevel> | |||
<FunctionLevelLinking>true</FunctionLevelLinking> | |||
<IntrinsicFunctions>true</IntrinsicFunctions> | |||
<SDLCheck>true</SDLCheck> | |||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||
<ConformanceMode>true</ConformanceMode> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
<EnableCOMDATFolding>true</EnableCOMDATFolding> | |||
<OptimizeReferences>true</OptimizeReferences> | |||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||
</Link> | |||
</ItemDefinitionGroup> | |||
<ItemGroup> | |||
<ClCompile Include="..\webserver.cc" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ClInclude Include="..\webserver.hh" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\..\..\pEpEngine\build-windows\pEpEngine.vcxproj"> | |||
<Project>{146e69f8-e1da-456a-b048-6dd29d9acf6b}</Project> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||
<ImportGroup Label="ExtensionTargets"> | |||
<Import Project="..\..\..\..\packages\boost.1.72.0.0\build\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.72.0.0\build\boost.targets')" /> | |||
<Import Project="..\..\..\..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets" Condition="Exists('..\..\..\..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets')" /> | |||
<Import Project="..\..\..\..\packages\boost_filesystem-vc142.1.72.0.0\build\boost_filesystem-vc142.targets" Condition="Exists('..\..\..\..\packages\boost_filesystem-vc142.1.72.0.0\build\boost_filesystem-vc142.targets')" /> | |||
<Import Project="..\..\..\..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets" Condition="Exists('..\..\..\..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" /> | |||
</ImportGroup> | |||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||
<PropertyGroup> | |||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> | |||
</PropertyGroup> | |||
<Error Condition="!Exists('..\..\..\..\packages\boost.1.72.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost.1.72.0.0\build\boost.targets'))" /> | |||
<Error Condition="!Exists('..\..\..\..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets'))" /> | |||