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

Diff of /imapfilter/file.c

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

revision 1.47 by lefcha, Fri Feb 21 18:31:29 2003 UTC revision 1.48 by lefcha, Sat Feb 22 16:06:41 2003 UTC
# Line 25  extern char *home; Line 25  extern char *home;
25    
26  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
27  char *passphr;                  /* Master password to access the passwords  char *passphr;                  /* Master password to access the passwords
28                                     file. */                                   * file. */
29    
30  #endif  #endif
31    
32    
33  /*  /*
34   * Find the path to configuration file, open it and call parse_config().   * Find the path to configuration file, open it and call parse_config().
35   */   */
36  int read_config(char *cfg)  int
37    read_config(char *cfg)
38  {  {
39      int r;          int r;
40      FILE *fd;          FILE *fd;
41      char *c = NULL;          char *c;
42    
43      if (!cfg) {          c = NULL;
44          cfg = c = (char *)xmalloc(PATH_MAX * sizeof(char));  
45          snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");          if (cfg == NULL) {
46      }                  cfg = c = (char *)xmalloc(PATH_MAX * sizeof(char));
47                    snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");
48            }
49  #ifdef DEBUG  #ifdef DEBUG
50      fprintf(stderr, "debug: configuration file: '%s'\n", cfg);          fprintf(stderr, "debug: configuration file: '%s'\n", cfg);
51  #endif  #endif
52  #ifdef CHECK_PERMISSIONS  #ifdef CHECK_PERMISSIONS
53      check_file_perms(cfg, S_IRUSR | S_IWUSR);          check_file_perms(cfg, S_IRUSR | S_IWUSR);
54  #endif  #endif
55      fd = fopen(cfg, "r");          fd = fopen(cfg, "r");
56            if (fd == NULL)
57      if (!fd)                  fatal(ERROR_FILE_OPEN, "opening config file %s; %s\n", cfg,
58          fatal(ERROR_FILE_OPEN, "imapfilter: opening config file %s; %s\n",                      strerror(errno));
59                cfg, strerror(errno));  
60            if (c != NULL)
61                    xfree(c);
62    
63            if ((r = parse_config(fd)))
64                    fatal(ERROR_CONFIG_PARSE,
65                        "parse error in config file at row %d\n", r);
66    
67      if (c)          fclose(fd);
         xfree(c);  
   
     if ((r = parse_config(fd)))  
         fatal(ERROR_CONFIG_PARSE,  
               "imapfilter: parse error in config file at row %d\n", r);  
   
     fclose(fd);  
68    
69  #ifdef DEBUG  #ifdef DEBUG
70      fprintf(stderr, "debug: options: %0#10x '%s'\n", options, charset);          fprintf(stderr, "debug: options: %0#10x '%s'\n", options, charset);
71  #endif  #endif
72    
73      return 0;          return 0;
74  }  }
75    
76    
77  /*  /*
78   * Parse configuration file.   * Parse configuration file.
79   */   */
80  int parse_config(FILE * fd)  int
81    parse_config(FILE * fd)
82  {  {
83      int i, r = 0;          int i, r;
84      unsigned int row = 0;          unsigned int row;
85      char line[LINE_MAX];          char line[LINE_MAX];
86      regex_t creg[13];          regex_t creg[13];
87      regmatch_t match[11];          regmatch_t match[11];
88      const char *reg[13] = {          const char *reg[13] = {
89          "^([[:blank:]]*\n|#.*\n)$",                  "^([[:blank:]]*\n|#.*\n)$",
90    
91          "^[[:blank:]]*ACCOUNT[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"                  "^[[:blank:]]*ACCOUNT[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
92          "(([[:graph:]]+):([[:graph:]]*)|([[:graph:]]+))@([[:alnum:].-]+)"                  "(([[:graph:]]+):([[:graph:]]*)|([[:graph:]]+))@"
93          "(:[[:digit:]]+)?[[:blank:]]*([[:blank:]]SSL|[[:blank:]]SSL2|"                  "([[:alnum:].-]+)(:[[:digit:]]+)?[[:blank:]]*"
94          "[[:blank:]]SSL3|[[:blank:]]TLS1)?[[:blank:]]*\n$",                  "([[:blank:]]SSL|[[:blank:]]SSL2|[[:blank:]]SSL3|"
95                    "[[:blank:]]TLS1)?[[:blank:]]*\n$",
96          "^[[:blank:]]*FOLDER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"  
97          "([[:print:]]+)[[:blank:]]*\n$",                  "^[[:blank:]]*FOLDER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
98                    "([[:print:]]+)[[:blank:]]*\n$",
99          "^[[:blank:]]*FILTER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]*"  
100          "([[:blank:]]OR|[[:blank:]]AND)?[[:blank:]]*\n$",                  "^[[:blank:]]*FILTER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]*"
101                    "([[:blank:]]OR|[[:blank:]]AND)?[[:blank:]]*\n$",
102          "^[[:blank:]]*ACTION[[:blank:]]+(DELETE|"  
103          "COPY[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|"                  "^[[:blank:]]*ACTION[[:blank:]]+(DELETE|"
104          "MOVE[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|"                  "COPY[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|"
105          "RCOPY[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"                  "MOVE[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|"
106          "(\"[[:print:]]*\"|[[:graph:]]+)|"                  "RCOPY[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
107          "RMOVE[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"                  "(\"[[:print:]]*\"|[[:graph:]]+)|"
108          "(\"[[:print:]]*\"|[[:graph:]]+)|"                  "RMOVE[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
109          "FLAG[[:blank:]]+(REPLACE|ADD|REMOVE)[[:blank:]]+"                  "(\"[[:print:]]*\"|[[:graph:]]+)|"
110          "([[:alpha:],]+)|"                  "FLAG[[:blank:]]+(REPLACE|ADD|REMOVE)[[:blank:]]+"
111          "LIST)[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",                  "([[:alpha:],]+)|"
112                    "LIST)[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",
113          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"  
114          "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"                  "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
115          "(ANSWERED|DELETED|DRAFT|FLAGGED|NEW|OLD|RECENT|SEEN|UNANSWERED|"                  "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
116          "UNDELETED|UNDRAFT|UNFLAGGED|UNSEEN)[[:blank:]]*\n$",                  "(ANSWERED|DELETED|DRAFT|FLAGGED|NEW|OLD|RECENT|SEEN|"
117                    "UNANSWERED|UNDELETED|UNDRAFT|UNFLAGGED|UNSEEN)[[:blank:]]*\n$",
118          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"  
119          "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"                  "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
120          "(BCC|BODY|CC|FROM|SUBJECT|TEXT|TO)[[:blank:]]+(\"[[:print:]]*\"|"                  "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
121          "[[:graph:]]+)[[:blank:]]*\n$",                  "(BCC|BODY|CC|FROM|SUBJECT|TEXT|TO)[[:blank:]]+"
122                    "(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",
123          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"  
124          "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"                  "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
125          "(HEADER)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]+"                  "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
126          "(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",                  "(HEADER)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)"
127                    "[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",
128          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"  
129          "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"                  "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
130          "(LARGER|SMALLER|OLDER|NEWER)[[:blank:]]+([[:digit:]]+)"                  "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
131          "[[:blank:]]*\n$",                  "(LARGER|SMALLER|OLDER|NEWER)[[:blank:]]+([[:digit:]]+)"
132                    "[[:blank:]]*\n$",
133          "^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+"  
134          "([[:alnum:],_-]+)[[:blank:]]*\n$",                  "^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+"
135                    "([[:alnum:],_-]+)[[:blank:]]*\n$",
136          "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE|CHARSET)"  
137          "[[:blank:]]*=[[:blank:]]*(\"[[:print:]]*\"|[[:graph:]]+)"                  "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE|CHARSET)"
138          "[[:blank:]]*\n$",                  "[[:blank:]]*=[[:blank:]]*(\"[[:print:]]*\"|[[:graph:]]+)"
139                    "[[:blank:]]*\n$",
140          "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(ERRORS|EXPUNGE|HEADERS|"  
141          "NAMESPACE|SUBSCRIBE|WARNING)[[:blank:]]*=[[:blank:]]*(YES|NO)"                  "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(ERRORS|EXPUNGE|"
142          "[[:blank:]]*\n$",                  "HEADERS|NAMESPACE|SUBSCRIBE|WARNING)[[:blank:]]*=[[:blank:]]*"
143                    "(YES|NO)[[:blank:]]*\n$",
144          "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(DAEMON|TIMEOUT)"  
145          "[[:blank:]]*=[[:blank:]]*([[:digit:]]+)\n$"                  "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(DAEMON|TIMEOUT)"
146      };                  "[[:blank:]]*=[[:blank:]]*([[:digit:]]+)\n$"
147            };
148      for (i = 0; i < 13; i++)  
149          regcomp(&creg[i], reg[i], REG_EXTENDED | REG_ICASE);          r = row = 0;
150    
151      /* First process all the variables.  This is done because some variables'          for (i = 0; i < 13; i++)
152         arguments are used before the other commands are processed. */                  regcomp(&creg[i], reg[i], REG_EXTENDED | REG_ICASE);
153      while (fgets(line, LINE_MAX - 1, fd))  
154          if (!regexec(&creg[10], line, 4, match, 0) ||          /* First process all the variables.  This is done because some
155              !regexec(&creg[11], line, 4, match, 0) ||           * variables' arguments are used before the other commands are
156              !regexec(&creg[12], line, 4, match, 0))           * processed. */
157              set_options(line, match);          while (fgets(line, LINE_MAX - 1, fd))
158                    if (!regexec(&creg[10], line, 4, match, 0) ||
159      /* Then rewind and process everything else. */                      !regexec(&creg[11], line, 4, match, 0) ||
160      fseek(fd, 0L, SEEK_SET);                      !regexec(&creg[12], line, 4, match, 0))
161      while (fgets(line, LINE_MAX - 1, fd)) {                          set_options(line, match);
         row++;  
         if (!regexec(&creg[0], line, 0, match, 0))  
             continue;  
         else if (!regexec(&creg[1], line, 9, match, 0))  
             set_account(line, match);  
         else if (!regexec(&creg[2], line, 3, match, 0))  
             r = set_mboxgrp(line, match);  
         else if (!regexec(&creg[3], line, 3, match, 0))  
             r = set_filter(line, match);  
         else if (!regexec(&creg[4], line, 11, match, 0))  
             r = set_action(line, match);  
         else if (!regexec(&creg[5], line, 5, match, 0))  
             r = set_mask(line, match, MASK_MATCH_1);  
         else if (!regexec(&creg[6], line, 6, match, 0))  
             r = set_mask(line, match, MASK_MATCH_2);  
         else if (!regexec(&creg[7], line, 7, match, 0))  
             r = set_mask(line, match, MASK_MATCH_3);  
         else if (!regexec(&creg[8], line, 6, match, 0))  
             r = set_mask(line, match, MASK_MATCH_4);  
         else if (!regexec(&creg[9], line, 3, match, 0))  
             r = set_job(line, match);  
         /* Skip variable processing. */  
         else if (!regexec(&creg[10], line, 4, match, 0) ||  
                  !regexec(&creg[11], line, 4, match, 0) ||  
                  !regexec(&creg[12], line, 4, match, 0));  
         else  
             return row;  
   
         if (r == ERROR_CONFIG_PARSE)  
             return row;  
     }  
162    
163      for (i = 0; i < 13; i++)          /* Then rewind and process everything else. */
164          regfree(&creg[i]);          fseek(fd, 0L, SEEK_SET);
165            while (fgets(line, LINE_MAX - 1, fd)) {
166                    row++;
167                    if (!regexec(&creg[0], line, 0, match, 0))
168                            continue;
169                    else if (!regexec(&creg[1], line, 9, match, 0))
170                            set_account(line, match);
171                    else if (!regexec(&creg[2], line, 3, match, 0))
172                            r = set_mboxgrp(line, match);
173                    else if (!regexec(&creg[3], line, 3, match, 0))
174                            r = set_filter(line, match);
175                    else if (!regexec(&creg[4], line, 11, match, 0))
176                            r = set_action(line, match);
177                    else if (!regexec(&creg[5], line, 5, match, 0))
178                            r = set_mask(line, match, MASK_MATCH_1);
179                    else if (!regexec(&creg[6], line, 6, match, 0))
180                            r = set_mask(line, match, MASK_MATCH_2);
181                    else if (!regexec(&creg[7], line, 7, match, 0))
182                            r = set_mask(line, match, MASK_MATCH_3);
183                    else if (!regexec(&creg[8], line, 6, match, 0))
184                            r = set_mask(line, match, MASK_MATCH_4);
185                    else if (!regexec(&creg[9], line, 3, match, 0))
186                            r = set_job(line, match);
187                    /* Skip variable processing. */
188                    else if (!regexec(&creg[10], line, 4, match, 0) ||
189                                !regexec(&creg[11], line, 4, match, 0) ||
190                        !regexec(&creg[12], line, 4, match, 0));
191                    else
192                            return row;
193    
194                    if (r == ERROR_CONFIG_PARSE)
195                            return row;
196            }
197    
198      destroy_data();          for (i = 0; i < 13; i++)
199                    regfree(&creg[i]);
200    
201      return 0;          destroy_data();
202    
203            return 0;
204  }  }
205    
206    
207  /*  /*
208   * Set other options found in config file.   * Set other options found in config file.
209   */   */
210  void set_options(char *line, regmatch_t * match)  void
211    set_options(char *line, regmatch_t * m)
212  {  {
213      if (!strncasecmp(line + match[2].rm_so, "logfile", 7)) {          if (!strncasecmp(line + m[2].rm_so, "logfile", 7)) {
214          if (!*logfile) {                  if (*logfile == '\0') {
215              if (*(line + match[3].rm_so) == '"' &&                          if (*(line + m[3].rm_so) == '"' &&
216                  *(line + match[3].rm_eo - 1) == '"')                              *(line + m[3].rm_eo - 1) == '"')
217                  strncat(logfile, line + match[3].rm_so + 1,                                  strncat(logfile, line + m[3].rm_so + 1,
218                          min((match[3].rm_eo - match[3].rm_so - 2),                                      min((m[3].rm_eo - m[3].rm_so - 2),
219                              PATH_MAX - 1));                                          PATH_MAX - 1));
220              else                          else
221                  strncat(logfile, line + match[3].rm_so,                                  strncat(logfile, line + m[3].rm_so,
222                          min((match[3].rm_eo - match[3].rm_so),                                      min((m[3].rm_eo - m[3].rm_so),
223                              PATH_MAX - 1));                                          PATH_MAX - 1));
224          }                  }
225      } else if (!strncasecmp(line + match[2].rm_so, "charset", 7)) {          } else if (!strncasecmp(line + m[2].rm_so, "charset", 7)) {
226          if (*(line + match[3].rm_so) == '"' &&                  if (*(line + m[3].rm_so) == '"' &&
227              *(line + match[3].rm_eo - 1) == '"')                      *(line + m[3].rm_eo - 1) == '"')
228              strncat(charset, line + match[3].rm_so + 1,                          strncat(charset, line + m[3].rm_so + 1,
229                      min((match[3].rm_eo - match[3].rm_so - 2),                              min((m[3].rm_eo - m[3].rm_so - 2),
230                          CHARSET_LEN - 1));                                  CHARSET_LEN - 1));
231          else                  else
232              strncat(charset, line + match[3].rm_so,                          strncat(charset, line + m[3].rm_so,
233                      min((match[3].rm_eo - match[3].rm_so), CHARSET_LEN - 1));                              min((m[3].rm_eo - m[3].rm_so), CHARSET_LEN - 1));
234      } else if (!strncasecmp(line + match[2].rm_so, "errors", 6)) {          } else if (!strncasecmp(line + m[2].rm_so, "errors", 6)) {
235          if (!strncasecmp(line + match[3].rm_so, "yes", 3))                  if (!strncasecmp(line + m[3].rm_so, "yes", 3))
236              options |= OPTION_ERRORS;                          options |= OPTION_ERRORS;
237          else                  else
238              options &= ~(OPTION_ERRORS);                          options &= ~(OPTION_ERRORS);
239      } else if (!strncasecmp(line + match[2].rm_so, "expunge", 7)) {          } else if (!strncasecmp(line + m[2].rm_so, "expunge", 7)) {
240          if (!strncasecmp(line + match[3].rm_so, "yes", 3))                  if (!strncasecmp(line + m[3].rm_so, "yes", 3))
241              options |= OPTION_EXPUNGE;                          options |= OPTION_EXPUNGE;
242          else                  else
243              options &= ~(OPTION_EXPUNGE);                          options &= ~(OPTION_EXPUNGE);
244      } else if (!strncasecmp(line + match[2].rm_so, "header", 6)) {          } else if (!strncasecmp(line + m[2].rm_so, "header", 6)) {
245          if (!strncasecmp(line + match[3].rm_so, "yes", 3))                  if (!strncasecmp(line + m[3].rm_so, "yes", 3))
246              options |= OPTION_HEADERS;                          options |= OPTION_HEADERS;
247          else                  else
248              options &= ~(OPTION_HEADERS);                          options &= ~(OPTION_HEADERS);
249      } else if (!strncasecmp(line + match[2].rm_so, "namespace", 9)) {          } else if (!strncasecmp(line + m[2].rm_so, "namespace", 9)) {
250          if (!strncasecmp(line + match[3].rm_so, "yes", 3))                  if (!strncasecmp(line + m[3].rm_so, "yes", 3))
251              options |= OPTION_NAMESPACE;                          options |= OPTION_NAMESPACE;
252          else                  else
253              options &= ~(OPTION_NAMESPACE);                          options &= ~(OPTION_NAMESPACE);
254      } else if (!strncasecmp(line + match[2].rm_so, "subscribe", 9)) {          } else if (!strncasecmp(line + m[2].rm_so, "subscribe", 9)) {
255          if (!strncasecmp(line + match[3].rm_so, "yes", 3))                  if (!strncasecmp(line + m[3].rm_so, "yes", 3))
256              options |= OPTION_SUBSCRIBE;                          options |= OPTION_SUBSCRIBE;
257          else                  else
258              options &= ~(OPTION_SUBSCRIBE);                          options &= ~(OPTION_SUBSCRIBE);
259      } else if (!strncasecmp(line + match[2].rm_so, "warning", 7)) {          } else if (!strncasecmp(line + m[2].rm_so, "warning", 7)) {
260          if (!strncasecmp(line + match[3].rm_so, "yes", 3))                  if (!strncasecmp(line + m[3].rm_so, "yes", 3))
261              options |= OPTION_WARNING;                          options |= OPTION_WARNING;
262          else                  else
263              options &= ~(OPTION_WARNING);                          options &= ~(OPTION_WARNING);
264      } else if (!strncasecmp(line + match[2].rm_so, "timeout", 7)) {          } else if (!strncasecmp(line + m[2].rm_so, "timeout", 7)) {
265          errno = 0;                  errno = 0;
266          timeout = strtol(line + match[3].rm_so, NULL, 10);                  timeout = strtol(line + m[3].rm_so, NULL, 10);
267          if (errno)                  if (errno)
268              timeout = 0;                          timeout = 0;
269      } else if (!strncasecmp(line + match[2].rm_so, "daemon", 6) &&          } else if (!strncasecmp(line + m[2].rm_so, "daemon", 6) &&
270                 !(options & OPTION_DAEMON_MODE)) {              !(options & OPTION_DAEMON_MODE)) {
271          options |= OPTION_DAEMON_MODE;                  options |= OPTION_DAEMON_MODE;
272          errno = 0;                  errno = 0;
273          interval = strtoul(line + match[3].rm_so, NULL, 10);                  interval = strtoul(line + m[3].rm_so, NULL, 10);
274          if (errno)                  if (errno)
275              interval = 0;                          interval = 0;
276      }          }
277  }  }
278    
279    
# Line 272  void set_options(char *line, regmatch_t Line 281  void set_options(char *line, regmatch_t
281  /*  /*
282   * Open password file and call parse_passwords().   * Open password file and call parse_passwords().
283   */   */
284  int read_passwords(void)  int
285    read_passwords(void)
286  {  {
287      FILE *fd;          FILE *fd;
288      char pwfile[PATH_MAX];          char pwfile[PATH_MAX];
289    
290      if (!(flags & FLAG_BLANK_PASSWORD))          if (!(flags & FLAG_BLANK_PASSWORD))
291          return ERROR_CONFIG_PARSE;                  return ERROR_CONFIG_PARSE;
292    
293      passphr = (char *)smalloc(PASSPHRASE_LEN);          passphr = (char *)smalloc(PASSPHRASE_LEN);
294      *passphr = 0;          *passphr = '\0';
295    
296      snprintf(pwfile, PATH_MAX, "%s/%s", home, ".imapfilter/passwords");          snprintf(pwfile, PATH_MAX, "%s/%s", home, ".imapfilter/passwords");
297  #ifdef DEBUG  #ifdef DEBUG
298      fprintf(stderr, "debug: passwords file: '%s'\n", pwfile);          fprintf(stderr, "debug: passwords file: '%s'\n", pwfile);
299  #endif  #endif
300    
301      if (!exists_file(pwfile))          if (!exists_file(pwfile))
302          return ERROR_FILE_OPEN;                  return ERROR_FILE_OPEN;
303    
304  #ifdef CHECK_PERMISSIONS  #ifdef CHECK_PERMISSIONS
305      check_file_perms(pwfile, S_IRUSR | S_IWUSR);          check_file_perms(pwfile, S_IRUSR | S_IWUSR);
306  #endif  #endif
307    
308      fd = fopen(pwfile, "r");          fd = fopen(pwfile, "r");
309            if (fd == NULL)
310      if (!fd)                  fatal(ERROR_FILE_OPEN, "opening passwords file %s; %s\n",
311          fatal(ERROR_FILE_OPEN, "imapfilter: opening passwords file %s; %s\n",                      pwfile, strerror(errno));
               pwfile, strerror(errno));  
312    
313      parse_passwords(fd);          parse_passwords(fd);
314    
315      fclose(fd);          fclose(fd);
316    
317      return 0;          return 0;
318  }  }
319    
320    
321  /*  /*
322   *  Parse unencrypted password file.   *  Parse unencrypted password file.
323   */   */
324  int parse_passwords(FILE * fd)  int
325    parse_passwords(FILE * fd)
326  {  {
327      int t = 3;          int t;
328      char *pe = NULL;          char *pe;
329      char user[USERNAME_LEN], serv[SERVER_LEN];          char user[USERNAME_LEN], serv[SERVER_LEN];
330      unsigned char *buf;          unsigned char *buf;
331      char *c, *cp, *line;          char *c, *cp, *line;
332      regex_t creg;          regex_t creg;
333      regmatch_t match[4];          regmatch_t match[4];
334      const char *reg = "([[:alnum:].-]+) ([[:graph:]]+) ([[:graph:]]+)";          const char *reg;
335      int r;          int r;
336    
337      do {          t = 3;
338          fseek(fd, 0L, SEEK_SET);          pe = NULL;
339          printf("Enter master passphrase: ");          reg = "([[:alnum:].-]+) ([[:graph:]]+) ([[:graph:]]+)";
340          get_password(passphr, PASSPHRASE_LEN);  
341      } while ((r = decrypt_passwords(&buf, fd)) && --t);  
342            do {
343      if (!t)                  fseek(fd, 0L, SEEK_SET);
344          return ERROR_PASSPHRASE;                  printf("Enter master passphrase: ");
345                    get_password(passphr, PASSPHRASE_LEN);
346      c = cp = sstrdup(buf);          } while ((r = decrypt_passwords(&buf, fd)) && --t != 0);
347    
348      regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);          if (!t)
349                    return ERROR_PASSPHRASE;
350      line = strtok_r(c, "\n", &c);  
351      while (line && !regexec(&creg, line, 4, match, 0)) {          c = cp = sstrdup(buf);
352          user[0] = serv[0] = 0;  
353            regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
354          strncat(serv, line + match[1].rm_so,  
355                  min(match[1].rm_eo - match[1].rm_so, SERVER_LEN - 1));          line = strtok_r(c, "\n", &c);
356          strncat(user, line + match[2].rm_so,          while (line != NULL && !regexec(&creg, line, 4, match, 0)) {
357                  min(match[2].rm_eo - match[2].rm_so, USERNAME_LEN - 1));                  user[0] = serv[0] = '\0';
358    
359                    strncat(serv, line + match[1].rm_so,
360                        min(match[1].rm_eo - match[1].rm_so, SERVER_LEN - 1));
361                    strncat(user, line + match[2].rm_so,
362                        min(match[2].rm_eo - match[2].rm_so, USERNAME_LEN - 1));
363    
364                    if ((pe = (char *)find_password(user, serv)))
365                            strncat(pe, line + match[3].rm_so,
366                                min(match[3].rm_eo - match[3].rm_so,
367                                    PASSWORD_LEN - 1));
368    
369          if ((pe = (char *)find_password(user, serv)))                  line = strtok_r(NULL, "\n", &c);
370              strncat(pe, line + match[3].rm_so,          }
                     min(match[3].rm_eo - match[3].rm_so, PASSWORD_LEN - 1));  
   
         line = strtok_r(NULL, "\n", &c);  
     }  
371    
372      regfree(&creg);          regfree(&creg);
373      sfree(cp);          sfree(cp);
374      sfree(buf);          sfree(buf);
375    
376      return 0;          return 0;
377  }  }
378    
379    
380  /*  /*
381   * Store encrypted passwords to file.   * Store encrypted passwords to file.
382   */   */
383  int store_passwords(account_t * accts[])  int
384    store_passwords(account_t * accts[])
385  {  {
386      char pwfile[PATH_MAX];          char pwfile[PATH_MAX];
387      FILE *fd;          FILE *fd;
388    
389      snprintf(pwfile, PATH_MAX, "%s/%s", home, ".imapfilter/passwords");          snprintf(pwfile, PATH_MAX, "%s/%s", home, ".imapfilter/passwords");
390    
391      create_file(pwfile, S_IRUSR | S_IWUSR);          create_file(pwfile, S_IRUSR | S_IWUSR);
392    
393      fd = fopen(pwfile, "w");          fd = fopen(pwfile, "w");
394    
395      if (!fd)          if (fd == NULL)
396          fatal(ERROR_FILE_OPEN, "imapfilter: opening passwords file %s; %s\n",                  fatal(ERROR_FILE_OPEN, "opening passwords file %s; %s\n",
397                pwfile, strerror(errno));                      pwfile, strerror(errno));
398    
399      encrypt_passwords(fd, accts);          encrypt_passwords(fd, accts);
400    
401      fclose(fd);          fclose(fd);
402    
403      return 0;          return 0;
404  }  }
405    
406  #endif                          /* ENCRYPTED_PASSWORDS */  #endif                          /* ENCRYPTED_PASSWORDS */
407    
408    
409  /*  /*
410   * Create $HOME/.imapfilter directory.   * Create $HOME/.imapfilter directory.
411   */   */
412  int create_homedir(void)  int
413    create_homedir(void)
414  {  {
415      char *hdn = ".imapfilter";          char *hdn;
416    
417      if (home)          hdn = ".imapfilter";
         if (chdir(home))  
             error("imapfilter: could not change directory; %s\n",  
                   strerror(errno));  
418    
419      if (!exists_dir(hdn))          if (home != NULL)
420          if (mkdir(hdn, S_IRUSR | S_IWUSR | S_IXUSR))                  if (chdir(home))
421              error("imapfilter: could not create directory %s; %s\n", hdn,                          error("could not change directory; %s\n",
422                    strerror(errno));                              strerror(errno));
423    
424            if (!exists_dir(hdn))
425                    if (mkdir(hdn, S_IRUSR | S_IWUSR | S_IXUSR))
426                            error("could not create directory %s; %s\n", hdn,
427                                strerror(errno));
428    
429      return 0;          return 0;
430  }  }
431    
432    
433  /*  /*
434   * Check if a file exists.   * Check if a file exists.
435   */   */
436  int exists_file(char *fname)  int
437    exists_file(char *fname)
438  {  {
439      struct stat fs;          struct stat fs;
440    
441      if (access(fname, F_OK))          if (access(fname, F_OK))
442          return 0;                  return 0;
443    
444      stat(fname, &fs);          stat(fname, &fs);
445      if (!S_ISREG(fs.st_mode)) {          if (!S_ISREG(fs.st_mode)) {
446          error("imapfilter: file %s not a regular file\n", fname);                  error("file %s not a regular file\n", fname);
447          return ERROR_FILE_OPEN;                  return ERROR_FILE_OPEN;
448      }          }
449      return 1;          return 1;
450  }  }
451    
452    
453  /*  /*
454   * Check if a directory exists.   * Check if a directory exists.
455   */   */
456  int exists_dir(char *dname)  int
457    exists_dir(char *dname)
458  {  {
459      struct stat ds;          struct stat ds;
460    
461      if (access(dname, F_OK))          if (access(dname, F_OK))
462          return 0;                  return 0;
463    
464      stat(dname, &ds);          stat(dname, &ds);
465      if (!S_ISDIR(ds.st_mode)) {          if (!S_ISDIR(ds.st_mode)) {
466          error("imapfilter: file %s not a directory\n", dname);                  error("file %s not a directory\n", dname);
467          return ERROR_FILE_OPEN;                  return ERROR_FILE_OPEN;
468      }          }
469      return 1;          return 1;
470  }  }
471    
472    
473  /*  /*
474   * Create a file with the specified permissions.   * Create a file with the specified permissions.
475   */   */
476  int create_file(char *fname, mode_t mode)  int
477    create_file(char *fname, mode_t mode)
478  {  {
479      int fd = 0;          int fd;
480    
481            fd = 0;
482    
483      if (!exists_file(fname)) {          if (!exists_file(fname)) {
484          fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode);                  fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode);
485          if (fd == -1) {                  if (fd == -1) {
486              error("imapfilter: could not create file %s; %s\n", fname,                          error("could not create file %s; %s\n", fname,
487                    strerror(errno));                              strerror(errno));
488              return ERROR_FILE_OPEN;                          return ERROR_FILE_OPEN;
489          }                  }
490          close(fd);                  close(fd);
491      }          }
492      return 0;          return 0;
493  }  }
494    
495    
# Line 471  int create_file(char *fname, mode_t mode Line 497  int create_file(char *fname, mode_t mode
497  /*  /*
498   * Check the permissions of a file.   * Check the permissions of a file.
499   */   */
500  int check_file_perms(char *fname, mode_t mode)  int
501    check_file_perms(char *fname, mode_t mode)
502  {  {
503      struct stat fs;          struct stat fs;
504    
505      if (stat(fname, &fs)) {          if (stat(fname, &fs)) {
506          error("imapfilter: getting file %s status; %s\n", fname,                  error("getting file %s status; %s\n", fname,
507                strerror(errno));                      strerror(errno));
508          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
509      }          }
510      if (!S_ISREG(fs.st_mode)) {          if (!S_ISREG(fs.st_mode)) {
511          error("imapfilter: file %s not a regular file\n", fname);                  error("file %s not a regular file\n", fname);
512          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
513      }          }
514      if ((fs.st_mode & 00777) != mode) {          if ((fs.st_mode & 00777) != mode) {
515          error("imapfilter: warning: improper file %s permissions\n"                  error("warning: improper file %s permissions\n", fname);
516                "imapfilter: warning: file's mode should be %o not %o\n",                  error("warning: file's mode should be %o not %o\n", mode,
517                fname, mode, fs.st_mode & 00777);                      fs.st_mode & 00777);
518          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
519      }          }
520      return 0;          return 0;
521  }  }
522    
523    
524  /*  /*
525   * Check the permissions of a directory.   * Check the permissions of a directory.
526   */   */
527  int check_dir_perms(char *dname, mode_t mode)  int
528    check_dir_perms(char *dname, mode_t mode)
529  {  {
530      struct stat ds;          struct stat ds;
531    
532      if (stat(dname, &ds)) {          if (stat(dname, &ds)) {
533          error("imapfilter: getting file %s status; %s\n", dname,                  error("getting file %s status; %s\n", dname,
534                strerror(errno));                      strerror(errno));
535          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
536      }          }
537      if (!S_ISDIR(ds.st_mode)) {          if (!S_ISDIR(ds.st_mode)) {
538          error("imapfilter: file %s not a directory\n", dname);                  error("file %s not a directory\n", dname);
539          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
540      }          }
541      if ((ds.st_mode & 00777) != mode) {          if ((ds.st_mode & 00777) != mode) {
542          error("imapfilter: warning: improper dir %s permissions\n"                  error("warning: improper dir %s permissions\n", dname);
543                "imapfilter: warning: file's mode should be %o not %o\n",                  error("warning: file's mode should be %o not %o\n", mode,
544                dname, mode, ds.st_mode & 00777);                      ds.st_mode & 00777);
545          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
546      }          }
547      return 0;          return 0;
548  }  }
549    
550  #endif                          /* CHECK_PERMISSIONS */  #endif                          /* CHECK_PERMISSIONS */

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.48

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26