* Split cmd_user() and cmd_pass() into frontend/backend functions
[citadel.git] / citadel / serv_smtp.c
1 /* $Id$ */
2 #include "sysdep.h"
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <fcntl.h>
7 #include <signal.h>
8 #include <pwd.h>
9 #include <errno.h>
10 #include <sys/types.h>
11 #include <sys/time.h>
12 #include <sys/wait.h>
13 #include <string.h>
14 #include <limits.h>
15 #include "citadel.h"
16 #include "server.h"
17 #include <time.h>
18 #include "sysdep_decls.h"
19 #include "citserver.h"
20 #include "support.h"
21 #include "config.h"
22 #include "dynloader.h"
23 #include "room_ops.h"
24 #include "user_ops.h"
25 #include "policy.h"
26 #include "database.h"
27 #include "msgbase.h"
28 #include "tools.h"
29
30 struct citsmtp {
31         int command_state;
32 };
33
34 enum {
35         smtp_command,
36         smtp_user,
37         smtp_password
38 };
39
40 #define SMTP ((struct citsmtp *)CtdlGetUserData(SYM_SMTP))
41
42 long SYM_SMTP;
43
44
45 /*
46  * Here's where our SMTP session begins its happy day.
47  */
48 void smtp_greeting(void) {
49
50         strcpy(CC->cs_clientname, "Citadel SMTP");
51         CtdlAllocUserData(SYM_SMTP, sizeof(struct citsmtp));
52
53         cprintf("220 Welcome to the Citadel/UX ESMTP server at %s\n",
54                 config.c_fqdn);
55 }
56
57
58 /*
59  * Implement HELO and EHLO commands.
60  */
61 void smtp_hello(char *argbuf, int is_esmtp) {
62
63         if (!is_esmtp) {
64                 cprintf("250 Greetings and joyous salutations.\n");
65         }
66         else {
67                 cprintf("250-Greetings and joyous salutations.\n");
68                 cprintf("250-HELP\n");
69                 cprintf("250-SIZE %ld\n", config.c_maxmsglen);
70                 cprintf("250 AUTH=LOGIN\n");
71         }
72 }
73
74
75 /*
76  * Implement HELP command.
77  */
78 void smtp_help(void) {
79         cprintf("214-Here's the frequency, Kenneth:\n");
80         cprintf("214-    EHLO\n");
81         cprintf("214-    HELO\n");
82         cprintf("214-    HELP\n");
83         cprintf("214-    NOOP\n");
84         cprintf("214-    QUIT\n");
85         cprintf("214 I'd tell you more, but then I'd have to kill you.\n");
86 }
87
88
89 /*
90  *
91  */
92 void smtp_get_user(char *argbuf) {
93         char buf[256];
94         char username[256];
95
96         decode_base64(username, argbuf);
97         lprintf(9, "Trying <%s>\n", username);
98         if (CtdlLoginExistingUser(username) == login_ok) {
99                 encode_base64(buf, "Password:");
100                 cprintf("334 %s\n", buf);
101                 SMTP->command_state = smtp_password;
102         }
103         else {
104                 cprintf("500 No such user.\n");
105                 SMTP->command_state = smtp_command;
106         }
107 }
108
109
110 /*
111  *
112  */
113 void smtp_get_pass(char *argbuf) {
114         char password[256];
115
116         decode_base64(password, argbuf);
117         lprintf(9, "Trying <%s>\n", password);
118         if (CtdlTryPassword(password) == pass_ok) {
119                 cprintf("235 Authentication successful.\n");
120                 lprintf(9, "SMTP auth login successful\n");
121         }
122         else {
123                 cprintf("500 Authentication failed.\n");
124         }
125         SMTP->command_state = smtp_command;
126 }
127
128
129 /*
130  *
131  */
132 void smtp_auth(char *argbuf) {
133         char buf[256];
134
135         if (strncasecmp(argbuf, "login", 5) ) {
136                 cprintf("500 We only support LOGIN authentication.\n");
137                 return;
138         }
139
140         if (strlen(argbuf) >= 7) {
141                 smtp_get_user(&argbuf[6]);
142         }
143
144         else {
145                 encode_base64(buf, "Username:");
146                 cprintf("334 %s\n", buf);
147                 SMTP->command_state = smtp_user;
148         }
149 }
150
151
152 /* 
153  * Main command loop for SMTP sessions.
154  */
155 void smtp_command_loop(void) {
156         char cmdbuf[256];
157
158         time(&CC->lastcmd);
159         memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
160         if (client_gets(cmdbuf) < 1) {
161                 lprintf(3, "SMTP socket is broken.  Ending session.\n");
162                 CC->kill_me = 1;
163                 return;
164         }
165         lprintf(5, "citserver[%3d]: %s\n", CC->cs_pid, cmdbuf);
166         while (strlen(cmdbuf) < 5) strcat(cmdbuf, " ");
167
168         if (SMTP->command_state == smtp_user) {
169                 smtp_get_user(cmdbuf);
170         }
171
172         else if (SMTP->command_state == smtp_password) {
173                 smtp_get_pass(cmdbuf);
174         }
175
176         else if (!strncasecmp(cmdbuf, "AUTH", 4)) {
177                 smtp_auth(&cmdbuf[5]);
178         }
179
180         else if (!strncasecmp(cmdbuf, "EHLO", 4)) {
181                 smtp_hello(&cmdbuf[5], 1);
182         }
183
184         else if (!strncasecmp(cmdbuf, "HELO", 4)) {
185                 smtp_hello(&cmdbuf[5], 0);
186         }
187
188         else if (!strncasecmp(cmdbuf, "HELP", 4)) {
189                 smtp_help();
190         }
191
192         else if (!strncasecmp(cmdbuf, "NOOP", 4)) {
193                 cprintf("250 This command successfully did nothing.\n");
194         }
195
196         else if (!strncasecmp(cmdbuf, "QUIT", 4)) {
197                 cprintf("221 Goodbye...\n");
198                 CC->kill_me = 1;
199                 return;
200                 }
201
202         else {
203                 cprintf("500 I'm afraid I can't do that, Dave.\n");
204         }
205
206 }
207
208
209
210 char *Dynamic_Module_Init(void)
211 {
212         SYM_SMTP = CtdlGetDynamicSymbol();
213         CtdlRegisterServiceHook(25,
214                                 smtp_greeting,
215                                 smtp_command_loop);
216         return "$Id$";
217 }