Delta Chat Core C-Library
mrapeerstate.c
1 /*******************************************************************************
2  *
3  * Delta Chat Core
4  * Copyright (C) 2017 Björn Petersen
5  * Contact: r10s@b44t.com, http://b44t.com
6  *
7  * This program is free software: you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later
10  * version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program. If not, see http://www.gnu.org/licenses/ .
19  *
20  ******************************************************************************/
21 
22 
23 #include "mrmailbox_internal.h"
24 #include "mrapeerstate.h"
25 #include "mraheader.h"
26 
27 
28 /*******************************************************************************
29  * mrapeerstate_t represents the state of an Autocrypt peer - Load/save
30  ******************************************************************************/
31 
32 
33 static void mrapeerstate_empty(mrapeerstate_t* ths)
34 {
35  if( ths == NULL ) {
36  return;
37  }
38 
39  ths->m_last_seen = 0;
40  ths->m_last_seen_autocrypt = 0;
41  ths->m_prefer_encrypt = 0;
42  ths->m_to_save = 0;
43 
44  free(ths->m_addr);
45  ths->m_addr = NULL;
46 
47  if( ths->m_public_key->m_binary ) {
48  mrkey_unref(ths->m_public_key);
49  ths->m_public_key = mrkey_new();
50  }
51 }
52 
53 
54 int mrapeerstate_load_from_db__(mrapeerstate_t* ths, mrsqlite3_t* sql, const char* addr)
55 {
56  int success = 0;
57  sqlite3_stmt* stmt;
58 
59  if( ths==NULL || sql == NULL || addr == NULL ) {
60  return 0;
61  }
62 
63  mrapeerstate_empty(ths);
64 
65  stmt = mrsqlite3_predefine__(sql, SELECT_aclpp_FROM_acpeerstates_WHERE_a,
66  "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key FROM acpeerstates WHERE addr=? COLLATE NOCASE;");
67  sqlite3_bind_text(stmt, 1, addr, -1, SQLITE_STATIC);
68  if( sqlite3_step(stmt) != SQLITE_ROW ) {
69  goto cleanup;
70  }
71  ths->m_addr = safe_strdup((char*)sqlite3_column_text (stmt, 0));
72  ths->m_last_seen = sqlite3_column_int64 (stmt, 1);
73  ths->m_last_seen_autocrypt = sqlite3_column_int64 (stmt, 2);
74  ths->m_prefer_encrypt = sqlite3_column_int (stmt, 3);
75  mrkey_set_from_stmt (ths->m_public_key, stmt, 4, MR_PUBLIC);
76 
77  success = 1;
78 
79 cleanup:
80  return success;
81 }
82 
83 
84 int mrapeerstate_save_to_db__(const mrapeerstate_t* ths, mrsqlite3_t* sql, int create)
85 {
86  int success = 0;
87  sqlite3_stmt* stmt;
88 
89  if( ths==NULL || sql==NULL
90  || ths->m_addr==NULL || ths->m_public_key->m_binary==NULL || ths->m_public_key->m_bytes<=0 ) {
91  return 0;
92  }
93 
94  if( create ) {
95  stmt = mrsqlite3_predefine__(sql, INSERT_INTO_acpeerstates_a, "INSERT INTO acpeerstates (addr) VALUES(?);");
96  sqlite3_bind_text(stmt, 1, ths->m_addr, -1, SQLITE_STATIC);
97  sqlite3_step(stmt);
98  }
99 
100  if( (ths->m_to_save&MRA_SAVE_ALL) || create )
101  {
102  stmt = mrsqlite3_predefine__(sql, UPDATE_acpeerstates_SET_lcpp_WHERE_a,
103  "UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, prefer_encrypted=?, public_key=? WHERE addr=?;");
104  sqlite3_bind_int64(stmt, 1, ths->m_last_seen);
105  sqlite3_bind_int64(stmt, 2, ths->m_last_seen_autocrypt);
106  sqlite3_bind_int64(stmt, 3, ths->m_prefer_encrypt);
107  sqlite3_bind_blob (stmt, 4, ths->m_public_key->m_binary, ths->m_public_key->m_bytes, SQLITE_STATIC);
108  sqlite3_bind_text (stmt, 5, ths->m_addr, -1, SQLITE_STATIC);
109  if( sqlite3_step(stmt) != SQLITE_DONE ) {
110  goto cleanup;
111  }
112  }
113  else if( ths->m_to_save&MRA_SAVE_LAST_SEEN )
114  {
115  stmt = mrsqlite3_predefine__(sql, UPDATE_acpeerstates_SET_l_WHERE_a,
116  "UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=? WHERE addr=?;");
117  sqlite3_bind_int64(stmt, 1, ths->m_last_seen);
118  sqlite3_bind_int64(stmt, 2, ths->m_last_seen_autocrypt);
119  sqlite3_bind_text (stmt, 3, ths->m_addr, -1, SQLITE_STATIC);
120  if( sqlite3_step(stmt) != SQLITE_DONE ) {
121  goto cleanup;
122  }
123  }
124 
125  success = 1;
126 
127 cleanup:
128  return success;
129 }
130 
131 
132 /*******************************************************************************
133  * Main interface
134  ******************************************************************************/
135 
136 
137 mrapeerstate_t* mrapeerstate_new()
138 {
139  mrapeerstate_t* ths = NULL;
140 
141  if( (ths=calloc(1, sizeof(mrapeerstate_t)))==NULL ) {
142  exit(43); /* cannot allocate little memory, unrecoverable error */
143  }
144 
145  ths->m_public_key = mrkey_new();
146 
147  return ths;
148 }
149 
150 
151 void mrapeerstate_unref(mrapeerstate_t* ths)
152 {
153  if( ths==NULL ) {
154  return;
155  }
156 
157  free(ths->m_addr);
158  mrkey_unref(ths->m_public_key);
159  free(ths);
160 }
161 
162 
163 /*******************************************************************************
164  * Change state
165  ******************************************************************************/
166 
167 
168 int mrapeerstate_init_from_header(mrapeerstate_t* ths, const mraheader_t* header, time_t message_time)
169 {
170  if( ths == NULL || header == NULL ) {
171  return 0;
172  }
173 
174  mrapeerstate_empty(ths);
175  ths->m_addr = safe_strdup(header->m_addr);
176  ths->m_last_seen = message_time;
177  ths->m_last_seen_autocrypt = message_time;
178  ths->m_to_save = MRA_SAVE_ALL;
179  ths->m_prefer_encrypt = header->m_prefer_encrypt;
180  mrkey_set_from_key(ths->m_public_key, header->m_public_key);
181  return 1;
182 }
183 
184 
185 int mrapeerstate_degrade_encryption(mrapeerstate_t* ths, time_t message_time)
186 {
187  if( ths==NULL ) {
188  return 0;
189  }
190 
191  ths->m_prefer_encrypt = MRA_PE_RESET;
192  ths->m_last_seen = message_time; /*last_seen_autocrypt is not updated as there was not Autocrypt:-header seen*/
193  ths->m_to_save = MRA_SAVE_ALL;
194  return 1;
195 }
196 
197 
198 int mrapeerstate_apply_header(mrapeerstate_t* ths, const mraheader_t* header, time_t message_time)
199 {
200  if( ths==NULL || header==NULL
201  || ths->m_addr==NULL
202  || header->m_addr==NULL || header->m_public_key->m_binary==NULL
203  || strcasecmp(ths->m_addr, header->m_addr)!=0 ) {
204  return 0;
205  }
206 
207  if( message_time > ths->m_last_seen_autocrypt )
208  {
209  ths->m_last_seen = message_time;
210  ths->m_last_seen_autocrypt = message_time;
211  ths->m_to_save |= MRA_SAVE_LAST_SEEN;
212 
213  if( (header->m_prefer_encrypt==MRA_PE_MUTUAL || header->m_prefer_encrypt==MRA_PE_NOPREFERENCE) /*this also switches from MRA_PE_RESET to MRA_PE_NOPREFERENCE, which is just fine as the function is only called _if_ the Autocrypt:-header is preset at all */
214  && header->m_prefer_encrypt != ths->m_prefer_encrypt )
215  {
216  ths->m_prefer_encrypt = header->m_prefer_encrypt;
217  ths->m_to_save |= MRA_SAVE_ALL;
218  }
219 
220  if( !mrkey_equals(ths->m_public_key, header->m_public_key) )
221  {
222  mrkey_set_from_key(ths->m_public_key, header->m_public_key);
223  ths->m_to_save |= MRA_SAVE_ALL;
224  }
225  }
226 
227  return ths->m_to_save? 1 : 0;
228 }
229