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

Diff of /imapfilter/passwd.c

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

revision 1.8 by lefcha, Sat Jul 13 22:31:37 2002 UTC revision 1.9 by lefcha, Sat Feb 22 16:06:41 2003 UTC
# Line 17  extern account_t *accounts; Line 17  extern account_t *accounts;
17    
18  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
19  extern char *passphr;  extern char *passphr;
20    
21  #endif  #endif
22    
23  /*  /*
24   * Get password from user interactively.   * Get password from user interactively.
25   */   */
26  void get_password(char *passwd, size_t pwlen)  void
27    get_password(char *passwd, size_t pwlen)
28  {  {
29      char *c;          char *c;
30    
31      tty_disable_echo();          tty_disable_echo();
32    
33      if (fgets(passwd, pwlen, stdin))          if (fgets(passwd, pwlen, stdin))
34          if ((c = strchr(passwd, '\n')))                  if ((c = strchr(passwd, '\n')))
35              *c = 0;                          *c = '\0';
36    
37      tty_restore();          tty_restore();
38    
39      putchar('\n');          putchar('\n');
40  }  }
41    
42    
43  #ifdef ENCRYPTED_PASSWORDS  #ifdef ENCRYPTED_PASSWORDS
44  /*  /*
45   * Encrypt and Base64 encode passwords.  Append the MD5 checksum of the passwords   * Encrypt and Base64 encode passwords.  Append the MD5 checksum of the
46   * before encrypting them.   * passwords before encrypting them.
47   */   */
48  int encrypt_passwords(FILE * fd, account_t * accts[])  int
49    encrypt_passwords(FILE * fd, account_t * accts[])
50  {  {
51      int i;          int i;
52      char *c;          char *c;
53      unsigned char iv[EVP_MAX_IV_LENGTH];          unsigned char iv[EVP_MAX_IV_LENGTH];
54      unsigned char *key;          unsigned char *key;
55      unsigned char buf[ENCRYPTION_BUF];          unsigned char buf[ENCRYPTION_BUF];
56      unsigned char ebuf[ENCRYPTION_BUF];          unsigned char ebuf[ENCRYPTION_BUF];
57      unsigned char bbuf[ENCRYPTION_BUF];          unsigned char bbuf[ENCRYPTION_BUF];
58      unsigned char mdv[EVP_MAX_MD_SIZE];          unsigned char mdv[EVP_MAX_MD_SIZE];
59      int mdl, ebufl, bbufl;          int mdl, ebufl, bbufl;
60      EVP_CIPHER_CTX ctx;          EVP_CIPHER_CTX ctx;
61      EVP_MD_CTX mdctx;          EVP_MD_CTX mdctx;
62      EVP_ENCODE_CTX bctx;          EVP_ENCODE_CTX bctx;
63    
64      key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);          key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
65    
66      srandom(time(NULL));          srandom(time(NULL));
67    
68      /* Initialization vector. */          /* Initialization vector. */
69      c = ultostr(1 + random() % 100000000, 10);          c = ultostr(1 + random() % 100000000, 10);
70      memset(iv, '0', EVP_MAX_IV_LENGTH);          memset(iv, '0', EVP_MAX_IV_LENGTH);
71      memcpy(iv + 8 - strlen(c), c, min(8, strlen(c)));          memcpy(iv + 8 - strlen(c), c, min(8, strlen(c)));
72      fprintf(fd, "%.8s\n", iv);          fprintf(fd, "%.8s\n", iv);
73    
74      EVP_CIPHER_CTX_init(&ctx);          EVP_CIPHER_CTX_init(&ctx);
75    
76      EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr), 1,          EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr), 1,
77                     key, NULL);              key, NULL);
78    
79      EVP_DigestInit(&mdctx, EVP_md5());          EVP_DigestInit(&mdctx, EVP_md5());
80      EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);          EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
81      EVP_EncodeInit(&bctx);          EVP_EncodeInit(&bctx);
82    
83      for (i = 0; accts[i]; i++) {          for (i = 0; accts[i] != NULL; i++) {
84          snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server, accts[i]->username,                  snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server,
85                   accts[i]->password);                      accts[i]->username, accts[i]->password);
86    
87                    EVP_DigestUpdate(&mdctx, buf, strlen(buf));
88                    EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
89                    EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
90    
91          EVP_DigestUpdate(&mdctx, buf, strlen(buf));                  fwrite(bbuf, sizeof(char), bbufl, fd);
92          EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));          }
         EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);  
   
         fwrite(bbuf, sizeof(char), bbufl, fd);  
     }  
93    
94      EVP_DigestFinal(&mdctx, mdv, &mdl);          EVP_DigestFinal(&mdctx, mdv, &mdl);
95    
96      xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);          xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
97    
98      /* MD5 checksum of data. */          /* MD5 checksum of data. */
99      for (i = 0; i < mdl; i++)          for (i = 0; i < mdl; i++)
100          snprintf(2 + buf + i * 2, ENCRYPTION_BUF - i * 2, "%02x", mdv[i]);                  snprintf(2 + buf + i * 2, ENCRYPTION_BUF - i * 2, "%02x",
101                        mdv[i]);
102    
103      EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));          EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
104      EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);          EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
105      fwrite(bbuf, sizeof(char), bbufl, fd);          fwrite(bbuf, sizeof(char), bbufl, fd);
106    
107      EVP_EncryptFinal(&ctx, ebuf, &ebufl);          EVP_EncryptFinal(&ctx, ebuf, &ebufl);
108      EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);          EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
109      EVP_EncodeFinal(&bctx, bbuf, &bbufl);          EVP_EncodeFinal(&bctx, bbuf, &bbufl);
110    
111      fwrite(bbuf, sizeof(char), bbufl, fd);          fwrite(bbuf, sizeof(char), bbufl, fd);
112    
113      EVP_CIPHER_CTX_cleanup(&ctx);          EVP_CIPHER_CTX_cleanup(&ctx);
114    
115      return 0;          return 0;
116  }  }
117    
118    
119  /*  /*
120   * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.   * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
121   */   */
122  int decrypt_passwords(unsigned char **buf, FILE * fd)  int
123    decrypt_passwords(unsigned char **buf, FILE * fd)
124  {  {
125      int i, j = 1;          int i, j;
126      unsigned char iv[EVP_MAX_IV_LENGTH];          unsigned char iv[EVP_MAX_IV_LENGTH];
127      unsigned char *key;          unsigned char *key;
128      unsigned char *c;          unsigned char *c;
129      unsigned char ebuf[LINE_MAX];          unsigned char ebuf[LINE_MAX];
130      unsigned char bbuf[LINE_MAX];          unsigned char bbuf[LINE_MAX];
131      unsigned char mdv[EVP_MAX_MD_SIZE];          unsigned char mdv[EVP_MAX_MD_SIZE];
132      unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];          unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
133      int mdl, bufl, ebufl;          int mdl, bufl, ebufl;
134      EVP_CIPHER_CTX *ctx;          EVP_CIPHER_CTX *ctx;
135      EVP_MD_CTX mdctx;          EVP_MD_CTX mdctx;
136      EVP_ENCODE_CTX bctx;          EVP_ENCODE_CTX bctx;
137    
138      c = *buf = (unsigned char *)smalloc(DECRYPTION_BUF * sizeof(char));          j = 1;
139      key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);  
140      ctx = (EVP_CIPHER_CTX *) smalloc(sizeof(EVP_CIPHER_CTX));          c = *buf = (unsigned char *)smalloc(DECRYPTION_BUF * sizeof(char));
141            key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
142      fgets(bbuf, LINE_MAX, fd);          ctx = (EVP_CIPHER_CTX *) smalloc(sizeof(EVP_CIPHER_CTX));
143    
144      memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);          fgets(bbuf, LINE_MAX, fd);
145    
146      EVP_CIPHER_CTX_init(ctx);          memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
147    
148      EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),          EVP_CIPHER_CTX_init(ctx);
149                     1, key, NULL);  
150            EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
151      EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);              1, key, NULL);
152      EVP_DecodeInit(&bctx);  
153            EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);
154      while (fgets(bbuf, LINE_MAX, fd)) {          EVP_DecodeInit(&bctx);
155          EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));  
156          if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl))          while (fgets(bbuf, LINE_MAX, fd)) {
157              goto fail;                  EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
158                    if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl))
159          c += bufl;                          goto fail;
160          *c = 0;  
161                    c += bufl;
162          if (c - *buf > DECRYPTION_BUF * j - 64) {                  *c = '\0';
163              i = c - *buf;  
164              *buf = (char *)srealloc(*buf, DECRYPTION_BUF * ++j);                  if (c - *buf > DECRYPTION_BUF * j - 64) {
165              c = *buf + i;                          i = c - *buf;
166              *c = 0;                          *buf = (char *)srealloc(*buf, DECRYPTION_BUF * ++j);
167                            c = *buf + i;
168                            *c = '\0';
169                    }
170          }          }
     }  
171    
172      EVP_DecodeFinal(&bctx, ebuf, &ebufl);          EVP_DecodeFinal(&bctx, ebuf, &ebufl);
173      if (!EVP_DecryptFinal(ctx, c, &bufl))          if (!EVP_DecryptFinal(ctx, c, &bufl))
174          goto fail;                  goto fail;
175    
176      c += bufl;          c += bufl;
177      *c = 0;          *c = '\0';
178    
179      /* Calculate the MD5 checksum and check if it is correct. */          /* Calculate the MD5 checksum and check if it is correct. */
180      if (!(c = strstr(*buf, "\n.\n")))          if (!(c = strstr(*buf, "\n.\n")))
181          goto fail;                  goto fail;
182    
183      EVP_DigestInit(&mdctx, EVP_md5());          EVP_DigestInit(&mdctx, EVP_md5());
184      EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);          EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
185      EVP_DigestFinal(&mdctx, mdv, &mdl);          EVP_DigestFinal(&mdctx, mdv, &mdl);
186    
187      for (i = 0; i < mdl; i++)          for (i = 0; i < mdl; i++)
188          snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x", mdv[i]);                  snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x",
189                        mdv[i]);
190    
191      c += 3;          c += 3;
192    
193      if (strncmp(c, mdc, 32))          if (strncmp(c, mdc, 32))
194          goto fail;                  goto fail;
195    
196      EVP_CIPHER_CTX_cleanup(ctx);          EVP_CIPHER_CTX_cleanup(ctx);
197    
198      sfree(key);          sfree(key);
199      sfree(ctx);          sfree(ctx);
200    
201      return 0;          return 0;
202    
203  fail:  fail:
204      error("Wrong master passphrase.\n");          error("Wrong master passphrase.\n");
205      EVP_CIPHER_CTX_cleanup(ctx);          EVP_CIPHER_CTX_cleanup(ctx);
206      sfree(*buf);          sfree(*buf);
207      sfree(key);          sfree(key);
208      sfree(ctx);          sfree(ctx);
209    
210      return ERROR_DECRYPT;          return ERROR_DECRYPT;
211  }  }
212    
213    
214  /*  /*
215   * Interactive encrypted passwords editor.   * Interactive encrypted passwords editor.
216   */   */
217  void password_editor(void)  void
218    password_editor(void)
219  {  {
220      int i, q, n;          int i, q, n;
221      char buf[LINE_MAX];          char buf[LINE_MAX];
222      char *c;          char *c;
223      char *p[2];          char *p[2];
224      account_t *a, *accts[EDITOR_PASSWORDS_MAX];          account_t *a, *accts[EDITOR_PASSWORDS_MAX];
225    
226      if (!(flags & FLAG_BLANK_PASSWORD)) {          if (!(flags & FLAG_BLANK_PASSWORD)) {
227          error("imapfilter: no candidate passwords for encryption found\n");                  error("no candidate passwords for encryption found\n");
228          return;                  return;
     }  
     q = 0;  
   
     memset(accts, 0, EDITOR_PASSWORDS_MAX);  
   
     for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX - 1 && a; a = a->next) {  
         if (a->passwdattr == PASSWORD_NONE ||  
             a->passwdattr == PASSWORD_ENCRYPTED)  
             accts[i++] = a;  
     }  
   
     do {  
         printf("command: ");  
         fgets(buf, LINE_MAX, stdin);  
         c = buf;  
         for (;; c++) {  
             if (*c == ' ' || *c == '\t')  
                 continue;  
             else if (*c == '?' || *c == 'h')  
                 printf("c       clear a password entry\n"  
                        "e       edit a password entry\n"  
                        "h       help\n"  
                        "l       list entries\n"  
                        "p       change master password\n"  
                        "q       quit without saving\n"  
                        "s       save changes\n"  
                        "x       save and exit\n");  
             else if (*c == 'q')  
                 q = 1;  
             else if (*c == 'l')  
                 for (i = 0; accts[i]; i++)  
                     printf("%d %s %s %s\n", i + 1, accts[i]->server,  
                            accts[i]->username, accts[i]->password);  
             else if (*c == 'e') {  
                 n = atoi(++c);  
                 if (!n || n < 1 || n > 128 || !accts[n - 1])  
                     break;  
                 accts[n - 1]->password[0] = 0;  
                 printf("Enter new password: ");  
                 if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))  
                     if ((c = strchr(accts[n - 1]->password, '\n')))  
                         *c = 0;  
             } else if (*c == 'c') {  
                 n = atoi(++c);  
                 if (!n || n < 1 || n > 128 || !accts[n - 1])  
                     break;  
                 accts[n - 1]->password[0] = 0;  
             } else if (*c == 'p') {  
                 p[0] = (char *)smalloc(PASSPHRASE_LEN);  
                 p[1] = (char *)smalloc(PASSPHRASE_LEN);  
                 do {  
                     for (i = 0; i < 2; i++) {  
                         printf("Enter %snew master password: ",  
                                i ? "again " : "");  
                         get_password(p[i], PASSPHRASE_LEN);  
                     }  
                 } while (strcmp(p[0], p[1]));  
                 xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);  
                 sfree(p[0]);  
                 sfree(p[1]);  
             } else if (*c == 's') {  
                 store_passwords(accts);  
             } else if (*c == 'x') {  
                 store_passwords(accts);  
                 q = 1;  
             } else  
                 break;  
229          }          }
230      } while (!q);          q = 0;
231    
232            memset(accts, 0, EDITOR_PASSWORDS_MAX);
233    
234            for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX - 1 && a != NULL;
235                a = a->next) {
236                    if (a->passwdattr == PASSWORD_NONE ||
237                        a->passwdattr == PASSWORD_ENCRYPTED)
238                            accts[i++] = a;
239            }
240    
241            do {
242                    printf("command: ");
243                    fgets(buf, LINE_MAX, stdin);
244                    c = buf;
245                    for (;; c++) {
246                            if (*c == ' ' || *c == '\t')
247                                    continue;
248                            else if (*c == '?' || *c == 'h')
249                                    printf("c\tclear a password entry\n"
250                                        "e\tedit a password entry\n"
251                                        "h\thelp\n"
252                                        "l\tlist entries\n"
253                                        "p\tchange master password\n"
254                                        "q\tquit without saving\n"
255                                        "s\tsave changes\n"
256                                        "x\tsave and exit\n");
257                            else if (*c == 'q')
258                                    q = 1;
259                            else if (*c == 'l')
260                                    for (i = 0; accts[i] != NULL; i++)
261                                            printf("%d %s %s %s\n", i + 1,
262                                                accts[i]->server,
263                                                accts[i]->username,
264                                                accts[i]->password);
265                            else if (*c == 'e') {
266                                    n = atoi(++c);
267                                    if (n == 0 || n < 1 || n > 128 ||
268                                        accts[n - 1] == NULL)
269                                            break;
270                                    accts[n - 1]->password[0] = '\0';
271                                    printf("Enter new password: ");
272                                    if (fgets(accts[n - 1]->password, PASSWORD_LEN,
273                                            stdin) &&
274                                        (c = strchr(accts[n - 1]->password, '\n')))
275                                            *c = '\0';
276                            } else if (*c == 'c') {
277                                    n = atoi(++c);
278                                    if (n == 0 || n < 1 || n > 128 ||
279                                        accts[n - 1] == NULL)
280                                            break;
281                                    accts[n - 1]->password[0] = '\0';
282                            } else if (*c == 'p') {
283                                    p[0] = (char *)smalloc(PASSPHRASE_LEN);
284                                    p[1] = (char *)smalloc(PASSPHRASE_LEN);
285                                    do {
286                                            for (i = 0; i < 2; i++) {
287                                                    printf("Enter %snew master "
288                                                        "password: ",
289                                                        i ? "again " : "");
290                                                    get_password(p[i],
291                                                        PASSPHRASE_LEN);
292                                            }
293                                    } while (strcmp(p[0], p[1]));
294                                    xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
295                                    sfree(p[0]);
296                                    sfree(p[1]);
297                            } else if (*c == 's') {
298                                    store_passwords(accts);
299                            } else if (*c == 'x') {
300                                    store_passwords(accts);
301                                    q = 1;
302                            } else
303                                    break;
304                    }
305            } while (!q);
306  }  }
307    
308  #endif  #endif                          /* ENCRYPTED_PASSWORDS */

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26