Checking code reworked to be more robust.
[cert-checker.git] / smtp.c
1 /******************************************************************************
2  * Filename: smtp.c
3  * Description: Simple smtp handling routines for cert-checker
4  *
5  * Version: 1.0
6  * Created: Oct 20 2010 17:31:31
7  * Last modified: Oct 20 2010 17:31:31
8  *
9  * Author: Ladislav L├íska
10  * e-mail: ladislav.laska@gmail.com
11  *
12  ******************************************************************************/
13
14 #define _XOPEN_SOURCE 500
15
16 #include <gnutls/gnutls.h>
17
18 #include <unistd.h>
19 #include <string.h>
20
21 #include "main.h"
22
23 /* Expect status code */
24 char* smtp_expect(int fd, char *str) {
25         char buffer[BUFFER_SIZE];
26         int len = strlen(str);
27         int bytes = read(fd, buffer, BUFFER_SIZE);
28         if (bytes < len) goto fail;
29         if (!strncmp(buffer,str,len)) {
30                 while (bytes == BUFFER_SIZE)
31                         bytes = read(fd, buffer, BUFFER_SIZE) > 0;
32                 return NULL;
33         }
34
35         fail:;
36         char *ptr = strdup(buffer);
37         while (bytes == BUFFER_SIZE)
38                 bytes = read(fd, buffer, BUFFER_SIZE) > 0;
39         return ptr;
40 }
41
42 /* Expect status code. This can be done better. */
43 char* ssl_smtp_expect(gnutls_session_t session, char *str) {
44         char buffer[BUFFER_SIZE];
45         int len = strlen(str);
46         int bytes = gnutls_record_recv(session, buffer, BUFFER_SIZE);
47         if (bytes < len) goto fail;
48         if (!strncmp(buffer,str,len)) {
49                 return NULL;
50         }
51
52         fail:;
53         return strdup(buffer);
54 }
55
56 /* Send EHLO and check for STARTTLS extension. */
57 int smtp_ehlo(int fd) {
58         return 0;
59 }
60
61 int smtp_starttls(int fd) {
62         smtp_expect(fd, "220"); /* Read everything in buffer */
63         char buffer[] = "STARTTLS\n";
64         write(fd, buffer, sizeof(buffer));
65         char *b;
66         if ((b = smtp_expect(fd, "220 "))) {
67                 dief("STARTTLS declined: %s.", b);
68         }
69         return 0;
70 }
71
72 /* Ugly, sending could fail and  other horrible things may happen. */
73 int smtp_quit(gnutls_session_t session) {
74         char buffer[] = "QUIT\n";
75         int sent = GNUTLS_E_AGAIN;
76         sent = gnutls_record_send(session, buffer, sizeof(buffer));
77         
78         ssl_smtp_expect(session, "221 ");
79
80         /* TODO: Better (read: some) error handling. */
81         return 0;
82 }