diff --git a/.gitignore b/.gitignore index 00289aea..344105fd 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ build-android/pEpEngine-android-1.zip build-android/third-party build-android/pEpEngine-android-1 build-linux/* +build-windows/libpEpasn1/libpEpasn1.vcxproj.user *.dSYM* *_test msg4.asc @@ -87,6 +88,13 @@ test/EngineTests test/googletest test/tmp/* +src/commit_hash.h +.idea/ +venv/ +venv2/ +cleangit.py +newgit + # ignore generated test data test/655_16F07F382FB3CF5DF977005D1069C7CACF9C23C6.asc diff --git a/.gitlab-ci-files/common-prepare.yml b/.gitlab-ci-files/common-prepare.yml new file mode 100644 index 00000000..8053794f --- /dev/null +++ b/.gitlab-ci-files/common-prepare.yml @@ -0,0 +1,22 @@ +.ensure_docker: &ensure_docker + # Check for docker and install if missing + - 'which docker || ( sudo apt-get update -y && sudo apt-get install docker.io -y )' + +.ensure_rsync: &ensure_rsync + # Install rsync and deps if missing + - 'which ssh-agent || ( sudo apt-get update -y && sudo apt-get install openssh-client -y )' + - 'which rsync || ( sudo apt-get update -y && sudo apt-get install rsync -y )' + - 'which make || ( sudo apt-get update -y && sudo apt-get install make -y )' + +.standard_job: + tags: [kvm] + before_script: + - *ensure_docker + - *ensure_rsync + +.make_in_docker: + extends: .standard_job + script: + - docker login -u ${DOCKER_REGISTRY_USER} -p ${DOCKER_REGISTRY_PASS} ${DOCKER_REGISTRY_HOST} + - cd scripts/${CI_DISTRO_TARGET} + - make diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..4dc84594 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,27 @@ +include: + - '.gitlab-ci-files/common-prepare.yml' + +stages: + - build + + +# Debian + +debian10:build: + extends: .make_in_docker + stage: build + variables: + CI_DISTRO_TARGET: "debian10" + DEBIAN_FRONTEND: "noninteractive" + rules: + - if: '$CI_COMMIT_TAG !~ /^Release_[0-9]+\.[0-9]+\.[0-9]+$/' + +debian10:tagged-build: + extends: .make_in_docker + stage: build + variables: + CI_DISTRO_TARGET: "debian10" + DEBIAN_FRONTEND: "noninteractive" + TAGGED_BUILD: "true" + rules: + - if: '$CI_COMMIT_TAG =~ /^Release_[0-9]+\.[0-9]+\.[0-9]+$/' diff --git a/DEPENDENCIES b/DEPENDENCIES new file mode 100644 index 00000000..9970c4ce --- /dev/null +++ b/DEPENDENCIES @@ -0,0 +1,4 @@ +# 1st Party Dependencies +## Prefer git tags instead of SHA hashes when possible. + +sequoia=365d00a08bec6a5a48d48a7c7893d78c27092b59 diff --git a/Makefile b/Makefile index 71d4db54..55628094 100644 --- a/Makefile +++ b/Makefile @@ -19,24 +19,37 @@ ifdef BUILD_CONFIG $(info ================================================) endif -.PHONY: all sync asn1 build install dbinstall uninstall clean tags test package db +BUILT_IN_MIME= -build: asn1 +ifdef PEP_MIME + BUILT_IN_MIME=pepmime +endif + +.PHONY: all $(BUILT_IN_MIME) sync asn1 build install dbinstall uninstall clean tags test package db + +build: $(BUILT_IN_MIME) asn1 $(MAKE) -C src all: build # `make all` is not for tests, that's what `make test` is for # $(MAKE) -C test +pepmime: + $(MAKE) -C pEpMIME lib + sync: $(MAKE) -C sync asn1: sync $(MAKE) -C asn.1 + install: build $(MAKE) -C src install $(MAKE) -C asn.1 install +ifeq ($(BUILT_IN_MIME),pepmime) + $(MAKE) -C pEpMIME install +endif beinstall: $(MAKE) -C src beinstall @@ -55,6 +68,9 @@ clean: $(MAKE) -C asn.1 clean $(MAKE) -C sync clean $(MAKE) -C build-android clean +ifdef PEP_MIME + $(MAKE) -C pEpMIME clean +endif tags: $(MAKE) -C asn.1 tags diff --git a/Makefile.conf b/Makefile.conf index ee27132f..a8c86bac 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -15,7 +15,6 @@ # It is possible to use multiple variants simultaniously. # If nothing is changed according to these 3 methods, a default configuration for your platform (specified below) will be used for the build. - ######### Header ######### HERE:=$(dir $(lastword $(MAKEFILE_LIST))) @@ -74,28 +73,29 @@ TARGET_ARCH= # The following two variables will be appended to. # You can thus not set them to a final, fixed value here. ifeq ($(BUILD_FOR),Linux) - LDFLAGS= + LDFLAGS+= else ifeq ($(BUILD_FOR),Darwin) # "-bind_at_load" helps find symbol resolution errors faster - LDFLAGS=-bind_at_load + LDFLAGS+=-bind_at_load endif +# Are we wiping this on purpose? LDLIBS= - ######### C ######### ifeq ($(BUILD_FOR),Linux) - CC=gcc -std=c99 -pthread + CC=gcc else ifeq ($(BUILD_FOR),Darwin) - # clang issues a warning when "-pthread" is used for linking. - # So, include it in CFLAGS, and not in CC - CC=clang -std=c99 + CC=clang endif +CFLAGS+=-std=c99 -pthread +CFLAGS+=-fPIC -fstrict-aliasing + ifeq ($(BUILD_FOR),Linux) - CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=auto + CFLAGS+=-fdiagnostics-color=auto else ifeq ($(BUILD_FOR),Darwin) - CFLAGS=-pthread -fPIC -fstrict-aliasing -fcolor-diagnostics + CFLAGS+=-fcolor-diagnostics endif # The flag -DNDEBUG will always be removed from CFLAGS for compiling tests. @@ -131,24 +131,28 @@ ifeq ($(BUILD_FOR),Linux) # otherwise printed during the compilation of every asn1c-generated C file. # It's a glibc specific warning, only present in few versions around ~2.19. # See https://lwn.net/Articles/590381/ for a discussion. - CFLAGS_GENERATED=-D_DEFAULT_SOURCE + CPPFLAGS_GENERATED=-D_DEFAULT_SOURCE else ifeq ($(BUILD_FOR),Darwin) - CFLAGS_GENERATED= + CPPFLAGS_GENERATED= endif ######### C++ ######### ifeq ($(BUILD_FOR),Linux) - CXX=g++ -std=gnu++11 -pthread + CXX=g++ + CXXFLAGS+=-std=gnu++11 else ifeq ($(BUILD_FOR),Darwin) - # clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX - CXX=clang -std=c++11 + CXX=clang + CXXFLAGS+=-std=c++11 endif -# The flag -DNDEBUG will always be removed from CXXFLAGS for compiling tests. +CXXFLAGS+=-pthread + +# The flag -DNDEBUG will always be removed from CPPFLAGS for compiling tests. +# # The tests do not work properly, if compiled with -DNDEBUG ifeq ($(BUILD_FOR),Linux) - CXXFLAGS=-fdiagnostics-color=auto -I../src -I../asn.1 $(ETPAN_INC) + CXXFLAGS+=-fdiagnostics-color=auto -I../src -I../asn.1 $(ETPAN_INC) ifdef WARN CXXFLAGS+= else @@ -157,10 +161,11 @@ ifeq ($(BUILD_FOR),Linux) ifdef DEBUG CXXFLAGS+= -g -ggdb else - CXXFLAGS+= -O3 -DNDEBUG + CXXFLAGS+= -O3 + CPPFLAGS+= -DNDEBUG endif else ifeq ($(BUILD_FOR),Darwin) - CXXFLAGS=-pthread -fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC) + CXXFLAGS+=-fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC) ifdef WARN CXXFLAGS+= else @@ -169,16 +174,18 @@ else ifeq ($(BUILD_FOR),Darwin) ifdef DEBUG CXXFLAGS+= -O0 -g else - CXXFLAGS+= -O3 -DNDEBUG + CXXFLAGS+= -O3 + CPPFLAGS+= -DNDEBUG endif endif ######### C and C++ ######### ifeq ($(BUILD_FOR),Darwin) - CPPFLAGS=-D_DARWIN_C_SOURCE + CPPFLAGS+=-D_DARWIN_C_SOURCE + LDLIBS+=-liconv else - CPPFLAGS= + LDLIBS+=-luuid endif @@ -200,39 +207,42 @@ ASN1C_INC= #ASN1C_INC=-I$(HOME)/include -######### libetpan ######### -# libetpan library search flag -ETPAN_LIB= -#ETPAN_LIB=-L$(HOME)/lib +######### sqlite3 ######### +# If empty (or undefined), compile sqlite3 from the sources shipped with the pEp distribution. +# Otherwise, use an sqlite3 implementation found in the OS's include/library paths. +SQLITE3_FROM_OS=placeholder -# libetpan include search flag -ETPAN_INC= -#ETPAN_INC=-I$(HOME)/include +######### MIME ######### ######### pEp MIME ######### -# set this to skip libetpan and use PEP_MIME instead -# PEP_MIME=1 +# Set pEpMIME= anything (there are ifdefs on it) in your local.conf if you want +# to compile built-in pEpMIME (requires a separate libppEpMIME source repo to be +# checked out elsewhere on the system - define or redefine these in local.conf +# if you want to use it; otherwise, we default to etpan. (This will eventually +# become the default, but not yet. # -# pEp MIME library search flag -PEP_MIME_LIB= -# pEp MIME include search flag -PEP_MIME_INC= +PEP_MIME= +PEP_MIME_SRC=$(HOME)/src/pEpMIME/src -######### sqlite3 ######### -# If empty (or undefined), compile sqlite3 from the sources shipped with the pEp distribution. -# Otherwise, use an sqlite3 implementation found in the OS's include/library paths. -SQLITE3_FROM_OS=placeholder +######### libetpan ######### +# libetpan library search flag +# +ETPAN_LIB= +#ETPAN_LIB=-L$(HOME)/lib +# libetpan include search flag +ETPAN_INC= +#ETPAN_INC=-I$(HOME)/include ######### OpenPGP ######### # Selects OpenPGP implementation. must be `SEQUOIA` OPENPGP=SEQUOIA # Sequoia-specific variables -SEQUOIA_CFLAGS= -SEQUOIA_LDFLAGS= +SEQUOIA_CFLAGS+= +SEQUOIA_LDFLAGS+= SEQUOIA_LIB= SEQUOIA_INC= @@ -258,6 +268,10 @@ EXCLUDE= ######### Footer ######### + +################################ +# Include local.conf for any overrides and additional flags +################################ -include $(HERE)/local.conf ifdef BUILD_CONFIG @@ -265,26 +279,43 @@ ifdef BUILD_CONFIG endif ######### Post processing assignments ######## -# These variables are ineffective when set anywhere else but here. -# KB: I have no idea why we do this - it totally defeats the purpose of -# local.conf. -# For now: set if has no value. + +# If sequoia has been set up and the SEQUOIA flags aren't defined, set them up. +# Otherwise, add them to the CFLAGS/CXXFLAGS/LDFLAGS and library/include variables ifeq ($(OPENPGP),SEQUOIA) ifeq ($(SEQUOIA_CFLAGS),) - SEQUOIA_CFLAGS=$(shell pkg-config --cflags-only-other sequoia-openpgp) + SEQUOIA_CFLAGS+=$(shell pkg-config --cflags-only-other sequoia-openpgp) endif ifeq ($(SEQUOIA_LDFLAGS),) - SEQUOIA_LDFLAGS=$(shell pkg-config --libs-only-l --libs-only-other sequoia-openpgp) + SEQUOIA_LDFLAGS+=$(shell pkg-config --libs-only-l sequoia-openpgp) endif ifeq ($(SEQUOIA_LIB),) - SEQUOIA_LIB=$(shell pkg-config --libs-only-L sequoia-openpgp) + SEQUOIA_LIB=$(shell pkg-config --libs-only-L --libs-only-other sequoia-openpgp) endif ifeq ($(SEQUOIA_INC),) SEQUOIA_INC=$(shell pkg-config --cflags-only-I sequoia-openpgp) endif CFLAGS+= $(SEQUOIA_CFLAGS) + CXXFLAGS+= $(SEQUOIA_CFLAGS) LD_FLAGS+= $(SEQUOIA_LDFLAGS) endif # YML_PATH is needed in the environment of every call to a program of the YML2 distribution export YML_PATH=$(YML2_PATH) + +# Postprocess for pEpMIME +ifdef PEP_MIME + # Replace c++11 with c++14 for now (limiting the subst to the ++11 means it doesn't matter if gnu or not) + CXXFLAGS:=$(subst ++11,++14,$(CXXFLAGS)) -fPIC -fvisibility=hidden +endif +ifdef PEP_MIME +ifndef PEP_MIME_SRC + $(error "Compiling with the PEP_MIME option set requires the value of PEP_MIME_SRC to be set to the source directory for libpEpMIME") +else + CPPFLAGS+=-DPEP_BUILTIN_MIME + LDLIBS+=-lstdc++ + ETPAN_LIB= + ETPAN_INC= +endif +endif + diff --git a/README.md b/README.md index 8351a108..ca6f7300 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ It is under active development by several full-time employees of the p≡p found The most recent version of the source code can be obtained here: . This is the only offical way to obtain a copy of the source code. -# I would like to contribute to the p≡p Engine or a realated project, where do I start? +# I would like to contribute to the p≡p Engine or a related project, where do I start? First of all, excellent! You can find further information here: # Legal notes diff --git a/asn.1/Makefile b/asn.1/Makefile index 483a020e..62d10a67 100644 --- a/asn.1/Makefile +++ b/asn.1/Makefile @@ -5,7 +5,7 @@ include ../Makefile.conf ALL_SOURCE=$(subst $(NO_SOURCE),,$(wildcard *.c)) ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE)) -CPPFLAGS+=$(CFLAGS_GENERATED) +CPPFLAGS+=$(CPPFLAGS_GENERATED) ASN1C_INC+= -I. .PHONY: all clean install uninstall @@ -17,7 +17,7 @@ libasn1.a: $(ALL_OBJECTS) $(AR) -rc $@ $(ALL_OBJECTS) %.o: %.c %.h - $(CC) $(CPPFLAGS) $(CFLAGS) $(OPTIMIZE) $(ASN1C_INC) -c $< -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $(OPTIMIZE) $(ASN1C_INC) -c $< -o $@ Sync.c: sync.asn1 keysync.asn1 pEp.asn1 $(ASN1C) -gen-PER -fincludes-quoted -fcompound-names -pdu=auto pEp.asn1 keysync.asn1 $< diff --git a/build-mac/pEpEngine.xcodeproj/project.pbxproj b/build-mac/pEpEngine.xcodeproj/project.pbxproj index 92494316..fa3f4e77 100644 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj @@ -6,11 +6,49 @@ objectVersion = 51; objects = { +/* Begin PBXAggregateTarget section */ + 150845DE25F13CE700D46DA6 /* generate_code */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 150845E525F13CE700D46DA6 /* Build configuration list for PBXAggregateTarget "generate_code" */; + buildPhases = ( + 150845EA25F13CF100D46DA6 /* ShellScript */, + ); + dependencies = ( + ); + name = generate_code; + productName = generate_code; + }; + 15B21C2225FB8BE70097927A /* create_commit_hash_dot.h */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 15B21C2925FB8BE70097927A /* Build configuration list for PBXAggregateTarget "create_commit_hash_dot.h" */; + buildPhases = ( + 15B21C2F25FB8BEC0097927A /* ShellScript */, + ); + dependencies = ( + ); + name = create_commit_hash_dot.h; + productName = create_commit_hash_dot.h; + }; +/* End PBXAggregateTarget section */ + /* Begin PBXBuildFile section */ 15147EF0237E9EA7003989FE /* NegotiationRequestGrouped.h in Headers */ = {isa = PBXBuildFile; fileRef = 15147EE8237E9EA7003989FE /* NegotiationRequestGrouped.h */; }; 15147EF1237E9EA7003989FE /* GroupHandshake.h in Headers */ = {isa = PBXBuildFile; fileRef = 15147EED237E9EA7003989FE /* GroupHandshake.h */; }; 15147EF2237E9EA7003989FE /* GroupKeysAndClose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15147EEE237E9EA7003989FE /* GroupKeysAndClose.c */; }; 15147EF3237E9EA7003989FE /* GroupKeysAndClose.h in Headers */ = {isa = PBXBuildFile; fileRef = 15147EEF237E9EA7003989FE /* GroupKeysAndClose.h */; }; + 1543DA422577F8BE0041EFB5 /* Sync_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188A9223C4B2DE008EF79C /* Sync_actions.c */; }; + 1543DA432577F8BE0041EFB5 /* Sync_event.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188A9023C4B2DE008EF79C /* Sync_event.c */; }; + 1543DA442577F8BE0041EFB5 /* Sync_func.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188A8E23C4B2DE008EF79C /* Sync_func.c */; }; + 1543DA452577F8BE0041EFB5 /* Sync_func.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188A8C23C4B2DE008EF79C /* Sync_func.h */; }; + 1543DA462577F8BE0041EFB5 /* sync_codec.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188A9123C4B2DE008EF79C /* sync_codec.h */; }; + 1543DA472577F8BE0041EFB5 /* KeySync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188A8B23C4B2DE008EF79C /* KeySync_fsm.c */; }; + 1543DA482577F8BE0041EFB5 /* sync_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188A8623C4B2DD008EF79C /* sync_codec.c */; }; + 1543DA492577F8BE0041EFB5 /* KeySync_fsm.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188A8923C4B2DD008EF79C /* KeySync_fsm.h */; }; + 1543DA4A2577F8BE0041EFB5 /* Sync_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188A8F23C4B2DE008EF79C /* Sync_impl.c */; }; + 1543DA4B2577F8BE0041EFB5 /* Sync_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188A8723C4B2DD008EF79C /* Sync_impl.h */; }; + 1543DA4C2577F8BE0041EFB5 /* Sync_event.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188A8823C4B2DD008EF79C /* Sync_event.h */; }; + 1543DAA9257801880041EFB5 /* baseprotocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C414C1D510D8800C63EFF /* baseprotocol.c */; }; + 1543DAAD257801A90041EFB5 /* resource_id.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F6921C1F164A47009418F5 /* resource_id.c */; }; 154917FD22B926700091B6D6 /* libnettle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917F922B9266F0091B6D6 /* libnettle.a */; }; 154917FE22B926700091B6D6 /* libsequoia_openpgp_ffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917FA22B926700091B6D6 /* libsequoia_openpgp_ffi.a */; }; 154917FF22B926700091B6D6 /* libhogweed.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917FB22B926700091B6D6 /* libhogweed.a */; }; @@ -24,6 +62,192 @@ 154918BC22B940200091B6D6 /* openpgp_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A322B9401F0091B6D6 /* openpgp_compat.h */; }; 154918BD22B940200091B6D6 /* growing_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A422B9401F0091B6D6 /* growing_buf.h */; }; 154918C322B940200091B6D6 /* blacklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918AA22B940200091B6D6 /* blacklist.h */; }; + 1552DB142577D4F100A92F71 /* pEpEngine_macOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 1552DB132577D4F100A92F71 /* pEpEngine_macOS.h */; }; + 1552DB162577D4F100A92F71 /* pEpEngine_macOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 1552DB152577D4F100A92F71 /* pEpEngine_macOS.m */; }; + 1552DB292577D5A800A92F71 /* GroupHandshake.h in Headers */ = {isa = PBXBuildFile; fileRef = 15147EED237E9EA7003989FE /* GroupHandshake.h */; }; + 1552DB2A2577D5A800A92F71 /* BIT_STRING.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378222B2B81E002D664C /* BIT_STRING.h */; }; + 1552DB2B2577D5A800A92F71 /* xer_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375B22B2B819002D664C /* xer_support.c */; }; + 1552DB2C2577D5A800A92F71 /* BIT_STRING.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377F22B2B81E002D664C /* BIT_STRING.c */; }; + 1552DB2D2577D5A800A92F71 /* CommitReject.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A222B2B822002D664C /* CommitReject.c */; }; + 1552DB2E2577D5A800A92F71 /* CommitAcceptForGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379B22B2B821002D664C /* CommitAcceptForGroup.h */; }; + 1552DB2F2577D5A800A92F71 /* constr_SEQUENCE_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375822B2B819002D664C /* constr_SEQUENCE_OF.c */; }; + 1552DB302577D5A800A92F71 /* KeyReset.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95323C49ED500CB1016 /* KeyReset.h */; }; + 1552DB312577D5A800A92F71 /* per_opentype.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379422B2B820002D664C /* per_opentype.c */; }; + 1552DB322577D5A800A92F71 /* GroupKeysUpdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 432714AA23A10B3B007EAD4A /* GroupKeysUpdate.c */; }; + 1552DB332577D5A800A92F71 /* PString.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376222B2B81A002D664C /* PString.c */; }; + 1552DB342577D5A800A92F71 /* ReceiverRating.c in Sources */ = {isa = PBXBuildFile; fileRef = 15EB7B7A250794D8004C176D /* ReceiverRating.c */; }; + 1552DB352577D5A800A92F71 /* INTEGER.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378F22B2B81F002D664C /* INTEGER.h */; }; + 1552DB362577D5A800A92F71 /* OwnKeysRequester.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379822B2B820002D664C /* OwnKeysRequester.h */; }; + 1552DB372577D5A800A92F71 /* PrintableString.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A322B2B822002D664C /* PrintableString.c */; }; + 1552DB382577D5A800A92F71 /* BOOLEAN.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A122B2B821002D664C /* BOOLEAN.c */; }; + 1552DB392577D5A800A92F71 /* Hex.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379122B2B820002D664C /* Hex.c */; }; + 1552DB3A2577D5A800A92F71 /* Distribution.c in Sources */ = {isa = PBXBuildFile; fileRef = 158FF95823C49ED600CB1016 /* Distribution.c */; }; + 1552DB3B2577D5A800A92F71 /* Command.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188AB023C4B6B9008EF79C /* Command.c */; }; + 1552DB3C2577D5A800A92F71 /* constr_SET_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379922B2B821002D664C /* constr_SET_OF.h */; }; + 1552DB3D2577D5A800A92F71 /* TID.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376A22B2B81B002D664C /* TID.h */; }; + 1552DB3E2577D5A800A92F71 /* Commands.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188AAB23C4B549008EF79C /* Commands.h */; }; + 1552DB3F2577D5A800A92F71 /* constr_CHOICE.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379C22B2B821002D664C /* constr_CHOICE.c */; }; + 1552DB402577D5A800A92F71 /* asn_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379F22B2B821002D664C /* asn_internal.h */; }; + 1552DB412577D5A800A92F71 /* asn_codecs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379D22B2B821002D664C /* asn_codecs.h */; }; + 1552DB422577D5A800A92F71 /* ISO639-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375D22B2B819002D664C /* ISO639-1.h */; }; + 1552DB432577D5A800A92F71 /* NegotiationOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374322B2B817002D664C /* NegotiationOpen.c */; }; + 1552DB442577D5A800A92F71 /* KeyReset.c in Sources */ = {isa = PBXBuildFile; fileRef = 158FF95223C49ED500CB1016 /* KeyReset.c */; }; + 1552DB452577D5A800A92F71 /* BOOLEAN.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375422B2B818002D664C /* BOOLEAN.h */; }; + 1552DB462577D5A800A92F71 /* GroupTrustThisKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377622B2B81D002D664C /* GroupTrustThisKey.c */; }; + 1552DB472577D5A800A92F71 /* CommitReject.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376822B2B81B002D664C /* CommitReject.h */; }; + 1552DB482577D5A800A92F71 /* constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377122B2B81C002D664C /* constraints.h */; }; + 1552DB492577D5A800A92F71 /* per_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375C22B2B819002D664C /* per_decoder.c */; }; + 1552DB4A2577D5A800A92F71 /* UTF8String.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376C22B2B81B002D664C /* UTF8String.h */; }; + 1552DB4B2577D5A800A92F71 /* TID.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377522B2B81D002D664C /* TID.c */; }; + 1552DB4C2577D5A800A92F71 /* Commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188AAA23C4B549008EF79C /* Commands.c */; }; + 1552DB4D2577D5A800A92F71 /* GroupKeysAndClose.h in Headers */ = {isa = PBXBuildFile; fileRef = 15147EEF237E9EA7003989FE /* GroupKeysAndClose.h */; }; + 1552DB4E2577D5A800A92F71 /* NegotiationRequestGrouped.h in Headers */ = {isa = PBXBuildFile; fileRef = 15147EE8237E9EA7003989FE /* NegotiationRequestGrouped.h */; }; + 1552DB4F2577D5A800A92F71 /* PrintableString.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375F22B2B81A002D664C /* PrintableString.h */; }; + 1552DB502577D5A800A92F71 /* SynchronizeGroupKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B75BDC23FA9F9D00DAE976 /* SynchronizeGroupKeys.c */; }; + 1552DB512577D5A800A92F71 /* NativeInteger.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374D22B2B818002D664C /* NativeInteger.h */; }; + 1552DB522577D5A800A92F71 /* OCTET_STRING.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378622B2B81E002D664C /* OCTET_STRING.h */; }; + 1552DB532577D5A800A92F71 /* constr_SEQUENCE.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374422B2B817002D664C /* constr_SEQUENCE.c */; }; + 1552DB542577D5A800A92F71 /* constr_SET_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378022B2B81E002D664C /* constr_SET_OF.c */; }; + 1552DB552577D5A800A92F71 /* constr_SEQUENCE_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378722B2B81E002D664C /* constr_SEQUENCE_OF.h */; }; + 1552DB562577D5A800A92F71 /* Sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374C22B2B818002D664C /* Sync.c */; }; + 1552DB572577D5A800A92F71 /* xer_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379522B2B820002D664C /* xer_support.h */; }; + 1552DB582577D5A800A92F71 /* constr_TYPE.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376522B2B81A002D664C /* constr_TYPE.h */; }; + 1552DB592577D5A800A92F71 /* der_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375022B2B818002D664C /* der_encoder.c */; }; + 1552DB5A2577D5A800A92F71 /* Beacon.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374822B2B817002D664C /* Beacon.c */; }; + 1552DB5B2577D5A800A92F71 /* KeySync.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376B22B2B81B002D664C /* KeySync.h */; }; + 1552DB5C2577D5A800A92F71 /* SynchronizeGroupKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B75BE123FA9F9D00DAE976 /* SynchronizeGroupKeys.h */; }; + 1552DB5D2577D5A800A92F71 /* Rollback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377222B2B81C002D664C /* Rollback.c */; }; + 1552DB5E2577D5A800A92F71 /* NegotiationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376922B2B81B002D664C /* NegotiationRequest.h */; }; + 1552DB5F2577D5A800A92F71 /* constr_TYPE.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377D22B2B81D002D664C /* constr_TYPE.c */; }; + 1552DB602577D5A800A92F71 /* InitUnledGroupKeyReset.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95423C49ED500CB1016 /* InitUnledGroupKeyReset.h */; }; + 1552DB612577D5A800A92F71 /* ReceiverRating.h in Headers */ = {isa = PBXBuildFile; fileRef = 15EB7B73250794D8004C176D /* ReceiverRating.h */; }; + 1552DB622577D5A800A92F71 /* asn_system.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374F22B2B818002D664C /* asn_system.h */; }; + 1552DB632577D5A800A92F71 /* Identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375622B2B819002D664C /* Identity.c */; }; + 1552DB642577D5A800A92F71 /* CommitAccept.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374122B2B817002D664C /* CommitAccept.c */; }; + 1552DB652577D5A800A92F71 /* asn_SEQUENCE_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A922B2B822002D664C /* asn_SEQUENCE_OF.h */; }; + 1552DB662577D5A800A92F71 /* ISO639-1.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376022B2B81A002D664C /* ISO639-1.c */; }; + 1552DB672577D5A800A92F71 /* GroupKeysUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95623C49ED600CB1016 /* GroupKeysUpdate.h */; }; + 1552DB682577D5A800A92F71 /* Identity.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374722B2B817002D664C /* Identity.h */; }; + 1552DB692577D5A800A92F71 /* CommitAccept.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378822B2B81F002D664C /* CommitAccept.h */; }; + 1552DB6A2577D5A800A92F71 /* UTF8String.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374522B2B817002D664C /* UTF8String.c */; }; + 1552DB6B2577D5A800A92F71 /* NativeEnumerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376422B2B81A002D664C /* NativeEnumerated.h */; }; + 1552DB6C2577D5A800A92F71 /* per_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378E22B2B81F002D664C /* per_support.h */; }; + 1552DB6D2577D5A800A92F71 /* constr_CHOICE.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377B22B2B81D002D664C /* constr_CHOICE.h */; }; + 1552DB6E2577D5A800A92F71 /* NativeInteger.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A022B2B821002D664C /* NativeInteger.c */; }; + 1552DB6F2577D5A800A92F71 /* ber_tlv_length.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0373F22B2B816002D664C /* ber_tlv_length.c */; }; + 1552DB702577D5A800A92F71 /* ElectGroupKeyResetLeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 4378C78B23D1AF1700D1AF3F /* ElectGroupKeyResetLeader.h */; }; + 1552DB712577D5A800A92F71 /* Version.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378B22B2B81F002D664C /* Version.c */; }; + 1552DB722577D5A800A92F71 /* xer_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376E22B2B81C002D664C /* xer_encoder.h */; }; + 1552DB732577D5A800A92F71 /* INTEGER.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378A22B2B81F002D664C /* INTEGER.c */; }; + 1552DB742577D5A800A92F71 /* ber_tlv_tag.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375322B2B818002D664C /* ber_tlv_tag.c */; }; + 1552DB752577D5A800A92F71 /* CommitAcceptForGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A622B2B822002D664C /* CommitAcceptForGroup.c */; }; + 1552DB762577D5A800A92F71 /* CommitAcceptOfferer.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375222B2B818002D664C /* CommitAcceptOfferer.h */; }; + 1552DB772577D5A800A92F71 /* pdu_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375922B2B819002D664C /* pdu_collection.c */; }; + 1552DB782577D5A800A92F71 /* IdentityList.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374B22B2B817002D664C /* IdentityList.h */; }; + 1552DB792577D5A800A92F71 /* Rollback.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374222B2B817002D664C /* Rollback.h */; }; + 1552DB7A2577D5A800A92F71 /* Rating.c in Sources */ = {isa = PBXBuildFile; fileRef = 15EB7B79250794D8004C176D /* Rating.c */; }; + 1552DB7B2577D5A800A92F71 /* per_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376622B2B81B002D664C /* per_encoder.c */; }; + 1552DB7C2577D5A800A92F71 /* Hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379022B2B81F002D664C /* Hash.c */; }; + 1552DB7D2577D5A800A92F71 /* GroupHandshake.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E4FBB32362C29100BC01F4 /* GroupHandshake.c */; }; + 1552DB7E2577D5A800A92F71 /* NegotiationRequestGrouped.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E4FBAD2362C05600BC01F4 /* NegotiationRequestGrouped.c */; }; + 1552DB7F2577D5A800A92F71 /* Beacon.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375A22B2B819002D664C /* Beacon.h */; }; + 1552DB802577D5A800A92F71 /* xer_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377922B2B81D002D664C /* xer_decoder.c */; }; + 1552DB812577D5A800A92F71 /* constraints.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378122B2B81E002D664C /* constraints.c */; }; + 1552DB822577D5A800A92F71 /* asn_SEQUENCE_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375722B2B819002D664C /* asn_SEQUENCE_OF.c */; }; + 1552DB832577D5A800A92F71 /* IdentityList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377422B2B81C002D664C /* IdentityList.c */; }; + 1552DB842577D5A800A92F71 /* constr_SEQUENCE.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377A22B2B81D002D664C /* constr_SEQUENCE.h */; }; + 1552DB852577D5A800A92F71 /* CommitAcceptRequester.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A522B2B822002D664C /* CommitAcceptRequester.h */; }; + 1552DB862577D5A800A92F71 /* CommitAcceptOfferer.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377E22B2B81D002D664C /* CommitAcceptOfferer.c */; }; + 1552DB872577D5A800A92F71 /* der_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378322B2B81E002D664C /* der_encoder.h */; }; + 1552DB882577D5A800A92F71 /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376322B2B81A002D664C /* Hash.h */; }; + 1552DB892577D5A800A92F71 /* ber_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378422B2B81E002D664C /* ber_decoder.h */; }; + 1552DB8A2577D5A800A92F71 /* per_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378C22B2B81F002D664C /* per_decoder.h */; }; + 1552DB8B2577D5A800A92F71 /* NegotiationRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374622B2B817002D664C /* NegotiationRequest.c */; }; + 1552DB8C2577D5A800A92F71 /* Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A422B2B822002D664C /* Sync.h */; }; + 1552DB8D2577D5A800A92F71 /* Hex.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379222B2B820002D664C /* Hex.h */; }; + 1552DB8E2577D5A800A92F71 /* Command.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188AB523C4B6B9008EF79C /* Command.h */; }; + 1552DB8F2577D5A800A92F71 /* per_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377722B2B81D002D664C /* per_encoder.h */; }; + 1552DB902577D5A800A92F71 /* OCTET_STRING.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374A22B2B817002D664C /* OCTET_STRING.c */; }; + 1552DB912577D5A800A92F71 /* xer_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375E22B2B81A002D664C /* xer_decoder.h */; }; + 1552DB922577D5A800A92F71 /* ber_tlv_tag.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376122B2B81A002D664C /* ber_tlv_tag.h */; }; + 1552DB932577D5A800A92F71 /* asn_codecs_prim.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377022B2B81C002D664C /* asn_codecs_prim.h */; }; + 1552DB942577D5A800A92F71 /* GroupKeysForNewMember.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95923C49ED600CB1016 /* GroupKeysForNewMember.h */; }; + 1552DB952577D5A800A92F71 /* InitUnledGroupKeyReset.c in Sources */ = {isa = PBXBuildFile; fileRef = 158FF95A23C49ED600CB1016 /* InitUnledGroupKeyReset.c */; }; + 1552DB962577D5A800A92F71 /* asn_SET_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376F22B2B81C002D664C /* asn_SET_OF.h */; }; + 1552DB972577D5A800A92F71 /* NegotiationOpen.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378522B2B81E002D664C /* NegotiationOpen.h */; }; + 1552DB982577D5A800A92F71 /* NativeEnumerated.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374E22B2B818002D664C /* NativeEnumerated.c */; }; + 1552DB992577D5A800A92F71 /* GroupTrustThisKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377C22B2B81D002D664C /* GroupTrustThisKey.h */; }; + 1552DB9A2577D5A800A92F71 /* per_opentype.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375522B2B819002D664C /* per_opentype.h */; }; + 1552DB9B2577D5A800A92F71 /* Version.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376D22B2B81C002D664C /* Version.h */; }; + 1552DB9C2577D5A800A92F71 /* ElectGroupKeyResetLeader.c in Sources */ = {isa = PBXBuildFile; fileRef = 4378C79023D1AF1700D1AF3F /* ElectGroupKeyResetLeader.c */; }; + 1552DB9D2577D5A800A92F71 /* ber_tlv_length.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379722B2B820002D664C /* ber_tlv_length.h */; }; + 1552DB9E2577D5A800A92F71 /* OwnKeysRequester.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375122B2B818002D664C /* OwnKeysRequester.c */; }; + 1552DB9F2577D5A800A92F71 /* PString.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374922B2B817002D664C /* PString.h */; }; + 1552DBA02577D5A800A92F71 /* Distribution.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95523C49ED600CB1016 /* Distribution.h */; }; + 1552DBA12577D5A800A92F71 /* Rating.h in Headers */ = {isa = PBXBuildFile; fileRef = 15EB7B78250794D8004C176D /* Rating.h */; }; + 1552DBA22577D5A800A92F71 /* GroupKeysForNewMember.c in Sources */ = {isa = PBXBuildFile; fileRef = 432713AF23A10B07007EAD4A /* GroupKeysForNewMember.c */; }; + 1552DBA32577D5A800A92F71 /* asn_application.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A822B2B822002D664C /* asn_application.h */; }; + 1552DBA42577D5A800A92F71 /* ber_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378922B2B81F002D664C /* ber_decoder.c */; }; + 1552DBA52577D5A800A92F71 /* xer_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379322B2B820002D664C /* xer_encoder.c */; }; + 1552DBA62577D5A800A92F71 /* OwnKeysOfferer.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378D22B2B81F002D664C /* OwnKeysOfferer.c */; }; + 1552DBA72577D5A800A92F71 /* GroupKeysAndClose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15147EEE237E9EA7003989FE /* GroupKeysAndClose.c */; }; + 1552DBA82577D5A800A92F71 /* asn_SET_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379622B2B820002D664C /* asn_SET_OF.c */; }; + 1552DBA92577D5A800A92F71 /* per_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379E22B2B821002D664C /* per_support.c */; }; + 1552DBAA2577D5A800A92F71 /* CommitAcceptRequester.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376722B2B81B002D664C /* CommitAcceptRequester.c */; }; + 1552DBAB2577D5A800A92F71 /* OwnKeysOfferer.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A722B2B822002D664C /* OwnKeysOfferer.h */; }; + 1552DBAC2577D5A800A92F71 /* asn_codecs_prim.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379A22B2B821002D664C /* asn_codecs_prim.c */; }; + 1552DBAD2577D5A800A92F71 /* KeySync.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377322B2B81C002D664C /* KeySync.c */; }; + 1552DC012577D67800A92F71 /* transport.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826751B455D0800EECAF0 /* transport.c */; }; + 1552DC052577D67D00A92F71 /* trans_auto.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826731B455D0800EECAF0 /* trans_auto.c */; }; + 1552DC092577D68000A92F71 /* timestamp.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826711B455D0800EECAF0 /* timestamp.c */; }; + 1552DC0D2577D68500A92F71 /* stringpair.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266F1B455D0800EECAF0 /* stringpair.c */; }; + 1552DC112577D68900A92F71 /* stringlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266D1B455D0800EECAF0 /* stringlist.c */; }; + 1552DC152577D68F00A92F71 /* platform_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826651B455D0800EECAF0 /* platform_unix.c */; }; + 1552DC192577D69300A92F71 /* pEpEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 64A826611B455D0800EECAF0 /* pEpEngine.h */; }; + 1552DC1D2577D69A00A92F71 /* pEpEngine.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826601B455D0800EECAF0 /* pEpEngine.c */; }; + 1552DC212577D6A000A92F71 /* mime.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8265D1B455D0800EECAF0 /* mime.c */; }; + 1552DC252577D6A600A92F71 /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8265B1B455D0800EECAF0 /* message.c */; }; + 1552DC292577D6AA00A92F71 /* message_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826591B455D0800EECAF0 /* message_api.c */; }; + 1552DC2D2577D6AE00A92F71 /* keymanagement.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826571B455D0800EECAF0 /* keymanagement.c */; }; + 1552DC312577D6B100A92F71 /* identity_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826551B455D0800EECAF0 /* identity_list.c */; }; + 1552DC352577D6B500A92F71 /* etpan_mime.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826531B455D0800EECAF0 /* etpan_mime.c */; }; + 1552DC392577D6B900A92F71 /* email.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826511B455D0800EECAF0 /* email.c */; }; + 1552DC3D2577D6BE00A92F71 /* cryptotech.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8264E1B455D0800EECAF0 /* cryptotech.c */; }; + 1552DC412577D6C200A92F71 /* bloblist.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8264C1B455D0800EECAF0 /* bloblist.c */; }; + 1552DC452577D6C600A92F71 /* blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 430D258A1C9ED75A00B94535 /* blacklist.c */; }; + 1552DC492577D6C900A92F71 /* map_asn1.h in Headers */ = {isa = PBXBuildFile; fileRef = 646788881CEB3D120001F54C /* map_asn1.h */; }; + 1552DC4D2577D6CD00A92F71 /* map_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = 646788871CEB3D120001F54C /* map_asn1.c */; }; + 1552DC512577D6D000A92F71 /* baseprotocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C414D1D510D8800C63EFF /* baseprotocol.h */; }; + 1552DC552577D6D700A92F71 /* pEp_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BCC462015EE800077E998 /* pEp_string.h */; }; + 1552DC592577D6DB00A92F71 /* pEp_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 430BCC472015EE800077E998 /* pEp_string.c */; }; + 1552DC5D2577D6DE00A92F71 /* sync_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C092166282C00AB4524 /* sync_api.c */; }; + 1552DC612577D6E000A92F71 /* openpgp_compat.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C032166282C00AB4524 /* openpgp_compat.c */; }; + 1552DC652577D6F900A92F71 /* keyreset_command.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188AA223C4B4B3008EF79C /* keyreset_command.c */; }; + 1552DC662577D6F900A92F71 /* distribution_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 43188ABE23C4BBDD008EF79C /* distribution_codec.c */; }; + 1552DC672577D6F900A92F71 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 436084222539A3B0005D56A7 /* sqlite3.c */; }; + 1552DC682577D6F900A92F71 /* internal_format.c in Sources */ = {isa = PBXBuildFile; fileRef = 43C3778D246A8C0300962D22 /* internal_format.c */; }; + 1552DC692577D6F900A92F71 /* growing_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C0A2166282C00AB4524 /* growing_buf.c */; }; + 1552DC6A2577D6F900A92F71 /* pgp_sequoia.c in Sources */ = {isa = PBXBuildFile; fileRef = 159EF42422B6D3E900149C0C /* pgp_sequoia.c */; }; + 1552DC6B2577D6F900A92F71 /* labeled_int_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 438C43B42167752C00C7425B /* labeled_int_list.c */; }; + 1552DC6C2577D6F900A92F71 /* key_reset.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C052166282C00AB4524 /* key_reset.c */; }; + 1552DC6D2577D6F900A92F71 /* aux_mime_msg.c in Sources */ = {isa = PBXBuildFile; fileRef = 154918A222B9401F0091B6D6 /* aux_mime_msg.c */; }; + 1552DC6E2577D6F900A92F71 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = C46EBAE7216E445F0042A6A3 /* base64.c */; }; + 1552DC722577D70000A92F71 /* key_reset.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04B222733A7E00CCE960 /* key_reset.h */; }; + 1552DC762577D70400A92F71 /* labeled_int_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43AF2167752C00C7425B /* labeled_int_list.h */; }; + 1552DC7A2577D70700A92F71 /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = C46EBAEC216E445F0042A6A3 /* base64.h */; }; + 1552DC7E2577D71800A92F71 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 436084232539A3B1005D56A7 /* sqlite3.h */; }; + 1552DC7F2577D71800A92F71 /* pgp_sequoia_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 159EF42622B6D3E900149C0C /* pgp_sequoia_internal.h */; }; + 1552DC802577D71800A92F71 /* fsm_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189222B9401D0091B6D6 /* fsm_common.h */; }; + 1552DC812577D71800A92F71 /* aux_mime_msg.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189922B9401E0091B6D6 /* aux_mime_msg.h */; }; + 1552DC822577D71800A92F71 /* resource_id.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A122B9401F0091B6D6 /* resource_id.h */; }; + 1552DC832577D71800A92F71 /* openpgp_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A322B9401F0091B6D6 /* openpgp_compat.h */; }; + 1552DC842577D71800A92F71 /* keyreset_command.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188AA723C4B4B3008EF79C /* keyreset_command.h */; }; + 1552DC852577D71800A92F71 /* blacklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918AA22B940200091B6D6 /* blacklist.h */; }; + 1552DC862577D71800A92F71 /* pgp_sequoia.h in Headers */ = {isa = PBXBuildFile; fileRef = 159EF42522B6D3E900149C0C /* pgp_sequoia.h */; }; + 1552DC872577D71800A92F71 /* growing_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A422B9401F0091B6D6 /* growing_buf.h */; }; + 1552DC882577D71800A92F71 /* internal_format.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C37788246A8C0300962D22 /* internal_format.h */; }; + 1552DC892577D71800A92F71 /* status_to_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189322B9401E0091B6D6 /* status_to_string.h */; }; + 1552DC8A2577D71800A92F71 /* distribution_codec.h in Headers */ = {isa = PBXBuildFile; fileRef = 43188ABF23C4BBDE008EF79C /* distribution_codec.h */; }; 158FF95B23C49ED600CB1016 /* KeyReset.c in Sources */ = {isa = PBXBuildFile; fileRef = 158FF95223C49ED500CB1016 /* KeyReset.c */; }; 158FF95C23C49ED600CB1016 /* KeyReset.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95323C49ED500CB1016 /* KeyReset.h */; }; 158FF95D23C49ED600CB1016 /* InitUnledGroupKeyReset.h in Headers */ = {isa = PBXBuildFile; fileRef = 158FF95423C49ED500CB1016 /* InitUnledGroupKeyReset.h */; }; @@ -214,6 +438,41 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 1508460625F24D1100D46DA6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 64796A371B455AA5004B1C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 644297BE1BE11C65002BC73B; + remoteInfo = pEpTrustWords; + }; + 15B21C3525FB8DD10097927A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 64796A371B455AA5004B1C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 150845DE25F13CE700D46DA6; + remoteInfo = generate_code; + }; + 15B21C3725FB8DDB0097927A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 64796A371B455AA5004B1C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 15B21C2225FB8BE70097927A; + remoteInfo = create_commit_hash_dot.h; + }; + 15B21C3E25FB8E160097927A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 64796A371B455AA5004B1C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 150845DE25F13CE700D46DA6; + remoteInfo = generate_code; + }; + 15B21C4025FB8E1B0097927A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 64796A371B455AA5004B1C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 15B21C2225FB8BE70097927A; + remoteInfo = create_commit_hash_dot.h; + }; 43D47AA0225CC82400E97C5B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 64796A371B455AA5004B1C24 /* Project object */; @@ -264,6 +523,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1508458825F101FB00D46DA6 /* libetpan.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libetpan.a; path = ../../local/lib/libetpan.a; sourceTree = ""; }; 15147EE8237E9EA7003989FE /* NegotiationRequestGrouped.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationRequestGrouped.h; path = ../asn.1/NegotiationRequestGrouped.h; sourceTree = ""; }; 15147EED237E9EA7003989FE /* GroupHandshake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupHandshake.h; path = ../asn.1/GroupHandshake.h; sourceTree = ""; }; 15147EEE237E9EA7003989FE /* GroupKeysAndClose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupKeysAndClose.c; path = ../asn.1/GroupKeysAndClose.c; sourceTree = ""; }; @@ -273,7 +533,6 @@ 154917FB22B926700091B6D6 /* libhogweed.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhogweed.a; path = ../../sequoia4ios/build/lib/libhogweed.a; sourceTree = ""; }; 154917FC22B926700091B6D6 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmp.a; path = ../../sequoia4ios/build/lib/libgmp.a; sourceTree = ""; }; 1549180D22B92EA20091B6D6 /* libiconv.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.2.tbd; path = usr/lib/libiconv.2.tbd; sourceTree = SDKROOT; }; - 1549181322B92EA50091B6D6 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; 1549189222B9401D0091B6D6 /* fsm_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fsm_common.h; path = ../src/fsm_common.h; sourceTree = ""; }; 1549189322B9401E0091B6D6 /* status_to_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = status_to_string.h; path = ../src/status_to_string.h; sourceTree = ""; }; 1549189922B9401E0091B6D6 /* aux_mime_msg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aux_mime_msg.h; path = ../src/aux_mime_msg.h; sourceTree = ""; }; @@ -282,6 +541,9 @@ 154918A322B9401F0091B6D6 /* openpgp_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = openpgp_compat.h; path = ../src/openpgp_compat.h; sourceTree = ""; }; 154918A422B9401F0091B6D6 /* growing_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = growing_buf.h; path = ../src/growing_buf.h; sourceTree = ""; }; 154918AA22B940200091B6D6 /* blacklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = blacklist.h; path = ../src/blacklist.h; sourceTree = ""; }; + 1552DB112577D4F100A92F71 /* libpEpEngine_macOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpEpEngine_macOS.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 1552DB132577D4F100A92F71 /* pEpEngine_macOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pEpEngine_macOS.h; sourceTree = ""; }; + 1552DB152577D4F100A92F71 /* pEpEngine_macOS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = pEpEngine_macOS.m; sourceTree = ""; }; 158FF95223C49ED500CB1016 /* KeyReset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeyReset.c; path = ../asn.1/KeyReset.c; sourceTree = ""; }; 158FF95323C49ED500CB1016 /* KeyReset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyReset.h; path = ../asn.1/KeyReset.h; sourceTree = ""; }; 158FF95423C49ED500CB1016 /* InitUnledGroupKeyReset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InitUnledGroupKeyReset.h; path = ../asn.1/InitUnledGroupKeyReset.h; sourceTree = ""; }; @@ -438,7 +700,6 @@ 438C43B42167752C00C7425B /* labeled_int_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = labeled_int_list.c; path = ../src/labeled_int_list.c; sourceTree = ""; }; 43C37788246A8C0300962D22 /* internal_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = internal_format.h; path = ../src/internal_format.h; sourceTree = ""; }; 43C3778D246A8C0300962D22 /* internal_format.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = internal_format.c; path = ../src/internal_format.c; sourceTree = ""; }; - 43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "pEpTrustWords-Info.plist"; path = "/Users/dirk/projects/pEp/pEpEngine/build-mac/pEpTrustWords-Info.plist"; sourceTree = ""; }; 43E4FBAD2362C05600BC01F4 /* NegotiationRequestGrouped.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationRequestGrouped.c; path = ../asn.1/NegotiationRequestGrouped.c; sourceTree = ""; }; 43E4FBB32362C29100BC01F4 /* GroupHandshake.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupHandshake.c; path = ../asn.1/GroupHandshake.c; sourceTree = ""; }; 43F6921C1F164A47009418F5 /* resource_id.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resource_id.c; path = ../src/resource_id.c; sourceTree = ""; }; @@ -497,6 +758,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 1552DB0F2577D4F100A92F71 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 644297BC1BE11C65002BC73B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -523,6 +791,7 @@ 154917EB22B926080091B6D6 /* Frameworks */ = { isa = PBXGroup; children = ( + 1508458825F101FB00D46DA6 /* libetpan.a */, 154917F422B926420091B6D6 /* sequoia4ios */, ); name = Frameworks; @@ -539,6 +808,15 @@ name = sequoia4ios; sourceTree = ""; }; + 1552DB122577D4F100A92F71 /* pEpEngine_macOS */ = { + isa = PBXGroup; + children = ( + 1552DB132577D4F100A92F71 /* pEpEngine_macOS.h */, + 1552DB152577D4F100A92F71 /* pEpEngine_macOS.m */, + ); + path = pEpEngine_macOS; + sourceTree = ""; + }; 43188A5523C4A7F8008EF79C /* sync-generated */ = { isa = PBXGroup; children = ( @@ -719,15 +997,14 @@ isa = PBXGroup; children = ( 1549180D22B92EA20091B6D6 /* libiconv.2.tbd */, - 1549181322B92EA50091B6D6 /* libz.dylib */, 64951A1B1BE0FCD800B10E71 /* system.db */, 64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */, 43188A5523C4A7F8008EF79C /* sync-generated */, 6406CE811CE382F400C14D77 /* asn.1 */, 64A8264B1B455C5600EECAF0 /* srcref */, 644297C01BE11C65002BC73B /* pEpTrustWords */, + 1552DB122577D4F100A92F71 /* pEpEngine_macOS */, 64796A401B455AA5004B1C24 /* Products */, - 43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */, 154917EB22B926080091B6D6 /* Frameworks */, ); sourceTree = ""; @@ -737,6 +1014,7 @@ children = ( 64796A3F1B455AA5004B1C24 /* libpEpEngine.a */, 644297BF1BE11C65002BC73B /* pEpTrustWords.bundle */, + 1552DB112577D4F100A92F71 /* libpEpEngine_macOS.a */, ); name = Products; sourceTree = ""; @@ -825,6 +1103,107 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 1552DB0D2577D4F100A92F71 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1552DC722577D70000A92F71 /* key_reset.h in Headers */, + 1552DB882577D5A800A92F71 /* Hash.h in Headers */, + 1552DB4A2577D5A800A92F71 /* UTF8String.h in Headers */, + 1543DA452577F8BE0041EFB5 /* Sync_func.h in Headers */, + 1552DBA12577D5A800A92F71 /* Rating.h in Headers */, + 1552DB412577D5A800A92F71 /* asn_codecs.h in Headers */, + 1543DA4B2577F8BE0041EFB5 /* Sync_impl.h in Headers */, + 1552DB292577D5A800A92F71 /* GroupHandshake.h in Headers */, + 1552DB512577D5A800A92F71 /* NativeInteger.h in Headers */, + 1552DB4D2577D5A800A92F71 /* GroupKeysAndClose.h in Headers */, + 1552DB622577D5A800A92F71 /* asn_system.h in Headers */, + 1552DB352577D5A800A92F71 /* INTEGER.h in Headers */, + 1552DB8D2577D5A800A92F71 /* Hex.h in Headers */, + 1552DB932577D5A800A92F71 /* asn_codecs_prim.h in Headers */, + 1552DB572577D5A800A92F71 /* xer_support.h in Headers */, + 1552DB8A2577D5A800A92F71 /* per_decoder.h in Headers */, + 1552DB422577D5A800A92F71 /* ISO639-1.h in Headers */, + 1552DB942577D5A800A92F71 /* GroupKeysForNewMember.h in Headers */, + 1552DB972577D5A800A92F71 /* NegotiationOpen.h in Headers */, + 1552DB582577D5A800A92F71 /* constr_TYPE.h in Headers */, + 1552DB522577D5A800A92F71 /* OCTET_STRING.h in Headers */, + 1552DC492577D6C900A92F71 /* map_asn1.h in Headers */, + 1552DB2E2577D5A800A92F71 /* CommitAcceptForGroup.h in Headers */, + 1552DB992577D5A800A92F71 /* GroupTrustThisKey.h in Headers */, + 1552DC7E2577D71800A92F71 /* sqlite3.h in Headers */, + 1552DB852577D5A800A92F71 /* CommitAcceptRequester.h in Headers */, + 1552DC762577D70400A92F71 /* labeled_int_list.h in Headers */, + 1552DB892577D5A800A92F71 /* ber_decoder.h in Headers */, + 1552DC8A2577D71800A92F71 /* distribution_codec.h in Headers */, + 1552DC872577D71800A92F71 /* growing_buf.h in Headers */, + 1552DC852577D71800A92F71 /* blacklist.h in Headers */, + 1543DA462577F8BE0041EFB5 /* sync_codec.h in Headers */, + 1552DC552577D6D700A92F71 /* pEp_string.h in Headers */, + 1552DB3D2577D5A800A92F71 /* TID.h in Headers */, + 1552DB2A2577D5A800A92F71 /* BIT_STRING.h in Headers */, + 1552DBAB2577D5A800A92F71 /* OwnKeysOfferer.h in Headers */, + 1552DB6C2577D5A800A92F71 /* per_support.h in Headers */, + 1552DB682577D5A800A92F71 /* Identity.h in Headers */, + 1552DB452577D5A800A92F71 /* BOOLEAN.h in Headers */, + 1552DB672577D5A800A92F71 /* GroupKeysUpdate.h in Headers */, + 1552DB782577D5A800A92F71 /* IdentityList.h in Headers */, + 1552DB8C2577D5A800A92F71 /* Sync.h in Headers */, + 1552DB402577D5A800A92F71 /* asn_internal.h in Headers */, + 1552DB702577D5A800A92F71 /* ElectGroupKeyResetLeader.h in Headers */, + 1552DB8F2577D5A800A92F71 /* per_encoder.h in Headers */, + 1552DC192577D69300A92F71 /* pEpEngine.h in Headers */, + 1552DB842577D5A800A92F71 /* constr_SEQUENCE.h in Headers */, + 1543DA492577F8BE0041EFB5 /* KeySync_fsm.h in Headers */, + 1552DB762577D5A800A92F71 /* CommitAcceptOfferer.h in Headers */, + 1552DB5B2577D5A800A92F71 /* KeySync.h in Headers */, + 1552DB142577D4F100A92F71 /* pEpEngine_macOS.h in Headers */, + 1552DB472577D5A800A92F71 /* CommitReject.h in Headers */, + 1552DB482577D5A800A92F71 /* constraints.h in Headers */, + 1552DB9B2577D5A800A92F71 /* Version.h in Headers */, + 1552DC842577D71800A92F71 /* keyreset_command.h in Headers */, + 1552DBA32577D5A800A92F71 /* asn_application.h in Headers */, + 1552DB552577D5A800A92F71 /* constr_SEQUENCE_OF.h in Headers */, + 1552DB912577D5A800A92F71 /* xer_decoder.h in Headers */, + 1552DB792577D5A800A92F71 /* Rollback.h in Headers */, + 1552DC7F2577D71800A92F71 /* pgp_sequoia_internal.h in Headers */, + 1552DB872577D5A800A92F71 /* der_encoder.h in Headers */, + 1552DB722577D5A800A92F71 /* xer_encoder.h in Headers */, + 1543DA4C2577F8BE0041EFB5 /* Sync_event.h in Headers */, + 1552DC512577D6D000A92F71 /* baseprotocol.h in Headers */, + 1552DB652577D5A800A92F71 /* asn_SEQUENCE_OF.h in Headers */, + 1552DB9A2577D5A800A92F71 /* per_opentype.h in Headers */, + 1552DB7F2577D5A800A92F71 /* Beacon.h in Headers */, + 1552DB8E2577D5A800A92F71 /* Command.h in Headers */, + 1552DB962577D5A800A92F71 /* asn_SET_OF.h in Headers */, + 1552DB3C2577D5A800A92F71 /* constr_SET_OF.h in Headers */, + 1552DB302577D5A800A92F71 /* KeyReset.h in Headers */, + 1552DB4E2577D5A800A92F71 /* NegotiationRequestGrouped.h in Headers */, + 1552DB5C2577D5A800A92F71 /* SynchronizeGroupKeys.h in Headers */, + 1552DB9D2577D5A800A92F71 /* ber_tlv_length.h in Headers */, + 1552DB9F2577D5A800A92F71 /* PString.h in Headers */, + 1552DC802577D71800A92F71 /* fsm_common.h in Headers */, + 1552DC862577D71800A92F71 /* pgp_sequoia.h in Headers */, + 1552DB602577D5A800A92F71 /* InitUnledGroupKeyReset.h in Headers */, + 1552DB6D2577D5A800A92F71 /* constr_CHOICE.h in Headers */, + 1552DB5E2577D5A800A92F71 /* NegotiationRequest.h in Headers */, + 1552DC832577D71800A92F71 /* openpgp_compat.h in Headers */, + 1552DB612577D5A800A92F71 /* ReceiverRating.h in Headers */, + 1552DC822577D71800A92F71 /* resource_id.h in Headers */, + 1552DC882577D71800A92F71 /* internal_format.h in Headers */, + 1552DB3E2577D5A800A92F71 /* Commands.h in Headers */, + 1552DB362577D5A800A92F71 /* OwnKeysRequester.h in Headers */, + 1552DB922577D5A800A92F71 /* ber_tlv_tag.h in Headers */, + 1552DB6B2577D5A800A92F71 /* NativeEnumerated.h in Headers */, + 1552DB692577D5A800A92F71 /* CommitAccept.h in Headers */, + 1552DBA02577D5A800A92F71 /* Distribution.h in Headers */, + 1552DC892577D71800A92F71 /* status_to_string.h in Headers */, + 1552DB4F2577D5A800A92F71 /* PrintableString.h in Headers */, + 1552DC7A2577D70700A92F71 /* base64.h in Headers */, + 1552DC812577D71800A92F71 /* aux_mime_msg.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 64A8268B1B455D8D00EECAF0 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -928,6 +1307,27 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 1552DB102577D4F100A92F71 /* pEpEngine_macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1552DB192577D4F100A92F71 /* Build configuration list for PBXNativeTarget "pEpEngine_macOS" */; + buildPhases = ( + 1552DB0D2577D4F100A92F71 /* Headers */, + 1552DB0E2577D4F100A92F71 /* Sources */, + 1552DB0F2577D4F100A92F71 /* Frameworks */, + 1508455925F0E0ED00D46DA6 /* Copy Build Artefacts To Custom Build Dir */, + ); + buildRules = ( + ); + dependencies = ( + 15B21C4125FB8E1B0097927A /* PBXTargetDependency */, + 15B21C3F25FB8E160097927A /* PBXTargetDependency */, + 1508460725F24D1100D46DA6 /* PBXTargetDependency */, + ); + name = pEpEngine_macOS; + productName = pEpEngine_macOS; + productReference = 1552DB112577D4F100A92F71 /* libpEpEngine_macOS.a */; + productType = "com.apple.product-type.library.static"; + }; 644297BE1BE11C65002BC73B /* pEpTrustWords */ = { isa = PBXNativeTarget; buildConfigurationList = 644297C21BE11C65002BC73B /* Build configuration list for PBXNativeTarget "pEpTrustWords" */; @@ -950,7 +1350,6 @@ isa = PBXNativeTarget; buildConfigurationList = 64796A531B455AA5004B1C24 /* Build configuration list for PBXNativeTarget "pEpEngine" */; buildPhases = ( - 43D47B08225DEBD600E97C5B /* Generate src files */, 64796A3B1B455AA5004B1C24 /* Sources */, 64796A3C1B455AA5004B1C24 /* Frameworks */, 64796A3D1B455AA5004B1C24 /* CopyFiles */, @@ -959,6 +1358,8 @@ buildRules = ( ); dependencies = ( + 15B21C3825FB8DDB0097927A /* PBXTargetDependency */, + 15B21C3625FB8DD10097927A /* PBXTargetDependency */, 43D47AA1225CC82400E97C5B /* PBXTargetDependency */, 64289E3F1B8B638800FC617B /* PBXTargetDependency */, ); @@ -976,6 +1377,15 @@ LastUpgradeCheck = 1020; ORGANIZATIONNAME = "p≡p Security S.A."; TargetAttributes = { + 150845DE25F13CE700D46DA6 = { + CreatedOnToolsVersion = 12.4; + }; + 1552DB102577D4F100A92F71 = { + CreatedOnToolsVersion = 12.2; + }; + 15B21C2225FB8BE70097927A = { + CreatedOnToolsVersion = 12.4; + }; 644297BE1BE11C65002BC73B = { CreatedOnToolsVersion = 7.1; }; @@ -1005,6 +1415,9 @@ targets = ( 64796A3E1B455AA5004B1C24 /* pEpEngine */, 644297BE1BE11C65002BC73B /* pEpTrustWords */, + 1552DB102577D4F100A92F71 /* pEpEngine_macOS */, + 150845DE25F13CE700D46DA6 /* generate_code */, + 15B21C2225FB8BE70097927A /* create_commit_hash_dot.h */, ); }; /* End PBXProject section */ @@ -1045,7 +1458,25 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 43D47B08225DEBD600E97C5B /* Generate src files */ = { + 1508455925F0E0ED00D46DA6 /* Copy Build Artefacts To Custom Build Dir */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Copy Build Artefacts To Custom Build Dir"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "CUSTOM_BUILD_DIR=${PROJECT_DIR}/build\nmkdir -p ${CUSTOM_BUILD_DIR}\ncp -r \"${BUILD_DIR}/${CONFIGURATION}/libpEpEngine_macOS.a\" ${CUSTOM_BUILD_DIR}\n"; + }; + 150845EA25F13CF100D46DA6 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1054,7 +1485,6 @@ ); inputPaths = ( ); - name = "Generate src files"; outputFileListPaths = ( "$(SRCROOT)/generated-files-asn1.txt", "$(SRCROOT)/generated-files-sync.txt", @@ -1062,9 +1492,26 @@ outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/bash; + shellPath = /bin/sh; shellScript = "export LANG=en_US.UTF-8\n\necho \"***************************************\"\necho \"*** Generate files: ACTION: $ACTION ***\"\necho \"***************************************\"\n\ncd \"$SRCROOT/..\"\n\nbash -l -c \"gmake -C sync\"\nbash -l -c \"make -C asn.1 Sync.c Distribution.c\"\n"; }; + 15B21C2F25FB8BEC0097927A /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Creates `commit_hash.h` required by Engine and missing as we do not use the makefile\n\nCOMMIT_HASH=$(git rev-parse HEAD)\necho \"#ifndef COMMIT_HASH_H\\n#define COMMIT_HASH_H\\n#define PEP_CURRENT_COMMIT_HASH = \\\"${COMMIT_HASH}\\\"\\n#endif\\n\" > ${PROJECT_DIR}/../src/commit_hash.h\n"; + }; 644297C61BE11D00002BC73B /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1081,6 +1528,118 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 1552DB0E2577D4F100A92F71 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1552DC292577D6AA00A92F71 /* message_api.c in Sources */, + 1552DB822577D5A800A92F71 /* asn_SEQUENCE_OF.c in Sources */, + 1552DC052577D67D00A92F71 /* trans_auto.c in Sources */, + 1552DBA92577D5A800A92F71 /* per_support.c in Sources */, + 1552DB802577D5A800A92F71 /* xer_decoder.c in Sources */, + 1552DB7B2577D5A800A92F71 /* per_encoder.c in Sources */, + 1552DC3D2577D6BE00A92F71 /* cryptotech.c in Sources */, + 1552DBA72577D5A800A92F71 /* GroupKeysAndClose.c in Sources */, + 1552DC452577D6C600A92F71 /* blacklist.c in Sources */, + 1552DB9E2577D5A800A92F71 /* OwnKeysRequester.c in Sources */, + 1552DC1D2577D69A00A92F71 /* pEpEngine.c in Sources */, + 1552DB4C2577D5A800A92F71 /* Commands.c in Sources */, + 1552DB5A2577D5A800A92F71 /* Beacon.c in Sources */, + 1552DB8B2577D5A800A92F71 /* NegotiationRequest.c in Sources */, + 1552DB442577D5A800A92F71 /* KeyReset.c in Sources */, + 1552DB5F2577D5A800A92F71 /* constr_TYPE.c in Sources */, + 1543DA432577F8BE0041EFB5 /* Sync_event.c in Sources */, + 1552DC092577D68000A92F71 /* timestamp.c in Sources */, + 1552DB2C2577D5A800A92F71 /* BIT_STRING.c in Sources */, + 1552DB772577D5A800A92F71 /* pdu_collection.c in Sources */, + 1552DC672577D6F900A92F71 /* sqlite3.c in Sources */, + 1552DC4D2577D6CD00A92F71 /* map_asn1.c in Sources */, + 1552DB342577D5A800A92F71 /* ReceiverRating.c in Sources */, + 1552DB662577D5A800A92F71 /* ISO639-1.c in Sources */, + 1552DC312577D6B100A92F71 /* identity_list.c in Sources */, + 1552DB7D2577D5A800A92F71 /* GroupHandshake.c in Sources */, + 1552DBA42577D5A800A92F71 /* ber_decoder.c in Sources */, + 1552DC682577D6F900A92F71 /* internal_format.c in Sources */, + 1552DB742577D5A800A92F71 /* ber_tlv_tag.c in Sources */, + 1552DB7C2577D5A800A92F71 /* Hash.c in Sources */, + 1552DB4B2577D5A800A92F71 /* TID.c in Sources */, + 1552DB9C2577D5A800A92F71 /* ElectGroupKeyResetLeader.c in Sources */, + 1543DAAD257801A90041EFB5 /* resource_id.c in Sources */, + 1552DB902577D5A800A92F71 /* OCTET_STRING.c in Sources */, + 1552DBAC2577D5A800A92F71 /* asn_codecs_prim.c in Sources */, + 1552DB332577D5A800A92F71 /* PString.c in Sources */, + 1552DB952577D5A800A92F71 /* InitUnledGroupKeyReset.c in Sources */, + 1552DB502577D5A800A92F71 /* SynchronizeGroupKeys.c in Sources */, + 1552DBA52577D5A800A92F71 /* xer_encoder.c in Sources */, + 1552DC6B2577D6F900A92F71 /* labeled_int_list.c in Sources */, + 1552DB3A2577D5A800A92F71 /* Distribution.c in Sources */, + 1552DB5D2577D5A800A92F71 /* Rollback.c in Sources */, + 1552DBA62577D5A800A92F71 /* OwnKeysOfferer.c in Sources */, + 1552DB532577D5A800A92F71 /* constr_SEQUENCE.c in Sources */, + 1552DC352577D6B500A92F71 /* etpan_mime.c in Sources */, + 1543DAA9257801880041EFB5 /* baseprotocol.c in Sources */, + 1552DB392577D5A800A92F71 /* Hex.c in Sources */, + 1552DB562577D5A800A92F71 /* Sync.c in Sources */, + 1552DC662577D6F900A92F71 /* distribution_codec.c in Sources */, + 1543DA472577F8BE0041EFB5 /* KeySync_fsm.c in Sources */, + 1552DB6E2577D5A800A92F71 /* NativeInteger.c in Sources */, + 1543DA442577F8BE0041EFB5 /* Sync_func.c in Sources */, + 1552DBAA2577D5A800A92F71 /* CommitAcceptRequester.c in Sources */, + 1552DB432577D5A800A92F71 /* NegotiationOpen.c in Sources */, + 1552DC652577D6F900A92F71 /* keyreset_command.c in Sources */, + 1552DB7A2577D5A800A92F71 /* Rating.c in Sources */, + 1552DC412577D6C200A92F71 /* bloblist.c in Sources */, + 1552DB2D2577D5A800A92F71 /* CommitReject.c in Sources */, + 1552DBAD2577D5A800A92F71 /* KeySync.c in Sources */, + 1552DC112577D68900A92F71 /* stringlist.c in Sources */, + 1552DB372577D5A800A92F71 /* PrintableString.c in Sources */, + 1552DC012577D67800A92F71 /* transport.c in Sources */, + 1552DC392577D6B900A92F71 /* email.c in Sources */, + 1543DA482577F8BE0041EFB5 /* sync_codec.c in Sources */, + 1552DC6D2577D6F900A92F71 /* aux_mime_msg.c in Sources */, + 1552DC252577D6A600A92F71 /* message.c in Sources */, + 1552DC6A2577D6F900A92F71 /* pgp_sequoia.c in Sources */, + 1552DB6F2577D5A800A92F71 /* ber_tlv_length.c in Sources */, + 1552DB712577D5A800A92F71 /* Version.c in Sources */, + 1552DB162577D4F100A92F71 /* pEpEngine_macOS.m in Sources */, + 1552DB642577D5A800A92F71 /* CommitAccept.c in Sources */, + 1552DC152577D68F00A92F71 /* platform_unix.c in Sources */, + 1552DB462577D5A800A92F71 /* GroupTrustThisKey.c in Sources */, + 1552DC212577D6A000A92F71 /* mime.c in Sources */, + 1552DC0D2577D68500A92F71 /* stringpair.c in Sources */, + 1552DB592577D5A800A92F71 /* der_encoder.c in Sources */, + 1552DC592577D6DB00A92F71 /* pEp_string.c in Sources */, + 1552DB322577D5A800A92F71 /* GroupKeysUpdate.c in Sources */, + 1552DB542577D5A800A92F71 /* constr_SET_OF.c in Sources */, + 1552DB2B2577D5A800A92F71 /* xer_support.c in Sources */, + 1543DA4A2577F8BE0041EFB5 /* Sync_impl.c in Sources */, + 1552DC6C2577D6F900A92F71 /* key_reset.c in Sources */, + 1552DBA22577D5A800A92F71 /* GroupKeysForNewMember.c in Sources */, + 1552DB7E2577D5A800A92F71 /* NegotiationRequestGrouped.c in Sources */, + 1552DC5D2577D6DE00A92F71 /* sync_api.c in Sources */, + 1552DB2F2577D5A800A92F71 /* constr_SEQUENCE_OF.c in Sources */, + 1552DC692577D6F900A92F71 /* growing_buf.c in Sources */, + 1552DC612577D6E000A92F71 /* openpgp_compat.c in Sources */, + 1552DBA82577D5A800A92F71 /* asn_SET_OF.c in Sources */, + 1552DC6E2577D6F900A92F71 /* base64.c in Sources */, + 1552DB732577D5A800A92F71 /* INTEGER.c in Sources */, + 1552DB3F2577D5A800A92F71 /* constr_CHOICE.c in Sources */, + 1552DB862577D5A800A92F71 /* CommitAcceptOfferer.c in Sources */, + 1552DB6A2577D5A800A92F71 /* UTF8String.c in Sources */, + 1552DB3B2577D5A800A92F71 /* Command.c in Sources */, + 1552DB832577D5A800A92F71 /* IdentityList.c in Sources */, + 1552DB312577D5A800A92F71 /* per_opentype.c in Sources */, + 1552DB812577D5A800A92F71 /* constraints.c in Sources */, + 1552DC2D2577D6AE00A92F71 /* keymanagement.c in Sources */, + 1552DB752577D5A800A92F71 /* CommitAcceptForGroup.c in Sources */, + 1552DB982577D5A800A92F71 /* NativeEnumerated.c in Sources */, + 1543DA422577F8BE0041EFB5 /* Sync_actions.c in Sources */, + 1552DB632577D5A800A92F71 /* Identity.c in Sources */, + 1552DB492577D5A800A92F71 /* per_decoder.c in Sources */, + 1552DB382577D5A800A92F71 /* BOOLEAN.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 644297BB1BE11C65002BC73B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1202,6 +1761,31 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 1508460725F24D1100D46DA6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 644297BE1BE11C65002BC73B /* pEpTrustWords */; + targetProxy = 1508460625F24D1100D46DA6 /* PBXContainerItemProxy */; + }; + 15B21C3625FB8DD10097927A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 150845DE25F13CE700D46DA6 /* generate_code */; + targetProxy = 15B21C3525FB8DD10097927A /* PBXContainerItemProxy */; + }; + 15B21C3825FB8DDB0097927A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 15B21C2225FB8BE70097927A /* create_commit_hash_dot.h */; + targetProxy = 15B21C3725FB8DDB0097927A /* PBXContainerItemProxy */; + }; + 15B21C3F25FB8E160097927A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 150845DE25F13CE700D46DA6 /* generate_code */; + targetProxy = 15B21C3E25FB8E160097927A /* PBXContainerItemProxy */; + }; + 15B21C4125FB8E1B0097927A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 15B21C2225FB8BE70097927A /* create_commit_hash_dot.h */; + targetProxy = 15B21C4025FB8E1B0097927A /* PBXContainerItemProxy */; + }; 43D47AA1225CC82400E97C5B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 644297BE1BE11C65002BC73B /* pEpTrustWords */; @@ -1215,6 +1799,96 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 150845DF25F13CE700D46DA6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NQLYU6MGPN; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 150845E025F13CE700D46DA6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NQLYU6MGPN; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 1552DB172577D4F100A92F71 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = x86_64; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = NQLYU6MGPN; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + OTHER_LIBTOOLFLAGS = "${PROJECT_DIR}/../../local/lib/libnettle.a ${PROJECT_DIR}/../../local/lib/libgmp.a ${PROJECT_DIR}/../../local/lib/libhogweed.a ${PROJECT_DIR}/../../local/lib/libsequoia_openpgp_ffi.a ${PROJECT_DIR}/../../local/lib/libetpan.a"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 1552DB182577D4F100A92F71 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = x86_64; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NQLYU6MGPN; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu11; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_FAST_MATH = YES; + OTHER_LIBTOOLFLAGS = "${PROJECT_DIR}/../../local/lib/libnettle.a ${PROJECT_DIR}/../../local/lib/libgmp.a ${PROJECT_DIR}/../../local/lib/libhogweed.a ${PROJECT_DIR}/../../local/lib/libsequoia_openpgp_ffi.a ${PROJECT_DIR}/../../local/lib/libetpan.a"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 15B21C2325FB8BE70097927A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NQLYU6MGPN; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 15B21C2425FB8BE70097927A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NQLYU6MGPN; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 644297C31BE11C65002BC73B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1239,6 +1913,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -1283,12 +1958,10 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)", - "$(SRCROOT)/../../OpenSSL-for-iPhone/include", - "$(SRCROOT)/../asn.1/", + "${PROJECT_DIR}/../../local/include/**", "$(PROJECT_DIR)/../../sequoia4ios/build/include", ); - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-DSQLITE3_FROM_OS"; @@ -1301,6 +1974,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -1345,12 +2019,10 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)", - "$(SRCROOT)/../../OpenSSL-for-iPhone/include", - "$(SRCROOT)/../asn.1/", + "${PROJECT_DIR}/../../local/include/**", "$(PROJECT_DIR)/../../sequoia4ios/build/include", ); - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-DSQLITE3_FROM_OS"; @@ -1368,7 +2040,7 @@ "DEBUG=1", ); HEADER_SEARCH_PATHS = "$(inherited)"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = "${inherited}"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/../../Sequoia4iOS/build/lib", @@ -1393,7 +2065,7 @@ buildSettings = { GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; HEADER_SEARCH_PATHS = "$(inherited)"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = "${inherited}"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/../../Sequoia4iOS/build/lib", @@ -1415,6 +2087,33 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 150845E525F13CE700D46DA6 /* Build configuration list for PBXAggregateTarget "generate_code" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 150845DF25F13CE700D46DA6 /* Debug */, + 150845E025F13CE700D46DA6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1552DB192577D4F100A92F71 /* Build configuration list for PBXNativeTarget "pEpEngine_macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1552DB172577D4F100A92F71 /* Debug */, + 1552DB182577D4F100A92F71 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 15B21C2925FB8BE70097927A /* Build configuration list for PBXAggregateTarget "create_commit_hash_dot.h" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 15B21C2325FB8BE70097927A /* Debug */, + 15B21C2425FB8BE70097927A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 644297C21BE11C65002BC73B /* Build configuration list for PBXNativeTarget "pEpTrustWords" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/build-mac/pEpEngine.xcodeproj/xcshareddata/xcschemes/pEpEngine.xcscheme b/build-mac/pEpEngine.xcodeproj/xcshareddata/xcschemes/pEpEngine.xcscheme index 7d604060..7e32f4d1 100644 --- a/build-mac/pEpEngine.xcodeproj/xcshareddata/xcschemes/pEpEngine.xcscheme +++ b/build-mac/pEpEngine.xcodeproj/xcshareddata/xcschemes/pEpEngine.xcscheme @@ -6,20 +6,6 @@ parallelizeBuildables = "NO" buildImplicitDependencies = "YES"> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pEpMIME/Makefile b/pEpMIME/Makefile new file mode 100644 index 00000000..1b4bd561 --- /dev/null +++ b/pEpMIME/Makefile @@ -0,0 +1,102 @@ +# This file is under GNU General Public License 3.0 +# see LICENSE.txt + +################################################################################## +# This is a modified Makefile based on that in the libpEpMIME repository. +# THEY ARE NOT INTERCHANGEABLE. This is SPECIFICALLY for the pEp engine and +# is only for the built-in variant of the compiler. +# +# Note that this is the only supported way of including pEpMIME within the engine. +# +# If additional object files are added to the repository object requirements, they +# will have to be included here specifically. +################################################################################## + +.PHONY: mimesrc lib all clean install test + +include ../Makefile.conf + +######### General ######### +BUILD_ON:=$(shell uname) + +# This variable specifies the platform that the engine should be cross-compiled for. +BUILD_FOR=$(BUILD_ON) + +# Cross-compiling is currently not supported. +# Maybe you can hack something with `local.conf`. +ifneq ($(BUILD_ON),$(BUILD_FOR)) + $(error I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).) +endif + +SED= +# MacOS needs -liconv, Linix don't. +ifeq ($(BUILD_FOR),Darwin) + LDLIBS+= -liconv + SED=sed -i '' +else + SED=sed -i +endif + +###################################################################### +# +# libpEpMIME can be built as a separate library in its own repository. +# +# However, it is dependent on the engine, which obviously does not +# work within the engine, as the engine is dependent upon IT. +# Because header files within the engine are local and not defined +# to exist in some installed library under pEp/header_file.h, we simply +# copy them into this directory and build/modify them as needed. +# +###################################################################### +# Repo source +PEPMIME_SRC_FILES:= $(wildcard $(PEP_MIME_SRC)/*.cc) $(wildcard $(PEP_MIME_SRC)/*.hh) $(wildcard $(PEP_MIME_SRC)/*.hxx) +# Stripped filenames +LOCAL_PEPMIME_SRC:= $(subst $(PEP_MIME_SRC)/,,$(PEPMIME_SRC_FILES)) + +all: lib + +lib: mimesrc libpEpMIME.a + +mimesrc: ${LOCAL_PEPMIME_SRC} + +# Copy the files to the local directory and change their engine header references to quoted references +%.hh : $(PEP_MIME_SRC)/%.hh + cp -p $< $@ + $(SED) 's/#include /#include "..\/src\/\1"/g' $@ + +%.cc : $(PEP_MIME_SRC)/%.cc + cp -p $< $@ + $(SED) 's/#include /#include "..\/src\/\1"/g' $@ + +%.hxx : $(PEP_MIME_SRC)/%.hxx + cp -p $< $@ + $(SED) 's/#include /#include "..\/src\/\1"/g' $@ + +LIB_OBJ=pEpMIME.o pEpMIME_internal.o rules.o bodyparser.o \ + attachment.o bodygenerator.o \ + headerparser.o parse_timestamp.o parse_address.o nulllogger.o \ + base64.o nfc.o mime_headers.o nfc_sets.o to_utf8.o quoted_printable.o \ + header_generator.o message.o pEpEngine_mime.o + +libpEpMIME.a: $(LIB_OBJ) + ${AR} rcs $@ $^ + +%.o : %.cc %.hh + ${CXX} ${CXXFLAGS} ${CPPFLAGS} -I${PREFIX}/include -o $@ -c $< + +%.o : %.cc + ${CXX} ${CXXFLAGS} ${CPPFLAGS} -I${PREFIX}/include -o $@ -c $< + +clean: + rm -vf *.o *.a + +srcclean: + rm *.cc *.hh *.hxx + +install: lib + mkdir -p "$(PREFIX)/lib/" + cp -v libpEpMIME.a $(PREFIX)/lib + +uninstall: + rm $(PREFIX)/lib/libpEpMIME.a + diff --git a/pEpMIME/README.md b/pEpMIME/README.md new file mode 100644 index 00000000..3c3e2f73 --- /dev/null +++ b/pEpMIME/README.md @@ -0,0 +1,38 @@ +# Instructions and caveats for using pEpMIME as the built-in engine parser + +## Makefile variables and local.conf + +We copy the necessary files from the user's *separate* libpEpMIME repository +on the machine. + +**Note: The Makefile in this directory is *different* from the libpEpMIME Makefile.** +**DO NOT REPLACE THE pEpEngine's pEpMIME Makefile with the one from the libpEpMIME repository. It won't work!** + +Source files in this directory are local copies only and will be copied over if the repository is +updated. We post-process the source to change the "installed-header" requirements of the "separate" +(quotes intentional) library. + +* PEP_MIME=1 +* PEP_MIME_SRC= + +## Known issues +On MacOS, the built-in standard BSD C library provides strlcat et al. **However**, for some weird reason, when +compiling the engine with pEpMIME, the compiler thinks strlcat is no longer defined, though everything links and runs +in the end. + +If you see something like: + +``` +platform_unix.c:280:5: warning: implicitly declaring library function 'strlcat' with type 'unsigned long (char *, const char *, unsigned long)' [-Wimplicit-function-declaration] + strlcat(*first, second, size); + ^ +platform_unix.c:280:5: note: include the header or explicitly provide a declaration for 'strlcat' +1 warning generated. +``` + +It doesn't seem to be an actual issue, and maybe it's a problem of compiling part of the engine with clang and part of it with clang++ and c++14, but anyway, watch out for it, and +don't complain to the engine team unless you figure out how to fix it ;) + +## TODO + +* git submodules would be a good way to handle our "copy this in because it really isn't a separate library" issue diff --git a/scripts/debian10/Makefile b/scripts/debian10/Makefile new file mode 100644 index 00000000..b0abdb0a --- /dev/null +++ b/scripts/debian10/Makefile @@ -0,0 +1,27 @@ +include ../../DEPENDENCIES +export +PEP_MACHINE_DIR= $(PKG_INSTALL_PATH)/share/pEp +SEQUOIA_VERSION=${sequoia} +CURRENT_DISTRO=$(shell basename $(shell pwd)) +IMAGE_NAME=${DOCKER_REGISTRY_HOST}/pep-$(CURRENT_DISTRO)-engine +DOCKERFILE=pEpEngine.$(CURRENT_DISTRO).Dockerfile +IS_TAGGED=${TAGGED_BUILD} +ifeq ($(IS_TAGGED), true) +# $CI_COMMIT_TAG is a predefined environment variable from Gitlab + PEPENGINE_VERSION=${CI_COMMIT_TAG} +else + PEPENGINE_VERSION=$(shell git rev-parse --short=8 HEAD) +endif +all: + -docker pull $(IMAGE_NAME):latest + cd ../../ && docker build --build-arg CURRENT_DISTRO=$(CURRENT_DISTRO) \ + --build-arg DOCKER_REGISTRY_HOST=${DOCKER_REGISTRY_HOST} \ + --build-arg PEPENGINE_VERSION=$(PEPENGINE_VERSION) \ + --build-arg SEQUOIA_VERSION=$(SEQUOIA_VERSION) \ + --build-arg PEP_MACHINE_DIR=$(PEP_MACHINE_DIR) \ + --cache-from $(IMAGE_NAME):latest \ + --tag=$(IMAGE_NAME):$(PEPENGINE_VERSION) \ + --tag=$(IMAGE_NAME):latest \ + -f scripts/${CURRENT_DISTRO}/$(DOCKERFILE) . + docker push $(IMAGE_NAME):$(PEPENGINE_VERSION) + docker push $(IMAGE_NAME):latest diff --git a/scripts/debian10/build_pEpEngine.sh b/scripts/debian10/build_pEpEngine.sh new file mode 100755 index 00000000..8a5b116e --- /dev/null +++ b/scripts/debian10/build_pEpEngine.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env sh +set -exo + +export LC_ALL=en_US.UTF-8 + +cat >local.conf <<__LOCAL__ +PREFIX=${INSTPREFIX} +SQLITE3_FROM_OS="" +PER_MACHINE_DIRECTORY=${PEP_MACHINE_DIR} +YML2_PATH=${INSTPREFIX}/yml2 +YML2_PROC=${INSTPREFIX}/yml2/yml2proc +ETPAN_LIB=-L${INSTPREFIX}/libetpan/lib +ETPAN_INC=-I${INSTPREFIX}/libetpan/include +ASN1C=${INSTPREFIX}/asn1c/bin/asn1c +ASN1C_INC=-I${INSTPREFIX}/asn1c/share/asn1c +OPENPGP=SEQUOIA +SEQUOIA_LIB=-L${INSTPREFIX}/lib +SEQUOIA_INC=-I${INSTPREFIX}/include +LDFLAGS += -L${INSTPREFIX}/lib -L${INSTPREFIX}/libetpan/lib -L${INSTPREFIX}/pep/lib -nostartfiles +__LOCAL__ + +cat local.conf + +export PKG_CONFIG_PATH=$INSTPREFIX/share/pkgconfig/ +make all && make db && make install diff --git a/scripts/debian10/build_pEpEngine_deps.sh b/scripts/debian10/build_pEpEngine_deps.sh new file mode 100755 index 00000000..b6731757 --- /dev/null +++ b/scripts/debian10/build_pEpEngine_deps.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env sh +set -exo + +### YML2 +cd $INSTPREFIX +wget https://fdik.org/yml2.tar.bz2 +tar -xf yml2.tar.bz2 +rm yml2.tar.bz2 + + +### libetpan +git clone https://github.com/fdik/libetpan $BUILDROOT/libetpan +cd $BUILDROOT/libetpan +test -f configure || NOCONFIGURE=absolutely ./autogen.sh +./configure --prefix=${INSTPREFIX}/libetpan \ + --without-openssl --without-gnutls --without-sasl \ + --without-curl --without-expat --without-zlib \ + --disable-dependency-tracking +make -j$(nproc) +make install +echo "${libetpan_ver}">${INSTPREFIX}/libetpan.ver + + +### ASN1c +git clone https://github.com/vlm/asn1c.git $BUILDROOT/asn1c +cd $BUILDROOT/asn1c +git checkout tags/v0.9.28 -b pep-engine +test -f configure || autoreconf -iv +./configure --prefix=${INSTPREFIX}/asn1c +make -j$(nproc) && make install +echo "${asn1c_ver}">${INSTPREFIX}/asn1c.ver diff --git a/scripts/debian10/install_pEpEngine_systemdb.sh b/scripts/debian10/install_pEpEngine_systemdb.sh new file mode 100755 index 00000000..2585e974 --- /dev/null +++ b/scripts/debian10/install_pEpEngine_systemdb.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +set -exo + +# Install systemdb (need to be root depending on the path) +cd $BUILDROOT/pEpEngine +export LC_ALL=en_US.UTF-8 +export PKG_CONFIG_PATH=$INSTPREFIX/share/pkgconfig/ +echo "Setup DB" +make -C db install diff --git a/scripts/debian10/pEpEngine.debian10.Dockerfile b/scripts/debian10/pEpEngine.debian10.Dockerfile new file mode 100644 index 00000000..1941b465 --- /dev/null +++ b/scripts/debian10/pEpEngine.debian10.Dockerfile @@ -0,0 +1,38 @@ +ARG DOCKER_REGISTRY_HOST +ARG CURRENT_DISTRO +ARG PEPENGINE_VERSION +FROM ${DOCKER_REGISTRY_HOST}/pep-${CURRENT_DISTRO}-sequoia:latest + +ENV BUILDROOT /build +ENV INSTPREFIX /install +ENV OUTDIR /out +ARG PEP_MACHINE_DIR + +### Setup working directory +RUN mkdir ${BUILDROOT}/pEpEngine +COPY . ${BUILDROOT}/pEpEngine + +USER root + +RUN chown -R pep-builder:pep-builder ${BUILDROOT}/pEpEngine +WORKDIR ${BUILDROOT}/pEpEngine + +ARG ENGINE_VERSION +ARG CURRENT_DISTRO + +RUN apt-get update && apt-get install -y wget bzip2 && \ + rm -rf /var/lib/apt/lists/* + +### Build pEpEngine dependencies +USER pep-builder + +RUN sh ./scripts/${CURRENT_DISTRO}/build_pEpEngine_deps.sh + +### Build pEpEngine +RUN sh ./scripts/${CURRENT_DISTRO}/build_pEpEngine.sh + +### Install Systemdb +USER root + +RUN sh ./scripts/${CURRENT_DISTRO}/install_pEpEngine_systemdb.sh && \ + rm -rf ${BUILDROOT}/* diff --git a/scripts/git/git-filter-clean-pEpEngine-commit-hash.sh b/scripts/git/git-filter-clean-pEpEngine-commit-hash.sh new file mode 100755 index 00000000..66350636 --- /dev/null +++ b/scripts/git/git-filter-clean-pEpEngine-commit-hash.sh @@ -0,0 +1,20 @@ +#! /bin/bash + +# +# Clean filter for pEpEngine's commit-hash header. +# + +if [[ "$OSTYPE" == "darwin"* ]]; then + SED='sed -i '"'""'" +else + SED="sed -i" +fi + +echo "Replacing PEP_CURRENT_COMMIT_HASH value in src/commit_hash.h with DUMMY_COMMIT_HASH_ERROR. See you next checkout or after the commit!" + +$($SED "s/\(PEP_CURRENT_COMMIT_HASH=\).*/\1\DUMMY_COMMIT_HASH_ERROR\"/" $1) + +# Honestly, I have no idea what git is doing with the stupid empty '' for sed, but I give up. It makes a commit_hash.h'' backup for no reason. So we eat it. +if [[ "$OSTYPE" == "darwin"* ]]; then + rm $1"'""'" +fi diff --git a/scripts/git/post-checkout b/scripts/git/post-checkout new file mode 100755 index 00000000..1db043f7 --- /dev/null +++ b/scripts/git/post-checkout @@ -0,0 +1,6 @@ +#! /bin/sh + +# Commit hash header file - if we don't run this, it won't build. +commit_hash="$(git rev-parse HEAD)" +sed "s/\(PEP_CURRENT_COMMIT_HASH\ \).*/\1\"$commit_hash\"/" templates/commit_hash.h > src/commit_hash.h + diff --git a/scripts/git/post-commit b/scripts/git/post-commit new file mode 100755 index 00000000..1db043f7 --- /dev/null +++ b/scripts/git/post-commit @@ -0,0 +1,6 @@ +#! /bin/sh + +# Commit hash header file - if we don't run this, it won't build. +commit_hash="$(git rev-parse HEAD)" +sed "s/\(PEP_CURRENT_COMMIT_HASH\ \).*/\1\"$commit_hash\"/" templates/commit_hash.h > src/commit_hash.h + diff --git a/scripts/git/post-merge-commit b/scripts/git/post-merge-commit new file mode 100755 index 00000000..1db043f7 --- /dev/null +++ b/scripts/git/post-merge-commit @@ -0,0 +1,6 @@ +#! /bin/sh + +# Commit hash header file - if we don't run this, it won't build. +commit_hash="$(git rev-parse HEAD)" +sed "s/\(PEP_CURRENT_COMMIT_HASH\ \).*/\1\"$commit_hash\"/" templates/commit_hash.h > src/commit_hash.h + diff --git a/scripts/git/pre-commit b/scripts/git/pre-commit new file mode 100755 index 00000000..829dd9e3 --- /dev/null +++ b/scripts/git/pre-commit @@ -0,0 +1,3 @@ +#! /bin/sh + +rm src/commit_hash.h diff --git a/src/Makefile b/src/Makefile index 07631e6b..78bf9580 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,28 +13,33 @@ ifdef PER_MACHINE_DIRECTORY EXTRA_MACROS+= -DPER_MACHINE_DIRECTORY=\"$(PER_MACHINE_DIRECTORY)\" endif -CFLAGS+= $(ETPAN_INC) $(PEP_MIME_INC) -I../asn.1 $(EXTRA_MACROS) -LDFLAGS+= $(ETPAN_LIB) $(PEP_MIME_LIB) -L../asn.1 -shared -LDLIBS+= -lc -lasn1 NO_SOURCE= ifndef PEP_MIME -LDLIBS+= -letpan + CFLAGS+= $(ETPAN_INC) + LDFLAGS+= $(ETPAN_LIB) + LDLIBS+= -letpan else -LDLIBS+= -lpEpMIME -NO_SOURCE+= etpan_mime.c + LDFLAGS+= -L../pEpMIME -shared + LDLIBS+= -lpEpMIME + NO_SOURCE+= etpan_mime.c endif + +CFLAGS+= -I../asn.1 $(EXTRA_MACROS) +CPPFLAGS+= -DSQLITE_THREADSAFE=1 + +LDFLAGS+= -L../asn.1 -shared +LDLIBS+= -lc -lasn1 ifeq ($(BUILD_ON),Darwin) ifeq ($(BUILD_FOR),Darwin) - CFLAGS+= -DSQLITE_THREADSAFE=1 LDLIBS+= -lz -liconv -mmacosx-version-min=10.10 else $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON)) endif else ifeq ($(BUILD_ON),Linux) ifeq ($(BUILD_FOR),Linux) - CFLAGS+= -DSQLITE_THREADSAFE=1 -D_GNU_SOURCE + CPPFLAGS+= -D_GNU_SOURCE LDLIBS+= -ldl -luuid else $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON)) @@ -43,14 +48,18 @@ else $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON)) endif +# Commit hash header file - if we don't run this, it won't build. +COMMIT_HASH:=$(shell git rev-parse HEAD) + ifdef SQLITE3_FROM_OS NO_SOURCE+= sqlite3.c - CFLAGS+= -DSQLITE3_FROM_OS + CPPFLAGS+= -DSQLITE3_FROM_OS LDLIBS+= -lsqlite3 endif ifeq ($(OPENPGP),SEQUOIA) - CFLAGS+= -DUSE_SEQUOIA $(SEQUOIA_CFLAGS) $(SEQUOIA_INC) + CPPFLAGS+= -DUSE_SEQUOIA + CFLAGS+= $(SEQUOIA_CFLAGS) $(SEQUOIA_INC) LDFLAGS+= $(SEQUOIA_LDFLAGS) LDLIBS+= $(SEQUOIA_LIB) else @@ -65,9 +74,9 @@ all: $(TARGET) -include Makefile.protocols -%.d: %.c +%.d: %.c commit_hash.h @set -e; rm -f $@; \ - $(CC) -MM $(CPPFLAGS) $(CFLAGS) $< > $@.$$$$; \ + $(CC) -MM $(CFLAGS) $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ @@ -77,24 +86,32 @@ ifneq ($(MAKECMDGOALS),clean) endif $(TARGET): libpEpEngine.a - $(CC) $(CFLAGS) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@ .PHONY: objects clean install_headers install uninstall beinstall -objects: $(ALL_OBJECTS) +commit_hash.h: +ifeq (,$(COMMIT_HASH)) + $(shell cp ../templates/commit_hash.h commit_hash.h) +else + sed "s/\(PEP_CURRENT_COMMIT_HASH\ \).*/\1\"$(COMMIT_HASH)\"/" ../templates/commit_hash.h > commit_hash.h +endif + +objects: $(ALL_OBJECTS) commit_hash.h -libpEpEngine.a: $(ALL_OBJECTS) +libpEpEngine.a: $(ALL_OBJECTS) commit_hash.h $(AR) -rc $@ $^ clean: rm -f *.d *.o *.a $(TARGET) *.dll *.so *.zip *.d.* *.def *~ rm -Rf $(TARGET).dSYM rm -f KeySync_fsm.* Sync_actions.c Sync_event.* Sync_func.* Sync_impl.* sync_codec.* distribution_codec.* + rm -f commit_hash.h # CAVEAT: -# install_headers is needed for building pEp MIME +# install_headers is needed for building *STANDALONE* pEp MIME - it is NOT used for built-in functionality!!! -install_headers: $(TARGET) +install_headers: $(TARGET) commit_hash.h mkdir -p $(PREFIX)/include/pEp cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h \ timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h \ @@ -103,6 +120,7 @@ install_headers: $(TARGET) status_to_string.h aux_mime_msg.h keyreset_command.h platform.h platform_unix.h ../asn.1/*.h \ $(PREFIX)/include/pEp/ +# FIXME: Does anyone but Roker use install_headers? Otherwise, remove the dependency. install: $(TARGET) install_headers mkdir -p "$(PREFIX)/lib/" cp -v $< $(PREFIX)/lib/ diff --git a/src/engine_sql.c b/src/engine_sql.c new file mode 100644 index 00000000..990d14a3 --- /dev/null +++ b/src/engine_sql.c @@ -0,0 +1,2663 @@ +#include "pEp_internal.h" +#include "engine_sql.h" + +// sql overloaded functions - modified from sqlite3.c +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] *ctx sqlite3_context + * @param[in] argc int + * @param[in] **argv sqlite3_value + * + */ +static void _sql_lower(sqlite3_context* ctx, int argc, sqlite3_value** argv) { + const char *z2; + int n; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + char *z1 = (char*)sqlite3_malloc(n+1); + if( z1 ){ + for(int i=0; i 0x7a) + c_mod = c; + z1[i] = c_mod; + } + z1[n] = '\0'; + sqlite3_result_text(ctx, z1, n, sqlite3_free); + } + } +} + +#ifdef _PEP_SQLITE_DEBUG +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] trace_constant unsigned + * @param[in] *context_ptr void + * @param[in] *P void + * @param[in] *X void + * + */ +int sql_trace_callback (unsigned trace_constant, + void* context_ptr, + void* P, + void* X) { + switch (trace_constant) { + case SQLITE_TRACE_STMT: + fprintf(stderr, "SQL_DEBUG: STMT - "); + const char* X_str = (const char*) X; + if (!EMPTYSTR(X_str) && X_str[0] == '-' && X_str[1] == '-') + fprintf(stderr, "%s\n", X_str); + else + fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P)); + break; + case SQLITE_TRACE_ROW: + fprintf(stderr, "SQL_DEBUG: ROW - "); + fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P)); + break; + case SQLITE_TRACE_CLOSE: + fprintf(stderr, "SQL_DEBUG: CLOSE - "); + break; + default: + break; + } + return 0; +} +#endif + +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] *pArg void + * @param[in] iErrCode int + * @param[in] *zMsg constchar + * + */ +void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){ + fprintf(stderr, "(%d) %s\n", iErrCode, zMsg); +} + +// TODO: refactor and generalise these two functions if possible. +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] session PEP_SESSION + * @param[in] *table_name constchar + * + */ +static int db_contains_table(PEP_SESSION session, const char* table_name) { + if (!session || !table_name) + return -1; + + // Table names can't be SQL parameters, so we do it this way. + + // these two must be the same number. + char sql_buf[500]; + const size_t max_q_len = 500; + + size_t t_size, q_size; + + const char* q1 = "SELECT name FROM sqlite_master WHERE type='table' AND name='{"; // 61 + const char* q2 = "}';"; // 3 + + q_size = 64; + t_size = strlen(table_name); + + size_t query_len = q_size + t_size + 1; + + if (query_len > max_q_len) + return -1; + + strlcpy(sql_buf, q1, max_q_len); + strlcat(sql_buf, table_name, max_q_len); + strlcat(sql_buf, q2, max_q_len); + + sqlite3_stmt *stmt; + + sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL); + + int retval = 0; + + int rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) { + retval = 1; + } + + sqlite3_finalize(stmt); + + return retval; + +} + +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] session PEP_SESSION + * @param[in] *table_name constchar + * @param[in] *col_name constchar + * + */ +static int table_contains_column(PEP_SESSION session, const char* table_name, + const char* col_name) { + + + if (!session || !table_name || !col_name) + return -1; + + // Table names can't be SQL parameters, so we do it this way. + + // these two must be the same number. + char sql_buf[500]; + const size_t max_q_len = 500; + + size_t t_size, c_size, q_size; + + const char* q1 = "SELECT "; // 7 + const char* q2 = " from "; // 6 + const char* q3 = ";"; // 1 + + q_size = 14; + t_size = strlen(table_name); + c_size = strlen(col_name); + + size_t query_len = q_size + c_size + t_size + 1; + + if (query_len > max_q_len) + return -1; + + strlcpy(sql_buf, q1, max_q_len); + strlcat(sql_buf, col_name, max_q_len); + strlcat(sql_buf, q2, max_q_len); + strlcat(sql_buf, table_name, max_q_len); + strlcat(sql_buf, q3, max_q_len); + + sqlite3_stmt *stmt; + + sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL); + + int retval = 0; + + int rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) { + retval = 1; + } + + sqlite3_finalize(stmt); + + return retval; +} + +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] session PEP_SESSION + * + */ +#define _PEP_MAX_AFFECTED 5 +PEP_STATUS repair_altered_tables(PEP_SESSION session) { + PEP_STATUS status = PEP_STATUS_OK; + + char* table_names[_PEP_MAX_AFFECTED] = {0}; + + const char* sql_query = "select tbl_name from sqlite_master WHERE sql LIKE '%REFERENCES%' AND sql LIKE '%_old%';"; + sqlite3_stmt *stmt; + sqlite3_prepare_v2(session->db, sql_query, -1, &stmt, NULL); + int i = 0; + int int_result = 0; + while ((int_result = sqlite3_step(stmt)) == SQLITE_ROW && i < _PEP_MAX_AFFECTED) { + table_names[i++] = strdup((const char*)(sqlite3_column_text(stmt, 0))); + } + + sqlite3_finalize(stmt); + + if ((int_result != SQLITE_DONE && int_result != SQLITE_OK) || i > (_PEP_MAX_AFFECTED + 1)) { + status = PEP_UNKNOWN_DB_ERROR; + goto pEp_free; + } + + for (i = 0; i < _PEP_MAX_AFFECTED; i++) { + const char* table_name = table_names[i]; + if (!table_name) + break; + + if (strcmp(table_name, "identity") == 0) { + int_result = sqlite3_exec(session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _identity_new (\n" + " address text,\n" + " user_id text\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " main_key_id text\n" + " references pgp_keypair (fpr)\n" + " on delete set null,\n" + " comment text,\n" + " flags integer default 0,\n" + " is_own integer default 0,\n" + " timestamp integer default (datetime('now')),\n" + " primary key (address, user_id)\n" + ");\n" + "INSERT INTO _identity_new SELECT * from identity;\n" + "DROP TABLE identity;\n" + "ALTER TABLE _identity_new RENAME TO identity;\n" + "COMMIT;\n" + "PRAGMA foreign_keys=on;" + , + NULL, + NULL, + NULL + ); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + } + else if (strcmp(table_name, "trust") == 0) { + int_result = sqlite3_exec(session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _trust_new (\n" + " user_id text not null\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " pgp_keypair_fpr text not null\n" + " references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " comm_type integer not null,\n" + " comment text,\n" + " primary key (user_id, pgp_keypair_fpr)\n" + ");\n" + "INSERT INTO _trust_new SELECT * from trust;\n" + "DROP TABLE trust;\n" + "ALTER TABLE _trust_new RENAME TO trust;\n" + "COMMIT;\n" + "PRAGMA foreign_keys=on;" + , + NULL, + NULL, + NULL + ); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + } + else if (strcmp(table_name, "alternate_user_id") == 0) { + int_result = sqlite3_exec(session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _alternate_user_id_new (\n" + " default_id text references person (id)\n" + " on delete cascade on update cascade,\n" + " alternate_id text primary key\n" + ");\n" + "INSERT INTO _alternate_user_id_new SELECT * from alternate_user_id;\n" + "DROP TABLE alternate_user_id;\n" + "ALTER TABLE _alternate_user_id_new RENAME TO alternate_user_id;\n" + "COMMIT;\n" + "PRAGMA foreign_keys=on;" + , + NULL, + NULL, + NULL + ); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + } + else if (strcmp(table_name, "revocation_contact_list") == 0) { + int_result = sqlite3_exec(session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _revocation_contact_list_new (\n" + " fpr text not null references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " contact_id text not null references person (id)\n" + " on delete cascade on update cascade,\n" + " timestamp integer default (datetime('now')),\n" + " PRIMARY KEY(fpr, contact_id)\n" + ");\n" + "INSERT INTO _revocation_contact_list_new SELECT * from revocation_contact_list;\n" + "DROP TABLE revocation_contact_list;\n" + "ALTER TABLE _revocation_contact_list_new RENAME TO revocation_contact_list;\n" + "COMMIT;\n" + "PRAGMA foreign_keys=on;" + , + NULL, + NULL, + NULL + ); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + } + else if (strcmp(table_name, "social_graph")) { + int_result = sqlite3_exec(session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _social_new (\n" + " own_userid text,\n" + " own_address text,\n" + " contact_userid text,\n" + " CONSTRAINT fk_own_identity\n" + " FOREIGN KEY(own_address, own_userid)\n" + " REFERENCES identity(address, user_id)\n" + " ON DELETE CASCADE ON UPDATE CASCADE\n" + ");\n" + "INSERT INTO _social_graph_new SELECT * from social_graph;\n" + "DROP TABLE social_graph;\n" + "ALTER TABLE _social_graph_new RENAME TO social_graph;\n" + "COMMIT;\n" + "PRAGMA foreign_keys=on;" + , + NULL, + NULL, + NULL + ); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + } + } + + int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_key_check;\n" + , + NULL, + NULL, + NULL + ); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + pEp_free: + for (i = 0; i < _PEP_MAX_AFFECTED; i++) { + free(table_names[i]); + } + return status; +} + +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] session PEP_SESSION + * + */ +static PEP_STATUS upgrade_revoc_contact_to_13(PEP_SESSION session) { + // I HATE SQLITE. + PEP_STATUS status = PEP_STATUS_OK; + int int_result = 0; + + // Ok, first we ADD the column so we can USE it. + // We will end up propagating the "error" this first time + // (one-to-one revoke-replace relationships), but since key reset + // hasn't been used in production, this is not a customer-facing + // issue. + + // Note: the check upfront is to deal with partially-upgraded DB issues + if (!table_contains_column(session, "revocation_contact_list", "own_address")) { + int_result = sqlite3_exec( + session->db, + "alter table revocation_contact_list\n" + " add column own_address text;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + } + + // the best we can do here is search per address, since these + // are no longer associated with an identity. For now, if we find + // something we can't add an address to, we'll delete the record. + // this should not, in the current environment, ever happen, but + // since we need to make the address part of the primary key, it's + // the right thing to do. sqlite does support null fields in a primary + // key for a weird version compatibility reason, but that doesn't + // mean we should use it, and we should be *safe*, not relying + // on an implementation-specific quirk which might be sanely removed + // in a future sqlite version. + + identity_list* id_list = NULL; + + sqlite3_stmt* tmp_own_id_retrieve = NULL; + sqlite3_prepare_v2(session->db, sql_own_identities_retrieve, -1, &tmp_own_id_retrieve, NULL); + + // Kludgey - put the stmt in temporarily, and then remove again, so less code dup. + // FIXME LATER: refactor if possible, but... chicken and egg, and thiis case rarely happens. + session->own_identities_retrieve = tmp_own_id_retrieve; + status = own_identities_retrieve(session, &id_list); + sqlite3_finalize(tmp_own_id_retrieve); + session->own_identities_retrieve = NULL; + + if (!status || !id_list) + return PEP_STATUS_OK; // it's empty AFAIK (FIXME) + + identity_list* curr_own = id_list; + + sqlite3_stmt* update_revoked_w_addr_stmt = NULL; + const char* sql_query = "update revocation_contact_list set own_address = ?1 where fpr = ?2;"; + sqlite3_prepare_v2(session->db, sql_query, -1, &update_revoked_w_addr_stmt, NULL); + + // Ok, go through and find any keys associated with this address + for ( ; curr_own && curr_own->ident; curr_own = curr_own->next) { + if (EMPTYSTR(curr_own->ident->address)) // shouldn't happen + continue; + stringlist_t* keylist = NULL; + status = find_keys(session, curr_own->ident->address, &keylist); + stringlist_t* curr_key = keylist; + for ( ; curr_key && curr_key->value; curr_key = curr_key->next) { + if (EMPTYSTR(curr_key->value)) + continue; + + // We just do this lazily - if this isn't a revoked key, it + // won't do anything. + sqlite3_bind_text(update_revoked_w_addr_stmt, 1, curr_own->ident->address, -1, + SQLITE_STATIC); + sqlite3_bind_text(update_revoked_w_addr_stmt, 2, curr_key->value, -1, + SQLITE_STATIC); + + int_result = sqlite3_step(update_revoked_w_addr_stmt); + assert(int_result == SQLITE_DONE); + + sqlite3_reset(update_revoked_w_addr_stmt); + + if (int_result != SQLITE_DONE) + return PEP_UNKNOWN_DB_ERROR; + + } + } + sqlite3_finalize(update_revoked_w_addr_stmt); + + int_result = sqlite3_exec( + session->db, + "delete from revocation_contact_list where own_address is NULL;\n" + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table if not exists _revocation_contact_list_new (\n" + " fpr text not null references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " own_address text,\n" + " contact_id text not null references person (id)\n" + " on delete cascade on update cascade,\n" + " timestamp integer default (datetime('now')),\n" + " PRIMARY KEY(fpr, own_address, contact_id)\n" + ");\n" + "INSERT INTO _revocation_contact_list_new (fpr, " + " own_address, " + " contact_id) " + " SELECT revocation_contact_list.fpr, " + " revocation_contact_list.own_address, " + " revocation_contact_list.contact_id " + " FROM revocation_contact_list " + " WHERE 1;\n" + "DROP TABLE revocation_contact_list;\n" + "ALTER TABLE _revocation_contact_list_new RENAME TO revocation_contact_list;\n" + "COMMIT;\n" + "\n" + "PRAGMA foreign_keys=on;\n" + , + NULL, + NULL, + NULL + ); + + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return status; +} + + +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] *_version void + * @param[in] count int + * @param[in] **text char + * @param[in] **name char + * + */ +static int user_version(void *_version, int count, char **text, char **name) +{ + if (!(_version && count == 1 && text && text[0])) + return -1; + + int *version = (int *) _version; + *version = atoi(text[0]); + return 0; +} + +PEP_STATUS init_databases(PEP_SESSION session) { + assert(LOCAL_DB); + if (LOCAL_DB == NULL) + return PEP_INIT_CANNOT_OPEN_DB; + +#ifdef _PEP_SQLITE_DEBUG + sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, NULL); +#endif + + int int_result = sqlite3_open_v2( + LOCAL_DB, + &session->db, + SQLITE_OPEN_READWRITE + | SQLITE_OPEN_CREATE + | SQLITE_OPEN_FULLMUTEX + | SQLITE_OPEN_PRIVATECACHE, + NULL + ); + + if (int_result != SQLITE_OK) + return PEP_INIT_CANNOT_OPEN_DB; + + int_result = sqlite3_exec( + session->db, + "PRAGMA locking_mode=NORMAL;\n" + "PRAGMA journal_mode=WAL;\n", + NULL, + NULL, + NULL + ); + + sqlite3_busy_timeout(session->db, BUSY_WAIT_TIME); + +#ifdef _PEP_SQLITE_DEBUG + sqlite3_trace_v2(session->db, + SQLITE_TRACE_STMT | SQLITE_TRACE_ROW | SQLITE_TRACE_CLOSE, + sql_trace_callback, + NULL); +#endif + + assert(SYSTEM_DB); + if (SYSTEM_DB == NULL) + return PEP_INIT_CANNOT_OPEN_SYSTEM_DB; + + int_result = sqlite3_open_v2( + SYSTEM_DB, &session->system_db, + SQLITE_OPEN_READONLY + | SQLITE_OPEN_FULLMUTEX + | SQLITE_OPEN_SHAREDCACHE, + NULL + ); + + if (int_result != SQLITE_OK) + return PEP_INIT_CANNOT_OPEN_SYSTEM_DB; + + sqlite3_busy_timeout(session->system_db, 1000); + return PEP_STATUS_OK; +} + +static PEP_STATUS _create_initial_tables(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "create table if not exists version_info (\n" + " id integer primary key,\n" + " timestamp integer default (datetime('now')),\n" + " version text,\n" + " comment text\n" + ");\n", + NULL, + NULL, + NULL + ); + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + // This string is now too large for the C standard, so we're going to break it up some. + // I presume we use the enormous string for performance purposes... terrible for debugging purposes, but OK. + int_result = sqlite3_exec( + session->db, + "PRAGMA application_id = 0x23423423;\n" + "create table if not exists log (\n" + " timestamp integer default (datetime('now')),\n" + " title text not null,\n" + " description text,\n" + " entity text not null,\n" + " comment text\n" + ");\n" + "create index if not exists log_timestamp on log (\n" + " timestamp\n" + ");\n" + , + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _create_core_tables(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "create table if not exists pgp_keypair (\n" + " fpr text primary key,\n" + " created integer,\n" + " expires integer,\n" + " comment text,\n" + " flags integer default 0\n" + ");\n" + "create index if not exists pgp_keypair_expires on pgp_keypair (\n" + " expires\n" + ");\n" + "create table if not exists person (\n" + " id text primary key,\n" + " username text not null,\n" + " main_key_id text\n" + " references pgp_keypair (fpr)\n" + " on delete set null,\n" + " lang text,\n" + " comment text,\n" + // " device_group text,\n" + " is_pEp_user integer default 0\n" + ");\n" + "create table if not exists identity (\n" + " address text,\n" + " user_id text\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " main_key_id text\n" + " references pgp_keypair (fpr)\n" + " on delete set null,\n" + " comment text,\n" + " flags integer default 0,\n" + " is_own integer default 0,\n" + " pEp_version_major integer default 0,\n" + " pEp_version_minor integer default 0,\n" + " enc_format integer default 0,\n" + " timestamp integer default (datetime('now')),\n" + " primary key (address, user_id)\n" + ");\n" + "create index if not exists identity_userid_addr on identity(address, user_id);\n" + "create table if not exists trust (\n" + " user_id text not null\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " pgp_keypair_fpr text not null\n" + " references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " comm_type integer not null,\n" + " comment text,\n" + " sticky integer default 0,\n" + " primary key (user_id, pgp_keypair_fpr)\n" + ");\n" + , + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _create_group_tables(PEP_SESSION session) { + if (!session) + return PEP_ILLEGAL_VALUE; + + int int_result = sqlite3_exec( + session->db, + // group information + "create table if not exists groups (\n" + " group_id text,\n" + " group_address text,\n" + " manager_userid text,\n" + " manager_address text,\n" + " active integer default 0,\n" + " constraint groups_pk\n" + " primary key (group_address, group_id),\n" + " constraint group_identity_fk\n" + " foreign key (group_address, group_id) references identity\n" + " on update cascade on delete cascade,\n" + " constraint manager_identity_fk\n" + " foreign key (manager_address, manager_userid) references identity\n" + " on update cascade on delete cascade\n" + ");\n" + "create table if not exists own_memberships (\n" + " group_id text,\n" + " group_address text,\n" + " own_id text,\n" + " own_address text,\n" + " have_joined int default 0,\n" + " constraint own_memberships_pk\n" + " primary key (group_address, group_id),\n" + " constraint own_memberships_own_id_fk\n" + " foreign key (own_address, own_id) references identity\n" + " on update cascade on delete cascade,\n" + " constraint own_memberships_group_fk\n" + " foreign key (group_address, group_id) references groups\n" + " on update cascade on delete cascade\n" + ");\n" + "create table if not exists own_groups_members (\n" + " group_id text,\n" + " group_address text,\n" + " member_id text,\n" + " member_address text,\n" + " active_member int default 0,\n" + " constraint own_groups_members_pk\n" + " primary key (group_address, group_id, member_address, member_id),\n" + " constraint group_ident_fk\n" + " foreign key (group_address, group_id) references groups\n" + " on update cascade on delete cascade,\n" + " constraint member_ident_fk\n" + " foreign key (member_address, member_id) references identity\n" + " on update cascade on delete cascade\n" + ");\n" + , + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _create_supplementary_key_tables(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + // blacklist + "create table if not exists blacklist_keys (\n" + " fpr text primary key\n" + ");\n" + "create table if not exists revoked_keys (\n" + " revoked_fpr text primary key,\n" + " replacement_fpr text not null\n" + " references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " revocation_date integer\n" + ");\n" + // mistrusted keys + "create table if not exists mistrusted_keys (\n" + " fpr text primary key\n" + ");\n" + // social graph for key resets + "create table if not exists social_graph (\n" + " own_userid text,\n" + " own_address text,\n" + " contact_userid text,\n" + " CONSTRAINT fk_own_identity\n" + " FOREIGN KEY(own_address, own_userid)\n" + " REFERENCES identity(address, user_id)\n" + " ON DELETE CASCADE ON UPDATE CASCADE\n" + ");\n" + // list of user_ids sent revocation + "create table if not exists revocation_contact_list (\n" + " fpr text not null references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " own_address text,\n" + " contact_id text not null references person (id)\n" + " on delete cascade on update cascade,\n" + " timestamp integer default (datetime('now')),\n" + " PRIMARY KEY(fpr, own_address, contact_id)\n" + ");\n" + , + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _create_misc_admin_tables(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + // sequences + "create table if not exists sequences(\n" + " name text primary key,\n" + " value integer default 0\n" + ");\n" + // user id aliases + "create table if not exists alternate_user_id (\n" + " default_id text references person (id)\n" + " on delete cascade on update cascade,\n" + " alternate_id text primary key\n" + ");\n" + , + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + + +// The create tables string is now too large for the C standard, so we're going to break it up some. +// I presume we use the enormous string for performance purposes... terrible for debugging purposes, but OK. +PEP_STATUS create_tables(PEP_SESSION session) { + + if (!session) + return PEP_ILLEGAL_VALUE; + + PEP_STATUS status = PEP_STATUS_OK; + + status = _create_initial_tables(session); + if (status != PEP_STATUS_OK) + return status; + + status = _create_core_tables(session); + if (status != PEP_STATUS_OK) + return status; + + status = _create_group_tables(session); + if (status != PEP_STATUS_OK) + return status; + + status = _create_supplementary_key_tables(session); + if (status != PEP_STATUS_OK) + return status; + + status = _create_misc_admin_tables(session); + + return status; +} + +PEP_STATUS get_db_user_version(PEP_SESSION session, int* version) { + int int_result = sqlite3_exec( + session->db, + "pragma user_version;", + user_version, + version, + NULL + ); + + assert(int_result == SQLITE_OK); + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _verify_version(PEP_SESSION session, int* version) { + // Sometimes the user_version wasn't set correctly. + bool version_changed = true; + int int_result; + if (table_contains_column(session, "groups", "group_identity")) { + *version = 15; + } + else if (table_contains_column(session, "identity", "enc_format")) { + *version = 14; + } else if (table_contains_column(session, "revocation_contact_list", "own_address")) { + *version = 13; + } else if (table_contains_column(session, "identity", "pEp_version_major")) { + *version = 12; + } else if (db_contains_table(session, "social_graph") > 0) { + if (!table_contains_column(session, "person", "device_group")) + *version = 10; + else + *version = 9; + } else if (table_contains_column(session, "identity", "timestamp") > 0) { + *version = 8; + } else if (table_contains_column(session, "person", "is_pEp_user") > 0) { + *version = 7; + } else if (table_contains_column(session, "identity", "is_own") > 0) { + *version = 6; + } else if (table_contains_column(session, "pgp_keypair", "flags") > 0) { + *version = 2; + } else { + version_changed = false; + } + + if (version_changed) { + // set it in the DB, finally. Yeesh. + char verbuf[21]; // enough digits for a max-sized 64 bit int, cmon. + sprintf(verbuf, "%d", *version); + + size_t query_size = strlen(verbuf) + 25; + char *query = calloc(query_size, 1); + + strlcpy(query, "pragma user_version = ", query_size); + strlcat(query, verbuf, query_size); + strlcat(query, ";", query_size); + + int_result = sqlite3_exec( + session->db, + query, + user_version, + &*version, + NULL + ); + free(query); + } + + // FIXME: status + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_2(PEP_SESSION session) { + // N.B. addition of device_group column removed in DDL v10 + int int_result = sqlite3_exec( + session->db, + "alter table pgp_keypair\n" + " add column flags integer default 0;\n", + // "alter table person\n" + // " add column device_group text;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_5(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "delete from pgp_keypair where fpr = '';", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_exec( + session->db, + "delete from trust where pgp_keypair_fpr = '';", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_6(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "alter table identity\n" + " add column is_own integer default 0;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_exec( + session->db, + "update identity\n" + " set is_own = 1\n" + " where (user_id = '" PEP_OWN_USERID "');\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + // Turns out that just adding "on update cascade" in + // sqlite is a PITA. We need to be able to cascade + // person->id replacements (for temp ids like "TOFU_") + // so here we go... + int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _identity_new (\n" + " address text,\n" + " user_id text\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " main_key_id text\n" + " references pgp_keypair (fpr)\n" + " on delete set null,\n" + " comment text,\n" + " flags integer default 0,\n" + " is_own integer default 0,\n" + " primary key (address, user_id)\n" + ");\n" + "INSERT INTO _identity_new SELECT * FROM identity;\n" + "DROP TABLE identity;\n" + "ALTER TABLE _identity_new RENAME TO identity;\n" + "COMMIT;\n" + "\n" + "BEGIN TRANSACTION;\n" + "create table _trust_new (\n" + " user_id text not null\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " pgp_keypair_fpr text not null\n" + " references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " comm_type integer not null,\n" + " comment text,\n" + " primary key (user_id, pgp_keypair_fpr)\n" + ");\n" + "INSERT INTO _trust_new SELECT * FROM trust;\n" + "DROP TABLE trust;\n" + "ALTER TABLE _trust_new RENAME TO trust;\n" + "COMMIT;\n" + "\n" + "PRAGMA foreign_keys=on;\n" + "create table if not exists alternate_user_id (\n" + " default_id text references person (id)\n" + " on delete cascade on update cascade,\n" + " alternate_id text primary key\n" + ");\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_key_check;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + // FIXME: foreign key check here + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_7(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "alter table person\n" + " add column is_pEp_user integer default 0;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_exec( + session->db, + "update person\n" + " set is_pEp_user = 1\n" + " where id = " + " (select distinct id from person " + " join trust on id = user_id " + " where (case when (comm_type = 127) then (id) " + " when (comm_type = 255) then (id) " + " else 0" + " end) = id );\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_exec( + session->db, + "create table if not exists mistrusted_keys (\n" + " fpr text primary key\n" + ");\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_8(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _identity_new (\n" + " address text,\n" + " user_id text\n" + " references person (id)\n" + " on delete cascade on update cascade,\n" + " main_key_id text\n" + " references pgp_keypair (fpr)\n" + " on delete set null,\n" + " comment text,\n" + " flags integer default 0,\n" + " is_own integer default 0,\n" + " timestamp integer default (datetime('now')),\n" + " primary key (address, user_id)\n" + ");\n" + "INSERT INTO _identity_new (address, user_id, main_key_id, " + " comment, flags, is_own) " + " SELECT identity.address, identity.user_id, " + " identity.main_key_id, identity.comment, " + " identity.flags, identity.is_own " + " FROM identity " + " WHERE 1;\n" + "DROP TABLE identity;\n" + "ALTER TABLE _identity_new RENAME TO identity;\n" + "COMMIT;\n" + "\n" + "PRAGMA foreign_keys=on;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_key_check;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + // FIXME: foreign key check + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + + +static PEP_STATUS _upgrade_DB_to_ver_9(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "create table if not exists social_graph (\n" + " own_userid text,\n" + " own_address text,\n" + " contact_userid text,\n" + " CONSTRAINT fk_own_identity\n" + " FOREIGN KEY(own_address, own_userid)\n" + " REFERENCES identity(address, user_id)\n" + " ON DELETE CASCADE ON UPDATE CASCADE\n" + ");\n" + "create table if not exists revocation_contact_list (\n" + " fpr text not null references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " contact_id text not null references person (id)\n" + " on delete cascade on update cascade,\n" + " timestamp integer default (datetime('now')),\n" + " PRIMARY KEY(fpr, contact_id)\n" + ");\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_10(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_keys=off;\n" + "BEGIN TRANSACTION;\n" + "create table _person_new (\n" + " id text primary key,\n" + " username text not null,\n" + " main_key_id text\n" + " references pgp_keypair (fpr)\n" + " on delete set null,\n" + " lang text,\n" + " comment text,\n" + " is_pEp_user integer default 0\n" + ");\n" + "INSERT INTO _person_new (id, username, main_key_id, " + " lang, comment, is_pEp_user) " + " SELECT person.id, person.username, " + " person.main_key_id, person.lang, " + " person.comment, person.is_pEp_user " + " FROM person " + " WHERE 1;\n" + "DROP TABLE person;\n" + "ALTER TABLE _person_new RENAME TO person;\n" + "COMMIT;\n" + "\n" + "PRAGMA foreign_keys=on;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_exec( + session->db, + "PRAGMA foreign_key_check;\n", + NULL, + NULL, + NULL + ); + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_12(PEP_SESSION session) { + PEP_STATUS status = PEP_STATUS_OK; + + int int_result = sqlite3_exec( + session->db, + "create index if not exists identity_userid_addr on identity(address, user_id);\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_exec( + session->db, + "alter table identity\n" + " add column pEp_version_major integer default 0;\n" + "alter table identity\n" + " add column pEp_version_minor integer default 0;\n", + NULL, + NULL, + NULL + ); + if (status != PEP_STATUS_OK) + return status; + + int_result = sqlite3_exec( + session->db, + "update identity\n" + " set pEp_version_major = 2\n" + " where exists (select * from person\n" + " where identity.user_id = person.id\n" + " and identity.is_own = 0\n" + " and person.is_pEp_user = 1);\n", + NULL, + NULL, + NULL + ); + if (status != PEP_STATUS_OK) + return status; + + // N.B. WE DEFINE PEP_VERSION - IF WE'RE AT 9-DIGIT MAJOR OR MINOR VERSIONS, ER, BAD. + char major_buf[10]; + char minor_buf[10]; + + // Guess we were abusing sscanf here, so we'll do it this way: + const char *cptr = PEP_VERSION; + size_t major_len = 0; + size_t minor_len = 0; + + char *bufptr = major_buf; + while (*cptr != '.' && *cptr != '\0') { + *bufptr++ = *cptr++; + major_len++; + } + *bufptr = '\0'; + bufptr = minor_buf; + + if (*cptr == '.') { + cptr++; + while (*cptr != '\0') { + *bufptr++ = *cptr++; + minor_len++; + } + } else { + *bufptr++ = '0'; + } + *bufptr = '\0'; + + const char *_ver_12_startstr = + "update identity\n" + " set pEp_version_major = "; + const char *_ver_12_midstr = ",\n" + " pEp_version_minor = "; + const char *_ver_12_endstr = + "\n" + " where identity.is_own = 1;\n"; + + size_t new_stringlen = strlen(_ver_12_startstr) + major_len + + strlen(_ver_12_midstr) + minor_len + + strlen(_ver_12_endstr); + + char *_ver_12_stmt = calloc(new_stringlen + 1, 1); + snprintf(_ver_12_stmt, new_stringlen + 1, "%s%s%s%s%s", + _ver_12_startstr, major_buf, _ver_12_midstr, minor_buf, _ver_12_endstr); + + int_result = sqlite3_exec( + session->db, + _ver_12_stmt, + NULL, + NULL, + NULL + ); + free(_ver_12_stmt); + if (status != PEP_STATUS_OK) + return status; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_14(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "alter table identity\n" + " add column enc_format integer default 0;\n", + NULL, + NULL, + NULL + ); + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _upgrade_DB_to_ver_15(PEP_SESSION session) { + return _create_group_tables(session); +} + +static PEP_STATUS _upgrade_DB_to_ver_16(PEP_SESSION session) { + int int_result = sqlite3_exec( + session->db, + "alter table trust\n" + " add column sticky integer default 0;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + return PEP_STATUS_OK; +} + +static PEP_STATUS _check_and_execute_upgrades(PEP_SESSION session, int version) { + PEP_STATUS status = PEP_STATUS_OK; + + switch(version) { + case 1: + status = _upgrade_DB_to_ver_2(session); + if (status != PEP_STATUS_OK) + return status; + case 2: + case 3: + case 4: + status = _upgrade_DB_to_ver_5(session); + if (status != PEP_STATUS_OK) + return status; + case 5: + status = _upgrade_DB_to_ver_6(session); + if (status != PEP_STATUS_OK) + return status; + case 6: + status = _upgrade_DB_to_ver_7(session); + if (status != PEP_STATUS_OK) + return status; + case 7: + status = _upgrade_DB_to_ver_8(session); + if (status != PEP_STATUS_OK) + return status; + case 8: + status = _upgrade_DB_to_ver_9(session); + if (status != PEP_STATUS_OK) + return status; + case 9: + if (version > 1) { + status = _upgrade_DB_to_ver_10(session); + if (status != PEP_STATUS_OK) + return status; + } + case 10: + status = repair_altered_tables(session); + assert(status == PEP_STATUS_OK); + if (status != PEP_STATUS_OK) + return status; + case 11: + status = _upgrade_DB_to_ver_12(session); + if (status != PEP_STATUS_OK) + return status; + case 12: + status = upgrade_revoc_contact_to_13(session); + assert(status == PEP_STATUS_OK); + if (status != PEP_STATUS_OK) + return status; + case 13: + status = _upgrade_DB_to_ver_14(session); + if (status != PEP_STATUS_OK) + return status; + case 14: + status = _upgrade_DB_to_ver_15(session); + if (status != PEP_STATUS_OK) + return status; + case 15: + status = _upgrade_DB_to_ver_16(session); + if (status != PEP_STATUS_OK) + return status; + case 16: + break; + default: + return PEP_ILLEGAL_VALUE; + } + return PEP_STATUS_OK; +} + + +PEP_STATUS pEp_sql_init(PEP_SESSION session) { + bool very_first = false; + PEP_STATUS status = create_tables(session); + if (status != PEP_STATUS_OK) + return status; + + int version = 0; + status = get_db_user_version(session, &version); + if (status != PEP_STATUS_OK) + return status; + + void (*xFunc_lower)(sqlite3_context *, int, sqlite3_value **) = &_sql_lower; + + int int_result = sqlite3_create_function_v2( + session->db, + "lower", + 1, + SQLITE_UTF8 | SQLITE_DETERMINISTIC, + NULL, + xFunc_lower, + NULL, + NULL, + NULL); + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_exec( + session->db, + "pragma foreign_keys=ON;\n", + NULL, + NULL, + NULL + ); + + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + if (version > atoi(_DDL_USER_VERSION)) { + // This is *explicitly* not allowed. + return PEP_INIT_DB_DOWNGRADE_VIOLATION; + } + + if (version == 1) { + // Sometimes the user_version wasn't set correctly. + status = _verify_version(session, &version); + if (status != PEP_STATUS_OK) + return PEP_ILLEGAL_VALUE; + } + + + if (version != 0) { + // Version has been already set + + // Early mistake : version 0 shouldn't have existed. + // Numbering should have started at 1 to detect newly created DB. + // Version 0 DBs are not anymore compatible. + status = _check_and_execute_upgrades(session, version); + if (status != PEP_STATUS_OK) + return PEP_ILLEGAL_VALUE; + } else { + // Version from DB was 0, it means this is initial setup. + // DB has just been created, and all tables are empty. + very_first = true; + } + + if (version < atoi(_DDL_USER_VERSION)) { + int_result = sqlite3_exec( + session->db, + "pragma user_version = "_DDL_USER_VERSION";\n" + "insert or replace into version_info (id, version)" + "values (1, '" PEP_ENGINE_VERSION "');", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + } + return PEP_STATUS_OK; +} + + +// This whole mess really does need to be generated somewhere. +PEP_STATUS pEp_prepare_sql_stmts(PEP_SESSION session) { + + int int_result = sqlite3_prepare_v2(session->system_db, sql_trustword, + (int)strlen(sql_trustword), &session->trustword, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_get_identity, + (int)strlen(sql_get_identity), &session->get_identity, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_get_identity_without_trust_check, + (int)strlen(sql_get_identity_without_trust_check), + &session->get_identity_without_trust_check, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_identities_by_address, + (int)strlen(sql_get_identities_by_address), + &session->get_identities_by_address, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_identities_by_userid, + (int)strlen(sql_get_identities_by_userid), + &session->get_identities_by_userid, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_identities_by_main_key_id, + (int)strlen(sql_get_identities_by_main_key_id), + &session->get_identities_by_main_key_id, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_user_default_key, + (int)strlen(sql_get_user_default_key), &session->get_user_default_key, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_all_keys_for_user, + (int)strlen(sql_get_all_keys_for_user), &session->get_all_keys_for_user, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_default_own_userid, + (int)strlen(sql_get_default_own_userid), &session->get_default_own_userid, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_userid_alias_default, + (int)strlen(sql_get_userid_alias_default), &session->get_userid_alias_default, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_add_userid_alias, + (int)strlen(sql_add_userid_alias), &session->add_userid_alias, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_replace_userid, + (int)strlen(sql_replace_userid), &session->replace_userid, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_delete_key, + (int)strlen(sql_delete_key), &session->delete_key, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_replace_main_user_fpr, + (int)strlen(sql_replace_main_user_fpr), &session->replace_main_user_fpr, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_replace_main_user_fpr_if_equal, + (int)strlen(sql_replace_main_user_fpr_if_equal), &session->replace_main_user_fpr_if_equal, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_main_user_fpr, + (int)strlen(sql_get_main_user_fpr), &session->get_main_user_fpr, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_refresh_userid_default_key, + (int)strlen(sql_refresh_userid_default_key), &session->refresh_userid_default_key, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_replace_identities_fpr, + (int)strlen(sql_replace_identities_fpr), + &session->replace_identities_fpr, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_remove_fpr_as_identity_default, + (int)strlen(sql_remove_fpr_as_identity_default), + &session->remove_fpr_as_identity_default, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_remove_fpr_as_user_default, + (int)strlen(sql_remove_fpr_as_user_default), + &session->remove_fpr_as_user_default, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_person, + (int)strlen(sql_set_person), &session->set_person, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_update_person, + (int)strlen(sql_update_person), &session->update_person, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_delete_person, + (int)strlen(sql_delete_person), &session->delete_person, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_exists_person, + (int)strlen(sql_exists_person), &session->exists_person, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_as_pEp_user, + (int)strlen(sql_set_as_pEp_user), &session->set_as_pEp_user, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_is_pEp_user, + (int)strlen(sql_is_pEp_user), &session->is_pEp_user, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_add_into_social_graph, + (int)strlen(sql_add_into_social_graph), &session->add_into_social_graph, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_get_own_address_binding_from_contact, + (int)strlen(sql_get_own_address_binding_from_contact), + &session->get_own_address_binding_from_contact, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_set_revoke_contact_as_notified, + (int)strlen(sql_set_revoke_contact_as_notified), + &session->set_revoke_contact_as_notified, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_get_contacted_ids_from_revoke_fpr, + (int)strlen(sql_get_contacted_ids_from_revoke_fpr), + &session->get_contacted_ids_from_revoke_fpr, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_was_id_for_revoke_contacted, + (int)strlen(sql_was_id_for_revoke_contacted), + &session->was_id_for_revoke_contacted, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_has_id_contacted_address, + (int)strlen(sql_has_id_contacted_address), + &session->has_id_contacted_address, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_get_last_contacted, + (int)strlen(sql_get_last_contacted), + &session->get_last_contacted, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, + sql_get_own_address_binding_from_contact, + (int)strlen(sql_get_own_address_binding_from_contact), + &session->get_own_address_binding_from_contact, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_pgp_keypair, + (int)strlen(sql_set_pgp_keypair), &session->set_pgp_keypair, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_set_pgp_keypair_flags, + (int)strlen(sql_set_pgp_keypair_flags), &session->set_pgp_keypair_flags, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_unset_pgp_keypair_flags, + (int)strlen(sql_unset_pgp_keypair_flags), &session->unset_pgp_keypair_flags, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_set_identity_entry, + (int)strlen(sql_set_identity_entry), &session->set_identity_entry, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_update_identity_entry, + (int)strlen(sql_update_identity_entry), &session->update_identity_entry, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_exists_identity_entry, + (int)strlen(sql_exists_identity_entry), &session->exists_identity_entry, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_identity_flags, + (int)strlen(sql_set_identity_flags), &session->set_identity_flags, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_unset_identity_flags, + (int)strlen(sql_unset_identity_flags), &session->unset_identity_flags, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_ident_enc_format, + (int)strlen(sql_set_ident_enc_format), &session->set_ident_enc_format, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_pEp_version, + (int)strlen(sql_set_pEp_version), &session->set_pEp_version, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_upgrade_pEp_version_by_user_id, + (int)strlen(sql_upgrade_pEp_version_by_user_id), &session->upgrade_pEp_version_by_user_id, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_clear_trust_info, + (int)strlen(sql_clear_trust_info), &session->clear_trust_info, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_trust, + (int)strlen(sql_set_trust), &session->set_trust, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_update_trust, + (int)strlen(sql_update_trust), &session->update_trust, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_update_trust_to_pEp, + (int)strlen(sql_update_trust_to_pEp), &session->update_trust_to_pEp, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_exists_trust_entry, + (int)strlen(sql_exists_trust_entry), &session->exists_trust_entry, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_update_trust_for_fpr, + (int)strlen(sql_update_trust_for_fpr), &session->update_trust_for_fpr, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_trust, + (int)strlen(sql_get_trust), &session->get_trust, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_trust_by_userid, + (int)strlen(sql_get_trust_by_userid), &session->get_trust_by_userid, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_least_trust, + (int)strlen(sql_least_trust), &session->least_trust, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_update_key_sticky_bit_for_user, + (int)strlen(sql_update_key_sticky_bit_for_user), + &session->update_key_sticky_bit_for_user, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_is_key_sticky_for_user, + (int)strlen(sql_is_key_sticky_for_user), + &session->is_key_sticky_for_user, NULL); + assert(int_result == SQLITE_OK); + + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_mark_as_compromised, + (int)strlen(sql_mark_as_compromised), &session->mark_compromised, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_crashdump, + (int)strlen(sql_crashdump), &session->crashdump, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->system_db, sql_languagelist, + (int)strlen(sql_languagelist), &session->languagelist, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->system_db, sql_i18n_token, + (int)strlen(sql_i18n_token), &session->i18n_token, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + // blacklist + + int_result = sqlite3_prepare_v2(session->db, sql_blacklist_add, + (int)strlen(sql_blacklist_add), &session->blacklist_add, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_blacklist_delete, + (int)strlen(sql_blacklist_delete), &session->blacklist_delete, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_blacklist_is_listed, + (int)strlen(sql_blacklist_is_listed), + &session->blacklist_is_listed, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_blacklist_retrieve, + (int)strlen(sql_blacklist_retrieve), &session->blacklist_retrieve, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + // Own keys + + int_result = sqlite3_prepare_v2(session->db, sql_own_key_is_listed, + (int)strlen(sql_own_key_is_listed), &session->own_key_is_listed, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_is_own_address, + (int)strlen(sql_is_own_address), &session->is_own_address, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_own_identities_retrieve, + (int)strlen(sql_own_identities_retrieve), + &session->own_identities_retrieve, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_own_keys_retrieve, + (int)strlen(sql_own_keys_retrieve), + &session->own_keys_retrieve, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + // int_result = sqlite3_prepare_v2(session->db, sql_set_own_key, + // (int)strlen(sql_set_own_key), + // &session->set_own_key, NULL); + // assert(int_result == SQLITE_OK); + + + // Sequence + + int_result = sqlite3_prepare_v2(session->db, sql_sequence_value1, + (int)strlen(sql_sequence_value1), &session->sequence_value1, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_sequence_value2, + (int)strlen(sql_sequence_value2), &session->sequence_value2, + NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + // Revocation tracking + + int_result = sqlite3_prepare_v2(session->db, sql_set_revoked, + (int)strlen(sql_set_revoked), &session->set_revoked, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_revoked, + (int)strlen(sql_get_revoked), &session->get_revoked, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_replacement_fpr, + (int)strlen(sql_get_replacement_fpr), &session->get_replacement_fpr, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_add_mistrusted_key, + (int)strlen(sql_add_mistrusted_key), &session->add_mistrusted_key, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_delete_mistrusted_key, + (int)strlen(sql_delete_mistrusted_key), &session->delete_mistrusted_key, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_is_mistrusted_key, + (int)strlen(sql_is_mistrusted_key), &session->is_mistrusted_key, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + /* Groups */ + int_result = sqlite3_prepare_v2(session->db, sql_create_group, + (int)strlen(sql_create_group), &session->create_group, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_enable_group, + (int)strlen(sql_enable_group), &session->enable_group, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_disable_group, + (int)strlen(sql_disable_group), &session->disable_group, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_exists_group_entry, + (int)strlen(sql_exists_group_entry), &session->exists_group_entry, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_group_add_member, + (int)strlen(sql_group_add_member), &session->group_add_member, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_set_group_member_status, + (int)strlen(sql_set_group_member_status), &session->set_group_member_status, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_join_group, + (int)strlen(sql_join_group), &session->join_group, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_leave_group, + (int)strlen(sql_leave_group), &session->leave_group, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_all_members, + (int)strlen(sql_get_all_members), &session->get_all_members, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + + int_result = sqlite3_prepare_v2(session->db, sql_get_active_members, + (int)strlen(sql_get_active_members), &session->get_active_members, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_all_groups, + (int)strlen(sql_get_all_groups), &session->get_all_groups, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_get_active_groups, + (int)strlen(sql_get_active_groups), &session->get_active_groups, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_add_own_membership_entry, + (int)strlen(sql_add_own_membership_entry), &session->add_own_membership_entry, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_get_own_membership_status, + (int)strlen(sql_get_own_membership_status), &session->get_own_membership_status, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_retrieve_own_membership_info_for_group_and_ident, + (int)strlen(sql_retrieve_own_membership_info_for_group_and_ident), &session->retrieve_own_membership_info_for_group_and_ident, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_retrieve_own_membership_info_for_group, + (int)strlen(sql_retrieve_own_membership_info_for_group), &session->retrieve_own_membership_info_for_group, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_get_group_manager, + (int)strlen(sql_get_group_manager), &session->get_group_manager, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_is_invited_group_member, + (int)strlen(sql_is_invited_group_member), &session->is_invited_group_member, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + + int_result = sqlite3_prepare_v2(session->db, sql_is_group_active, + (int)strlen(sql_is_group_active), &session->is_group_active, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + +// int_result = sqlite3_prepare_v2(session->db, sql_group_invite_exists, +// (int)strlen(sql_group_invite_exists), &session->group_invite_exists, NULL); +// assert(int_result == SQLITE_OK); +// +// if (int_result != SQLITE_OK) +// return PEP_UNKNOWN_DB_ERROR; + + int_result = sqlite3_prepare_v2(session->db, sql_log, + (int)strlen(sql_log), &session->log, NULL); + assert(int_result == SQLITE_OK); + + if (int_result != SQLITE_OK) + return PEP_UNKNOWN_DB_ERROR; + + /* End groups */ + return PEP_STATUS_OK; +} + +PEP_STATUS pEp_finalize_sql_stmts(PEP_SESSION session) { + if (session->log) + sqlite3_finalize(session->log); + if (session->trustword) + sqlite3_finalize(session->trustword); + if (session->get_identity) + sqlite3_finalize(session->get_identity); + if (session->get_identity_without_trust_check) + sqlite3_finalize(session->get_identity_without_trust_check); + if (session->get_identities_by_address) + sqlite3_finalize(session->get_identities_by_address); + if (session->get_identities_by_userid) + sqlite3_finalize(session->get_identities_by_userid); + if (session->get_identities_by_main_key_id) + sqlite3_finalize(session->get_identities_by_main_key_id); + if (session->get_user_default_key) + sqlite3_finalize(session->get_user_default_key); + if (session->get_all_keys_for_user) + sqlite3_finalize(session->get_all_keys_for_user); + if (session->get_default_own_userid) + sqlite3_finalize(session->get_default_own_userid); + if (session->get_userid_alias_default) + sqlite3_finalize(session->get_userid_alias_default); + if (session->add_userid_alias) + sqlite3_finalize(session->add_userid_alias); + if (session->replace_identities_fpr) + sqlite3_finalize(session->replace_identities_fpr); + if (session->remove_fpr_as_identity_default) + sqlite3_finalize(session->remove_fpr_as_identity_default); + if (session->remove_fpr_as_user_default) + sqlite3_finalize(session->remove_fpr_as_user_default); + if (session->set_person) + sqlite3_finalize(session->set_person); + if (session->delete_person) + sqlite3_finalize(session->delete_person); + if (session->set_as_pEp_user) + sqlite3_finalize(session->set_as_pEp_user); + if (session->upgrade_pEp_version_by_user_id) + sqlite3_finalize(session->upgrade_pEp_version_by_user_id); + if (session->is_pEp_user) + sqlite3_finalize(session->is_pEp_user); + if (session->exists_person) + sqlite3_finalize(session->exists_person); + if (session->add_into_social_graph) + sqlite3_finalize(session->add_into_social_graph); + if (session->get_own_address_binding_from_contact) + sqlite3_finalize(session->get_own_address_binding_from_contact); + if (session->set_revoke_contact_as_notified) + sqlite3_finalize(session->set_revoke_contact_as_notified); + if (session->get_contacted_ids_from_revoke_fpr) + sqlite3_finalize(session->get_contacted_ids_from_revoke_fpr); + if (session->was_id_for_revoke_contacted) + sqlite3_finalize(session->was_id_for_revoke_contacted); + if (session->has_id_contacted_address) + sqlite3_finalize(session->has_id_contacted_address); + if (session->get_last_contacted) + sqlite3_finalize(session->get_last_contacted); + if (session->set_pgp_keypair) + sqlite3_finalize(session->set_pgp_keypair); + if (session->exists_identity_entry) + sqlite3_finalize(session->exists_identity_entry); + if (session->set_identity_entry) + sqlite3_finalize(session->set_identity_entry); + if (session->update_identity_entry) + sqlite3_finalize(session->update_identity_entry); + if (session->set_identity_flags) + sqlite3_finalize(session->set_identity_flags); + if (session->unset_identity_flags) + sqlite3_finalize(session->unset_identity_flags); + if (session->set_ident_enc_format) + sqlite3_finalize(session->set_ident_enc_format); + if (session->set_pEp_version) + sqlite3_finalize(session->set_pEp_version); + if (session->exists_trust_entry) + sqlite3_finalize(session->exists_trust_entry); + if (session->clear_trust_info) + sqlite3_finalize(session->clear_trust_info); + if (session->set_trust) + sqlite3_finalize(session->set_trust); + if (session->update_trust) + sqlite3_finalize(session->update_trust); + if (session->update_trust_to_pEp) + sqlite3_finalize(session->update_trust_to_pEp); + if (session->update_trust_for_fpr) + sqlite3_finalize(session->update_trust_for_fpr); + if (session->get_trust) + sqlite3_finalize(session->get_trust); + if (session->get_trust_by_userid) + sqlite3_finalize(session->get_trust_by_userid); + if (session->least_trust) + sqlite3_finalize(session->least_trust); + if (session->update_key_sticky_bit_for_user) + sqlite3_finalize(session->update_key_sticky_bit_for_user); + if (session->is_key_sticky_for_user) + sqlite3_finalize(session->is_key_sticky_for_user); + if (session->mark_compromised) + sqlite3_finalize(session->mark_compromised); + if (session->crashdump) + sqlite3_finalize(session->crashdump); + if (session->languagelist) + sqlite3_finalize(session->languagelist); + if (session->i18n_token) + sqlite3_finalize(session->i18n_token); + if (session->replace_userid) + sqlite3_finalize(session->replace_userid); + if (session->delete_key) + sqlite3_finalize(session->delete_key); + if (session->replace_main_user_fpr) + sqlite3_finalize(session->replace_main_user_fpr); + if (session->replace_main_user_fpr_if_equal) + sqlite3_finalize(session->replace_main_user_fpr_if_equal); + if (session->get_main_user_fpr) + sqlite3_finalize(session->get_main_user_fpr); + if (session->refresh_userid_default_key) + sqlite3_finalize(session->refresh_userid_default_key); + if (session->blacklist_add) + sqlite3_finalize(session->blacklist_add); + if (session->blacklist_delete) + sqlite3_finalize(session->blacklist_delete); + if (session->blacklist_is_listed) + sqlite3_finalize(session->blacklist_is_listed); + if (session->blacklist_retrieve) + sqlite3_finalize(session->blacklist_retrieve); + if (session->own_key_is_listed) + sqlite3_finalize(session->own_key_is_listed); + if (session->is_own_address) + sqlite3_finalize(session->is_own_address); + if (session->own_identities_retrieve) + sqlite3_finalize(session->own_identities_retrieve); + if (session->own_keys_retrieve) + sqlite3_finalize(session->own_keys_retrieve); + // if (session->set_own_key) + // sqlite3_finalize(session->set_own_key); + if (session->sequence_value1) + sqlite3_finalize(session->sequence_value1); + if (session->sequence_value2) + sqlite3_finalize(session->sequence_value2); + if (session->set_revoked) + sqlite3_finalize(session->set_revoked); + if (session->get_revoked) + sqlite3_finalize(session->get_revoked); + if (session->get_replacement_fpr) + sqlite3_finalize(session->get_replacement_fpr); + if (session->add_mistrusted_key) + sqlite3_finalize(session->add_mistrusted_key); + if (session->delete_mistrusted_key) + sqlite3_finalize(session->delete_mistrusted_key); + if (session->is_mistrusted_key) + sqlite3_finalize(session->is_mistrusted_key); + if (session->create_group) + sqlite3_finalize(session->create_group); + if (session->enable_group) + sqlite3_finalize(session->enable_group); + if (session->disable_group) + sqlite3_finalize(session->disable_group); + if (session->exists_group_entry) + sqlite3_finalize(session->exists_group_entry); + if (session->group_add_member) + sqlite3_finalize(session->group_add_member); + if (session->set_group_member_status) + sqlite3_finalize(session->set_group_member_status); + if (session->join_group) + sqlite3_finalize(session->join_group); + if (session->leave_group) + sqlite3_finalize(session->leave_group); + if (session->get_all_members) + sqlite3_finalize(session->get_all_members); + if (session->get_active_members) + sqlite3_finalize(session->get_active_members); + if (session->get_active_groups) + sqlite3_finalize(session->get_active_groups); + if (session->get_all_groups) + sqlite3_finalize(session->get_all_groups); + if (session->add_own_membership_entry) + sqlite3_finalize(session->add_own_membership_entry); + if (session->get_own_membership_status) + sqlite3_finalize(session->get_own_membership_status); + if (session->retrieve_own_membership_info_for_group_and_ident) + sqlite3_finalize(session->retrieve_own_membership_info_for_group_and_ident); + if (session->retrieve_own_membership_info_for_group) + sqlite3_finalize(session->retrieve_own_membership_info_for_group); + if (session->get_group_manager) + sqlite3_finalize(session->get_group_manager); + if (session->is_invited_group_member) + sqlite3_finalize(session->is_invited_group_member); + if (session->is_group_active) + sqlite3_finalize(session->is_group_active); + if (session->set_pgp_keypair_flags) + sqlite3_finalize(session->set_pgp_keypair_flags); + if (session->unset_pgp_keypair_flags) + sqlite3_finalize(session->unset_pgp_keypair_flags); + // retrieve_own_membership_info_for_group_and_ident + // if (session->group_invite_exists) +// sqlite3_finalize(session->group_invite_exists); + return PEP_STATUS_OK; +} diff --git a/src/engine_sql.h b/src/engine_sql.h new file mode 100644 index 00000000..d0057d4e --- /dev/null +++ b/src/engine_sql.h @@ -0,0 +1,586 @@ +#pragma once + +#include "pEp_internal.h" + +// increment this when patching DDL +#define _DDL_USER_VERSION "16" + +PEP_STATUS init_databases(PEP_SESSION session); +PEP_STATUS pEp_sql_init(PEP_SESSION session); +PEP_STATUS pEp_prepare_sql_stmts(PEP_SESSION session); +PEP_STATUS pEp_finalize_sql_stmts(PEP_SESSION session); + +/** + * Strings to feed into prepared statements + */ +static const char *sql_log = + "insert into log (title, entity, description, comment)" + "values (?1, ?2, ?3, ?4);"; + +static const char *sql_trustword = + "select id, word from wordlist where lang = lower(?1) " + "and id = ?2 ;"; + +// FIXME?: problems if we don't have a key for the user - we get nothing +// Also: we've never used pgp_keypair.flags before now, but it seems to me that +// having combination of those flags is a road to ruin. Changing this for now. +static const char *sql_get_identity = + "select identity.main_key_id, username, comm_type, lang," + " identity.flags," +// " identity.flags | pgp_keypair.flags," + " is_own, pEp_version_major, pEp_version_minor, enc_format" + " from identity" + " join person on id = identity.user_id" + " left join pgp_keypair on fpr = identity.main_key_id" + " left join trust on id = trust.user_id" + " and pgp_keypair_fpr = identity.main_key_id" + " where (case when (address = ?1) then (1)" + " when (lower(address) = lower(?1)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" + " else 0" + " end) = 1" + " and identity.user_id = ?2" + " order by is_own desc, " + " timestamp desc; "; + +static const char *sql_get_identities_by_main_key_id = + "select address, identity.user_id, username, comm_type, lang," + " identity.flags," +// " identity.flags | pgp_keypair.flags," + " is_own, pEp_version_major, pEp_version_minor, enc_format" + " from identity" + " join person on id = identity.user_id" + " left join pgp_keypair on fpr = identity.main_key_id" + " left join trust on id = trust.user_id" + " and pgp_keypair_fpr = identity.main_key_id" + " where identity.main_key_id = ?1" + " order by is_own desc, " + " timestamp desc; "; + +static const char *sql_get_identity_without_trust_check = + "select identity.main_key_id, username, lang," + " identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format" + " from identity" + " join person on id = identity.user_id" + " where (case when (address = ?1) then (1)" + " when (lower(address) = lower(?1)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" + " else 0" + " end) = 1" + " and identity.user_id = ?2 " + " order by is_own desc, " + " timestamp desc; "; + +static const char *sql_get_identities_by_address = + "select user_id, identity.main_key_id, username, lang," + " identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format" + " from identity" + " join person on id = identity.user_id" + " where (case when (address = ?1) then (1)" + " when (lower(address) = lower(?1)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" + " else 0" + " end) = 1 " + " order by is_own desc, " + " timestamp desc; "; + +static const char *sql_get_identities_by_userid = + "select address, identity.main_key_id, username, comm_type, lang," + " identity.flags," +// " identity.flags | pgp_keypair.flags," + " is_own, pEp_version_major, pEp_version_minor, enc_format" + " from identity" + " join person on id = identity.user_id" + " left join pgp_keypair on fpr = identity.main_key_id" + " left join trust on id = trust.user_id" + " and pgp_keypair_fpr = identity.main_key_id" + " where identity.user_id = ?1" + " order by is_own desc, " + " timestamp desc; "; + +static const char *sql_replace_identities_fpr = + "update identity" + " set main_key_id = ?1 " + " where main_key_id = ?2 ;"; + +static const char *sql_remove_fpr_as_identity_default = + "update identity set main_key_id = NULL where main_key_id = ?1 ;"; + +static const char *sql_remove_fpr_as_user_default = + "update person set main_key_id = NULL where main_key_id = ?1 ;"; + +// Set person, but if already exist, only update. +// if main_key_id already set, don't touch. +static const char *sql_set_person = + "insert into person (id, username, lang, main_key_id)" + " values (?1, ?2, ?3, ?4) ;"; + +static const char *sql_update_person = + "update person " + " set username = ?2, " + " lang = ?3, " + " main_key_id = " + " (select coalesce( " + " (select main_key_id from person where id = ?1), " + " upper(replace(?4,' ',''))))" + " where id = ?1 ;"; + +// Will cascade. +static const char *sql_delete_person = + "delete from person where id = ?1 ;"; + +static const char *sql_set_as_pEp_user = + "update person set is_pEp_user = 1 " + " where id = ?1 ; "; + +static const char *sql_is_pEp_user = + "select is_pEp_user from person " + " where id = ?1 ; "; + +static const char* sql_exists_person = + "select count(*) from person " + " where id = ?1 ;"; + +// This will cascade to identity and trust +static const char* sql_replace_userid = + "update person set id = ?1 " + " where id = ?2;"; + +// Hopefully this cascades and removes trust entries... +static const char *sql_delete_key = + "delete from pgp_keypair " + " where fpr = ?1 ; "; + +static const char *sql_replace_main_user_fpr = + "update person " + " set main_key_id = ?1 " + " where id = ?2 ;"; + +static const char *sql_get_main_user_fpr = + "select main_key_id from person" + " where id = ?1 ;"; + +static const char *sql_replace_main_user_fpr_if_equal = + "update person " + " set main_key_id = ?1 " + " where id = ?2 and main_key_id = ?3;"; + +static const char *sql_refresh_userid_default_key = + "update person " + " set main_key_id = " + " (select identity.main_key_id from identity " + " join trust on trust.user_id = identity.user_id " + " and trust.pgp_keypair_fpr = identity.main_key_id " + " join person on person.id = identity.user_id " + " where identity.user_id = ?1 " + " order by trust.comm_type desc " + " limit 1) " + "where id = ?1 ; "; + +static const char *sql_set_pgp_keypair = + "insert or ignore into pgp_keypair (fpr) " + "values (upper(replace(?1,' ',''))) ;"; + +static const char *sql_set_pgp_keypair_flags = + "update pgp_keypair set flags = " + " ((?1 & 65535) | (select flags from pgp_keypair " + " where fpr = (upper(replace(?2,' ',''))))) " + " where fpr = (upper(replace(?2,' ',''))) ;"; + +static const char *sql_unset_pgp_keypair_flags = + "update pgp_keypair set flags = " + " ( ~(?1 & 65535) & (select flags from pgp_keypair" + " where fpr = (upper(replace(?2,' ',''))))) " + " where fpr = (upper(replace(?2,' ',''))) ;"; + +static const char* sql_exists_identity_entry = + "select count(*) from identity " + " where (case when (address = ?1) then (1)" + " when (lower(address) = lower(?1)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" + " else 0" + " end) = 1" + " and user_id = ?2;"; + +static const char *sql_set_identity_entry = + "insert into identity (" + " address, main_key_id, " + " user_id, flags, is_own," + " pEp_version_major, pEp_version_minor" + " ) values (" + " ?1," + " upper(replace(?2,' ',''))," + " ?3," + " ?4," + " ?5," + " ?6," + " ?7" + " );"; + +static const char* sql_update_identity_entry = + "update identity " + " set main_key_id = upper(replace(?2,' ','')), " + " flags = ?4, " + " is_own = ?5, " + " pEp_version_major = ?6, " + " pEp_version_minor = ?7 " + " where (case when (address = ?1) then (1)" + " when (lower(address) = lower(?1)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1) " + " else 0 " + " end) = 1 " + " and user_id = ?3 ;"; + +// " (select" +// " coalesce(" +// " (select flags from identity" +// " where address = ?1 and" +// " user_id = ?3)," +// " 0)" +// " ) | (?4 & 255)" +/* set_identity ignores previous flags, and doesn't filter machine flags */ + +static const char *sql_set_identity_flags = + "update identity set flags = " + " ((?1 & 65535) | (select flags from identity" + " where (case when (address = ?2) then (1)" + " when (lower(address) = lower(?2)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" + " else 0 " + " end) = 1 " + " and user_id = ?3)) " + " where (case when (address = ?2) then (1)" + " when (lower(address) = lower(?2)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" + " else 0" + " end) = 1" + " and user_id = ?3 ;"; + +static const char *sql_unset_identity_flags = + "update identity set flags = " + " ( ~(?1 & 65535) & (select flags from identity" + " where (case when (address = ?2) then (1)" + " when (lower(address) = lower(?2)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" + " else 0 " + " end) = 1 " + " and user_id = ?3)) " + " where (case when (address = ?2) then (1)" + " when (lower(address) = lower(?2)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" + " else 0" + " end) = 1" + " and user_id = ?3 ;"; + +static const char *sql_set_ident_enc_format = + "update identity " + " set enc_format = ?1 " + " where (case when (address = ?2) then (1)" + " when (lower(address) = lower(?2)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1) " + " else 0 " + " end) = 1 " + " and user_id = ?3 ;"; + +static const char *sql_set_pEp_version = + "update identity " + " set pEp_version_major = ?1, " + " pEp_version_minor = ?2 " + " where (case when (address = ?3) then (1)" + " when (lower(address) = lower(?3)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?3),'.','')) then (1) " + " else 0 " + " end) = 1 " + " and user_id = ?4 ;"; + +static const char *sql_upgrade_pEp_version_by_user_id = + "update identity " + " set pEp_version_major = ?1, " + " pEp_version_minor = ?2 " + " where user_id = ?3 " + " and (case when (pEp_version_major < ?1) then (1)" + " when (pEp_version_major > ?1) then (0)" + " when (pEp_version_minor < ?2) then (1)" + " else 0 " + " end) = 1 ;"; + +static const char *sql_set_trust = + "insert into trust (user_id, pgp_keypair_fpr, comm_type) " + "values (?1, upper(replace(?2,' ','')), ?3) ;"; + +static const char *sql_update_trust = + "update trust set comm_type = ?3 " + " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; + +static const char *sql_clear_trust_info = + "delete from trust " + " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; + +static const char *sql_update_trust_to_pEp = + "update trust set comm_type = comm_type + 71 " + " where (user_id = ?1 " + " and (case when (comm_type = 56) then (1) " + " when (comm_type = 184) then (1) " + " else 0" + " end) = 1); "; + +static const char* sql_exists_trust_entry = + "select count(*) from trust " + " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; + +static const char *sql_update_trust_for_fpr = + "update trust " + "set comm_type = ?1 " + "where pgp_keypair_fpr = upper(replace(?2,' ','')) ;"; + +static const char *sql_get_trust = + "select comm_type from trust where user_id = ?1 " + "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;"; + +static const char *sql_get_trust_by_userid = + "select pgp_keypair_fpr, comm_type from trust where user_id = ?1 "; + +static const char *sql_least_trust = + "select min(comm_type) from trust where" + " pgp_keypair_fpr = upper(replace(?1,' ',''))" + " and comm_type != 0;"; // ignores PEP_ct_unknown +// returns PEP_ct_unknown only when no known trust is recorded + +static const char *sql_update_key_sticky_bit_for_user = + "update trust set sticky = ?1 " + " where user_id = ?2 and pgp_keypair_fpr = upper(replace(?3,' ','')) ;"; + +static const char *sql_is_key_sticky_for_user = + "select sticky from trust " + " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ','')) ; "; + +static const char *sql_mark_as_compromised = + "update trust not indexed set comm_type = 15" + " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_crashdump = + "select timestamp, title, entity, description, comment" + " from log order by timestamp desc limit ?1 ;"; + +static const char *sql_languagelist = + "select i18n_language.lang, name, phrase" + " from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ; + +static const char *sql_i18n_token = + "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;"; + +// blacklist +static const char *sql_blacklist_add = + "insert or ignore into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;" + "delete from identity where main_key_id = upper(replace(?1,' ','')) ;" + "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_blacklist_delete = + "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_blacklist_is_listed = + "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_blacklist_retrieve = + "select * from blacklist_keys ;"; + + +// Own keys +// We only care if it's 0 or non-zero +static const char *sql_own_key_is_listed = + "select count(*) from (" + " select pgp_keypair_fpr from trust" + " join identity on trust.user_id = identity.user_id" + " where pgp_keypair_fpr = upper(replace(?1,' ',''))" + " and identity.is_own = 1" + ");"; + +static const char *sql_is_own_address = + "select count(*) from (" + " select address from identity" + " where (case when (address = ?1) then (1)" + " when (lower(address) = lower(?1)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" + " else 0" + " end) = 1 " + " and identity.is_own = 1" + ");"; + +static const char *sql_own_identities_retrieve = + "select address, identity.main_key_id, identity.user_id, username," + " lang," + " identity.flags," +// " identity.flags | pgp_keypair.flags," + " pEp_version_major, pEp_version_minor" + " from identity" + " join person on id = identity.user_id" + " left join pgp_keypair on fpr = identity.main_key_id" + " left join trust on id = trust.user_id" + " and pgp_keypair_fpr = identity.main_key_id" + " where identity.is_own = 1" + " and (identity.flags & ?1) = 0;"; + +static const char *sql_own_keys_retrieve = + "select distinct pgp_keypair_fpr from trust" + " join identity on trust.user_id = identity.user_id" + " where identity.is_own = 1"; + +static const char* sql_get_user_default_key = + "select main_key_id from person" + " where id = ?1;"; + +static const char* sql_get_all_keys_for_user = + "select pgp_keypair_fpr from trust" + " where user_id = ?1; "; + +static const char* sql_get_default_own_userid = + "select id from person" + " join identity on id = identity.user_id" + " where identity.is_own = 1"; + +// Sequence +static const char *sql_sequence_value1 = + "insert or replace into sequences (name, value) " + "values (?1, " + " (select coalesce((select value + 1 from sequences " + " where name = ?1), 1 ))); "; + +static const char *sql_sequence_value2 = + "select value from sequences where name = ?1 ;"; + +// Revocation tracking +static const char *sql_set_revoked = + "insert or replace into revoked_keys (" + " revoked_fpr, replacement_fpr, revocation_date) " + "values (upper(replace(?1,' ',''))," + " upper(replace(?2,' ',''))," + " ?3) ;"; + +static const char *sql_get_revoked = + "select revoked_fpr, revocation_date from revoked_keys" + " where replacement_fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_get_replacement_fpr = + "select replacement_fpr, revocation_date from revoked_keys" + " where revoked_fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_get_userid_alias_default = + "select default_id from alternate_user_id " + " where alternate_id = ?1 ; "; + +// Revocation tracking +static const char *sql_add_mistrusted_key = + "insert or replace into mistrusted_keys (fpr) " + " values (upper(replace(?1,' ',''))) ;"; + +static const char *sql_delete_mistrusted_key = + "delete from mistrusted_keys where fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_is_mistrusted_key = + "select count(*) from mistrusted_keys where fpr = upper(replace(?1,' ','')) ;"; + +static const char *sql_add_userid_alias = + "insert or replace into alternate_user_id (alternate_id, default_id) " + "values (?2, ?1) ;"; + +static const char *sql_add_into_social_graph = + "insert or replace into social_graph(own_userid, own_address, contact_userid) " + "values (?1, ?2, ?3) ;"; + +static const char *sql_get_own_address_binding_from_contact = + "select own_address from social_graph where own_userid = ?1 and contact_userid = ?2 ;"; + +static const char *sql_set_revoke_contact_as_notified = + "insert or replace into revocation_contact_list(fpr, own_address, contact_id) values (?1, ?2, ?3) ;"; + +static const char *sql_get_contacted_ids_from_revoke_fpr = + "select * from revocation_contact_list where fpr = ?1 ;"; + +static const char *sql_was_id_for_revoke_contacted = + "select count(*) from revocation_contact_list where fpr = ?1 and own_address = ?2 and contact_id = ?3 ;"; + +static const char *sql_has_id_contacted_address = + "select count(*) from social_graph where own_address = ?1 and contact_userid = ?2 ;"; + +// We only need user_id and address, since in the main usage, we'll call update_identity +// on this anyway when sending out messages. +static const char *sql_get_last_contacted = + "select user_id, address from identity where datetime('now') < datetime(timestamp, '+14 days') ; "; + +static const char *sql_create_group = + "insert into groups (group_id, group_address, manager_userid, manager_address) " + "VALUES (?1, ?2, ?3, ?4) ;"; + +static const char *sql_enable_group = + "update groups set active = 1 " + " where group_id = ?1 and group_address = ?2 ;"; + +static const char *sql_disable_group = + "update groups set active = 0 " + " where group_id = ?1 and group_address = ?2 ;"; + +static const char *sql_exists_group_entry = + "select count(*) from groups " + " where group_id = ?1 and group_address = ?2;"; +static const char *sql_group_add_member = + "insert or ignore into own_groups_members (group_id, group_address, member_id, member_address) " + " values (?1, ?2, ?3, ?4) ;"; +static const char *sql_set_group_member_status = + "update own_groups_members set active_member = ?1 " + " where group_id = ?2 and group_address = ?3 and " + " member_id = ?4 and member_address = ?5; "; +static const char *sql_join_group = + "update own_memberships set have_joined = 1 " + " where group_id = ?1 and group_address = ?2 and " + " own_id = ?3 and own_address = ?4; "; +static const char *sql_leave_group = + "update own_memberships set have_joined = 0 " + " where group_id = ?1 and group_address = ?2 and " + " own_id = ?3 and own_address = ?4; "; +static const char *sql_get_all_members = + "select member_id, member_address, active_member from own_groups_members " + " where group_id = ?1 and group_address = ?2; "; +static const char *sql_get_active_members = + "select member_id, member_address from own_groups_members " + " where group_id = ?1 and group_address = ?2 and active_member = 1; "; +static const char *sql_get_group_manager = + "select manager_userid, manager_address from groups " + " where group_id = ?1 and group_address = ?2; "; +static const char *sql_is_invited_group_member = + "select count(*) from own_groups_members " + " where group_id = ?1 and group_address = ?2 and member_id = ?3 and member_address = ?4; "; +static const char *sql_get_all_groups = + "select group_id, group_address from own_memberships; "; +static const char *sql_get_active_groups = + "select group_id, group_address from own_memberships where have_joined = 1; "; +static const char *sql_add_own_membership_entry = + "insert or replace into own_memberships (group_id, group_address, own_id, own_address, have_joined) " + " values (?1, ?2, ?3, ?4, 0) ; "; +static const char *sql_is_group_active = + "select count(*) from groups " + " where group_id = ?1 and group_address = ?2 and active = 1; "; + +// This below can return multiple entries for multiple idents in same group +// FIXME: decide what we really need here +static const char *sql_retrieve_own_membership_info_for_group = + "select own_id, own_address, have_joined " + " from own_memberships " + " inner join groups using (group_id, group_address) " + " where group_id = ?1 and group_address = ?2; "; + +static const char *sql_retrieve_own_membership_info_for_group_and_ident = + "select have_joined, manager_userid, manager_address, active " + " from own_memberships " + " inner join groups using (group_id, group_address) " + " where group_id = ?1 and group_address = ?2 and own_id = ?3 and own_address = ?4; "; + +// This will return all membership info for all identities +static const char *sql_retrieve_all_own_membership_info = + "select group_id, group_address, own_id, own_address, have_joined, manager_id, manager_address, active " + " from own_memberships " + " inner join using (group_id, group_address); "; + +static const char* sql_get_own_membership_status = + "select have_joined from own_memberships " + " where group_id = ?1 and group_address = ?2 and " + " own_id = ?3 and own_address = ?4; "; diff --git a/src/etpan_mime.c b/src/etpan_mime.c index f2a20822..31ab922e 100644 --- a/src/etpan_mime.c +++ b/src/etpan_mime.c @@ -2381,35 +2381,38 @@ static identity_list * mal_to_identity_list( pEp_identity *ident; struct mailimf_address *addr = clist_content(cur); - switch(addr->ad_type) { - case MAILIMF_ADDRESS_MAILBOX: - ident = mailbox_to_identity(addr->ad_data.ad_mailbox); - if (ident == NULL) - goto enomem; - _il = identity_list_add(_il, ident); - if (_il == NULL) - goto enomem; - break; + if (addr) { + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + ident = mailbox_to_identity(addr->ad_data.ad_mailbox); + if (ident == NULL) + goto enomem; + _il = identity_list_add(_il, ident); + if (_il == NULL) + goto enomem; + break; - case MAILIMF_ADDRESS_GROUP: - { - struct mailimf_mailbox_list * mbl = + case MAILIMF_ADDRESS_GROUP: { + struct mailimf_mailbox_list *mbl = addr->ad_data.ad_group->grp_mb_list; - for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL; - cur2 = clist_next(cur2)) { - ident = mailbox_to_identity(clist_content(cur)); - if (ident == NULL) - goto enomem; - _il = identity_list_add(_il, ident); - if (_il == NULL) - goto enomem; + if (mbl) { + for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL; + cur2 = clist_next(cur2)) { + ident = mailbox_to_identity(clist_content(cur)); + if (ident == NULL) + goto enomem; + _il = identity_list_add(_il, ident); + if (_il == NULL) + goto enomem; + } } } - break; + break; - default: - assert(0); - goto enomem; + default: + assert(0); + goto enomem; + } } } @@ -2552,7 +2555,7 @@ static PEP_STATUS read_fields(message *msg, clist *fieldlist) { struct mailimf_address_list *mal = _field->fld_data.fld_to->to_addr_list; - identity_list *il = mal_to_identity_list(mal); + identity_list *il = mal ? mal_to_identity_list(mal) : new_identity_list(NULL); if (il == NULL) goto enomem; diff --git a/src/key_reset.c b/src/key_reset.c index 1c1139f0..0ee936df 100644 --- a/src/key_reset.c +++ b/src/key_reset.c @@ -24,21 +24,6 @@ #define KEY_RESET_MAJOR_VERSION 1L #define KEY_RESET_MINOR_VERSION 0L -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] *msg message - * - */ -static void _add_auto_consume(message* msg) { - add_opt_field(msg, "pEp-auto-consume", "yes"); - msg->in_reply_to = stringlist_add(msg->in_reply_to, "pEp-auto-consume@pEp.foundation"); -} - /** * @internal * @@ -1364,6 +1349,13 @@ DYNAMIC_API PEP_STATUS key_reset_own_grouped_keys(PEP_SESSION session) { for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) { identity_list* key_idents = NULL; const char* own_key = curr_key->value; + + // If the sticky bit is set, ignore this beast + bool is_sticky = false; + status = get_key_sticky_bit_for_user(session, user_id, own_key, &is_sticky); + if (is_sticky) + continue; + status = get_identities_by_main_key_id(session, own_key, &key_idents); if (status == PEP_CANNOT_FIND_IDENTITY) { diff --git a/src/keymanagement.c b/src/keymanagement.c index 688d7cac..bcc8d953 100644 --- a/src/keymanagement.c +++ b/src/keymanagement.c @@ -2112,6 +2112,58 @@ DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **key return _own_keys_retrieve(session, keylist, 0, true); } + +PEP_STATUS update_key_sticky_bit_for_user(PEP_SESSION session, + pEp_identity* ident, + const char* fpr, + bool sticky) { + if (!session || !ident || EMPTYSTR(ident->user_id) || EMPTYSTR(fpr)) + return PEP_ILLEGAL_VALUE; + + sqlite3_reset(session->update_key_sticky_bit_for_user); + sqlite3_bind_int(session->update_key_sticky_bit_for_user, 1, sticky); + sqlite3_bind_text(session->update_key_sticky_bit_for_user, 2, ident->user_id, -1, + SQLITE_STATIC); + sqlite3_bind_text(session->update_key_sticky_bit_for_user, 3, fpr, -1, + SQLITE_STATIC); + int result = sqlite3_step(session->update_key_sticky_bit_for_user); + sqlite3_reset(session->update_key_sticky_bit_for_user); + if (result != SQLITE_DONE) { + return PEP_CANNOT_SET_TRUST; + } + + return PEP_STATUS_OK; + +} + +PEP_STATUS get_key_sticky_bit_for_user(PEP_SESSION session, + const char* user_id, + const char* fpr, + bool* is_sticky) { + + PEP_STATUS status = PEP_STATUS_OK; + if (!session || !is_sticky || EMPTYSTR(user_id) || EMPTYSTR(fpr)) + return PEP_ILLEGAL_VALUE; + + sqlite3_reset(session->is_key_sticky_for_user); + sqlite3_bind_text(session->is_key_sticky_for_user, 1, user_id, -1, + SQLITE_STATIC); + sqlite3_bind_text(session->is_key_sticky_for_user, 2, fpr, -1, + SQLITE_STATIC); + + int result = sqlite3_step(session->is_key_sticky_for_user); + switch (result) { + case SQLITE_ROW: { + *is_sticky = sqlite3_column_int(session->is_key_sticky_for_user, 0); + break; + } + default: + status = PEP_KEY_NOT_FOUND; + } + + return status; +} + // Returns PASSPHRASE errors when necessary DYNAMIC_API PEP_STATUS set_own_key( PEP_SESSION session, @@ -2136,7 +2188,7 @@ DYNAMIC_API PEP_STATUS set_own_key( // renew if needed, but do not generate status = _myself(session, me, false, true, true, false); - // we do not need a valid key but dislike other errors + // Pass through invalidity errors, and reject other errors if (status != PEP_STATUS_OK && status != PEP_GET_KEY_FAILED && status != PEP_KEY_UNSUITABLE) return status; status = PEP_STATUS_OK; @@ -2169,6 +2221,41 @@ DYNAMIC_API PEP_STATUS set_own_key( return status; } +// This differs from set_own_key because it can set a manually-imported bit in the trust DB +// and tests to see if the key will encrypt +DYNAMIC_API PEP_STATUS set_own_imported_key( + PEP_SESSION session, + pEp_identity* me, + const char* fpr, + bool sticky) { + + PEP_STATUS status = PEP_STATUS_OK; + + assert(session && me); + assert(!EMPTYSTR(fpr)); + assert(!EMPTYSTR(me->address)); + assert(!EMPTYSTR(me->user_id)); + assert(!EMPTYSTR(me->username)); + + if (!session || !me || EMPTYSTR(fpr) || EMPTYSTR(me->address) || + EMPTYSTR(me->user_id) || EMPTYSTR(me->username)) + return PEP_ILLEGAL_VALUE; + + // Last, but not least, be sure we can encrypt with it + status = probe_encrypt(session, fpr); + if (status) + return status; + + status = set_own_key(session, me, fpr); + if (status != PEP_STATUS_OK) + return status; + + status = update_key_sticky_bit_for_user(session, me, fpr, sticky); + + return status; +} + + PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr, bool *has_private) { diff --git a/src/keymanagement.h b/src/keymanagement.h index 710a5a91..c3e4fb99 100644 --- a/src/keymanagement.h +++ b/src/keymanagement.h @@ -519,6 +519,59 @@ DYNAMIC_API PEP_STATUS set_own_key( const char *fpr ); +/** + * + * + * @brief Mark a key as an own default key, test to be sure the private key is + * present and can be used, and set or unset the sticky bit as indicated by the boolean + * value. The sticky bit is intended to tell the engine to not automatically remove this + * key as a default through protocols like sync, for example. + * + * @param[in] session session to use + * @param[in,out] me own identity this key is used for + * @param[in] fpr fingerprint of the key to mark as own key + * @param[in] sticky boolean, true if we should set a sticky bit so + * it will not be automatically reset by sync and should + * win sync key elections if no other competing key + * for the same identity has its sticky bit set, + * false otherwise + * + * @warning the key has to be in the key ring already + * me->address, me->user_id and me->username must be set to valid data + * myself() is called by set_own_key() from within this call without key generation + * me->flags are ignored + * me->address must not be an alias + * me->fpr will be ignored and replaced by fpr, but + * caller MUST surrender ownership of the me->fpr reference, because + * it may be freed and replaced within the myself call. caller owns + * me->fpr memory again upon return. + * CAN GENERATE A PASSPHRASE REQUEST + * + */ +DYNAMIC_API PEP_STATUS set_own_imported_key( + PEP_SESSION session, + pEp_identity* me, + const char* fpr, + bool sticky + ); + +// +// clean_own_key_defaults() +// +// Remove any broken, unrenewable expired, or revoked +// own keys from identity and user defaults in the database. +// +// parameters: +// session (in) session to use +// +// return value: +// PEP_STATUS_OK if all went well +// PEP_PASSPHRASE_REQUIRED if a key needs to be renewed +// but cached passphrase isn't present +// PEP_WRONG_PASSPHRASE if passphrase required for expired key renewal +// but passphrase is the wrong one +// Otherwise, database and keyring errors as appropriate +// /** * * @@ -648,6 +701,23 @@ PEP_STATUS get_valid_pubkey(PEP_SESSION session, bool* is_address_default, bool check_blacklist); +/** + * + * + * @brief Get value of sticky bit for this user and key + * + * @param[in] session PEP_SESSION + * @param[in] user_id user_id of key owner to get the sticky bit for + * @param[in] fpr fingerprint of user's key to consider + * @param[out] is_sticky (by reference) true if sticky bit is set for this user and fpr, + * else false + * + */ +PEP_STATUS get_key_sticky_bit_for_user(PEP_SESSION session, + const char* user_id, + const char* fpr, + bool* is_sticky); + #ifdef __cplusplus } #endif diff --git a/src/message.c b/src/message.c index d35a5963..40a9420d 100644 --- a/src/message.c +++ b/src/message.c @@ -57,8 +57,6 @@ DYNAMIC_API void free_message(message *msg) DYNAMIC_API message * message_dup(const message *src) { message * msg = NULL; - pEp_identity * from = NULL; - identity_list * to = NULL; assert(src); @@ -202,14 +200,7 @@ DYNAMIC_API message * message_dup(const message *src) return msg; enomem: - if (msg) { - free_message(msg); - } - else { - free_identity(from); - free_identity_list(to); - } - + free_message(msg); return NULL; } diff --git a/src/message_api.c b/src/message_api.c index c3a1c462..400261a9 100644 --- a/src/message_api.c +++ b/src/message_api.c @@ -1282,7 +1282,7 @@ static message* wrap_message_as_attachment(message* envelope, else { _envelope->longmsg = strdup( "This message was encrypted with p≡p (https://pep.software). If you are seeing this message,\n" - "your client does not support raising message attachments. Please click on the message attachment to\n" + "your client does not support raising message attachments. Please click on the message attachment\n" "to view it, or better yet, consider using p≡p!\n" ); } @@ -2413,24 +2413,6 @@ static void update_encryption_format(identity_list* id_list, PEP_enc_format* enc } } -DYNAMIC_API PEP_STATUS probe_encrypt(PEP_SESSION session, const char *fpr) -{ - assert(session); - if (!session || EMPTYSTR(fpr)) - return PEP_ILLEGAL_VALUE; - - stringlist_t *keylist = new_stringlist(fpr); - if (!keylist) - return PEP_OUT_OF_MEMORY; - - char *ctext = NULL; - size_t csize = 0; - PEP_STATUS status = encrypt_and_sign(session, keylist, "pEp", 4, &ctext, &csize); - free(ctext); - - return status; -} - /** * @internal * @@ -2803,9 +2785,13 @@ DYNAMIC_API PEP_STATUS encrypt_message( else { // hide subject if (enc_format != PEP_enc_inline && enc_format != PEP_enc_inline_EA) { - status = replace_subject(_src); - if (status == PEP_OUT_OF_MEMORY) - goto enomem; + // do not replace subject if message format 1.x and unencrypted + // subject is enabled + if (!(wrap_type == PEP_message_unwrapped && session->unencrypted_subject)) { + status = replace_subject(_src); + if (status == PEP_OUT_OF_MEMORY) + goto enomem; + } } if (!(flags & PEP_encrypt_flag_force_no_attached_key)) added_key_to_real_src = true; diff --git a/src/message_api.h b/src/message_api.h index 8bb9b456..78801e49 100644 --- a/src/message_api.h +++ b/src/message_api.h @@ -728,22 +728,6 @@ PEP_STATUS try_encrypt_message( PEP_encrypt_flags_t flags ); -/** - * - * - * @brief Test if passphrase for a key is working in current session - * - * @param[in] session session handle - * @param[in] fpr fingerprint of key to test - * - * @retval PEP_STATUS_OK in case passphrase works - * @retval PEP_ILLEGAL_VALUE illegal parameter values - * @retval PEP_OUT_OF_MEMORY out of memory - * @retval any other value on error - * - */ - -DYNAMIC_API PEP_STATUS probe_encrypt(PEP_SESSION session, const char *fpr); #ifdef __cplusplus } diff --git a/src/pEpEngine.c b/src/pEpEngine.c index 547640bd..12391b73 100644 --- a/src/pEpEngine.c +++ b/src/pEpEngine.c @@ -10,6 +10,7 @@ #include "transport.h" #include "blacklist.h" #include "KeySync_fsm.h" +#include "engine_sql.h" #include #include @@ -20,2553 +21,75 @@ static volatile int init_count = -1; -// sql overloaded functions - modified from sqlite3.c -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] *ctx sqlite3_context - * @param[in] argc int - * @param[in] **argv sqlite3_value - * - */ -static void _sql_lower(sqlite3_context* ctx, int argc, sqlite3_value** argv) { - const char *z2; - int n; - z2 = (char*)sqlite3_value_text(argv[0]); - n = sqlite3_value_bytes(argv[0]); - /* Verify that the call to _bytes() does not invalidate the _text() pointer */ - assert( z2==(char*)sqlite3_value_text(argv[0]) ); - if( z2 ){ - char *z1 = (char*)sqlite3_malloc(n+1); - if( z1 ){ - for(int i=0; i 0x7a) - c_mod = c; - z1[i] = c_mod; - } - z1[n] = '\0'; - sqlite3_result_text(ctx, z1, n, sqlite3_free); - } - } -} - -#ifdef _PEP_SQLITE_DEBUG -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] trace_constant unsigned - * @param[in] *context_ptr void - * @param[in] *P void - * @param[in] *X void - * - */ -int sql_trace_callback (unsigned trace_constant, - void* context_ptr, - void* P, - void* X) { - switch (trace_constant) { - case SQLITE_TRACE_STMT: - fprintf(stderr, "SQL_DEBUG: STMT - "); - const char* X_str = (const char*) X; - if (!EMPTYSTR(X_str) && X_str[0] == '-' && X_str[1] == '-') - fprintf(stderr, "%s\n", X_str); - else - fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P)); - break; - case SQLITE_TRACE_ROW: - fprintf(stderr, "SQL_DEBUG: ROW - "); - fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P)); - break; - case SQLITE_TRACE_CLOSE: - fprintf(stderr, "SQL_DEBUG: CLOSE - "); - break; - default: - break; - } - return 0; -} -#endif - -// sql manipulation statements -static const char *sql_log = - "insert into log (title, entity, description, comment)" - "values (?1, ?2, ?3, ?4);"; - -static const char *sql_trustword = - "select id, word from wordlist where lang = lower(?1) " - "and id = ?2 ;"; - -// FIXME?: problems if we don't have a key for the user - we get nothing -static const char *sql_get_identity = - "select identity.main_key_id, username, comm_type, lang," - " identity.flags | pgp_keypair.flags," - " is_own, pEp_version_major, pEp_version_minor, enc_format" - " from identity" - " join person on id = identity.user_id" - " left join pgp_keypair on fpr = identity.main_key_id" - " left join trust on id = trust.user_id" - " and pgp_keypair_fpr = identity.main_key_id" - " where (case when (address = ?1) then (1)" - " when (lower(address) = lower(?1)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" - " else 0" - " end) = 1" - " and identity.user_id = ?2" - " order by is_own desc, " - " timestamp desc; "; - -static const char *sql_get_identities_by_main_key_id = - "select address, identity.user_id, username, comm_type, lang," - " identity.flags | pgp_keypair.flags," - " is_own, pEp_version_major, pEp_version_minor, enc_format" - " from identity" - " join person on id = identity.user_id" - " left join pgp_keypair on fpr = identity.main_key_id" - " left join trust on id = trust.user_id" - " and pgp_keypair_fpr = identity.main_key_id" - " where identity.main_key_id = ?1" - " order by is_own desc, " - " timestamp desc; "; - -static const char *sql_get_identity_without_trust_check = - "select identity.main_key_id, username, lang," - " identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format" - " from identity" - " join person on id = identity.user_id" - " where (case when (address = ?1) then (1)" - " when (lower(address) = lower(?1)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" - " else 0" - " end) = 1" - " and identity.user_id = ?2 " - " order by is_own desc, " - " timestamp desc; "; - -static const char *sql_get_identities_by_address = - "select user_id, identity.main_key_id, username, lang," - " identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format" - " from identity" - " join person on id = identity.user_id" - " where (case when (address = ?1) then (1)" - " when (lower(address) = lower(?1)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" - " else 0" - " end) = 1 " - " order by is_own desc, " - " timestamp desc; "; - -static const char *sql_get_identities_by_userid = - "select address, identity.main_key_id, username, comm_type, lang," - " identity.flags | pgp_keypair.flags," - " is_own, pEp_version_major, pEp_version_minor, enc_format" - " from identity" - " join person on id = identity.user_id" - " left join pgp_keypair on fpr = identity.main_key_id" - " left join trust on id = trust.user_id" - " and pgp_keypair_fpr = identity.main_key_id" - " where identity.user_id = ?1" - " order by is_own desc, " - " timestamp desc; "; - -static const char *sql_replace_identities_fpr = - "update identity" - " set main_key_id = ?1 " - " where main_key_id = ?2 ;"; - -static const char *sql_remove_fpr_as_identity_default = - "update identity set main_key_id = NULL where main_key_id = ?1 ;"; - -static const char *sql_remove_fpr_as_user_default = - "update person set main_key_id = NULL where main_key_id = ?1 ;"; - -// Set person, but if already exist, only update. -// if main_key_id already set, don't touch. -static const char *sql_set_person = - "insert into person (id, username, lang, main_key_id)" - " values (?1, ?2, ?3, ?4) ;"; - -static const char *sql_update_person = - "update person " - " set username = ?2, " - " lang = ?3, " - " main_key_id = " - " (select coalesce( " - " (select main_key_id from person where id = ?1), " - " upper(replace(?4,' ',''))))" - " where id = ?1 ;"; - -// Will cascade. -static const char *sql_delete_person = - "delete from person where id = ?1 ;"; - -static const char *sql_set_as_pEp_user = - "update person set is_pEp_user = 1 " - " where id = ?1 ; "; - -static const char *sql_is_pEp_user = - "select is_pEp_user from person " - " where id = ?1 ; "; - -static const char* sql_exists_person = - "select count(*) from person " - " where id = ?1 ;"; - -// This will cascade to identity and trust -static const char* sql_replace_userid = - "update person set id = ?1 " - " where id = ?2;"; - -// Hopefully this cascades and removes trust entries... -static const char *sql_delete_key = - "delete from pgp_keypair " - " where fpr = ?1 ; "; - -static const char *sql_replace_main_user_fpr = - "update person " - " set main_key_id = ?1 " - " where id = ?2 ;"; - -static const char *sql_get_main_user_fpr = - "select main_key_id from person" - " where id = ?1 ;"; - -static const char *sql_replace_main_user_fpr_if_equal = - "update person " - " set main_key_id = ?1 " - " where id = ?2 and main_key_id = ?3;"; - -static const char *sql_refresh_userid_default_key = - "update person " - " set main_key_id = " - " (select identity.main_key_id from identity " - " join trust on trust.user_id = identity.user_id " - " and trust.pgp_keypair_fpr = identity.main_key_id " - " join person on person.id = identity.user_id " - " where identity.user_id = ?1 " - " order by trust.comm_type desc " - " limit 1) " - "where id = ?1 ; "; - -static const char *sql_set_pgp_keypair = - "insert or ignore into pgp_keypair (fpr) " - "values (upper(replace(?1,' ',''))) ;"; - -static const char* sql_exists_identity_entry = - "select count(*) from identity " - " where (case when (address = ?1) then (1)" - " when (lower(address) = lower(?1)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" - " else 0" - " end) = 1" - " and user_id = ?2;"; - -static const char *sql_set_identity_entry = - "insert into identity (" - " address, main_key_id, " - " user_id, flags, is_own," - " pEp_version_major, pEp_version_minor" - " ) values (" - " ?1," - " upper(replace(?2,' ',''))," - " ?3," - " ?4," - " ?5," - " ?6," - " ?7" - " );"; - -static const char* sql_update_identity_entry = - "update identity " - " set main_key_id = upper(replace(?2,' ','')), " - " flags = ?4, " - " is_own = ?5, " - " pEp_version_major = ?6, " - " pEp_version_minor = ?7 " - " where (case when (address = ?1) then (1)" - " when (lower(address) = lower(?1)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1) " - " else 0 " - " end) = 1 " - " and user_id = ?3 ;"; - - // " (select" - // " coalesce(" - // " (select flags from identity" - // " where address = ?1 and" - // " user_id = ?3)," - // " 0)" - // " ) | (?4 & 255)" - /* set_identity ignores previous flags, and doesn't filter machine flags */ - -static const char *sql_set_identity_flags = - "update identity set flags = " - " ((?1 & 65535) | (select flags from identity" - " where (case when (address = ?2) then (1)" - " when (lower(address) = lower(?2)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" - " else 0 " - " end) = 1 " - " and user_id = ?3)) " - " where (case when (address = ?2) then (1)" - " when (lower(address) = lower(?2)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" - " else 0" - " end) = 1" - " and user_id = ?3 ;"; - -static const char *sql_unset_identity_flags = - "update identity set flags = " - " ( ~(?1 & 65535) & (select flags from identity" - " where (case when (address = ?2) then (1)" - " when (lower(address) = lower(?2)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" - " else 0 " - " end) = 1 " - " and user_id = ?3)) " - " where (case when (address = ?2) then (1)" - " when (lower(address) = lower(?2)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)" - " else 0" - " end) = 1" - " and user_id = ?3 ;"; - -static const char *sql_set_ident_enc_format = - "update identity " - " set enc_format = ?1 " - " where (case when (address = ?2) then (1)" - " when (lower(address) = lower(?2)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1) " - " else 0 " - " end) = 1 " - " and user_id = ?3 ;"; - -static const char *sql_set_pEp_version = - "update identity " - " set pEp_version_major = ?1, " - " pEp_version_minor = ?2 " - " where (case when (address = ?3) then (1)" - " when (lower(address) = lower(?3)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?3),'.','')) then (1) " - " else 0 " - " end) = 1 " - " and user_id = ?4 ;"; - -static const char *sql_upgrade_pEp_version_by_user_id = - "update identity " - " set pEp_version_major = ?1, " - " pEp_version_minor = ?2 " - " where user_id = ?3 " - " and (case when (pEp_version_major < ?1) then (1)" - " when (pEp_version_major > ?1) then (0)" - " when (pEp_version_minor < ?2) then (1)" - " else 0 " - " end) = 1 ;"; - -static const char *sql_set_trust = - "insert into trust (user_id, pgp_keypair_fpr, comm_type) " - "values (?1, upper(replace(?2,' ','')), ?3) ;"; - -static const char *sql_update_trust = - "update trust set comm_type = ?3 " - " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; - -static const char *sql_clear_trust_info = - "delete from trust " - " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; - -static const char *sql_update_trust_to_pEp = - "update trust set comm_type = comm_type + 71 " - " where (user_id = ?1 " - " and (case when (comm_type = 56) then (1) " - " when (comm_type = 184) then (1) " - " else 0" - " end) = 1); "; - -static const char* sql_exists_trust_entry = - "select count(*) from trust " - " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; - -static const char *sql_update_trust_for_fpr = - "update trust " - "set comm_type = ?1 " - "where pgp_keypair_fpr = upper(replace(?2,' ','')) ;"; - -static const char *sql_get_trust = - "select comm_type from trust where user_id = ?1 " - "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;"; - -static const char *sql_get_trust_by_userid = - "select pgp_keypair_fpr, comm_type from trust where user_id = ?1 "; - -static const char *sql_least_trust = - "select min(comm_type) from trust where" - " pgp_keypair_fpr = upper(replace(?1,' ',''))" - " and comm_type != 0;"; // ignores PEP_ct_unknown - // returns PEP_ct_unknown only when no known trust is recorded - -static const char *sql_mark_as_compromised = - "update trust not indexed set comm_type = 15" - " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_crashdump = - "select timestamp, title, entity, description, comment" - " from log order by timestamp desc limit ?1 ;"; - -static const char *sql_languagelist = - "select i18n_language.lang, name, phrase" - " from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ; - -static const char *sql_i18n_token = - "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;"; - -// blacklist -static const char *sql_blacklist_add = - "insert or ignore into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;" - "delete from identity where main_key_id = upper(replace(?1,' ','')) ;" - "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_blacklist_delete = - "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_blacklist_is_listed = - "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_blacklist_retrieve = - "select * from blacklist_keys ;"; - - -// Own keys -// We only care if it's 0 or non-zero -static const char *sql_own_key_is_listed = - "select count(*) from (" - " select pgp_keypair_fpr from trust" - " join identity on trust.user_id = identity.user_id" - " where pgp_keypair_fpr = upper(replace(?1,' ',''))" - " and identity.is_own = 1" - ");"; - -static const char *sql_is_own_address = - "select count(*) from (" - " select address from identity" - " where (case when (address = ?1) then (1)" - " when (lower(address) = lower(?1)) then (1)" - " when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)" - " else 0" - " end) = 1 " - " and identity.is_own = 1" - ");"; - -static const char *sql_own_identities_retrieve = - "select address, identity.main_key_id, identity.user_id, username," - " lang, identity.flags | pgp_keypair.flags, pEp_version_major, pEp_version_minor" - " from identity" - " join person on id = identity.user_id" - " left join pgp_keypair on fpr = identity.main_key_id" - " left join trust on id = trust.user_id" - " and pgp_keypair_fpr = identity.main_key_id" - " where identity.is_own = 1" - " and (identity.flags & ?1) = 0;"; - -static const char *sql_own_keys_retrieve = - "select distinct pgp_keypair_fpr from trust" - " join identity on trust.user_id = identity.user_id" - " where identity.is_own = 1"; - -static const char* sql_get_user_default_key = - "select main_key_id from person" - " where id = ?1;"; - -static const char* sql_get_all_keys_for_user = - "select pgp_keypair_fpr from trust" - " where user_id = ?1; "; - -static const char* sql_get_default_own_userid = - "select id from person" - " join identity on id = identity.user_id" - " where identity.is_own = 1"; - -// Sequence -static const char *sql_sequence_value1 = - "insert or replace into sequences (name, value) " - "values (?1, " - " (select coalesce((select value + 1 from sequences " - " where name = ?1), 1 ))); "; - -static const char *sql_sequence_value2 = - "select value from sequences where name = ?1 ;"; - -// Revocation tracking -static const char *sql_set_revoked = - "insert or replace into revoked_keys (" - " revoked_fpr, replacement_fpr, revocation_date) " - "values (upper(replace(?1,' ',''))," - " upper(replace(?2,' ',''))," - " ?3) ;"; - -static const char *sql_get_revoked = - "select revoked_fpr, revocation_date from revoked_keys" - " where replacement_fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_get_replacement_fpr = - "select replacement_fpr, revocation_date from revoked_keys" - " where revoked_fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_get_userid_alias_default = - "select default_id from alternate_user_id " - " where alternate_id = ?1 ; "; - -// Revocation tracking -static const char *sql_add_mistrusted_key = - "insert or replace into mistrusted_keys (fpr) " - " values (upper(replace(?1,' ',''))) ;"; - -static const char *sql_delete_mistrusted_key = - "delete from mistrusted_keys where fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_is_mistrusted_key = - "select count(*) from mistrusted_keys where fpr = upper(replace(?1,' ','')) ;"; - -static const char *sql_add_userid_alias = - "insert or replace into alternate_user_id (alternate_id, default_id) " - "values (?2, ?1) ;"; - -static const char *sql_add_into_social_graph = - "insert or replace into social_graph(own_userid, own_address, contact_userid) " - "values (?1, ?2, ?3) ;"; - -static const char *sql_get_own_address_binding_from_contact = - "select own_address from social_graph where own_userid = ?1 and contact_userid = ?2 ;"; - -static const char *sql_set_revoke_contact_as_notified = - "insert or replace into revocation_contact_list(fpr, own_address, contact_id) values (?1, ?2, ?3) ;"; - -static const char *sql_get_contacted_ids_from_revoke_fpr = - "select * from revocation_contact_list where fpr = ?1 ;"; - -static const char *sql_was_id_for_revoke_contacted = - "select count(*) from revocation_contact_list where fpr = ?1 and own_address = ?2 and contact_id = ?3 ;"; - -static const char *sql_has_id_contacted_address = - "select count(*) from social_graph where own_address = ?1 and contact_userid = ?2 ;"; - -// We only need user_id and address, since in the main usage, we'll call update_identity -// on this anyway when sending out messages. -static const char *sql_get_last_contacted = - "select user_id, address from identity where datetime('now') < datetime(timestamp, '+14 days') ; "; - -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] *_version void - * @param[in] count int - * @param[in] **text char - * @param[in] **name char - * - */ -static int user_version(void *_version, int count, char **text, char **name) -{ - if (!(_version && count == 1 && text && text[0])) - return -1; - - int *version = (int *) _version; - *version = atoi(text[0]); - return 0; -} - -// TODO: refactor and generalise these two functions if possible. -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] session session handle - * @param[in] *table_name constchar - * - */ -static int db_contains_table(PEP_SESSION session, const char* table_name) { - if (!session || !table_name) - return -1; - - // Table names can't be SQL parameters, so we do it this way. - - // these two must be the same number. - char sql_buf[500]; - const size_t max_q_len = 500; - - size_t t_size, q_size; - - const char* q1 = "SELECT name FROM sqlite_master WHERE type='table' AND name='{"; // 61 - const char* q2 = "}';"; // 3 - - q_size = 64; - t_size = strlen(table_name); - - size_t query_len = q_size + t_size + 1; - - if (query_len > max_q_len) - return -1; - - strlcpy(sql_buf, q1, max_q_len); - strlcat(sql_buf, table_name, max_q_len); - strlcat(sql_buf, q2, max_q_len); - - sqlite3_stmt *stmt; - - sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL); - - int retval = 0; - - int rc = sqlite3_step(stmt); - if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) { - retval = 1; - } - - sqlite3_finalize(stmt); - - return retval; - -} - -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] session session handle - * @param[in] *table_name constchar - * @param[in] *col_name constchar - * - */ -static int table_contains_column(PEP_SESSION session, const char* table_name, - const char* col_name) { - - - if (!session || !table_name || !col_name) - return -1; - - // Table names can't be SQL parameters, so we do it this way. - - // these two must be the same number. - char sql_buf[500]; - const size_t max_q_len = 500; - - size_t t_size, c_size, q_size; - - const char* q1 = "SELECT "; // 7 - const char* q2 = " from "; // 6 - const char* q3 = ";"; // 1 - - q_size = 14; - t_size = strlen(table_name); - c_size = strlen(col_name); - - size_t query_len = q_size + c_size + t_size + 1; - - if (query_len > max_q_len) - return -1; - - strlcpy(sql_buf, q1, max_q_len); - strlcat(sql_buf, col_name, max_q_len); - strlcat(sql_buf, q2, max_q_len); - strlcat(sql_buf, table_name, max_q_len); - strlcat(sql_buf, q3, max_q_len); - - sqlite3_stmt *stmt; - - sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL); - - int retval = 0; - - int rc = sqlite3_step(stmt); - if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) { - retval = 1; - } - - sqlite3_finalize(stmt); - - return retval; -} - -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] session session handle - * - */ -#define _PEP_MAX_AFFECTED 5 -PEP_STATUS repair_altered_tables(PEP_SESSION session) { - PEP_STATUS status = PEP_STATUS_OK; - - char* table_names[_PEP_MAX_AFFECTED] = {0}; - - const char* sql_query = "select tbl_name from sqlite_master WHERE sql LIKE '%REFERENCES%' AND sql LIKE '%_old%';"; - sqlite3_stmt *stmt; - sqlite3_prepare_v2(session->db, sql_query, -1, &stmt, NULL); - int i = 0; - int int_result = 0; - while ((int_result = sqlite3_step(stmt)) == SQLITE_ROW && i < _PEP_MAX_AFFECTED) { - table_names[i++] = strdup((const char*)(sqlite3_column_text(stmt, 0))); - } - - sqlite3_finalize(stmt); - - if ((int_result != SQLITE_DONE && int_result != SQLITE_OK) || i > (_PEP_MAX_AFFECTED + 1)) { - status = PEP_UNKNOWN_DB_ERROR; - goto pEp_free; - } - - for (i = 0; i < _PEP_MAX_AFFECTED; i++) { - const char* table_name = table_names[i]; - if (!table_name) - break; - - if (strcmp(table_name, "identity") == 0) { - int_result = sqlite3_exec(session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _identity_new (\n" - " address text,\n" - " user_id text\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " main_key_id text\n" - " references pgp_keypair (fpr)\n" - " on delete set null,\n" - " comment text,\n" - " flags integer default 0,\n" - " is_own integer default 0,\n" - " timestamp integer default (datetime('now')),\n" - " primary key (address, user_id)\n" - ");\n" - "INSERT INTO _identity_new SELECT * from identity;\n" - "DROP TABLE identity;\n" - "ALTER TABLE _identity_new RENAME TO identity;\n" - "COMMIT;\n" - "PRAGMA foreign_keys=on;" - , - NULL, - NULL, - NULL - ); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - } - else if (strcmp(table_name, "trust") == 0) { - int_result = sqlite3_exec(session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _trust_new (\n" - " user_id text not null\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " pgp_keypair_fpr text not null\n" - " references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " comm_type integer not null,\n" - " comment text,\n" - " primary key (user_id, pgp_keypair_fpr)\n" - ");\n" - "INSERT INTO _trust_new SELECT * from trust;\n" - "DROP TABLE trust;\n" - "ALTER TABLE _trust_new RENAME TO trust;\n" - "COMMIT;\n" - "PRAGMA foreign_keys=on;" - , - NULL, - NULL, - NULL - ); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - } - else if (strcmp(table_name, "alternate_user_id") == 0) { - int_result = sqlite3_exec(session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _alternate_user_id_new (\n" - " default_id text references person (id)\n" - " on delete cascade on update cascade,\n" - " alternate_id text primary key\n" - ");\n" - "INSERT INTO _alternate_user_id_new SELECT * from alternate_user_id;\n" - "DROP TABLE alternate_user_id;\n" - "ALTER TABLE _alternate_user_id_new RENAME TO alternate_user_id;\n" - "COMMIT;\n" - "PRAGMA foreign_keys=on;" - , - NULL, - NULL, - NULL - ); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - } - else if (strcmp(table_name, "revocation_contact_list") == 0) { - int_result = sqlite3_exec(session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _revocation_contact_list_new (\n" - " fpr text not null references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " contact_id text not null references person (id)\n" - " on delete cascade on update cascade,\n" - " timestamp integer default (datetime('now')),\n" - " PRIMARY KEY(fpr, contact_id)\n" - ");\n" - "INSERT INTO _revocation_contact_list_new SELECT * from revocation_contact_list;\n" - "DROP TABLE revocation_contact_list;\n" - "ALTER TABLE _revocation_contact_list_new RENAME TO revocation_contact_list;\n" - "COMMIT;\n" - "PRAGMA foreign_keys=on;" - , - NULL, - NULL, - NULL - ); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - } - else if (strcmp(table_name, "social_graph")) { - int_result = sqlite3_exec(session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _social_new (\n" - " own_userid text,\n" - " own_address text,\n" - " contact_userid text,\n" - " CONSTRAINT fk_own_identity\n" - " FOREIGN KEY(own_address, own_userid)\n" - " REFERENCES identity(address, user_id)\n" - " ON DELETE CASCADE ON UPDATE CASCADE\n" - ");\n" - "INSERT INTO _social_graph_new SELECT * from social_graph;\n" - "DROP TABLE social_graph;\n" - "ALTER TABLE _social_graph_new RENAME TO social_graph;\n" - "COMMIT;\n" - "PRAGMA foreign_keys=on;" - , - NULL, - NULL, - NULL - ); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - } - } - - int_result = sqlite3_exec( - session->db, - "PRAGMA foreign_key_check;\n" - , - NULL, - NULL, - NULL - ); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - -pEp_free: - for (i = 0; i < _PEP_MAX_AFFECTED; i++) { - free(table_names[i]); - } - return status; -} -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] *pArg void - * @param[in] iErrCode int - * @param[in] *zMsg constchar - * - */ -void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){ - fprintf(stderr, "(%d) %s\n", iErrCode, zMsg); -} - -/** - * @internal - * - * - * - * @brief TODO - * - * @param[in] session session handle - * - */ -static PEP_STATUS upgrade_revoc_contact_to_13(PEP_SESSION session) { - // I HATE SQLITE. - PEP_STATUS status = PEP_STATUS_OK; - int int_result = 0; - - // Ok, first we ADD the column so we can USE it. - // We will end up propagating the "error" this first time - // (one-to-one revoke-replace relationships), but since key reset - // hasn't been used in production, this is not a customer-facing - // issue. - - // Note: the check upfront is to deal with partially-upgraded DB issues - if (!table_contains_column(session, "revocation_contact_list", "own_address")) { - int_result = sqlite3_exec( - session->db, - "alter table revocation_contact_list\n" - " add column own_address text;\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - - // the best we can do here is search per address, since these - // are no longer associated with an identity. For now, if we find - // something we can't add an address to, we'll delete the record. - // this should not, in the current environment, ever happen, but - // since we need to make the address part of the primary key, it's - // the right thing to do. sqlite does support null fields in a primary - // key for a weird version compatibility reason, but that doesn't - // mean we should use it, and we should be *safe*, not relying - // on an implementation-specific quirk which might be sanely removed - // in a future sqlite version. - - identity_list* id_list = NULL; - - sqlite3_stmt* tmp_own_id_retrieve = NULL; - sqlite3_prepare_v2(session->db, sql_own_identities_retrieve, -1, &tmp_own_id_retrieve, NULL); - - // Kludgey - put the stmt in temporarily, and then remove again, so less code dup. - // FIXME LATER: refactor if possible, but... chicken and egg, and thiis case rarely happens. - session->own_identities_retrieve = tmp_own_id_retrieve; - status = own_identities_retrieve(session, &id_list); - sqlite3_finalize(tmp_own_id_retrieve); - session->own_identities_retrieve = NULL; - - if (!status || !id_list) - return PEP_STATUS_OK; // it's empty AFAIK (FIXME) - - identity_list* curr_own = id_list; - - sqlite3_stmt* update_revoked_w_addr_stmt = NULL; - const char* sql_query = "update revocation_contact_list set own_address = ?1 where fpr = ?2;"; - sqlite3_prepare_v2(session->db, sql_query, -1, &update_revoked_w_addr_stmt, NULL); - - // Ok, go through and find any keys associated with this address - for ( ; curr_own && curr_own->ident; curr_own = curr_own->next) { - if (EMPTYSTR(curr_own->ident->address)) // shouldn't happen - continue; - stringlist_t* keylist = NULL; - status = find_keys(session, curr_own->ident->address, &keylist); - stringlist_t* curr_key = keylist; - for ( ; curr_key && curr_key->value; curr_key = curr_key->next) { - if (EMPTYSTR(curr_key->value)) - continue; - - // We just do this lazily - if this isn't a revoked key, it - // won't do anything. - sqlite3_bind_text(update_revoked_w_addr_stmt, 1, curr_own->ident->address, -1, - SQLITE_STATIC); - sqlite3_bind_text(update_revoked_w_addr_stmt, 2, curr_key->value, -1, - SQLITE_STATIC); - - int_result = sqlite3_step(update_revoked_w_addr_stmt); - assert(int_result == SQLITE_DONE); - - sqlite3_reset(update_revoked_w_addr_stmt); - - if (int_result != SQLITE_DONE) - return PEP_UNKNOWN_DB_ERROR; - - } - } - sqlite3_finalize(update_revoked_w_addr_stmt); - - int_result = sqlite3_exec( - session->db, - "delete from revocation_contact_list where own_address is NULL;\n" - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table if not exists _revocation_contact_list_new (\n" - " fpr text not null references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " own_address text,\n" - " contact_id text not null references person (id)\n" - " on delete cascade on update cascade,\n" - " timestamp integer default (datetime('now')),\n" - " PRIMARY KEY(fpr, own_address, contact_id)\n" - ");\n" - "INSERT INTO _revocation_contact_list_new (fpr, " - " own_address, " - " contact_id) " - " SELECT revocation_contact_list.fpr, " - " revocation_contact_list.own_address, " - " revocation_contact_list.contact_id " - " FROM revocation_contact_list " - " WHERE 1;\n" - "DROP TABLE revocation_contact_list;\n" - "ALTER TABLE _revocation_contact_list_new RENAME TO revocation_contact_list;\n" - "COMMIT;\n" - "\n" - "PRAGMA foreign_keys=on;\n" - , - NULL, - NULL, - NULL - ); - - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - return status; -} - -DYNAMIC_API PEP_STATUS init( - PEP_SESSION *session, - messageToSend_t messageToSend, - inject_sync_event_t inject_sync_event, - ensure_passphrase_t ensure_passphrase - ) -{ - PEP_STATUS status = PEP_STATUS_OK; - int int_result; - - bool in_first = false; - bool very_first = false; - - assert(sqlite3_threadsafe()); - if (!sqlite3_threadsafe()) - return PEP_INIT_SQLITE3_WITHOUT_MUTEX; - - // a little race condition - but still a race condition - // mitigated by calling caveat (see documentation) - - // this increment is made atomic IN THE ADAPTERS by - // guarding the call to init with the appropriate mutex. - int _count = ++init_count; - if (_count == 0) - in_first = true; - - // Race condition mitigated by calling caveat starts here : - // If another call to init() preempts right now, then preemptive call - // will have in_first false, will not create SQL tables, and following - // calls relying on those tables will fail. - // - // Therefore, as above, adapters MUST guard init() with a mutex. - // - // Therefore, first session - // is to be created and last session to be deleted alone, and not - // concurently to other sessions creation or deletion. - // We expect adapters to enforce this either by implicitely creating a - // client session, or by using synchronization primitive to protect - // creation/deletion of first/last session from the app. - - if (session == NULL) - return PEP_ILLEGAL_VALUE; - - *session = NULL; - - pEpSession *_session = calloc(1, sizeof(pEpSession)); - assert(_session); - if (_session == NULL) - goto enomem; - - _session->version = PEP_ENGINE_VERSION; - _session->messageToSend = messageToSend; - _session->inject_sync_event = inject_sync_event; - _session->ensure_passphrase = ensure_passphrase; - - assert(LOCAL_DB); - if (LOCAL_DB == NULL) { - status = PEP_INIT_CANNOT_OPEN_DB; - goto pEp_error; - } - -#ifdef _PEP_SQLITE_DEBUG - sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, NULL); -#endif - - int_result = sqlite3_open_v2( - LOCAL_DB, - &_session->db, - SQLITE_OPEN_READWRITE - | SQLITE_OPEN_CREATE - | SQLITE_OPEN_FULLMUTEX - | SQLITE_OPEN_PRIVATECACHE, - NULL - ); - - if (int_result != SQLITE_OK) { - status = PEP_INIT_CANNOT_OPEN_DB; - goto pEp_error; - } - - int_result = sqlite3_exec( - _session->db, - "PRAGMA locking_mode=NORMAL;\n" - "PRAGMA journal_mode=WAL;\n", - NULL, - NULL, - NULL - ); - - - sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME); - -#ifdef _PEP_SQLITE_DEBUG - sqlite3_trace_v2(_session->db, - SQLITE_TRACE_STMT | SQLITE_TRACE_ROW | SQLITE_TRACE_CLOSE, - sql_trace_callback, - NULL); -#endif - - assert(SYSTEM_DB); - if (SYSTEM_DB == NULL) { - status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB; - goto pEp_error; - } - - int_result = sqlite3_open_v2( - SYSTEM_DB, &_session->system_db, - SQLITE_OPEN_READONLY - | SQLITE_OPEN_FULLMUTEX - | SQLITE_OPEN_SHAREDCACHE, - NULL - ); - - if (int_result != SQLITE_OK) { - status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB; - goto pEp_error; - } - - sqlite3_busy_timeout(_session->system_db, 1000); - -// increment this when patching DDL -#define _DDL_USER_VERSION "14" - - if (in_first) { - - int_result = sqlite3_exec( - _session->db, - "create table if not exists version_info (\n" - " id integer primary key,\n" - " timestamp integer default (datetime('now')),\n" - " version text,\n" - " comment text\n" - ");\n", - NULL, - NULL, - NULL - ); - int_result = sqlite3_exec( - _session->db, - "PRAGMA application_id = 0x23423423;\n" - "create table if not exists log (\n" - " timestamp integer default (datetime('now')),\n" - " title text not null,\n" - " description text,\n" - " entity text not null,\n" - " comment text\n" - ");\n" - "create index if not exists log_timestamp on log (\n" - " timestamp\n" - ");\n" - "create table if not exists pgp_keypair (\n" - " fpr text primary key,\n" - " created integer,\n" - " expires integer,\n" - " comment text,\n" - " flags integer default 0\n" - ");\n" - "create index if not exists pgp_keypair_expires on pgp_keypair (\n" - " expires\n" - ");\n" - "create table if not exists person (\n" - " id text primary key,\n" - " username text not null,\n" - " main_key_id text\n" - " references pgp_keypair (fpr)\n" - " on delete set null,\n" - " lang text,\n" - " comment text,\n" -// " device_group text,\n" - " is_pEp_user integer default 0\n" - ");\n" - "create table if not exists identity (\n" - " address text,\n" - " user_id text\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " main_key_id text\n" - " references pgp_keypair (fpr)\n" - " on delete set null,\n" - " comment text,\n" - " flags integer default 0,\n" - " is_own integer default 0,\n" - " pEp_version_major integer default 0,\n" - " pEp_version_minor integer default 0,\n" - " enc_format integer default 0,\n" - " timestamp integer default (datetime('now')),\n" - " primary key (address, user_id)\n" - ");\n" - "create index if not exists identity_userid_addr on identity(address, user_id);\n" - "create table if not exists trust (\n" - " user_id text not null\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " pgp_keypair_fpr text not null\n" - " references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " comm_type integer not null,\n" - " comment text,\n" - " primary key (user_id, pgp_keypair_fpr)\n" - ");\n" - // blacklist - "create table if not exists blacklist_keys (\n" - " fpr text primary key\n" - ");\n" - // sequences - "create table if not exists sequences(\n" - " name text primary key,\n" - " value integer default 0\n" - ");\n" - "create table if not exists revoked_keys (\n" - " revoked_fpr text primary key,\n" - " replacement_fpr text not null\n" - " references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " revocation_date integer\n" - ");\n" - // user id aliases - "create table if not exists alternate_user_id (\n" - " default_id text references person (id)\n" - " on delete cascade on update cascade,\n" - " alternate_id text primary key\n" - ");\n" - // mistrusted keys - "create table if not exists mistrusted_keys (\n" - " fpr text primary key\n" - ");\n" - // social graph for key resets - "create table if not exists social_graph (\n" - " own_userid text,\n" - " own_address text,\n" - " contact_userid text,\n" - " CONSTRAINT fk_own_identity\n" - " FOREIGN KEY(own_address, own_userid)\n" - " REFERENCES identity(address, user_id)\n" - " ON DELETE CASCADE ON UPDATE CASCADE\n" - ");\n" - // list of user_ids sent revocation - "create table if not exists revocation_contact_list (\n" - " fpr text not null references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " own_address text,\n" - " contact_id text not null references person (id)\n" - " on delete cascade on update cascade,\n" - " timestamp integer default (datetime('now')),\n" - " PRIMARY KEY(fpr, own_address, contact_id)\n" - ");\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int version; - int_result = sqlite3_exec( - _session->db, - "pragma user_version;", - user_version, - &version, - NULL - ); - - assert(int_result == SQLITE_OK); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - void (*xFunc_lower)(sqlite3_context*,int,sqlite3_value**) = &_sql_lower; - - int_result = sqlite3_create_function_v2( - _session->db, - "lower", - 1, - SQLITE_UTF8 | SQLITE_DETERMINISTIC, - NULL, - xFunc_lower, - NULL, - NULL, - NULL); - - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_exec( - _session->db, - "pragma foreign_keys=ON;\n", - NULL, - NULL, - NULL - ); - - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - if (version > atoi(_DDL_USER_VERSION)) { - // This is *explicitly* not allowed. - return PEP_INIT_DB_DOWNGRADE_VIOLATION; - } - - // Sometimes the user_version wasn't set correctly. - if (version == 1) { - bool version_changed = true; - if (table_contains_column(_session, "identity", "enc_format")) { - version = 14; - } - else if (table_contains_column(_session, "revocation_contact_list", "own_address")) { - version = 13; - } - else if (table_contains_column(_session, "identity", "pEp_version_major")) { - version = 12; - } - else if (db_contains_table(_session, "social_graph") > 0) { - if (!table_contains_column(_session, "person", "device_group")) - version = 10; - else - version = 9; - } - else if (table_contains_column(_session, "identity", "timestamp") > 0) { - version = 8; - } - else if (table_contains_column(_session, "person", "is_pEp_user") > 0) { - version = 7; - } - else if (table_contains_column(_session, "identity", "is_own") > 0) { - version = 6; - } - else if (table_contains_column(_session, "pgp_keypair", "flags") > 0) { - version = 2; - } - else { - version_changed = false; - } - - if (version_changed) { - // set it in the DB, finally. Yeesh. - char verbuf[21]; // enough digits for a max-sized 64 bit int, cmon. - sprintf(verbuf,"%d",version); - - size_t query_size = strlen(verbuf) + 25; - char* query = calloc(query_size, 1); - - strlcpy(query, "pragma user_version = ", query_size); - strlcat(query, verbuf, query_size); - strlcat(query, ";", query_size); - - int_result = sqlite3_exec( - _session->db, - query, - user_version, - &version, - NULL - ); - free(query); - } - } - - - if(version != 0) { - // Version has been already set - - // Early mistake : version 0 shouldn't have existed. - // Numbering should have started at 1 to detect newly created DB. - // Version 0 DBs are not anymore compatible. - - // // Was version 0 compat code. - // if (version < 1) { - // int_result = sqlite3_exec( - // _session->db, - // "alter table identity\n" - // " add column flags integer default 0;\n", - // NULL, - // NULL, - // NULL - // ); - // assert(int_result == SQLITE_OK); - // } - - if (version < 2) { - // N.B. addition of device_group column removed in DDL v10 - int_result = sqlite3_exec( - _session->db, - "alter table pgp_keypair\n" - " add column flags integer default 0;\n", - // "alter table person\n" - // " add column device_group text;\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - - if (version < 5) { - int_result = sqlite3_exec( - _session->db, - "delete from pgp_keypair where fpr = '';", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - int_result = sqlite3_exec( - _session->db, - "delete from trust where pgp_keypair_fpr = '';", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - - if (version < 6) { - int_result = sqlite3_exec( - _session->db, - "alter table identity\n" - " add column is_own integer default 0;\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - int_result = sqlite3_exec( - _session->db, - "update identity\n" - " set is_own = 1\n" - " where (user_id = '" PEP_OWN_USERID "');\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - // Turns out that just adding "on update cascade" in - // sqlite is a PITA. We need to be able to cascade - // person->id replacements (for temp ids like "TOFU_") - // so here we go... - int_result = sqlite3_exec( - _session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _identity_new (\n" - " address text,\n" - " user_id text\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " main_key_id text\n" - " references pgp_keypair (fpr)\n" - " on delete set null,\n" - " comment text,\n" - " flags integer default 0,\n" - " is_own integer default 0,\n" - " primary key (address, user_id)\n" - ");\n" - "INSERT INTO _identity_new SELECT * FROM identity;\n" - "DROP TABLE identity;\n" - "ALTER TABLE _identity_new RENAME TO identity;\n" - "COMMIT;\n" - "\n" - "BEGIN TRANSACTION;\n" - "create table _trust_new (\n" - " user_id text not null\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " pgp_keypair_fpr text not null\n" - " references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " comm_type integer not null,\n" - " comment text,\n" - " primary key (user_id, pgp_keypair_fpr)\n" - ");\n" - "INSERT INTO _trust_new SELECT * FROM trust;\n" - "DROP TABLE trust;\n" - "ALTER TABLE _trust_new RENAME TO trust;\n" - "COMMIT;\n" - "\n" - "PRAGMA foreign_keys=on;\n" - "create table if not exists alternate_user_id (\n" - " default_id text references person (id)\n" - " on delete cascade on update cascade,\n" - " alternate_id text primary key\n" - ");\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_exec( - _session->db, - "PRAGMA foreign_key_check;\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - // FIXME: foreign key check here - } - if (version < 7) { - int_result = sqlite3_exec( - _session->db, - "alter table person\n" - " add column is_pEp_user integer default 0;\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - int_result = sqlite3_exec( - _session->db, - "update person\n" - " set is_pEp_user = 1\n" - " where id = " - " (select distinct id from person " - " join trust on id = user_id " - " where (case when (comm_type = 127) then (id) " - " when (comm_type = 255) then (id) " - " else 0" - " end) = id );\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_exec( - _session->db, - "create table if not exists mistrusted_keys (\n" - " fpr text primary key\n" - ");\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - if (version < 8) { - int_result = sqlite3_exec( - _session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _identity_new (\n" - " address text,\n" - " user_id text\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " main_key_id text\n" - " references pgp_keypair (fpr)\n" - " on delete set null,\n" - " comment text,\n" - " flags integer default 0,\n" - " is_own integer default 0,\n" - " timestamp integer default (datetime('now')),\n" - " primary key (address, user_id)\n" - ");\n" - "INSERT INTO _identity_new (address, user_id, main_key_id, " - " comment, flags, is_own) " - " SELECT identity.address, identity.user_id, " - " identity.main_key_id, identity.comment, " - " identity.flags, identity.is_own " - " FROM identity " - " WHERE 1;\n" - "DROP TABLE identity;\n" - "ALTER TABLE _identity_new RENAME TO identity;\n" - "COMMIT;\n" - "\n" - "PRAGMA foreign_keys=on;\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_exec( - _session->db, - "PRAGMA foreign_key_check;\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - // FIXME: foreign key check - } - if (version < 9) { - int_result = sqlite3_exec( - _session->db, - "create table if not exists social_graph (\n" - " own_userid text,\n" - " own_address text,\n" - " contact_userid text,\n" - " CONSTRAINT fk_own_identity\n" - " FOREIGN KEY(own_address, own_userid)\n" - " REFERENCES identity(address, user_id)\n" - " ON DELETE CASCADE ON UPDATE CASCADE\n" - ");\n" - "create table if not exists revocation_contact_list (\n" - " fpr text not null references pgp_keypair (fpr)\n" - " on delete cascade,\n" - " contact_id text not null references person (id)\n" - " on delete cascade on update cascade,\n" - " timestamp integer default (datetime('now')),\n" - " PRIMARY KEY(fpr, contact_id)\n" - ");\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - if (version < 10 && version > 1) { - int_result = sqlite3_exec( - _session->db, - "PRAGMA foreign_keys=off;\n" - "BEGIN TRANSACTION;\n" - "create table _person_new (\n" - " id text primary key,\n" - " username text not null,\n" - " main_key_id text\n" - " references pgp_keypair (fpr)\n" - " on delete set null,\n" - " lang text,\n" - " comment text,\n" - " is_pEp_user integer default 0\n" - ");\n" - "INSERT INTO _person_new (id, username, main_key_id, " - " lang, comment, is_pEp_user) " - " SELECT person.id, person.username, " - " person.main_key_id, person.lang, " - " person.comment, person.is_pEp_user " - " FROM person " - " WHERE 1;\n" - "DROP TABLE person;\n" - "ALTER TABLE _person_new RENAME TO person;\n" - "COMMIT;\n" - "\n" - "PRAGMA foreign_keys=on;\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - int_result = sqlite3_exec( - _session->db, - "PRAGMA foreign_key_check;\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - if (version < 11) { - status = repair_altered_tables(_session); - assert(status == PEP_STATUS_OK); - if (status != PEP_STATUS_OK) - return status; - } - if (version < 12) { - int_result = sqlite3_exec( - _session->db, - "create index if not exists identity_userid_addr on identity(address, user_id);\n" - , - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_exec( - _session->db, - "alter table identity\n" - " add column pEp_version_major integer default 0;\n" - "alter table identity\n" - " add column pEp_version_minor integer default 0;\n", - NULL, - NULL, - NULL - ); - if (status != PEP_STATUS_OK) - return status; - - int_result = sqlite3_exec( - _session->db, - "update identity\n" - " set pEp_version_major = 2\n" - " where exists (select * from person\n" - " where identity.user_id = person.id\n" - " and identity.is_own = 0\n" - " and person.is_pEp_user = 1);\n", - NULL, - NULL, - NULL - ); - if (status != PEP_STATUS_OK) - return status; - - // N.B. WE DEFINE PEP_VERSION - IF WE'RE AT 9-DIGIT MAJOR OR MINOR VERSIONS, ER, BAD. - char major_buf[10]; - char minor_buf[10]; - - // Guess we were abusing sscanf here, so we'll do it this way: - const char* cptr = PEP_VERSION; - size_t major_len = 0; - size_t minor_len = 0; - - char* bufptr = major_buf; - while (*cptr != '.' && *cptr != '\0') { - *bufptr++ = *cptr++; - major_len++; - } - *bufptr = '\0'; - bufptr = minor_buf; - - if (*cptr == '.') { - cptr++; - while (*cptr != '\0') { - *bufptr++ = *cptr++; - minor_len++; - } - } - else { - *bufptr++ = '0'; - } - *bufptr = '\0'; - - const char* _ver_12_startstr = - "update identity\n" - " set pEp_version_major = "; - const char* _ver_12_midstr = ",\n" - " pEp_version_minor = "; - const char* _ver_12_endstr = - "\n" - " where identity.is_own = 1;\n"; - - size_t new_stringlen = strlen(_ver_12_startstr) + major_len + - strlen(_ver_12_midstr) + minor_len + - strlen(_ver_12_endstr); - - char* _ver_12_stmt = calloc(new_stringlen + 1, 1); - snprintf(_ver_12_stmt, new_stringlen + 1, "%s%s%s%s%s", - _ver_12_startstr, major_buf, _ver_12_midstr, minor_buf, _ver_12_endstr); - - int_result = sqlite3_exec( - _session->db, - _ver_12_stmt, - NULL, - NULL, - NULL - ); - free(_ver_12_stmt); - if (status != PEP_STATUS_OK) - return status; - } - if (version < 13) { - status = upgrade_revoc_contact_to_13(_session); - assert(status == PEP_STATUS_OK); - if (status != PEP_STATUS_OK) - return status; - } - if (version < 14) { - int_result = sqlite3_exec( - _session->db, - "alter table identity\n" - " add column enc_format integer default 0;\n", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - - } - else { - // Version from DB was 0, it means this is initial setup. - // DB has just been created, and all tables are empty. - very_first = true; - } - - if (version < atoi(_DDL_USER_VERSION)) { - int_result = sqlite3_exec( - _session->db, - "pragma user_version = "_DDL_USER_VERSION";\n" - "insert or replace into version_info (id, version)" - "values (1, '" PEP_ENGINE_VERSION "');", - NULL, - NULL, - NULL - ); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - } - - // We need to init a few globals for message id that we'd rather not - // calculate more than once. - _init_globals(); - } - - int_result = sqlite3_prepare_v2(_session->db, sql_log, - (int)strlen(sql_log), &_session->log, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword, - (int)strlen(sql_trustword), &_session->trustword, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_identity, - (int)strlen(sql_get_identity), &_session->get_identity, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_identity_without_trust_check, - (int)strlen(sql_get_identity_without_trust_check), - &_session->get_identity_without_trust_check, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_identities_by_address, - (int)strlen(sql_get_identities_by_address), - &_session->get_identities_by_address, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_identities_by_userid, - (int)strlen(sql_get_identities_by_userid), - &_session->get_identities_by_userid, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_identities_by_main_key_id, - (int)strlen(sql_get_identities_by_main_key_id), - &_session->get_identities_by_main_key_id, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_user_default_key, - (int)strlen(sql_get_user_default_key), &_session->get_user_default_key, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_all_keys_for_user, - (int)strlen(sql_get_all_keys_for_user), &_session->get_all_keys_for_user, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_default_own_userid, - (int)strlen(sql_get_default_own_userid), &_session->get_default_own_userid, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_userid_alias_default, - (int)strlen(sql_get_userid_alias_default), &_session->get_userid_alias_default, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_add_userid_alias, - (int)strlen(sql_add_userid_alias), &_session->add_userid_alias, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_replace_userid, - (int)strlen(sql_replace_userid), &_session->replace_userid, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_delete_key, - (int)strlen(sql_delete_key), &_session->delete_key, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_replace_main_user_fpr, - (int)strlen(sql_replace_main_user_fpr), &_session->replace_main_user_fpr, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_replace_main_user_fpr_if_equal, - (int)strlen(sql_replace_main_user_fpr_if_equal), &_session->replace_main_user_fpr_if_equal, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_main_user_fpr, - (int)strlen(sql_get_main_user_fpr), &_session->get_main_user_fpr, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_refresh_userid_default_key, - (int)strlen(sql_refresh_userid_default_key), &_session->refresh_userid_default_key, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr, - (int)strlen(sql_replace_identities_fpr), - &_session->replace_identities_fpr, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_identity_default, - (int)strlen(sql_remove_fpr_as_identity_default), - &_session->remove_fpr_as_identity_default, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_user_default, - (int)strlen(sql_remove_fpr_as_user_default), - &_session->remove_fpr_as_user_default, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_person, - (int)strlen(sql_set_person), &_session->set_person, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_update_person, - (int)strlen(sql_update_person), &_session->update_person, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_delete_person, - (int)strlen(sql_delete_person), &_session->delete_person, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_exists_person, - (int)strlen(sql_exists_person), &_session->exists_person, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_as_pEp_user, - (int)strlen(sql_set_as_pEp_user), &_session->set_as_pEp_user, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_is_pEp_user, - (int)strlen(sql_is_pEp_user), &_session->is_pEp_user, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_add_into_social_graph, - (int)strlen(sql_add_into_social_graph), &_session->add_into_social_graph, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_get_own_address_binding_from_contact, - (int)strlen(sql_get_own_address_binding_from_contact), - &_session->get_own_address_binding_from_contact, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_set_revoke_contact_as_notified, - (int)strlen(sql_set_revoke_contact_as_notified), - &_session->set_revoke_contact_as_notified, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_get_contacted_ids_from_revoke_fpr, - (int)strlen(sql_get_contacted_ids_from_revoke_fpr), - &_session->get_contacted_ids_from_revoke_fpr, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_was_id_for_revoke_contacted, - (int)strlen(sql_was_id_for_revoke_contacted), - &_session->was_id_for_revoke_contacted, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_has_id_contacted_address, - (int)strlen(sql_has_id_contacted_address), - &_session->has_id_contacted_address, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_get_last_contacted, - (int)strlen(sql_get_last_contacted), - &_session->get_last_contacted, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, - sql_get_own_address_binding_from_contact, - (int)strlen(sql_get_own_address_binding_from_contact), - &_session->get_own_address_binding_from_contact, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair, - (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_entry, - (int)strlen(sql_set_identity_entry), &_session->set_identity_entry, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_update_identity_entry, - (int)strlen(sql_update_identity_entry), &_session->update_identity_entry, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_exists_identity_entry, - (int)strlen(sql_exists_identity_entry), &_session->exists_identity_entry, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags, - (int)strlen(sql_set_identity_flags), &_session->set_identity_flags, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_unset_identity_flags, - (int)strlen(sql_unset_identity_flags), &_session->unset_identity_flags, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_ident_enc_format, - (int)strlen(sql_set_ident_enc_format), &_session->set_ident_enc_format, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_pEp_version, - (int)strlen(sql_set_pEp_version), &_session->set_pEp_version, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_upgrade_pEp_version_by_user_id, - (int)strlen(sql_upgrade_pEp_version_by_user_id), &_session->upgrade_pEp_version_by_user_id, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_clear_trust_info, - (int)strlen(sql_clear_trust_info), &_session->clear_trust_info, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_set_trust, - (int)strlen(sql_set_trust), &_session->set_trust, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_update_trust, - (int)strlen(sql_update_trust), &_session->update_trust, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_update_trust_to_pEp, - (int)strlen(sql_update_trust_to_pEp), &_session->update_trust_to_pEp, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_exists_trust_entry, - (int)strlen(sql_exists_trust_entry), &_session->exists_trust_entry, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_update_trust_for_fpr, - (int)strlen(sql_update_trust_for_fpr), &_session->update_trust_for_fpr, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_trust, - (int)strlen(sql_get_trust), &_session->get_trust, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_trust_by_userid, - (int)strlen(sql_get_trust_by_userid), &_session->get_trust_by_userid, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_least_trust, - (int)strlen(sql_least_trust), &_session->least_trust, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromised, - (int)strlen(sql_mark_as_compromised), &_session->mark_compromised, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_crashdump, - (int)strlen(sql_crashdump), &_session->crashdump, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist, - (int)strlen(sql_languagelist), &_session->languagelist, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token, - (int)strlen(sql_i18n_token), &_session->i18n_token, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - // blacklist - - int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add, - (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete, - (int)strlen(sql_blacklist_delete), &_session->blacklist_delete, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed, - (int)strlen(sql_blacklist_is_listed), - &_session->blacklist_is_listed, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - +DYNAMIC_API PEP_STATUS init( + PEP_SESSION *session, + messageToSend_t messageToSend, + inject_sync_event_t inject_sync_event, + ensure_passphrase_t ensure_passphrase + ) +{ + PEP_STATUS status = PEP_STATUS_OK; - int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve, - (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve, - NULL); - assert(int_result == SQLITE_OK); + bool in_first = false; - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; + assert(sqlite3_threadsafe()); + if (!sqlite3_threadsafe()) + return PEP_INIT_SQLITE3_WITHOUT_MUTEX; + // a little race condition - but still a race condition + // mitigated by calling caveat (see documentation) - // Own keys + // this increment is made atomic IN THE ADAPTERS by + // guarding the call to init with the appropriate mutex. + int _count = ++init_count; + if (_count == 0) + in_first = true; - int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed, - (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_is_own_address, - (int)strlen(sql_is_own_address), &_session->is_own_address, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_own_identities_retrieve, - (int)strlen(sql_own_identities_retrieve), - &_session->own_identities_retrieve, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_own_keys_retrieve, - (int)strlen(sql_own_keys_retrieve), - &_session->own_keys_retrieve, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - // int_result = sqlite3_prepare_v2(_session->db, sql_set_own_key, - // (int)strlen(sql_set_own_key), - // &_session->set_own_key, NULL); - // assert(int_result == SQLITE_OK); - - - // Sequence - - int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1, - (int)strlen(sql_sequence_value1), &_session->sequence_value1, - NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - + // Race condition mitigated by calling caveat starts here : + // If another call to init() preempts right now, then preemptive call + // will have in_first false, will not create SQL tables, and following + // calls relying on those tables will fail. + // + // Therefore, as above, adapters MUST guard init() with a mutex. + // + // Therefore, first session + // is to be created and last session to be deleted alone, and not + // concurently to other sessions creation or deletion. + // We expect adapters to enforce this either by implicitely creating a + // client session, or by using synchronization primitive to protect + // creation/deletion of first/last session from the app. - int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2, - (int)strlen(sql_sequence_value2), &_session->sequence_value2, - NULL); - assert(int_result == SQLITE_OK); + if (session == NULL) + return PEP_ILLEGAL_VALUE; - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; + *session = NULL; + pEpSession *_session = calloc(1, sizeof(pEpSession)); + assert(_session); + if (_session == NULL) + goto enomem; - // Revocation tracking + _session->version = PEP_ENGINE_VERSION; + _session->messageToSend = messageToSend; + _session->inject_sync_event = inject_sync_event; + _session->ensure_passphrase = ensure_passphrase; - int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked, - (int)strlen(sql_set_revoked), &_session->set_revoked, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked, - (int)strlen(sql_get_revoked), &_session->get_revoked, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_get_replacement_fpr, - (int)strlen(sql_get_replacement_fpr), &_session->get_replacement_fpr, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_add_mistrusted_key, - (int)strlen(sql_add_mistrusted_key), &_session->add_mistrusted_key, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; - - - int_result = sqlite3_prepare_v2(_session->db, sql_delete_mistrusted_key, - (int)strlen(sql_delete_mistrusted_key), &_session->delete_mistrusted_key, NULL); - assert(int_result == SQLITE_OK); - - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; + status = init_databases(_session); + if (status != PEP_STATUS_OK) + return status; + if (in_first) { - int_result = sqlite3_prepare_v2(_session->db, sql_is_mistrusted_key, - (int)strlen(sql_is_mistrusted_key), &_session->is_mistrusted_key, NULL); - assert(int_result == SQLITE_OK); + status = pEp_sql_init(_session); - if (int_result != SQLITE_OK) - return PEP_UNKNOWN_DB_ERROR; + // We need to init a few globals for message id that we'd rather not + // calculate more than once. + _init_globals(); + } + status = pEp_prepare_sql_stmts(_session); + if (status != PEP_STATUS_OK) + goto pEp_error; status = init_cryptotech(_session, in_first); if (status != PEP_STATUS_OK) @@ -2623,151 +146,7 @@ DYNAMIC_API void release(PEP_SESSION session) free_Sync_state(session); if (session->db) { - if (session->log) - sqlite3_finalize(session->log); - if (session->trustword) - sqlite3_finalize(session->trustword); - if (session->get_identity) - sqlite3_finalize(session->get_identity); - if (session->get_identity_without_trust_check) - sqlite3_finalize(session->get_identity_without_trust_check); - if (session->get_identities_by_address) - sqlite3_finalize(session->get_identities_by_address); - if (session->get_identities_by_userid) - sqlite3_finalize(session->get_identities_by_userid); - if (session->get_identities_by_main_key_id) - sqlite3_finalize(session->get_identities_by_main_key_id); - if (session->get_user_default_key) - sqlite3_finalize(session->get_user_default_key); - if (session->get_all_keys_for_user) - sqlite3_finalize(session->get_all_keys_for_user); - if (session->get_default_own_userid) - sqlite3_finalize(session->get_default_own_userid); - if (session->get_userid_alias_default) - sqlite3_finalize(session->get_userid_alias_default); - if (session->add_userid_alias) - sqlite3_finalize(session->add_userid_alias); - if (session->replace_identities_fpr) - sqlite3_finalize(session->replace_identities_fpr); - if (session->remove_fpr_as_identity_default) - sqlite3_finalize(session->remove_fpr_as_identity_default); - if (session->remove_fpr_as_user_default) - sqlite3_finalize(session->remove_fpr_as_user_default); - if (session->set_person) - sqlite3_finalize(session->set_person); - if (session->delete_person) - sqlite3_finalize(session->delete_person); - if (session->set_as_pEp_user) - sqlite3_finalize(session->set_as_pEp_user); - if (session->upgrade_pEp_version_by_user_id) - sqlite3_finalize(session->upgrade_pEp_version_by_user_id); - if (session->is_pEp_user) - sqlite3_finalize(session->is_pEp_user); - if (session->exists_person) - sqlite3_finalize(session->exists_person); - if (session->add_into_social_graph) - sqlite3_finalize(session->add_into_social_graph); - if (session->get_own_address_binding_from_contact) - sqlite3_finalize(session->get_own_address_binding_from_contact); - if (session->set_revoke_contact_as_notified) - sqlite3_finalize(session->set_revoke_contact_as_notified); - if (session->get_contacted_ids_from_revoke_fpr) - sqlite3_finalize(session->get_contacted_ids_from_revoke_fpr); - if (session->was_id_for_revoke_contacted) - sqlite3_finalize(session->was_id_for_revoke_contacted); - if (session->has_id_contacted_address) - sqlite3_finalize(session->has_id_contacted_address); - if (session->get_last_contacted) - sqlite3_finalize(session->get_last_contacted); - if (session->set_pgp_keypair) - sqlite3_finalize(session->set_pgp_keypair); - if (session->exists_identity_entry) - sqlite3_finalize(session->exists_identity_entry); - if (session->set_identity_entry) - sqlite3_finalize(session->set_identity_entry); - if (session->update_identity_entry) - sqlite3_finalize(session->update_identity_entry); - if (session->set_identity_flags) - sqlite3_finalize(session->set_identity_flags); - if (session->unset_identity_flags) - sqlite3_finalize(session->unset_identity_flags); - if (session->set_ident_enc_format) - sqlite3_finalize(session->set_ident_enc_format); - if (session->set_pEp_version) - sqlite3_finalize(session->set_pEp_version); - if (session->exists_trust_entry) - sqlite3_finalize(session->exists_trust_entry); - if (session->clear_trust_info) - sqlite3_finalize(session->clear_trust_info); - if (session->set_trust) - sqlite3_finalize(session->set_trust); - if (session->update_trust) - sqlite3_finalize(session->update_trust); - if (session->update_trust_to_pEp) - sqlite3_finalize(session->update_trust_to_pEp); - if (session->update_trust_for_fpr) - sqlite3_finalize(session->update_trust_for_fpr); - if (session->get_trust) - sqlite3_finalize(session->get_trust); - if (session->get_trust_by_userid) - sqlite3_finalize(session->get_trust_by_userid); - if (session->least_trust) - sqlite3_finalize(session->least_trust); - if (session->mark_compromised) - sqlite3_finalize(session->mark_compromised); - if (session->crashdump) - sqlite3_finalize(session->crashdump); - if (session->languagelist) - sqlite3_finalize(session->languagelist); - if (session->i18n_token) - sqlite3_finalize(session->i18n_token); - if (session->replace_userid) - sqlite3_finalize(session->replace_userid); - if (session->delete_key) - sqlite3_finalize(session->delete_key); - if (session->replace_main_user_fpr) - sqlite3_finalize(session->replace_main_user_fpr); - if (session->replace_main_user_fpr_if_equal) - sqlite3_finalize(session->replace_main_user_fpr_if_equal); - if (session->get_main_user_fpr) - sqlite3_finalize(session->get_main_user_fpr); - if (session->refresh_userid_default_key) - sqlite3_finalize(session->refresh_userid_default_key); - if (session->blacklist_add) - sqlite3_finalize(session->blacklist_add); - if (session->blacklist_delete) - sqlite3_finalize(session->blacklist_delete); - if (session->blacklist_is_listed) - sqlite3_finalize(session->blacklist_is_listed); - if (session->blacklist_retrieve) - sqlite3_finalize(session->blacklist_retrieve); - if (session->own_key_is_listed) - sqlite3_finalize(session->own_key_is_listed); - if (session->is_own_address) - sqlite3_finalize(session->is_own_address); - if (session->own_identities_retrieve) - sqlite3_finalize(session->own_identities_retrieve); - if (session->own_keys_retrieve) - sqlite3_finalize(session->own_keys_retrieve); - // if (session->set_own_key) - // sqlite3_finalize(session->set_own_key); - if (session->sequence_value1) - sqlite3_finalize(session->sequence_value1); - if (session->sequence_value2) - sqlite3_finalize(session->sequence_value2); - if (session->set_revoked) - sqlite3_finalize(session->set_revoked); - if (session->get_revoked) - sqlite3_finalize(session->get_revoked); - if (session->get_replacement_fpr) - sqlite3_finalize(session->get_replacement_fpr); - if (session->add_mistrusted_key) - sqlite3_finalize(session->add_mistrusted_key); - if (session->delete_mistrusted_key) - sqlite3_finalize(session->delete_mistrusted_key); - if (session->is_mistrusted_key) - sqlite3_finalize(session->is_mistrusted_key); - + pEp_finalize_sql_stmts(session); if (session->db) { if (out_last) { sqlite3_exec( @@ -2846,6 +225,10 @@ DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable) session->service_log = enable; } +DYNAMIC_API const char* get_commit_hash() { + return PEP_CURRENT_COMMIT_HASH; +} + DYNAMIC_API PEP_STATUS log_event( PEP_SESSION session, const char *title, @@ -5319,6 +2702,23 @@ PEP_STATUS sign_only(PEP_SESSION session, } +DYNAMIC_API PEP_STATUS probe_encrypt(PEP_SESSION session, const char *fpr) +{ + assert(session); + if (!session || EMPTYSTR(fpr)) + return PEP_ILLEGAL_VALUE; + + stringlist_t *keylist = new_stringlist(fpr); + if (!keylist) + return PEP_OUT_OF_MEMORY; + + char *ctext = NULL; + size_t csize = 0; + PEP_STATUS status = encrypt_and_sign(session, keylist, "pEp", 4, &ctext, &csize); + free(ctext); + + return status; +} DYNAMIC_API PEP_STATUS verify_text( diff --git a/src/pEpEngine.h b/src/pEpEngine.h index 0e1c63a6..41623167 100644 --- a/src/pEpEngine.h +++ b/src/pEpEngine.h @@ -513,6 +513,31 @@ DYNAMIC_API PEP_STATUS encrypt_and_sign( size_t psize, char **ctext, size_t *csize ); +/** + * + * + * @brief Test if passphrase for a key is working in current session + * + * @param[in] session session handle + * @param[in] fpr fingerprint of key to test + * + * @retval PEP_STATUS_OK in case passphrase works + * @retval error if not + * + * + */ + +DYNAMIC_API PEP_STATUS probe_encrypt(PEP_SESSION session, const char *fpr); + +/** + * + * + * @brief Get the commit hash of this build + * + * @retval commit_hash string constant referring to the commit hash + * + */ +DYNAMIC_API const char* get_commit_hash(); /** * @@ -750,10 +775,10 @@ typedef enum _identity_flags { typedef unsigned int identity_flags_t; -// typedef enum _keypair_flags { -// } keypair_flags; - -typedef unsigned int keypair_flags_t; +//typedef enum _keypair_flags { +//} keypair_flags; +// +//typedef unsigned int keypair_flags_t; /** * @struct pEp_identity diff --git a/src/pEp_internal.h b/src/pEp_internal.h index 73f46ecc..a6384647 100644 --- a/src/pEp_internal.h +++ b/src/pEp_internal.h @@ -7,6 +7,16 @@ #ifndef PEP_INTERNAL_H #define PEP_INTERNAL_H +#if defined __has_include +# if __has_include ("commit_hash.h") +# include "commit_hash.h" +# else +# define PEP_CURRENT_COMMIT_HASH = "DUMMY_COMMIT_HASH_ERROR" +# endif +#else +# include "commit_hash.h" +#endif + // maximum attachment size to import as key 25MB, maximum of 20 attachments #define MAX_KEY_SIZE (25 * 1024 * 1024) #define MAX_KEYS_TO_IMPORT 20 @@ -106,6 +116,9 @@ #include "pgp_sequoia_internal.h" #endif +#include "../asn.1/Distribution.h" +#include "../asn.1/Sync.h" + #include "keymanagement.h" #include "cryptotech.h" #include "transport.h" @@ -195,6 +208,8 @@ struct _pEpSession { // sqlite3_stmt *set_device_group; // sqlite3_stmt *get_device_group; sqlite3_stmt *set_pgp_keypair; + sqlite3_stmt *set_pgp_keypair_flags; + sqlite3_stmt *unset_pgp_keypair_flags; sqlite3_stmt *set_identity_entry; sqlite3_stmt *update_identity_entry; sqlite3_stmt *exists_identity_entry; @@ -211,6 +226,8 @@ struct _pEpSession { sqlite3_stmt *get_trust; sqlite3_stmt *get_trust_by_userid; sqlite3_stmt *least_trust; + sqlite3_stmt *update_key_sticky_bit_for_user; + sqlite3_stmt *is_key_sticky_for_user; sqlite3_stmt *mark_compromised; sqlite3_stmt *reset_trust; sqlite3_stmt *crashdump; @@ -235,6 +252,26 @@ struct _pEpSession { sqlite3_stmt *get_default_own_userid; + // groups + sqlite3_stmt *create_group; + sqlite3_stmt *enable_group; + sqlite3_stmt *disable_group; + sqlite3_stmt *exists_group_entry; + sqlite3_stmt *group_add_member; + sqlite3_stmt *join_group; + sqlite3_stmt *leave_group; + sqlite3_stmt *set_group_member_status; + sqlite3_stmt *get_all_members; + sqlite3_stmt *get_active_members; + sqlite3_stmt *get_active_groups; + sqlite3_stmt *get_all_groups; + sqlite3_stmt *add_own_membership_entry; + sqlite3_stmt *get_own_membership_status; + sqlite3_stmt *retrieve_own_membership_info_for_group_and_ident; + sqlite3_stmt *retrieve_own_membership_info_for_group; + sqlite3_stmt *get_group_manager; + sqlite3_stmt *is_invited_group_member; + sqlite3_stmt *is_group_active; // sqlite3_stmt *set_own_key; @@ -734,16 +771,20 @@ extern double _pEp_log2_36; /** * - * + * + * @internal + * * @brief TODO * - * + * Please leave _patch_asn1_codec COMMENTED OUT unless you're working + * in a branch or patching the asn1 is a solution */ static inline void _init_globals() { _pEp_rand_max_bits = (int) ceil(log2((double) RAND_MAX)); _pEp_log2_36 = log2(36); } + // spinlock implementation /** @@ -763,4 +804,20 @@ static inline int Sqlite3_step(sqlite3_stmt* stmt) return rc; } +/** + * @internal + * + * + * + * @brief TODO + * + * @param[in] *msg message + * + */ +static inline void _add_auto_consume(message* msg) { + add_opt_field(msg, "pEp-auto-consume", "yes"); + msg->in_reply_to = stringlist_add(msg->in_reply_to, "pEp-auto-consume@pEp.foundation"); +} + + #endif diff --git a/src/sync_api.c b/src/sync_api.c index 2ca24c91..f03b2c25 100644 --- a/src/sync_api.c +++ b/src/sync_api.c @@ -378,3 +378,25 @@ DYNAMIC_API PEP_STATUS disable_identity_for_sync(PEP_SESSION session, status = key_reset_identity(session, ident, NULL); return status; } + +DYNAMIC_API PEP_STATUS disable_all_sync_channels(PEP_SESSION session) +{ + assert(session); + if (!session) + return PEP_ILLEGAL_VALUE; + + identity_list *own_identities = NULL; + PEP_STATUS status = own_identities_retrieve(session, &own_identities); + if (status) + return status; + + for (identity_list *oi = own_identities; oi && oi->ident; oi = oi->next) { + status = set_identity_flags(session, oi->ident, PEP_idf_not_for_sync); + if (status) + break; + } + + free_identity_list(own_identities); + return status; +} + diff --git a/src/sync_api.h b/src/sync_api.h index eaa34d3c..52f98b8a 100644 --- a/src/sync_api.h +++ b/src/sync_api.h @@ -306,6 +306,19 @@ DYNAMIC_API PEP_STATUS disable_identity_for_sync(PEP_SESSION session, pEp_identity *ident); +/** + * + * + * @brief Disable sync for all identities; use this function to reset + * the state which identities will be synced and which not + * This function is intended to be used at app init + * + * + */ + +DYNAMIC_API PEP_STATUS disable_all_sync_channels(PEP_SESSION session); + + #ifdef __cplusplus } #endif diff --git a/sync/cond_act_sync.yml2 b/sync/cond_act_sync.yml2 index 5f2cd58e..1ccc7549 100644 --- a/sync/cond_act_sync.yml2 +++ b/sync/cond_act_sync.yml2 @@ -603,6 +603,7 @@ action disable action resetOwnGroupedKeys || + // Will NOT reset keys with the sticky bit set return key_reset_own_grouped_keys(session); || diff --git a/sync/gen_messages.ysl2 b/sync/gen_messages.ysl2 index c2cce39f..a77ef886 100644 --- a/sync/gen_messages.ysl2 +++ b/sync/gen_messages.ysl2 @@ -48,7 +48,9 @@ tstylesheet { `` for "fsm" | IMPORTS «@name» FROM «yml:ucase(@name)»; «@name» ::= CHOICE { - `` for "fsm" |> «yml:lcase(@name)» [APPLICATION «@id»] «@name»`if "position()!=last()" > , ` + «yml:lcase(fsm[1]/@name)» [APPLICATION «fsm[1]/@id»] «fsm[1]/@name»`if "count(fsm)>1" > ,` + `` if "count(fsm)>1" |> ..., + `` for "fsm[position()>1]" |> «yml:lcase(@name)» [APPLICATION «@id»] «@name»`if "position()!=last()" > ,` } END diff --git a/sync/gen_statemachine.ysl2 b/sync/gen_statemachine.ysl2 index 26b7ca83..fea986e8 100644 --- a/sync/gen_statemachine.ysl2 +++ b/sync/gen_statemachine.ysl2 @@ -691,6 +691,10 @@ tstylesheet { message *_m = NULL; char *_data = NULL; + // FIX ENGINE-814: skip identities without key + if (EMPTYSTR(li->ident->fpr)) + continue; + _data = malloc(size); assert(_data); if (!_data) { @@ -714,7 +718,9 @@ tstylesheet { ); if (status) { free(_data); - goto the_end; + if (status == PEP_OUT_OF_MEMORY) + goto the_end; + continue; } attach_own_key(session, _m); decorate_message(session, _m, PEP_rating_undefined, NULL, true, true); @@ -725,10 +731,9 @@ tstylesheet { `` for "fsm/message[@security='untrusted' and ../@name='KeySync']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»: // add fpr of key of comm partner - assert(session->«yml:lcase(@name)»_state.transport.sender_fpr); if (!session->«yml:lcase(@name)»_state.transport.sender_fpr) { status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } extra = new_stringlist(session->«yml:lcase(@name)»_state.transport.sender_fpr); @@ -748,14 +753,18 @@ tstylesheet { &_m ); if (status) { + if (status == PEP_OUT_OF_MEMORY) + goto the_end; free(_data); - goto the_end; + continue; } status = try_encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0); if (status) { + if (status == PEP_OUT_OF_MEMORY) + goto the_end; status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } add_opt_field(m, "pEp-auto-consume", "yes"); m->in_reply_to = stringlist_add(m->in_reply_to, "pEp-auto-consume@pEp.foundation"); @@ -781,15 +790,12 @@ tstylesheet { // secret keys if (transaction) { - assert(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr && - session->«yml:lcase(@name)»_state.transport.from && - session->«yml:lcase(@name)»_state.transport.from->user_id); if (!(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr && session->«yml:lcase(@name)»_state.transport.from && session->«yml:lcase(@name)»_state.transport.from->user_id)) { status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } // test if this is a green channel @@ -812,7 +818,7 @@ tstylesheet { if (ident->comm_type != PEP_ct_pEp) { free_identity(ident); status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } free_identity(ident); @@ -825,10 +831,9 @@ tstylesheet { assert(!status); if (status) goto the_end; - assert(is_own_key); if (!is_own_key) { status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } // if so add key of comm partner to extra keys @@ -852,7 +857,9 @@ tstylesheet { ); if (status) { free(_data); - goto the_end; + if (status == PEP_OUT_OF_MEMORY) + goto the_end; + continue; } // export secret keys into memory @@ -935,8 +942,10 @@ tstylesheet { status = try_encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0); if (status) { + if (status == PEP_OUT_OF_MEMORY) + goto the_end; status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } add_opt_field(m, "pEp-auto-consume", "yes"); m->in_reply_to = stringlist_add(m->in_reply_to, "pEp-auto-consume@pEp.foundation"); @@ -957,7 +966,9 @@ tstylesheet { ); if (status) { free(_data); - goto the_end; + if (status == PEP_OUT_OF_MEMORY) + goto the_end; + continue; } // export secret keys into memory @@ -1041,8 +1052,10 @@ tstylesheet { // we do not support extra keys here and will only encrypt to ourselves status = try_encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0); if (status) { + if (status == PEP_OUT_OF_MEMORY) + goto the_end; status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + continue; } add_opt_field(m, "pEp-auto-consume", "yes"); m->in_reply_to = stringlist_add(m->in_reply_to, "pEp-auto-consume@pEp.foundation"); @@ -1062,13 +1075,17 @@ tstylesheet { ); if (status) { free(_data); - goto the_end; + if (status == PEP_OUT_OF_MEMORY) + goto the_end; + continue; } status = try_encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0); if (status) { status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT; - goto the_end; + if (status == PEP_OUT_OF_MEMORY) + goto the_end; + continue; } add_opt_field(m, "pEp-auto-consume", "yes"); m->in_reply_to = stringlist_add(m->in_reply_to, "pEp-auto-consume@pEp.foundation"); diff --git a/templates/commit_hash.h b/templates/commit_hash.h new file mode 100644 index 00000000..c41343b7 --- /dev/null +++ b/templates/commit_hash.h @@ -0,0 +1,7 @@ +#ifndef COMMIT_HASH_H +#define COMMIT_HASH_H + +#define PEP_CURRENT_COMMIT_HASH "DUMMY_COMMIT_HASH_ERROR" + +#endif + diff --git a/test/Makefile b/test/Makefile index fff580de..6a4068ce 100644 --- a/test/Makefile +++ b/test/Makefile @@ -26,15 +26,15 @@ ifeq ($(shell grep -c $(GTEST_SUITE_SYM) $(GTEST_SRC_DIR)/src/gtest.cc),0) GTEST_SUITE_SYM=test_case_name endif -CXXFLAGS+= -DGTEST_SUITE_SYM=$(GTEST_SUITE_SYM) +CPPFLAGS+= -DGTEST_SUITE_SYM=$(GTEST_SUITE_SYM) -ifeq ($(OPENPGP),GPG) - LDFLAGS+= $(GPGME_LIB) -else ifeq ($(OPENPGP),NETPGP) - LDFLAGS+= $(NETGPG_LIB) +ifdef PEP_MIME + LDLIBS+= -lpEpMIME +else + LDLIBS+= -letpan endif -LDLIBS+= -letpan -lpEpEngine -lstdc++ -lasn1 +LDLIBS+= -lpEpEngine -lstdc++ -lasn1 ifeq ($(BUILD_FOR),Linux) LDLIBS+= -luuid @@ -43,7 +43,8 @@ endif ifeq ($(OPENPGP),SEQUOIA) LDFLAGS+= $(SEQUOIA_LDFLAGS) LDLIBS+= $(SEQUOIA_LIB) - CXXFLAGS+= $(SEQUOIA_CFLAGS) -DUSE_SEQUOIA + CXXFLAGS+= $(SEQUOIA_CFLAGS) + CPPFLAGS+= -DUSE_SEQUOIA INC_FLAGS+= $(SEQUOIA_INC) endif @@ -51,35 +52,16 @@ ifdef SQLITE3_FROM_OS LDLIBS+= -lsqlite3 endif -ifeq ($(OPENPGP),GPG) - #LDLIBS+= -lgpgme -else ifeq ($(OPENPGP),NETPGP) - LDLIBS+= -lnetpgp - ifeq ($(BUILD_FOR),Linux) - LDLIBS+= -ltre - endif -endif - -CXXFLAGS:=-I$(GTEST_INC_DIR) $(filter-out -DNDEBUG,$(CXXFLAGS)) +CXXFLAGS:=$(filter-out -DNDEBUG,$(CXXFLAGS)) -I$(GTEST_INC_DIR) +CPPFLAGS:=$(filter-out -DNDEBUG,$(CPPFLAGS)) -# FIXME Possibly missing incdirs: ASN1C_INC -CXXFLAGS+= -I./src -I../sync $(INC_FLAGS) -Wno-deprecated -Wno-unused-variable - -ifeq ($(OPENPGP),GPG) - CXXFLAGS+= -DUSE_GPG $(GPGME_INC) -else ifeq ($(OPENPGP),NETPGP) - CXXFLAGS+= -DUSE_NETPGP $(NETPGP_INC) -endif +CXXFLAGS+= -I./src -I../src -I ../asn.1 -I../sync $(INC_FLAGS) -Wno-deprecated -Wno-unused-variable EXTRA_LIB_PATHS=.:../src: +ifndef PEP_MIME ifdef ETPAN_LIB EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(ETPAN_LIB)): endif -ifdef GPGME_LIB - EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(GPGME_LIB)): -endif -ifdef NETPGP_LIB - EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(NETPGP_LIB)): endif # Remove trailing ':' @@ -102,10 +84,10 @@ all: make $(TARGET) %.d: %.cc - $(CXX) -MM $(CPPFLAGS) $(CXXFLAGS) $< | sed -e 's,\($*\)\.o[ :]*,\1.o $@: ,g' > $@ + $(CXX) -MM $(CXXFLAGS) $(CPPFLAGS) $< | sed -e 's,\($*\)\.o[ :]*,\1.o $@: ,g' > $@ $(TARGET): $(OBJS) - ${CXX} ${LDFLAGS} -L${PREFIX}/lib -o $@ $^ -lpEpEngine -lgtest -lgtest_main -lsequoia_openpgp_ffi $(LDLIBS) + ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} -L${PREFIX}/lib -o $@ $^ -lpEpEngine -lgtest -lgtest_main -lsequoia_openpgp_ffi $(LDLIBS) test: all diff --git a/test/src/KeyResetMessageTest.cc b/test/src/KeyResetMessageTest.cc index 2fa9f4d2..db0b47f6 100644 --- a/test/src/KeyResetMessageTest.cc +++ b/test/src/KeyResetMessageTest.cc @@ -1208,19 +1208,142 @@ TEST_F(KeyResetMessageTest, check_reset_all_own_grouped) { ofstream outfile; int i = 0; for (vector::iterator it = m_queue.begin(); it != m_queue.end(); it++, i++) { - message* curr_sent_msg = *it; + message* curr_sent_msg = *it; string fname = string("test_mails/check_reset_all_own_grouped") + to_string(i) + ".eml"; outfile.open(fname); char* msg_txt = NULL; mime_encode_message(curr_sent_msg, false, &msg_txt, false); outfile << msg_txt; - outfile.close(); + outfile.close(); } cout << " // For " << alex_id->address << endl; - cout << " const char* replkey1 = \"" << alex_id->fpr << "\";" << endl; - cout << " // For " << alex_id3->address << endl; - cout << " const char* replkey3 = \"" << alex_id3->fpr << "\";" << endl; - } + cout << " const char* replkey1 = \"" << alex_id->fpr << "\";" << endl; + cout << " // For " << alex_id3->address << endl; + cout << " const char* replkey3 = \"" << alex_id3->fpr << "\";" << endl; + } + + free_identity(alex_id); + free_identity(alex_id2); + free_identity(alex_id3); +} + +TEST_F(KeyResetMessageTest, check_reset_all_own_grouped_with_sticky) { + char* pubkey1 = strdup("74D79B4496E289BD8A71B70BA8E2C4530019697D"); + char* pubkey2 = strdup("2E21325D202A44BFD9C607FCF095B202503B14D8"); + char* pubkey3 = strdup("3C1E713D8519D7F907E3142D179EAA24A216E95A"); + + pEp_identity* alex_id = new_identity("pep.test.alexander@darthmama.org", + NULL, + "AlexID", + "Alexander Braithwaite"); + + pEp_identity* alex_id2 = new_identity("pep.test.alexander6@darthmama.org", + NULL, + "AlexID", + "Alexander Braithwaite"); + + pEp_identity* alex_id3 = new_identity("pep.test.alexander6a@darthmama.org", + NULL, + "AlexID", + "Alexander Braithwaite"); + + + PEP_STATUS status = read_file_and_import_key(session, "test_keys/pub/pep.test.alexander6-0x0019697D_pub.asc"); + status = read_file_and_import_key(session, "test_keys/pub/pep.test.alexander6-0x503B14D8_pub.asc"); + status = read_file_and_import_key(session, "test_keys/pub/pep.test.alexander6-0xA216E95A_pub.asc"); + status = read_file_and_import_key(session, "test_keys/priv/pep.test.alexander6-0x0019697D_priv.asc"); + status = read_file_and_import_key(session, "test_keys/priv/pep.test.alexander6-0x503B14D8_priv.asc"); + status = read_file_and_import_key(session, "test_keys/priv/pep.test.alexander6-0xA216E95A_priv.asc"); + + // sticky - false + alex_id->me = true; + status = set_own_key(session, alex_id, pubkey1); + ASSERT_EQ(status, PEP_STATUS_OK); + status = set_identity_flags(session, alex_id, alex_id->flags | PEP_idf_devicegroup); + ASSERT_EQ(status , PEP_STATUS_OK); + + // sticky - true + alex_id2->me = true; + status = set_own_imported_key(session, alex_id2, pubkey2, true); + ASSERT_EQ(status, PEP_STATUS_OK); + status = set_identity_flags(session, alex_id2, alex_id2->flags | PEP_idf_not_for_sync); + ASSERT_EQ(status , PEP_STATUS_OK); + + // sticky - true + alex_id3->me = true; + status = set_own_imported_key(session, alex_id3, pubkey3, true); + ASSERT_EQ(status, PEP_STATUS_OK); + status = set_identity_flags(session, alex_id3, alex_id3->flags | PEP_idf_devicegroup); + ASSERT_EQ(status , PEP_STATUS_OK); + + status = myself(session, alex_id); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey1, alex_id->fpr); + + status = myself(session, alex_id2); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey2, alex_id2->fpr); + + status = myself(session, alex_id3); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey3, alex_id3->fpr); + + status = key_reset_own_grouped_keys(session); + + free(alex_id->fpr); + alex_id->fpr = strdup(pubkey1); + status = get_trust(session, alex_id); + ASSERT_EQ(alex_id->comm_type , PEP_ct_mistrusted); + + free(alex_id2->fpr); + alex_id2->fpr = strdup(pubkey2); + status = get_trust(session, alex_id2); + ASSERT_EQ(alex_id2->comm_type , PEP_ct_pEp); + + free(alex_id3->fpr); + alex_id3->fpr = strdup(pubkey3); + status = get_trust(session, alex_id3); + ASSERT_EQ(alex_id3->comm_type , PEP_ct_pEp); + + bool revoked = false; + status = key_revoked(session, pubkey1, &revoked); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_TRUE(revoked); + + revoked = false; + status = key_revoked(session, pubkey2, &revoked); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_FALSE(revoked); + + revoked = false; + status = key_revoked(session, pubkey3, &revoked); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_FALSE(revoked); + + status = myself(session, alex_id); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STRNE(pubkey1, alex_id->fpr); + + status = myself(session, alex_id2); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey2, alex_id2->fpr); + + status = myself(session, alex_id3); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey3, alex_id3->fpr); + + ASSERT_EQ(m_queue.size(),1); + if (false) { + ofstream outfile; + string fname = "test_mails/check_reset_all_own_grouped_sticky.eml"; + outfile.open(fname); + char* msg_txt = NULL; + mime_encode_message(m_queue[0], false, &msg_txt, false); + outfile << msg_txt; + outfile.close(); + cout << " // For " << alex_id->address << endl; + cout << " const char* replkey1 = \"" << alex_id->fpr << "\";" << endl; + } free_identity(alex_id); free_identity(alex_id2); @@ -1237,7 +1360,7 @@ TEST_F(KeyResetMessageTest, check_reset_all_own_grouped_recv) { const char* replkey1 = "0F9C2FBFB898AD3A1242257F300EFFDE4CE2C33F"; // For pep.test.alexander6a@darthmama.org const char* replkey3 = "3671C09D3C79260C65045AE9A62A64E4CBEDAFDA"; - + pEp_identity* alex_id = new_identity("pep.test.alexander@darthmama.org", NULL, "AlexID", @@ -1312,7 +1435,7 @@ TEST_F(KeyResetMessageTest, check_reset_all_own_grouped_recv) { ASSERT_EQ(status, PEP_STATUS_OK); status = decrypt_message(session, new_msg, &dec_msg, &keylist, &rating, &flags); - ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_EQ(status, PEP_STATUS_OK); } char* new_main_key = NULL; @@ -1332,6 +1455,109 @@ TEST_F(KeyResetMessageTest, check_reset_all_own_grouped_recv) { ASSERT_STREQ(replkey3, alex_id3->fpr); } +TEST_F(KeyResetMessageTest, check_reset_all_own_grouped_recv_with_sticky) { + PEP_STATUS status = PEP_STATUS_OK; + char* pubkey1 = strdup("74D79B4496E289BD8A71B70BA8E2C4530019697D"); + char* pubkey2 = strdup("2E21325D202A44BFD9C607FCF095B202503B14D8"); + char* pubkey3 = strdup("3C1E713D8519D7F907E3142D179EAA24A216E95A"); + + // For pep.test.alexander@darthmama.org + const char* replkey1 = "8FDB872F88BD76F2C6C2DE0E8453FAEA21DD0DCF"; + + pEp_identity* alex_id = new_identity("pep.test.alexander@darthmama.org", + NULL, + "AlexID", + "Alexander Braithwaite"); + + pEp_identity* alex_id2 = new_identity("pep.test.alexander6@darthmama.org", + NULL, + "AlexID", + "Alexander Braithwaite"); + + pEp_identity* alex_id3 = new_identity("pep.test.alexander6a@darthmama.org", + NULL, + "AlexID", + "Alexander Braithwaite"); + + + status = read_file_and_import_key(session, "test_keys/pub/pep.test.alexander6-0x0019697D_pub.asc"); + status = read_file_and_import_key(session, "test_keys/pub/pep.test.alexander6-0x503B14D8_pub.asc"); + status = read_file_and_import_key(session, "test_keys/pub/pep.test.alexander6-0xA216E95A_pub.asc"); + status = read_file_and_import_key(session, "test_keys/priv/pep.test.alexander6-0x0019697D_priv.asc"); + status = read_file_and_import_key(session, "test_keys/priv/pep.test.alexander6-0x503B14D8_priv.asc"); + status = read_file_and_import_key(session, "test_keys/priv/pep.test.alexander6-0xA216E95A_priv.asc"); + + alex_id->me = true; + status = set_own_key(session, alex_id, pubkey1); + ASSERT_EQ(status, PEP_STATUS_OK); + status = set_identity_flags(session, alex_id, alex_id->flags | PEP_idf_devicegroup); + ASSERT_EQ(status , PEP_STATUS_OK); + + alex_id2->me = true; + status = set_own_key(session, alex_id2, pubkey2); + ASSERT_EQ(status, PEP_STATUS_OK); + status = set_identity_flags(session, alex_id2, alex_id2->flags | PEP_idf_devicegroup); + ASSERT_EQ(status , PEP_STATUS_OK); + + alex_id3->me = true; + status = set_own_key(session, alex_id3, pubkey3); + ASSERT_EQ(status, PEP_STATUS_OK); + status = set_identity_flags(session, alex_id3, alex_id3->flags | PEP_idf_devicegroup); + ASSERT_EQ(status , PEP_STATUS_OK); + + status = myself(session, alex_id); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey1, alex_id->fpr); + + status = myself(session, alex_id2); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey2, alex_id2->fpr); + + status = myself(session, alex_id3); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey3, alex_id3->fpr); + + char* old_main_key = NULL; + status = get_main_user_fpr(session, "AlexID", &old_main_key); + ASSERT_NE(old_main_key, nullptr); + + + const int num_msgs = 1; + + // receive reset messages + message* dec_msg = NULL; + stringlist_t* keylist = NULL; + PEP_rating rating; + PEP_decrypt_flags_t flags = 0; + + string fname = "test_mails/check_reset_all_own_grouped_sticky.eml"; + string mailstr = slurp(fname.c_str()); + message* new_msg = NULL; + status = mime_decode_message(mailstr.c_str(), mailstr.size(), &new_msg, NULL); + ASSERT_NE(new_msg, nullptr); + ASSERT_EQ(status, PEP_STATUS_OK); + + status = decrypt_message(session, new_msg, &dec_msg, &keylist, &rating, &flags); + ASSERT_EQ(status, PEP_STATUS_OK); + + char* new_main_key = NULL; + status = get_main_user_fpr(session, "AlexID", &new_main_key); + ASSERT_STRNE(old_main_key, new_main_key); + + status = myself(session, alex_id); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(replkey1, alex_id->fpr); + + status = myself(session, alex_id2); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey2, alex_id2->fpr); + + status = myself(session, alex_id3); + ASSERT_EQ(status, PEP_STATUS_OK); + ASSERT_STREQ(pubkey3, alex_id3->fpr); +} + + TEST_F(KeyResetMessageTest, check_reset_grouped_own_multiple_keys_multiple_idents_reset_all_recv) { PEP_STATUS status = PEP_STATUS_OK; char* pubkey1 = strdup("74D79B4496E289BD8A71B70BA8E2C4530019697D"); diff --git a/test/src/StickyBitTest.cc b/test/src/StickyBitTest.cc new file mode 100644 index 00000000..209932f5 --- /dev/null +++ b/test/src/StickyBitTest.cc @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "pEpEngine.h" +#include "test_util.h" +#include "TestConstants.h" +#include "Engine.h" + +#include + + +namespace { + + //The fixture for StickyBitTest + class StickyBitTest : public ::testing::Test { + public: + Engine* engine; + PEP_SESSION session; + + protected: + // You can remove any or all of the following functions if its body + // is empty. + StickyBitTest() { + // You can do set-up work for each test here. + test_suite_name = ::testing::UnitTest::GetInstance()->current_test_info()->GTEST_SUITE_SYM(); + test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + test_path = get_main_test_home_dir() + "/" + test_suite_name + "/" + test_name; + } + + ~StickyBitTest() override { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + void SetUp() override { + // Code here will be called immediately after the constructor (right + // before each test). + + // Leave this empty if there are no files to copy to the home directory path + std::vector> init_files = std::vector>(); + + // Get a new test Engine. + engine = new Engine(test_path); + ASSERT_NE(engine, nullptr); + + // Ok, let's initialize test directories etc. + engine->prep(NULL, NULL, NULL, init_files); + + // Ok, try to start this bugger. + engine->start(); + ASSERT_NE(engine->session, nullptr); + session = engine->session; + + // Engine is up. Keep on truckin' + } + + void TearDown() override { + // Code here will be called immediately after each test (right + // before the destructor). + engine->shut_down(); + delete engine; + engine = NULL; + session = NULL; + } + + private: + const char* test_suite_name; + const char* test_name; + string test_path; + // Objects declared here can be used by all tests in the StickyBitTest suite. + + }; + +} // namespace + + +TEST_F(StickyBitTest, check_set_sticky_bit_normal) { + + PEP_STATUS status = PEP_STATUS_OK; + + ASSERT_TRUE(slurp_and_import_key(session, "test_keys/pub/pep-test-bob-0xC9C2EE39_pub.asc")); + ASSERT_TRUE(slurp_and_import_key(session, "test_keys/priv/pep-test-bob-0xC9C2EE39_priv.asc")); + + const char* bob_name = "STOP MESSING WITH ME ALICE"; + const char* bob_fpr = "BFCDB7F301DEEEBBF947F29659BFF488C9C2EE39"; + pEp_identity* me = new_identity("pep.test.bob@pep-project.org", NULL, PEP_OWN_USERID, bob_name); + status = set_own_imported_key(session, me, bob_fpr, true); + ASSERT_EQ(status , PEP_STATUS_OK); + status = myself(session, me); + ASSERT_EQ(status , PEP_STATUS_OK); + bool sticky = false; + status = get_key_sticky_bit_for_user(session, me->user_id, bob_fpr, &sticky); + ASSERT_TRUE(sticky); + free_identity(me); +} diff --git a/test/test_mails/check_reset_all_own_grouped_sticky.eml b/test/test_mails/check_reset_all_own_grouped_sticky.eml new file mode 100644 index 00000000..b83cc1d9 --- /dev/null +++ b/test/test_mails/check_reset_all_own_grouped_sticky.eml @@ -0,0 +1,284 @@ +Message-ID: +From: Alexander Braithwaite +To: Alexander Braithwaite +Subject: =?utf-8?Q?p=E2=89=A1p?= +In-Reply-To: +X-pEp-Version: 2.1 +pEp-auto-consume: yes +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="238e1f2946e87ccd3d1b58ba507ed7ab"; + protocol="application/pgp-encrypted" + +--238e1f2946e87ccd3d1b58ba507ed7ab +Content-Type: application/pgp-encrypted + +Version: 1 +--238e1f2946e87ccd3d1b58ba507ed7ab +Content-Type: application/octet-stream +Content-Transfer-Encoding: 7bit +Content-Disposition: inline; filename="msg.asc" + +-----BEGIN PGP MESSAGE----- + +wcDMA+k2+vmtOIxsAQv/aeMvRD4OwtkEc0AUn1dlueKa2DsatpVj4QZhT+HKc6ls +IyjCovmFW368X8wIm32a/YrxjGLBARPhiuE3RdVbeU8tG5extGGF6Z0welVGM06N +7Jyv5u+XQFcx2VTZX4HKqQ+b3laz/VYLtR3ss7YDBUFD3NeKLFGnwP/AzxYQtxkF +zaS2NAMQVkyAwln0DoLqaDYR0EmZoTbEMSUiPW0FftAmiKkQ8RLmHcSXl3ARZJ6I +PGov0LqcAmjHu04NHxY/CtmXJAC0+eyQ0UJtlCo2Gzq2VwmnexsGyWXVes4zW5eB +vNjAng5asb6rD2+e1K3o8vrEj9PmKdNQwMPNiWS7jzHwbhNfwKKp0UpyT5z7j9Jx +tN1wPsMI632xagqWiVVvYNW0d88iF2X8PjBq1x1s/V/MAF/gy6dK87f1xmLx0yn7 +CSjftDwjmJlRCyu2tWOcPObl9uV9qloOUELqq1laF3KbhOkn+6YLsw1evaPTxdOM +R/4lTa8W3xR+2JU4IqZ2wcDMA+k2+vmtOIxsAQv/W0H+mk0Fcdf1I+r48L+MmWZc +kcnL5VQUPvS3VOTt4WTvKWBbo/eP2I/nEKknt+Q4dwr1lLTzaknGHEMP+HCCjJWP +lOBwr2tqf9V35wKbjIrIP/Vt0yWnby+nOYuFqpQaKpWg/FhX/t2au3AiZF1VL543 +YmQ76CJqR4OyLmzyk6HK0plINn/BO79Y5RrzaVN4InHA4SIpzNTncEqByOsHmd0M +6Lzba1m7ygEK+UOmlGDexxRqZi9fCu1fgw4Ei4fiG5DEBtwqQIwd5/IJPyYmfyS8 +XutbyKxI6tY+gsYO/kg5EGZQaD9KPwN8xAXjAq9S+GsI4OfHTi5iwUA/5X3k+/k7 +nB065HGBr0WrZ4tNmpUya0vzx561Ty4P2mjdYyeRo/Bo0kzUOuBiG+ji7tHtYjyL +KPSJIht8rN80uFNqVFHkAVPhzFBU+BaaYammx4UmeIm0irn4trqdD1qDc4JA/et7 +tcm3VSyL+GVeSH8bJCq0yCoBGk9SjNS4Psmc8ju/0v8AAC0pAe4b0H/cSZYmj3Xh +XrUpXKrxM6nSMc9wkB3/w3InaeKcsKGP7RxlAzH04qGoptXUHWIpV/7TxVNeiMBM +26J/z21iswY2hVPwQuXCnfaeY2a7fRYb48Anb+Xe/4wb8ucIeFJVVjDl/5ZnBboZ +T3KJqHSxjG3YaIYKjDvws/qVOwQlgJpfe+wVl0mY8je9QPnKv3DlpQvx2yR422jo +iaYW4Jrx1WCFlgK/gBgJTYrQrh2dnLH9dFCAlopMhP3IaeNBvxujWCOCF7x/OqFq +HaDdTLxibF0tuftkV6G9PH/5VPHhFvwkgDc8eZbeOprP1GlD+ytEM+Sj8F39AVYg +GTj9PUpnCsvxRtj4Kt3I6iyFKPad71+3vrkJ8eofpdyNZjxTmRMb6qE9r0GW5FF3 +IRPu0VSuKtZb3Yl5siXcykvD2pyggxJbxuU3UKlsSWMwrWP9se/yhwgF6apL7BC6 +rtd+y+2VeVViju7KzqYgmmKOauu9JHJbAy4gu10roOp5ujnbIAa//vBCOQ4HCDff +TTgs54+HBxQhDQPAlvNi2NZA/AW/bD1NMUeYx9FXLqzXLdyPX3FeW6NMJNp/AjAy +A3ThyY481x2XQR4JypT5ZSY3qAhGoV5TMaDvslJO4lwexM9bwnPjbVTUYvnTa4Yu +8eNzVKBWjZG3KxXhefHsJ6AcpeuMq7VbxAKrNoWeTopINc/wRnWbqEVqku9yZW0C +8i2mE8LpCfgLGW4hFmSe+XfYMhLJNzsbH0XRQsz8tIeeSINZwc6sjQ0ull+GeUST +e9zjScKWJ4voMd/gw5+K+PHU3RktJX5aJFAm5Z+BN93pzzPdoxBNPsWPcjhvEr4H +sJZ0Lqq/Ml/9gK1ePKnHB7xrXgLh2nkGNxA69+LTRzJ0IK+OWi9R0npVz2ei6ghn +cTZKng7LW4ARMRO1bYtXOp3P+V9rxkzwq40Yju4TMcCq7sAgWOiHd5AuooPnvrhS +S5uxLmzjITduoiPNfzP8IFZQhpCS45ny1pWrJ7/MYo3+eWh7G0Ps69fXf7rqubAy +CHIvh73aoq80uMLs1uYiCPuXqsFvc25OjoB8/K6jMnQiCXqeyEQT7/407HfdoEkc +G+7Z73lrHrgYGXFykFUq04LkNyJ9ev29NQDnb0jkHpERlqBrrmSeZvJcjoYTsUdu +CFopjZfEwjKKYDOK13wiSu6gbJQUAf7grLe+vujNASSKNaKHwxi+q8U3FGJCs0ST +oOTVJivYpfvoKYaxq3wLdtP4JxmMUAyP5uJ5lpbXRSrxWX4vusigHyBHNCUCWYGE +xUgQLrrT+mito6DwT0ljey/doErSGR0p/O0Zcc60EPu1AP/t5NP4BvfKLrbHS14H +WcM8SxV984Pqncv72Trdq3yR2Z9qNA57xgKFII841NTMLkezAL981dliAtKkqj/r +JwywGikXDHPBmPZPE62c/hCh5w6gJ/AC0c36YkVw5K/OwMLVGlv1fEpBNTpGQeNm +TiNFRNnP7KNlIswPC6JEyX/tk/SF0ShlMT1l8s0mbBNOHvxi/iqA36ifMTEwSW9o +VtMzKiurA2vOBhpQHg0pHXmYl5LJlZM6MbYrmjVczR1EosHY4XLJ2Ls0WZ1POznY +J5XgWhhQqv8SZECksSb/DpOmx5eGz4GgQ5MKdQWBS7Fabnwj8shaMgoRT3InThVz +0v/VmCCd+ePK7JUrZN+zeF4/BczztontJ+dQdiGSOW6DSADDd7B53EwXj6MLis4K +xGK7z/PasO+mVYc+SL8Z1/2jpEowUWqtjF4RXuhybdW+DRKhgqqasm/sOM3Mx3Hr +aTucsHClANEsavvTwptv2bLElyadpO9ArHwhRFp9AugLLyMTZtf/6PpCc11GVGhQ +xtTt6GVN2rhveWKHrYkCyLsO8zfE4lcwgYCDgX75JOsyt8+pNWTRhR9H2kVdm0Gq +sClEukYUPcxobbvYK7osuA8wA4wg/hqg6/6xMXlO7gBfd4pxOloZZ7lz7DopbBkP +YAfBdPEicW+7kl9cMpSm+Wu6FwmFhmgLfEZLYZxiXDJ3Lx8VBKueNT4ttvhAxiGT +4MfBBvFb/qGbrquY4m13Z7Yy/IG23VDrJ6zq7QuG1ktZQ0ISUzlGyg7B9V/Qo7Nc +Ag+80pkeoUhSrtbox2VLLzZ2rZMmtF4wggxxclWjf/A/9nnKSKi5sPR6OWOI3ECR +D+Ix+8c68GpYa/vTZY7uiu44Qmk91LCvk8xFNMCAMkkepCoEe/hhhq9MuUm4o8G3 +1eaNhMloFBE+dqnOXq6Blan0gSJbqNMhLCDTe4ZrAUMjcKv5nbhOTnLHjDzGO67H +6ue+7mSLHZzLvg4AvnKmjww4YVvH81KnaheBVmalrS2Po5TaD7xKPCtwwuezLtJZ +H5JWCzhElkmjx1su16kXxj+dmqA667kwzyt4lxqip8fCo17iOHrDyoeqAuu7+XYp +f4FK46TqCnf0l4fBJXrTB36Wri7rCLVuhQwDcd3XuMmI7oswhPdF4haiEaTOGQ5S +cuqusC9C52o7jt9tArCHkytqA4wtDKFG8BAUBMcHxKbwcedEf6SZIsngsx7g9Yu0 +5Ogg+6xy9475JeX5i3eWgQyFhQ6ytIb1PCZnjU84SfPRSI/ntoKUCtDKQ4ov5+pq +yPiYPXI2njFp4uEymRH6KqFWtBMraJqJkaRmgt5yfQz7XPn/tBO+s8PpYrHoyiL2 +YpXsV/TT5QlZ0/d8rpwRofcbpSU/7YkIaq/sT8pbhbngEun1nERjANORhWGooMWd +6YiAhajuzeD82VzWFrPh97rE0FMEkBzKwZhohth0PB4+0PwI9aFCayp56NMVqP6R +5g23fywEnCeJElWxtlg7feY5OX/yOK8zXDxGe8mtJDNOWwBeio5BBCYtbKBGoqmv +ubs0gr+734hYm8wa48OFP10vEtzrAa4ALPjeWPxzGBx/7K7MSzy9i8aOq/yj4yy2 +5CpJqzu1JNgne9Vi8NKj0Uf4/B0b+iP3xgy7taxxbnAcDmH4ZLdw7W3inrrXpDfc +zdoUQh40HGHskIu0Mz9VtalbnlmWNVcHxKQ1OSnukR88RxW0z7fbBy44KH6N96nd +GkqF4UQj1H6qBSRWIVoy+lH7PGGCJjeoUDK8EKgwGBkTcyOP7pherf5zueQCIZtP +MZ/UabI/JsN37xQinT+yWnhsdAnxrRYOYSeLGkgw/iSyJ9DGSF5XkAebkhAjRA7q +77SuJgLkQrs+l1YRk6ILcJFOhhBOrQs9d4QEyL3wMa4YNAmAZJxX2101ZUvwaH6O +g0KsSulcAZrOIuJYfmWSxpnL9o1lEtNV/x7eCuKL35IJIINxk9Dy2zPsNa9FecCE +tol1nM1WI5wUKDTssxPEoOZBos8rFf2TiRGYC/v7ZZnq976CuNyWZ4wG3AUxibLp +9Wl4bd1Fq126iwJ8YsF+WHG2hzzj6UJ3o5Xa9oJCkK50bv/kJ6B0IiMu4e5rxLxY +J40b+XM8oX+sJe06ksBMZ6+mqze/JyQJHE5PWBJxihyt3BLny3XZZl1gomjFlmD4 +LrBbHP3JNThBiUsJGm58K0Rzjjqfi+lADXVFMt2sztfoAISe0dNpe+PZfH/EHRpp +Wm/WPabZRefP8gxNiu4tKm3AiisgqtS2iHquvfwAZfu4+8HUPerTnZqumY0ZCIn3 +Od27GRMb3r7ths8+9mUOq7TNqIa8Sav0CE0/EXBbyC9SU5AKf0QvT3FBc2JAD7Pn +C4uC2BPLf3kyHkkbaCsMAnJhkVclHehlMY0JVP16Iq5m0NPvdk8RDpzoZE0j3Nhy +jbOZS2O/74JitrH+bJz8EEhOHadX2ISwZNbXKBw9Htv8CyRi1ZzmQdWE7cy9Fbk8 +7AvdOEyV5HeqctYDoKEYSgrwMk5nbUuzILY9fphUgAKdkyZBK3mo8YnvIMsnVWA6 +uBdopJB7Gvd8YD4woq4XtBpUgVK8HQ3/GAUGbV4ikM3rrD+8YcdugKIadMSUPp7N +6srBX7+0AeNmfczct7xk59hmq67wo6oOtGagSeZB9xZuaKYCa9RixEUPPn0SMlvw +7HT3TmhkhXymKwhQhqmKThRiGID5/b8qxbMEXPdXppYB5NUUtkYvR086ZUzrL5mb +aio7K04o7Or5Df7DkJnYUwSbfvwOYkTVQ81YNFta3cMZzVn1/6w3haEfZ2sguyVp +FfjaPvl/NIBg0OIlX5RcIKYN61cSarGQnij0kIbwmLfSP27s0pWJnT7EPRrmLgWe +6UdmIfmCUgOdv0gz9pqdQXQ5c21k1pll2Ii7Y+qirDSqlWs+It+b9EqAnZAUx1U8 +5MrGDYx3nWxl3bgNaaQK8qUyoQwcDe/dGBY3DuA0dPDF9+AGB9DrKyVk6Y6aq8SL +ERm5SN0QT2zkwbY9dlKxIbFfoZ1INzcjAt4LwQFS59RTgbf2j1tpEpTBn99frHIT +57ba66r7dOySNTg8LILhBQM/d9lDC7X9Cr3OWL0ctS6G69ceDloR5Z4fuudWQaID +rqQnrtBOcup7fYPtzkgyt/l8I5wS7oHge7U0j6kGFmIHaYSdocQ0l7yo3Z7S5PRs +5fBaLG8RqsIhZRuTV6+zXVnXQF8BgkXjyC74lxtAwWyvJM7MxuK37lFffcZ5d6Fe +mrdX5YNrqbmUGzWCK2FAuqI7LEKE0LUrQCqmxSTzHv8YzhyJjcytczro1owIB75k +EHQZWfO3fpFbDTWH3FFdkpFF4hiLf1OZjspxrmlU1CcmYm5Fs8CrULi2CTjsvXH1 +locyo2jQu2h5fvFebyzpgQkyBXL9BNNojDUkThVG5E/hp5rpGgukMhfPAc9GF2qb +JjRC2GRkLOXyZJT01dYuetrSWZz3vH74K4PGBVVqDqzBhjOcV4aEz7mrioL6Fe6s +xQAabbiKtFwEs2fI3c7hUZIKwq7+y1TyhXpKdylRrqJl8o/Iz9J7BDi3EUc1yA+I +qHJ49OytzmVcLZSOhFB1t9QCIjL/16Mo4L3ZQM+3vRe0tTGqLUEMNasCeBJZuU9r +MkwsM506Hxgb5vz7vj4hi8Mf0j9iknQHW6Dxj6xa9tEdKVQzpzTL64CRtUEHg6zR +A2LxvPLIyg2H5m1N+W9KvJ84XSbgR2UwbcCdF9rMvvaztVFR0MyCe4WSCfkZCJvS +vQNfRI9Vg+6Kec2hyK/8RJDUedUYK473Rvo2wVL+no+AL2uLODuy7yi4D3siOkwv +uXlNvyP1gS5DgVDYZi1MeP6bO0OQWNsnq1nbSEsTtO3GGzlNPL+7I67bluevvRGM +dNomv+aRQSPFZ3rFoL5UWCM9OSpJgIF1DqCJ7qLoJdRGLtcOnPoV4QU2Acss3yf8 +EJ2FvdCqfx+Hm8HW+LhkPDI+pyYVHJjfKJASqAGxEcnaz9xaPKSHuSKeWOE9ZKyU +RWEgbs2XfJTbdz9B+oKuTQfxhnjf9ucPoKiAg/PTQSNXFh9zjDdTVlLxCB2KeE0a +BIvnMAZW+Sbgv8G1/pUZS7/3Is3hlCziM2ndYAxjup0WVilUEfvm3Uhi/1CWlXZH +sE4wv0kTrmIXpTYLT5hgvAxQE1uLgVUBwgHqifN9pthN0pvwbVsIvSdwR5f/9RI9 +sYXwffrY3KgcFCIPlr4Y+F8GpxZ7eFATwxVTgrgSv3kBsfNb0rHhJ03Jw/431ws/ +zBIs4Mb2BCPfU9qEVEBTOjFxRv9flZmLtacgIzLsU2F4qmJHDhWDWJATPKOaTnJp +2h6r5nQ/gUaKiCm4sG4V/Oqaml4JDn0hI7lhJ77b1qE2YDNQWn0SHwFIca7+rS3/ +f5RJBaU05I4IEUdjJb44md6s034E304fvA5S9Agm2coQpkOcQ2BWTpc5Ta+0/MSI +ERwNuVaZZqJsVd6y4FaPiaUL6seJ/Da/HVRBZsIsNMg+eBgc/qysHBBv4f37k9Ey +Q4m+aScT6EWOPgM5NydDgxUWfMys78cySokC2ItGEHKoR/AeiKcMdNwxrsdtmuNq +JCBeeP7uWPPGoqIEf0HZvLrGxfreo0inNyC3oBGLebPE9qJna4SH6z6CJwkExRpq +NDDsUhhZgYPJ9aHHM65VLMKvtVxh3o0vzSw0bWE0sp7VeQooxcbM0KluCCZ6gvn+ +DqWGvaaUkP7vYJDUy34l4vVCVt5aSYEVdv82luXZthSHAHQ2pUHyVkJiJugZvVTk +yXH3wzSX+aHpwFnvo6RNpOe4+0CRyS6i1hxKZ/hLwxPxwcef+UG3gGpOaxdYEx3a +uiguDwblQUti1vvceJ/t2scbVXZhtU98B5jgLlcydnboAeeCQC/bwZ7sk1n9KlM8 +O16tf7EPUum4YK/hWZaZyIpxkwDHtrd5VYgBqnkAen+d6wYYikS5k9X+MHQd+WDR +9qg3bilLDzKIIf9I5KVnDk2zIQmKuN5MMMLWIhYBpyJo9h6kaBZNcDFDmpYX1oPP +Kd5W0ViOE0ahlGpY8oDjxEQLo0CW8o5IBncgr0ekb/575/g6z8RWAYsOf1coL7wd +PldHq6l5N/2TBSnDSi+WqqWV5Gww6vNGlGHsjlqTuZOJHmfopb9ZSYXcLf0ECHdy +2AyPoyH8bHfFF7vDGn5tKTTrSgAUFMaYprtem6ZfMViwfdLadtDKBkw99r8O21t6 +5HOzZWQfuIwDvt9QGJACfNSvFNNf2Gx7PdgDtiIET5whm2hzbp4DugvcUHopyEGI +EQg4BNfImJ3Z2sPkhw5Boh2zwPS9vK6yVBuZtWptt4tLgAIJLT1c7JP1oXwLb94u +iGZV+PSxc4Tv8NyNueJqdbHZRkdcQBir4jMtMDXzkio0NBzrob+CCnBu2mbo3JBb +DFFpy0Bcm5jG6m8uq7g1QOvn+c30qNDRKoSp+72IASST20frL8Zl82F1PvGndfWV +er/D/UUlqv9J7815/ukTlLw4wOOtnAHxklx9lsaSxd5VylNXxFliXKSWxULLBszu +KKoHW+C3+T8gs8Plpck9kbvBlhIXsGOdpyQXoux9LIy+JJkYYpXIa440cvWwLfVX +HoN2b+fBh6x4/hG+MYPx1peWN9xFXUhlYR8Qiw0bbr405Mn6XMRvBi+a/9ATth+z +WfpL3bxyogYPMLnI6a0zALglnkgnrIRUrl/z6Iuk+9u3a1aOPOfD71YN7Q6xlidm +daYNs6cOnvjtFCWtnPe82Oj257FcfOuDCIB79129h+dh/kC1QiVw1Lp0n9PFiy7V +X9VtCLMzIMiWY8IeipQqsOucH3B5aBZkxPj6oT70h2JTetKUL5Lx46x371VQ2ctw +oaRODRXkqIz7rXTT+09OHBf44Oli5EP/GG959Aj7JAQKcij8Zx3XNb5wu8n4wDyD +Yn21G0YUR0CqfwgVwJnlIp54Xp/J9VJSkABsqQZa0cXDZQlAujGvbd/zLVntbTZL ++Mgm0YRaa8V406qswEXykkYP+ipdZY6hCMRCA+Co4gal0euUN3ukqmzWVs9jEcGS +PXQ4zIpbFqysxrX+3LdU0lIHd6ymK3qHBQziHRZYKvQLmyzTI/VIVh5rW9MGYU/d +kNJU37Q2o1sMfiqklDy5mpTuicqYOIO6Y14dIzN0/lF3uSE1wIEJyAeY5xT9WXbv +wFvWPNB+1AwuoczWa/KQqgc+Qgt6N3dLZHbK9YQ7ovlPrbtK+9iBawWQsbbf9o16 +8Mq/WWt7Mp8bAgEyrLZIJy32Ey+wG81salnnfbagvT83ssFIdb9MK6j/5ht6kqU6 +1p8N05gwLQ1pdf/25j81zSnSNMdQB7sjDYng55A0UxVK2MBE8kiJf8OPPlt3tBiR +qTzycIMttx3J2b5sfoEUuK3gIVdbkYRDlklZBsr4vg4NJY2iAl9ce70azToMmALu +RaXj5pjSJG5TVF7xQ94wrSWoLcThVl/SV68QKKcKdnFRkqEBU4iaoVycbz2j3+O5 +XvgHeViiEsTlvy6x0NZP69uznmxsD4Is4zc04+TTxYj965tmckNX9LTsy13g1Y0J +w5M6Im1mKpU1X5ThkaCFNwMOcczBA1MTlIGhzDdxDRgGUIWAYzMG2+FPijIWT4XO +2pnnP1r8O1IS4C18yTvO+WKHaI6Pklrn8QXRGDSlTv/ZKDZdASp/IOOrazhCyBY5 +8mvaHSAy8JLm383j+UoAMFq6jZEEXr1fnG1fWiBnBBq2G5F8Y/rxmLFwWA3HcXVd +leUUljcybk4tImoN+D0KEwXCzqFQ7VifsXZiKYqEvfRcUxnGMDGg+CpA+gsBxoap +G6c+j728NBfl2Pg/WcejdLDFD+yA/++VHb0a9QuPbPurXNjtX8f9SQprCr7Tm+vk +5a4LBkc/OdVdw8KD5RRxFA9xwndPmuICTNp6A4p6U1M7nBQV1t/2uuDPakYmFRRL +di7bsRLJmHfD1hDDwWKFQsxaUAXxwj8qKwjG3W0UDIF9V8mr6hpHjfjxr7DtYLLM +ryjx/Lgmts/OnFkW1tXwzBwHqYWTKEMoU1cai92x1tGoc5bvMSzR8zS19TZIJzC5 +73o+gFeB/4iV6RWjqROzYSGCzyfXHBgfGtrQ28fdAKPIh4XxiR0jBKIsP7Yy1vZH +jRN8ujIlfCjyZkSRLiIwMuVt723LGX3ocxYtbx7sEE7zE2T+jJJfRZzBc7g9IPE0 +xzfdbJW1jNokH2Q2EpUz9ikTPJn3uDpfGG5NtrXavRdVvrsf8nXgbztswhb7mKcg +smQFA5BsEL2ixz7qj1Xyhuo8mXtaOayza7bzAmoEos1ldS4kLEFTHJLfZpGyHvrc +EAgaAvTXS6EcwCWZel38gHMoEbNvM5Whp2AaQuhyku7D7MWn/BNOIY0GYBgm9fRY +FbiPfFBzAyCTmWxefQW7AFE1LKsxYWm9pofHOpXu5f5xhm8oeBHuEgBnH/U+l2IT +Zv4cFaxZgKLn5korT40czPq/PXG5+LW/eqImtQX9r0MdLG/mYD5VtdVvL4AphFoi +UeEK6pfnexaGyfPrxnz9Kg3Dkb2c7vyCFwzjNE/SgB/qWmJGJ0mXSgOlZuhZ0JZ0 +QQwxlhBMQNL4gqeQ5iyYtX0jmyGizxRjzpaz0TzEe0FUmoAW06T7XhIbEgib21VS +cBmfp8RWAVj3lfdEmdgE1mLq5L5Hiss/GL2f5+7PKluyrJgXNZGvv42/yZ7d7/7E ++kehX/RRE3WNkOYrmotDVSsturcyduqm1FRlDXixjNM+XrQsLGoyG8Rq0r3YUO/C +GcbAtJ5knlaBbXq2qJY+q0cfzPN8smeiAWdkPI/XLuLlhuHpKGG6CP7V+8CSCEal +Sk+j7Ie8RygpO3c5oHRmpdgVCsgeZJF+3nVU/HlvPOkNnMfwLTCcrG3SJx6fCaRb ++LRhE6foE/aFySYf51e+twW1w/ylfElsSzKavc9gmD37hUP05WTAfVwS0yGmCNiZ +EbeacURa6cojciY9sL3j4wwOtmksxV6NPdmgAvioLPRoTQTHHKLSufgxn1UAYGxX +HNLS0iLZjMEC0DDRmvKGn9x1LKhxkMX7Uw9EaW0Hz1UcpzPQ6h78atxnbO4bFLh3 +b61eEwLv+hIyG0IPAN3nBcwDEo3wzOQ3PQ9sizJ9IwS6qgApPhT+lSFFBI9Ga9fu +o0feuyzC0smdZwJJOXmB30Vkcne5Zax7WxKjFFtfU08dg0ZpYNV3JFfzBGZBSvza +QSSaOegpU900dPrvCcEiIZEBlaj/txJZv7e2MYhQ36gFc6kAPqlS1wMqSZmaBh2d +BFZ40tlki7Ppn8YXeYCXTNOrbrP7YaU0EMR1VztOnfJJx1oSzoJhq1CNydADoz80 +Gpo2MfwuHdwBiaQPDIvd3US4rtGSJXswq54YzWBeNzITHZ5S/BSnCnQ4l1mkZpuU +HflOu+D2ZI29YC3Z1DAHNINY6GBPfiduwM5FYCxtXH+wjzJnWfqS2feEg1HsmuGX +FTiNBZzdhQ4Wzm/mhMI3cr1QsoEJub6LaRlf8yFgXkZKrRRN44A2Wf0Ls6JXCsLV +MNG2c0SgSTn8RPEeC29DDNGv87n6GdU71Z53HCi8uyKuTFfjqjzA5agtMvscC/9i +9qUaoZ8Zubez9pFWCCNaHmrpc0IqVOQfMc1BaQ2jQLoNTC/5feK9kn3vrWhfCKKH +/vclMYzm6jkC+Rg5FAY8KnYsPejQ9mDMmOxmeeXFs+LiWQGXqxx3xjdOkDk9l8so +10tvZjgKWMolFq0n2MxzCY6cUlE0BKBSwM13IpbAWiRfT780HsXeCwjYGTdxAUlt +GoUsHELYgAaCcSsjJFXBRmXGn10xfTox0I6wF/YQ0OQqt8LJ8e5ezBIVRBrYIYJd +3WSAUbE3Vg7GDr2diBIbg7tga4o4s6jUuFGspF8QEoY4gVKJ1QG50hqbSxXNif2R +xoZkS95KfRrz9ne9QUhTXGjeeb/ra8cQjP/i+b8HjoodzC0wW227AUk+knoWBVE0 +5SCuPOz9fpIyihO252v10HhHLEgwZBruLUIWw2SQDOZYpLDXFeetC7VwJKHDo0W8 +JBxg2jZ7tMgwDQxYQJx3Vk4McP+ObEVIwG2Pxspt3fR9kim5/XV4L+Zb+IDYpgnd +E20IAb7x73+11suwH3rKi5y+/IOC+J2o8L4F1Ma9tVly8068SmqFH7HfEYsp3L9G +1wXhbpdW8af4e6Nlii3FKuqVfwiWZaJ2hLgkq735ccGnNOPt9UZCYgfSQ4ky6MZC +tJJGS/WmeEqCxL2xlWD/KVdVB5gaqHsivypl7aK2qJ/rQAIHavxl6JdcYk0+DuWr +REd8qlya+ivCHVCl5rpV59Cb1uprBV3oWNcNd3uIgbhXYSWNUggy2tDxX8XgM0dU +RJ4/e8Kp0oOAEIXdQ7egtDgbO1+/rLj+YgtkkkhAlWbhn44G272q+VAfGFcH4jLX +20ghS32n5SUj/wv7N9NLuB3JA6PYWkN6COSvvRUkzZ8mbOSFpmpu2EZPrOY/8maX +iDwzPC/lFhGaAiqMziqhyCrN2tqoF/qZsXK7sn89toxSepCEulu+/uwj7oAf+avw +35ZMrJWhJf3lz/QrRukpFadMyAAbhPdOqOvwodkdphYgfRNP8ZRPCWw587U0BobC +W1skkX5dPsn8R/UYIXhHEBuxVFTQa2PS5g5g/WOd7YNmCopFJOmvHe0CJcFYog2U +hPY4K/snNBo2b5ywEYU8XRqm3Dh0F/VBJ4PBOGeK6HdoSXnGbGFy25zlDJZZzWeg +Lo5R3ru/ENDE5/mlLmgl6SMJDETQSA8ptFURyPwXv7eEtwRn/zDvzaDgfL2dhTjY +m1tS9+w7K2FxHIeAZIR1BC9H9jHsH25P8Dvk+pL9iBGvmag103NQczXm544zvWfS +tTXbKu2krwJNesCnxuqk8oXV49s0krWY577JvhIrY/a3KcNwMuMwZOG9lrJFC/qE +p6PyEB0jk7WvBwdbxQCrd1umhmeF0DIOxaJGZJ5pi2omVZTJjVm63BUGwaKWweu8 +vtrUOuhw3UeX+UNVr/aipvNRunh33cnislcnVTFqMCU95joVjLYZvhhBf4Mpj+q3 +j+MdbN2F9LO91zhQBo528ABx2UVGB+XFrZVtpIC1uESFIetvP1imYaS/imC+OaEf +lat1ft6+uiKHBQxmCbtGKmWaq0GGM7uTVhuAKtZxfcE8ynditCLJdOL2jr4CwJle +v9OFCtArz7c656RZUKyLkyDvaQLjsNsXLDN+bsebpbo/Jr+EC9FufawgmBkSK5aF +cjU8mfy5pQf0BItG3ATdMonyZhuj8KoM7D/zGOnFDRz5ZgqWP6T2rwargjciApgM +14WV5GaRuJUxgzDy1G7ohEVJxVQYgJxjEN12UxP8YNAS4qjLMCMSjYEQtwHKbpVN +SM75Qgr34G50hn1x8addKX3cTqxWC6n0V5bjePTP6EmB0CGK6/34s5vHQyYbNlYg +4zPi+kGbtWUYB2B3Luj2eCPDJQ09m+G7Kvz19nh8X1pDSiidZkkC/bwQBko6UaIT +Fsj57L1fHknE348qTO8iogAEUUa62jdDx0OezL/XuWlq+LpabYC1gU5FX5CBt+3Y +Ku8s2fPoqqBhDs9BNIcpe9xnVbrSMYfPvp/rF0EKvLdxpL+3TRk/1o9YvT4FIPVP +RjzH6wrty3omwWLubnB6Ss4xlSW7ZCiUQf5e7daHfPISQo7mkdKOSLan2kIGhda1 +eKZloA31tm3jVM7HVSkGHFYiFXsUwKmjQaWJ9TzpA96oOR4KnpCcmYkTDbnSXQ8a +/Tn/NxYUXjXBscpLZliFqsJQN4yCUlrLIADxIdo2PeDf/5xAxaa4ewhBCr3qtquq +AHFRo/L97s4ETPBf73zN1kbJlXzonarovYnNRO41Hx6J8BWt2sjRGlJta8H/GAfA +G2Y1msuzPcAKrbxm829hW9NkStZV85BHdLRB4iopiSveZIZuI3z/31kcO1xfOr1u +w9GdaxxTiw/sCRRDXqhMNfnVENfaCkLmOa0T6aYtRRjvnpJwQqm/KKqXhn0szPPW +TNSho/jIJcJ3t0tXmLDZ++suJ4V228zcscMqkx+6I9y1orgaaiM6NOgZgX5mD6rX +j+AWeIGxj2+n+SybZEoGBwJT6pCNouezfI8MqAw7jKChsEprV3NjWGHkYYza1S7X +3Zh8AFmuFJgoNpJaaxgqqbjwYgyMYuPJDftA44pSm9fbeWMwRBrnjOlVVjkpT/S4 +e1tVWGzP7jRF2ro0KSwQWtZB4ad9mjOIQpizGCDQRg9mhHycyEi5Fe99RE+rcW26 +abqccAEagQb86x2uG6VHABbqoL81B5PxuxAk+AmcWYkIY+/AzfboZT4CbJYLfNj2 +C7IoLuqllYbrkWhub8p8braQky1bJgpYTLb5vaFWW8XHbAl2OJvRsJuJcEGrAHoG +QeoozWlvqILgyX7f0+7MpMACT0NkKheQzDCqOf665jF9BPwyAKRP5Tdod5LFNV9M +NoPhHzcVDwZzMlg8R8sGpc5VTL+mxA5A3Ha3HB+5R35ytNMKdYeCnMFb1kwkuaJh +IZdtW96oOj9HgTC/6DiUY0HG+i5Nw0vkT5LRuL5i687me1Q3a8spnRDb5K7gmc14 +JROfdmxOaJup+uQ5eF1XjQ0saJi/CNYK8QSodl5cjYEKMnI73OUUPsOgNzhJ0ohy +vskE2VWweiOHdzNDGTrnk96xPgllouDRG6QWGetzTRXWgCsOHlpjOHJ2ygiz2oSA +e/zHoTP7PlfLi7RyTqUh2bBsi8eGTZdEimFWhYwQsQiodb3vVBTGaLU7gH7t6uIn +q9L2gV7yT/uggZYygOnk0f4nDJSQQzx1VAk2koMi287FAVvL0m48HhNIT2AcktZ7 +kttwjJhxLuVK1tTdsRqhK6wgt1NlprOP8CmeGLU4wm/G10G4fXSR/frJlbyNvEEO +W/CWQbuymyH5tyVTw4W/LApDt3J/k7K+TbkkXS827whdQ46n8kv429AN/zJbie9P +SoE5i3HUy5u7qzcpjKn/AwH6Vf2reaiaQe90e2sDf7BRpyeAS+e7ocolrhDvxLoo +TyflkmCxiaN8wrRyG3yrg9tKuOesqNmVzRFXsdxCtqn390ACWgfArBaHLXJs6vgW +C55VSUKXl5sfE8uUUGbw5iWfhHcWkWuudN3bq/q2EqcnU7Dn0rmlsjUV7B7K9RTF +BKhG+0S0fPwXZ9c+w1QdlORplcj0B86Tsa89sXZdpmLnY/cRh65vAfkT/tFYa7bP +UZ361BNdyD4NfzfU9KEmGImjRko4Ass0RrE0pRkmo7KhQf63sBWjt5D+/3QiyZYd +UPT1M3QR+yM5xR0fML6IzyvTAmCKswoW6goLRuhyeKscMVrW1DzIogAbsS2t8kFW +tVFQE1CV9kn2JogOMAdAr5MU8jUJPHys0dSFOOw5e/HGD+5oMbjiUcJQi2bGOpTh +B1vPTCF3aojxQ+XI0RxbDClovornBduVQH6eb5trzlFE0qE4Sy4p3+IJCfvRAHTl +PbgH7Yd3X3kbcjrSkq1ZhIVXVsIpDfVWJ9f3SU3NvFEidjfORx4k2uA5OHYSGdgn +JpVqXcKD0P3X9KsjnzmLm/4zITcKPiT0sR48DwaqSnCG0Us/oRCzsbQi+w6al9xZ +rl3SphO/3XLoBRbjzPHQuJL1bq3A81Dx09EqKhXoXqhl28a8dyi8EoI/fBNbthMG +soSfsKKP7uKu0SLX42+3i7Af82GdMVY0bO/PbaK6yyD5Efdw4RT9PuyWO+gedlVX +qOSF1bHYqVhqqko+MvDahEB+k1H2g0T+rP5JPJIOJ+uRwV9ncLDc8dMLYs19OP9t +seoasxpC4/naGKQTooEW3x/QrPSCcusIv6OaczjtF6xO3PH4G8YlrrrmzLc6U9zI +1dhNJYR38k245PnZjzV0RZ9Sqqhpo60Gsa54e0mUCtFyJYipFw1nZr7mpUWp2OEd +hFrxmwPu17jFmWpWyRFWlGQLtzyTY9b8bAiLAZvqZZiz4AI4XV4ObQHi6E2OjEzq +NPLHrmFUu3gQYttVrRMgtEvzOYE7s5OG658EsNbWnIcGs1Jd3D7xA6CdvwctaUBa +R9FK78YCX8kX1eE3VSy1Fir5eKm051ODJxOCRhOaUCXcVMtSXRcAQQ/nLoIxt8ps +FHZT8Vq6jshI8+l3zoYpyLfUn7T8rNS2ESO1JlJpkDdsdd8C4TyleAIYFfuBwqZ6 +bwhawPIQXPYxtN+hUPFtwDG9EtvYYMBIOz4Muix1quuWumPBfPmNhA32xBJl6pmd +hREBpdnvvKfS8GKPq/iYAou51a7+GIRNpFPibffyqWgz0W4c5VAkMW9GQl4uBc/x +YVbzOULUUXOObkzx1nR/CumPeAJtfzIJlP2TKteCAmWYyuMq6MliqTSeEOn5aFQf +iAurUoVvpclfC/+Sitw3WRvoc/IwNjOqZtae81o9ppaDr9/387KSeWd6QbzdB+j/ +ckrMqm43N8P68WuA3PvrZlc7alRA1IXiKPsbjPGwvqlDBKPPTVlqlcp8HOMPQ4iF +U6noii34cBGu8LRdNUOe9fT/WCxCV0IY6R4mUtMpqqml2wbUYsF9I4SpIQhwmWwQ +Ck+3YXbx+sqkl2VsI8kRVfx9usx6KC795291LWP+oRqI6G/QOpS5ZDHRgDujvwmY +1WxR4nNdXK5z97156JXxeAXA6yNvHvaCagIE7dYyugR0yyZUKfeJBdXEk2pqN5+e +XUQjCNsWvBncfIt6lDhOSHnMt/2IAfhf4MttetjuRRrdPyX1lDNo5d7IcKaNIkFV +1H35HmcfLTSrXkbGGiAm1i+znQk7ojvMIMKUF25shCIjHsngdmTkZdWf3ClzojWp +cF55vXTuGj3mIjCdnLugG6fcJVTPpdgRlYWnwqBLuJxEfbooV/p9vnMjd/eUYGeW +QJzCdMtGb4N+baWv4QAsDABSIVSYKbGIyHBTUTF4ncyX56bYTiva2iiJEDSGoWPA +ewwiJsHeRRXxg91Pv+mHYlInURF2M0vTFcUaP9k= +=eNGJ +-----END PGP MESSAGE----- + +--238e1f2946e87ccd3d1b58ba507ed7ab--