Compare commits

...

9 Commits

104 changed files with 331 additions and 17051 deletions
Split View
  1. +0
    -747
      API reference details.md
  2. +0
    -96
      API reference.md
  3. +37
    -691
      README.md
  4. +0
    -172
      build-windows/pEp/libpEpwebserver/libpEpWebserver.vcxproj
  5. +0
    -30
      build-windows/pEp/libpEpwebserver/libpEpWebserver.vcxproj.filters
  6. +0
    -7
      build-windows/pEp/libpEpwebserver/packages.config
  7. +0
    -268
      build-windows/pEp/webserver.cc
  8. +0
    -99
      build-windows/pEp/webserver.hh
  9. +0
    -139
      build-windows/pEpJSONServerAdapter/pEpJSONServerAdapter.vcxproj
  10. +0
    -39
      build-windows/pEpJSONServerAdapter/pEpJSONServerAdapter.vcxproj.filters
  11. +0
    -186
      build-windows/pEpJSONServerAdapter/pEpJSONServerAdapterLibrary.vcxproj
  12. +0
    -186
      build-windows/pEpJSONServerAdapter/pEpJSONServerAdapterLibrary.vcxproj.filters
  13. +0
    -151
      build-windows/pEpJSONServerAdapter/pEpJSONServerAdapterUnittests.vcxproj
  14. +0
    -10
      build-windows/pEpJSONServerAdapter/packages.config
  15. +0
    -19
      hotfixes/Makefile
  16. +0
    -11
      hotfixes/gpg.conf.broken
  17. +0
    -16
      hotfixes/gpg.conf.fixed
  18. +0
    -580
      hotfixes/main.c
  19. +0
    -38
      html/crashview.html
  20. +0
    -90
      html/crashview.js
  21. +0
    -88
      html/index.html
  22. +0
    -685
      html/interactive.js
  23. +0
    -4
      html/jquery-2.2.0.min.js
  24. BIN
      html/json-test.ico
  25. +33
    -0
      html/logview.js
  26. +0
    -32
      html/test-encode-decode.js
  27. +0
    -41
      html/unittests.js
  28. +0
    -196
      server/Makefile
  29. +0
    -150
      server/base64.cc
  30. +0
    -12
      server/base64.hh
  31. +0
    -21
      server/c_string.cc
  32. +0
    -149
      server/c_string.hh
  33. +0
    -29
      server/config.hh
  34. +0
    -46
      server/context.cc
  35. +0
    -43
      server/context.hh
  36. +0
    -13
      server/daemonize.hh
  37. +0
    -16
      server/daemonize_unix.cc
  38. +0
    -172
      server/daemonize_windows.cc
  39. +0
    -5
      server/download_boost_1_68.sh
  40. +0
    -418
      server/ev_server.cc
  41. +0
    -55
      server/ev_server.hh
  42. +0
    -76
      server/function_map.cc
  43. +0
    -369
      server/function_map.hh
  44. +0
    -175
      server/inout.cc
  45. +0
    -301
      server/inout.hh
  46. +0
    -496
      server/json-adapter.cc
  47. +0
    -156
      server/json-adapter.hh
  48. +0
    -151
      server/json_rpc.cc
  49. +0
    -37
      server/json_rpc.hh
  50. +0
    -24
      server/json_spirit/LICENSE.txt
  51. +0
    -22
      server/json_spirit/Makefile
  52. +0
    -18
      server/json_spirit/json_spirit.h
  53. +0
    -40
      server/json_spirit/json_spirit_error_position.h
  54. +0
    -181
      server/json_spirit/json_spirit_reader.cc
  55. +0
    -62
      server/json_spirit/json_spirit_reader.h
  56. +0
    -688
      server/json_spirit/json_spirit_reader_template.h
  57. +0
    -70
      server/json_spirit/json_spirit_stream_reader.h
  58. +0
    -63
      server/json_spirit/json_spirit_utils.h
  59. +0
    -6
      server/json_spirit/json_spirit_value.cc
  60. +0
    -609
      server/json_spirit/json_spirit_value.h
  61. +0
    -113
      server/json_spirit/json_spirit_writer.cc
  62. +0
    -65
      server/json_spirit/json_spirit_writer.h
  63. +0
    -35
      server/json_spirit/json_spirit_writer_options.h
  64. +0
    -338
      server/json_spirit/json_spirit_writer_template.h
  65. +0
    -3
      server/main.hh
  66. +0
    -38
      server/mini-adapter-impl.cc
  67. +0
    -30
      server/mini-adapter-impl.hh
  68. +0
    -207
      server/mini-adapter-main.cc
  69. +0
    -505
      server/nfc.cc
  70. +0
    -60
      server/nfc.hh
  71. +0
    -3078
      server/nfc_sets.cc
  72. +0
    -28
      server/nfc_sets.hh
  73. +0
    -806
      server/pEp-types.cc
  74. +0
    -59
      server/pEp-types.hh
  75. +0
    -39
      server/pEp-utils-json.hh
  76. +0
    -14
      server/pEp-utils.cc
  77. +0
    -17
      server/pEp-utils.hh
  78. +0
    -216
      server/parse_mail.cc
  79. +0
    -11
      server/prefix-config.cc
  80. +0
    -2
      server/prefix-config.hh
  81. +0
    -134
      server/registry.cc
  82. +0
    -134
      server/registry.hh
  83. +0
    -99
      server/scripts/gen_sets.sh
  84. +0
    -133
      server/security-token.cc
  85. +0
    -15
      server/security-token.hh
  86. +0
    -227
      server/server_version.cc
  87. +0
    -32
      server/server_version.hh
  88. +0
    -119
      server/servertest.cc
  89. +0
    -108
      server/session_registry.cc
  90. +0
    -60
      server/session_registry.hh
  91. +0
    -83
      server/unittest_decompose.cc
  92. +0
    -141
      server/unittest_encrypt_decrypt.cc
  93. +0
    -197
      server/unittest_json.cc
  94. +0
    -79
      server/unittest_logger.cc
  95. +0
    -75
      server/unittest_nfc.cc
  96. +0
    -185
      server/unittest_pEp.cc
  97. +0
    -231
      server/unittest_rpc.cc
  98. +0
    -41
      server/unittest_string.cc
  99. +100
    -0
      src/Makefile
  100. +0
    -0
      src/local.conf.example

+ 0
- 747
API reference details.md View File

@ -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

+ 0
- 96
API reference.md View File

@ -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 | |

+ 37
- 691
README.md View File

@ -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`

+ 0
- 172
build-windows/pEp/libpEpwebserver/libpEpWebserver.vcxproj View File

@ -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'))" />