Line data Source code
1 12 : int pop_capa(LOGGER log, CONNECTION* client, DATABASE* database){
2 12 : CLIENT* client_data = (CLIENT*)client->aux_data;
3 12 : LISTENER* listener_data = (LISTENER*)client_data->listener->aux_data;
4 :
5 12 : logprintf(log, LOG_DEBUG, "Client requested capability listing\n");
6 :
7 12 : client_send(log, client, "+OK Capability listing\r\n");
8 :
9 : //allow tls-only auth
10 : #ifndef CMAIL_NO_TLS
11 12 : if(client->tls_mode == TLS_ONLY || !listener_data->tls_require){
12 : #endif
13 10 : client_send(log, client, "UIDL\r\n");
14 10 : client_send(log, client, "USER\r\n");
15 10 : client_send(log, client, "SASL LOGIN\r\n");
16 : #ifndef CMAIL_NO_TLS
17 : }
18 : #endif
19 :
20 : #ifndef CMAIL_NO_TLS
21 : //do not announce when already in tls or no tls possible
22 12 : if(client->tls_mode == TLS_NONE && client_data->listener->tls_mode == TLS_NEGOTIATE){
23 2 : client_send(log, client, "STLS\r\n");
24 : }
25 : #endif
26 :
27 12 : client_send(log, client, "IMPLEMENTATION %s\r\n", VERSION);
28 12 : client_send(log, client, "XYZZY\r\n", VERSION);
29 12 : client_send(log, client, ".\r\n", VERSION);
30 :
31 12 : return 0;
32 : }
33 :
34 0 : int pop_stat(LOGGER log, CONNECTION* client, DATABASE* database){
35 0 : unsigned maildrop_bytes = 0, i;
36 0 : CLIENT* client_data = (CLIENT*)client->aux_data;
37 :
38 : //calculate maildrop size
39 0 : for(i = 0; i < client_data->maildrop.count; i++){
40 0 : maildrop_bytes += client_data->maildrop.mails[i].mail_size;
41 : }
42 :
43 0 : client_send(log, client, "+OK %d %d\r\n", client_data->maildrop.count, maildrop_bytes);
44 0 : return 0;
45 : }
46 :
47 0 : int pop_list(LOGGER log, CONNECTION* client, DATABASE* database, unsigned mail){
48 : unsigned i;
49 0 : CLIENT* client_data = (CLIENT*)client->aux_data;
50 :
51 0 : if(mail == 0){
52 : //list all mail, multiline
53 0 : client_send(log, client, "+OK Scan listing follows\r\n");
54 0 : for(i = 0; i < client_data->maildrop.count; i++){
55 0 : if(!client_data->maildrop.mails[i].flag_delete){
56 0 : client_send(log, client, "%d %d\r\n", i + 1, client_data->maildrop.mails[i].mail_size);
57 : }
58 : }
59 0 : client_send(log, client, ".\r\n");
60 : }
61 0 : else if(mail <= client_data->maildrop.count){
62 0 : if(client_data->maildrop.mails[mail - 1].flag_delete){
63 0 : client_send(log, client, "-ERR Mail marked for deletion\r\n");
64 0 : return -1;
65 : }
66 : else{
67 0 : client_send(log, client, "+OK %d %d\r\n", mail, client_data->maildrop.mails[mail - 1].mail_size);
68 : }
69 : }
70 : else{
71 0 : client_send(log, client, "-ERR No such mail\r\n");
72 0 : return -1;
73 : }
74 :
75 0 : return 0;
76 : }
77 :
78 0 : int pop_uidl(LOGGER log, CONNECTION* client, DATABASE* database, unsigned mail){
79 : unsigned i;
80 0 : CLIENT* client_data = (CLIENT*)client->aux_data;
81 :
82 0 : if(mail == 0){
83 : //list all mail, multiline
84 0 : client_send(log, client, "+OK UID listing follows\r\n");
85 0 : for(i = 0; i < client_data->maildrop.count; i++){
86 0 : if(!client_data->maildrop.mails[i].flag_delete){
87 0 : client_send(log, client, "%d %s\r\n", i + 1, client_data->maildrop.mails[i].message_id);
88 : }
89 : }
90 0 : client_send(log, client, ".\r\n");
91 : }
92 0 : else if(mail <= client_data->maildrop.count){
93 0 : if(client_data->maildrop.mails[mail - 1].flag_delete){
94 0 : client_send(log, client, "-ERR Mail marked for deletion\r\n");
95 0 : return -1;
96 : }
97 : else{
98 0 : client_send(log, client, "+OK %d %s\r\n", mail, client_data->maildrop.mails[mail - 1].message_id);
99 : }
100 : }
101 : else{
102 0 : client_send(log, client, "-ERR No such mail\r\n");
103 0 : return -1;
104 : }
105 :
106 0 : return 0;
107 : }
108 :
109 0 : int pop_retr(LOGGER log, CONNECTION* client, DATABASE* database, unsigned mail){
110 0 : CLIENT* client_data = (CLIENT*)client->aux_data;
111 : sqlite3_stmt* fetch_stmt;
112 0 : char* mail_data = NULL;
113 0 : char* mail_bytestuff = NULL;
114 :
115 0 : if(mail == 0 || mail>client_data->maildrop.count){
116 0 : client_send(log, client, "-ERR No such mail\r\n");
117 0 : return -1;
118 : }
119 0 : else if(client_data->maildrop.mails[mail - 1].flag_delete){
120 0 : client_send(log, client, "-ERR Mail marked for deletion\r\n");
121 0 : return -1;
122 : }
123 :
124 0 : if(client_data->maildrop.mails[mail - 1].flag_master){
125 0 : fetch_stmt = database->fetch_master;
126 : }
127 : else{
128 0 : fetch_stmt = client_data->maildrop.fetch_user;
129 : }
130 :
131 0 : if(sqlite3_bind_int(fetch_stmt, 1, client_data->maildrop.mails[mail - 1].database_id) == SQLITE_OK){
132 0 : switch(sqlite3_step(fetch_stmt)){
133 : case SQLITE_ROW:
134 0 : client_send(log, client, "+OK Here it comes\r\n");
135 0 : mail_data = (char*)sqlite3_column_text(fetch_stmt, 0);
136 0 : if(mail_data[0] == '.'){
137 0 : client_send(log, client, ".");
138 : }
139 : do{
140 0 : mail_bytestuff = strstr(mail_data, "\r\n.");
141 0 : if(mail_bytestuff){
142 : //logprintf(log, LOG_DEBUG, "Sending %d intermediate bytes\n", mail_bytestuff-mail_data);
143 0 : client_send_raw(log, client, mail_data, mail_bytestuff - mail_data);
144 0 : client_send(log, client, "\r\n..");
145 0 : mail_data=mail_bytestuff + 3;
146 : }
147 : else{
148 : //logprintf(log, LOG_DEBUG, "Sending %d bytes message data\n", strlen(mail_data));
149 0 : client_send_raw(log, client, mail_data, strlen(mail_data));
150 : }
151 : }
152 0 : while(mail_bytestuff);
153 0 : break;
154 : default:
155 0 : logprintf(log, LOG_WARNING, "Failed to fetch mail: %s\n", sqlite3_errmsg(database->conn));
156 0 : client_send(log, client, "-ERR Failed to fetch mail\r\n");
157 0 : break;
158 : }
159 : }
160 :
161 0 : sqlite3_reset(fetch_stmt);
162 0 : sqlite3_clear_bindings(fetch_stmt);
163 :
164 0 : client_send(log, client, "\r\n.\r\n");
165 0 : return 0;
166 : }
167 :
168 8 : int pop_quit(LOGGER log, CONNECTION* client, DATABASE* database){
169 8 : CLIENT* client_data = (CLIENT*)client->aux_data;
170 :
171 8 : if(client_data->state == STATE_TRANSACTION){
172 : //update the maildrop
173 4 : if(maildrop_update(log, database, &(client_data->maildrop), client_data->auth.user.authorized) < 0){
174 0 : client_send(log, client, "-ERR Failed to update the maildrop\r\n");
175 : }
176 : else{
177 4 : client_send(log, client, "+OK Maildrop updated\r\n");
178 : }
179 : }
180 : else{
181 4 : client_send(log, client, "+OK No change\r\n");
182 : }
183 :
184 8 : return client_close(log, client, database);
185 : }
186 :
187 0 : int pop_dele(LOGGER log, CONNECTION* client, DATABASE* database, unsigned mail){
188 0 : CLIENT* client_data = (CLIENT*)client->aux_data;
189 :
190 0 : if(mail > client_data->maildrop.count || mail < 1){
191 0 : client_send(log, client, "-ERR No such mail\r\n");
192 0 : return -1;
193 : }
194 :
195 0 : if(client_data->maildrop.mails[mail - 1].flag_delete){
196 0 : client_send(log, client, "-ERR Message already deleted\r\n");
197 0 : return -1;
198 : }
199 :
200 : //add a mark in the deletion table
201 0 : if(maildrop_mark(log, database, client_data->auth.user.authorized, &(client_data->maildrop), mail - 1) < 0){
202 0 : logprintf(log, LOG_ERROR, "Failed to mark message as deleted: %s");
203 : }
204 :
205 0 : client_data->maildrop.mails[mail - 1].flag_delete = true;
206 0 : client_send(log, client, "+OK Marked for deletion\r\n");
207 :
208 0 : return 0;
209 : }
210 :
211 0 : int pop_rset(LOGGER log, CONNECTION* client, DATABASE* database){
212 0 : unsigned i = 0;
213 0 : CLIENT* client_data = (CLIENT*)client->aux_data;
214 :
215 : //reset all deletion marks in the master database deletion table
216 0 : if(maildrop_unmark(log, database->conn, database->unmark_deletions, client_data->auth.user.authorized) < 0){
217 0 : logprintf(log, LOG_ERROR, "Failed to reset the master database deletion marks\n");
218 0 : client_send(log, client, "-ERR Internal error resetting\r\n");
219 0 : return 0;
220 : }
221 :
222 0 : if(client_data->maildrop.user_conn && maildrop_unmark(log, client_data->maildrop.user_conn, client_data->maildrop.unmark_deletions, client_data->auth.user.authorized) < 0){
223 0 : logprintf(log, LOG_ERROR, "Failed to reset the user database deletion marks\n");
224 0 : client_send(log, client, "-ERR Internal error resetting\r\n");
225 0 : return 0;
226 : }
227 :
228 0 : for(i = 0; i < client_data->maildrop.count; i++){
229 0 : client_data->maildrop.mails[i].flag_delete = false;
230 : }
231 :
232 0 : client_send(log, client, "+OK Deletion flags cleared\r\n");
233 0 : return 0;
234 : }
235 :
236 4 : int pop_xyzzy(LOGGER log, CONNECTION* client, DATABASE* database){
237 4 : CLIENT* client_data = (CLIENT*)client->aux_data;
238 :
239 4 : logprintf(log, LOG_INFO, "Client performs incantation\n");
240 : #ifndef CMAIL_NO_TLS
241 4 : logprintf(log, LOG_DEBUG, "Client TLS status: %s\n", tls_modestring(client->tls_mode));
242 : #endif
243 4 : logprintf(log, LOG_DEBUG, "Auth state: %s, Method: %s\n", client_data->auth.auth_ok ? "true":"false", client_data->auth.method==AUTH_USER ? "USER":"SASL");
244 4 : logprintf(log, LOG_DEBUG, "Authentication: %s, Authorization: %s\n", client_data->auth.user.authenticated ? client_data->auth.user.authenticated:"null", client_data->auth.user.authorized ? client_data->auth.user.authorized:"null");
245 4 : logprintf(log, LOG_DEBUG, "Connection score: %d\n", client_data->connection_score);
246 4 : client_send(log, client, "+OK Nothing happens\r\n");
247 4 : return 0;
248 : }
|