/[imapfilter]/imapfilter/imapfilter.c
ViewVC logotype

Diff of /imapfilter/imapfilter.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.34.2.5 by lefcha, Fri Mar 28 16:57:52 2003 UTC revision 1.70 by lefcha, Sat Feb 14 23:09:20 2004 UTC
# Line 1  Line 1 
1  #include <stdio.h>  #include <stdio.h>
2  #include <stdlib.h>  #include <stdlib.h>
3    #include <sys/types.h>
4  #include <unistd.h>  #include <unistd.h>
5  #include <string.h>  #include <string.h>
 #include <limits.h>  
6  #include <errno.h>  #include <errno.h>
7    #include <limits.h>
8    #include <fcntl.h>
9  #include <setjmp.h>  #include <setjmp.h>
10    #include <locale.h>
11    
12  #include "config.h"  #include "config.h"
13  #include "imapfilter.h"  #include "imapfilter.h"
14  #include "data.h"  #include "version.h"
15    #include "account.h"
16    #include "filter.h"
17    #include "buffer.h"
18    
19  #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS  #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS || defined CRAM_MD5
20    #include <openssl/opensslv.h>
21  #include <openssl/crypto.h>  #include <openssl/crypto.h>
22  #endif  #endif
23    
24    
 extern int sockpri;  
25  extern account_t *accounts;  extern account_t *accounts;
26  extern filter_t *filters;  extern filter_t *filters;
27  extern namesp_t nsppri;  extern buffer_t ibuf, obuf;
28    
29  unsigned int options;           /* Program options. */  options_t opts;                 /* Program options. */
30  unsigned int flags = 0;         /* Program flags. */  unsigned int flags = 0;         /* Program flags. */
31  unsigned int capabilities;      /* Capabilities of mail server. */  
32  unsigned int interval = 0;      /* Poll at the specified interval. */  connection_t connpri, connaux;  /* Primary and auxiliary IMAP connection. */
33  char logfile[PATH_MAX];         /* Log file. */  
34  char *home = NULL;              /* User's home directory. */  char *home = NULL;              /* User's home directory. */
35  #ifdef MEMORY_LOCK  
36  uid_t ruid, euid;               /* Real and effective UID. */  jmp_buf acctloop;               /* Non-local exit in case of network error. */
37  #endif  
38  jmp_buf acctloop;  
39    void imapfilter(void);
40    void daemonize(void);
41    void usage(void);
42    void version(void);
43    
44    
45  /*  /*
46   * In the beginning there was main()...   * IMAPFilter: an IMAP mail filtering utility.
47   */   */
48  int main(int argc, char *argv[])  int
49    main(int argc, char *argv[])
50  {  {
51      int c, r, f = 0;          int c;
52      pid_t pid;          char *cf;
     char *confile = NULL;       /* Configuration file. */  
     account_t *ca;              /* Current account. */  
     mbox_t *cm;                 /* Current mailbox. */  
   
 #ifdef MEMORY_LOCK  
     ruid = getuid();  
     euid = geteuid();  
     seteuid(ruid);              /* Drop root privileges. */  
 #endif  
   
     home = getenv("HOME");  
     options = (OPTION_DETAILS_NORMAL | OPTION_NAMESPACE | OPTION_WARNING);  
     *logfile = 0;  
53    
54      while ((c = getopt(argc, argv, "c:d:hkl:"          setlocale(LC_ALL, "");
55    
56            opts.debug = 0;
57            opts.verbosity = 0;
58            opts.timeout = -1;
59            opts.daemon = 0;
60            opts.headers = 0;
61            opts.errors = 0;
62            opts.namespace = 1;
63            opts.expunge = 0;
64            opts.subscribe = 0;
65            opts.peek = 1;
66            opts.passwd_editor = 0;
67            opts.charset[0] = '\0';
68            opts.logfile[0] = '\0';
69            opts.force_protocol = PROTOCOL_NONE;
70    
71            home = getenv("HOME");
72            cf = NULL;
73            connpri.sock = connaux.sock = -1;
74    
75            while ((c = getopt(argc, argv, "DVc:d:kl:"
76  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
77                         "p"              "p"
78  #endif  #endif
79                         "qvV")) != -1) {              "qv")) != -1) {
80          switch (c) {                  switch (c) {
81          case 'c':                  case 'D':
82              confile = optarg;                          if (opts.debug < 2)
83              break;                                  opts.debug++;
84          case 'd':                          break;
85              options |= OPTION_DAEMON_MODE;                  case 'V':
86              errno = 0;                          version();
87              interval = strtoul(optarg, NULL, 10);                          /* NOTREACHED */
88              if (errno)                  case 'c':
89                  interval = 0;                          cf = optarg;
90              break;                          break;
91          case 'h':                  case 'd':
92              usage();                          errno = 0;
93              exit(ERROR_UNDEFINED);                          opts.daemon = strtoul(optarg, NULL, 10);
94              break;                          if (errno)
95          case 'k':                                  opts.daemon = 0;
96              kill_imapfilter();                          break;
97              break;                  case 'k':
98          case 'l':                          kill_imapfilter();
99              strncat(logfile, optarg, PATH_MAX - 1);                          break;
100              break;                  case 'l':
101                            strncat(opts.logfile, optarg, PATH_MAX - 1);
102                            break;
103  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
104          case 'p':                  case 'p':
105              options |= OPTION_PASSWORD_EDITOR;                          opts.passwd_editor = 1;
106              break;                          break;
107  #endif  #endif
108          case 'q':                  case 'q':
109              options &= OPTION_DETAILS_CLEAR;                          if (opts.verbosity > -2)
110              options |= OPTION_DETAILS_QUIET;                                  opts.verbosity--;
111              break;                          break;
112          case 'v':                  case 'v':
113              options &= OPTION_DETAILS_CLEAR;                          if (opts.verbosity < 2)
114              options |= OPTION_DETAILS_VERBOSE;                                  opts.verbosity++;
115              break;                          break;
116          case 'V':                  case '?':
117              version();                  default:
118              exit(ERROR_UNDEFINED);                          usage();
119              break;                          /* NOTREACHED */
120          default:                  }
             usage();  
             exit(ERROR_UNDEFINED);  
             break;  
121          }          }
     }  
122    
123      create_homedir();          debug_start();
124    
125            create_homedir();
126    
127      lockfile_check();          lockfile_check();
128      lockfile_create();          lockfile_create();
129    
130      corefile_disable();          if (!opts.debug)
131                    corefile_disable();
132    
133      tty_store();          tty_store();
     catch_signals();  
134    
135      read_config(confile);          catch_signals();
136    
137            read_config(cf);
138    
139  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
140      read_passwords();          read_passwords();
141    
142      if ((options & OPTION_PASSWORD_EDITOR)) {          if (opts.passwd_editor) {
143          password_editor();                  password_editor();
144    
145          secmem_clear();                  secmem_clear();
146          lockfile_remove();                  lockfile_remove();
147    
148          exit(0);                  exit(0);
149      }          }
150  #endif  #endif
151    
152      open_logfile();          log_start();
153    
154      init_vbuf();          buffer_init(&ibuf);
155            buffer_init(&obuf);
156    
157      if (options & OPTION_DAEMON_MODE) {          if (opts.daemon)
158          f = 1;                  opts.verbosity = -2;
         options &= OPTION_DETAILS_CLEAR;  
         options |= OPTION_DETAILS_QUIET;  
     }  
     do {  
         for (ca = accounts; ca; ca = ca->next) {  
159    
160              if (setjmp(acctloop))          do {
161                  continue;                  imapfilter();
162    
163                    if (opts.daemon && !(flags & FLAG_DAEMON))
164                            daemonize();
165                    if (opts.daemon && flags & FLAG_SIGUSR1) {
166                            reread_config(cf);
167                            continue;
168                    }
169                    if (opts.daemon > 0)
170                            sleep(opts.daemon);
171            } while (opts.daemon);
172    
173              if (init_connection(&sockpri, ca->server, ca->port, ca->ssl))          log_stop();
                 continue;  
174    
175              r = greeting_response(&sockpri);          secmem_clear();
176    
177              if (check_capabilities(&sockpri))          lockfile_remove();
                 continue;  
               
             log_info(LOG_ACCOUNT, ca->key);  
178    
179  #ifdef DEBUG          debug_stop();
180              test(&sockpri);  
181  #endif          exit(0);
182    }
183    
             if (r != RESPONSE_PREAUTH) {  
                 if (ca->passwdattr == PASSWORD_NONE) {  
                     printf("Enter password for %s@%s: ", ca->username,  
                            ca->server);  
                     get_password(ca->password, PASSWORD_LEN);  
                     ca->passwdattr = PASSWORD_PLAIN;  
                 }  
                 if (login(&sockpri, ca->username, ca->password) ==  
                     RESPONSE_NO) {  
                     error("imapfilter: username %s or password rejected "  
                           "at %s\n", ca->username, ca->server);  
                     continue;  
                 }  
             }  
             check_namespace(&sockpri, &nsppri);  
184    
185              for (cm = ca->mboxes; cm; cm = cm->next)  /*
186                  if (!*cm->filters)   * Go through all accounts and apply filters to mailboxes as defined.
187                      mailbox_status(&sockpri, cm->name, &nsppri);   */
188                  else if (!select_mailbox(&sockpri, cm->name, &nsppri)) {  void
189                      apply_filters(cm->filters);  imapfilter(void)
190                      close_mailbox(&sockpri);  {
191            int r;
192            account_t *ca;
193            mbox_t *cm;
194    
195            for (ca = accounts; ca != NULL; ca = ca->next) {
196    
197                    if (setjmp(acctloop))
198                            continue;
199    
200                    if (init_connection(&connpri, ca->server, ca->port, ca->ssl))
201                            continue;
202    
203                    r = response_greeting(&connpri);
204    
205                    if (opts.debug)
206                            test(&connpri);
207    
208                    if (check_capabilities(&connpri))
209                            continue;
210    
211    #ifdef SSL_TLS
212                    if (ca->ssl == SSL_DISABLED &&
213                        connpri.caps & CAPABILITY_STARTTLS)
214                            if (negotiate_tls(&connpri) == RESPONSE_OK)
215                                    check_capabilities(&connpri);
216    #endif
217    
218                    log_info(LOG_ACCOUNT, ca->key);
219    
220                    if (r != RESPONSE_PREAUTH) {
221                            if (ca->pass_attr == PASS_ATTR_NONE) {
222                                    printf("Enter password for %s@%s: ",
223                                        ca->user, ca->server);
224                                    get_password(ca->pass, PASS_LEN);
225                                    ca->pass_attr = PASS_ATTR_PLAIN;
226                            }
227    #ifdef CRAM_MD5
228                            if (connpri.caps & CAPABILITY_CRAMMD5)
229                                    r = auth_cram_md5(&connpri, ca->user, ca->pass);
230                            else
231    #endif
232                                    r = login(&connpri, ca->user, ca->pass);
233    
234                            if (r == RESPONSE_NO) {
235                                    error("username %s or password rejected "
236                                        "at %s\n", ca->user, ca->server);
237                                    continue;
238                            }
239                  }                  }
240              logout(&sockpri);                  check_namespace(&connpri);
241    
242                    for (cm = ca->mboxes; cm != NULL; cm = cm->next)
243                            if (*cm->filters == NULL)
244                                    mailbox_status(&connpri, cm->name);
245                            else if (!select_mailbox(&connpri, cm->name)) {
246                                    apply_filters(cm->name, cm->filters);
247                                    close_mailbox(&connpri);
248                            }
249                    logout(&connpri);
250    
251              close_connection(&sockpri);                  close_connection(&connpri);
252          }          }
253    }
254    
255          /* Fork if in daemon mode. */  
256          if (f) {  /*
257              f = 0;   * Fork if in daemon mode.
258              pid = fork();   */
259              switch (pid) {  void
260              case -1:  daemonize(void)
261                  fatal(ERROR_FORK, "imapfilter: forking; %s\n", strerror(errno));  {
262                  break;  
263              case 0:          switch (fork()) {
264  #ifdef MEMORY_LOCK                  case -1:
265                  secmem_lock();                  fatal(ERROR_FORK, "forking; %s\n", strerror(errno));
266                  setuid(ruid);   /* Capability to regain root privileges will                  break;
267                                     not be needed any more. */          case 0:
 #endif  
                 lockfile_create();  
                 corefile_disable();  
268                  break;                  break;
269              default:          default:
270                    log_stop();
271                  secmem_clear();                  secmem_clear();
272                  close_logfile();                  debug_stop();
273                  exit(0);                  exit(0);
274                  break;                  break;
             }  
275          }          }
         if (interval)  
             sleep(interval);  
     } while (options & OPTION_DAEMON_MODE && interval);  
276    
277      secmem_clear();          if (setsid() == -1)
278      close_logfile();                  fatal(ERROR_FORK, "creating session; %s\n", strerror(errno));
279    
280            switch (fork()) {
281            case -1:
282                    fatal(ERROR_FORK, "forking; %s\n", strerror(errno));
283                    break;
284            case 0:
285                    break;
286            default:
287                    log_stop();
288                    secmem_clear();
289                    debug_stop();
290                    exit(0);
291                    break;
292            }
293    
294      lockfile_remove();          close(STDIN_FILENO);
295            close(STDOUT_FILENO);
296            close(STDERR_FILENO);
297            if (open("/dev/null", O_RDWR) != -1) {
298                    dup(STDIN_FILENO);
299                    dup(STDIN_FILENO);
300            }
301            lockfile_create();
302            corefile_disable();
303    
304      exit(0);          flags |= FLAG_DAEMON;
305  }  }
306    
307    
308  /*  /*
309   * Print a very brief usage message.   * Print a very brief usage message.
310   */   */
311  void usage(void)  void
312    usage(void)
313  {  {
314      fprintf(stderr,  
315              "usage: imapfilter [-hk"          fprintf(stderr,
316                "usage: imapfilter [-DVbk"
317  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
318              "p"              "p"
319  #endif  #endif
320              "qvV] [-c configfile] [-d interval] [-l logfile]\n");              "qv] [-c configfile] [-d interval] [-l logfile]\n");
321    
322            exit(ERROR_UNDEFINED);
323  }  }
324    
325    
326  /*  /*
327   * Print program's version, and if it is built in, OpenSSL's version number.   * Print program's version, and if it is built in, OpenSSL's version number.
328   */   */
329  void version(void)  void
330    version(void)
331  {  {
332      fprintf(stderr, "IMAPFilter %s"  
333  #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS          fprintf(stderr, "IMAPFilter %s"
334    #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS || defined CRAM_MD5
335              ", OpenSSL 0x%8.8lx"              ", OpenSSL 0x%8.8lx"
336  #endif  #endif
337              "\n", IMAPFILTER_VERSION              "\n", IMAPFILTER_VERSION
338  #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS  #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS || defined CRAM_MD5
339              ,SSLeay()              ,SSLeay()
340  #endif  #endif
341      );          );
342    
343            exit(ERROR_UNDEFINED);
344  }  }

Legend:
Removed from v.1.34.2.5  
changed lines
  Added in v.1.70

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26