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

Diff of /imapfilter/passwd.c

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

revision 1.1 by lefcha, Sat Dec 8 14:47:01 2001 UTC revision 1.2 by lefcha, Mon Jan 14 18:12:38 2002 UTC
# Line 1  Line 1 
1  #include <stdio.h>  #include <stdio.h>
2  #include <string.h>  #include <string.h>
3    #include <stdlib.h>
4    #include <limits.h>
5    
6    #include "config.h"
7  #include "imapfilter.h"  #include "imapfilter.h"
8  #include "data.h"  #include "data.h"
9    
10    #ifdef ENCRYPTED_PASSWORDS
11    #include <openssl/evp.h>
12    #endif
13    
 static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
14    
15    extern account_t *accounts;
16    
17    #ifdef ENCRYPTED_PASSWORDS
18    extern char passphr[PASSPHRASE_LEN];
19    #endif
20    
21  /*  /*
22   * Get password from user interactively.   * Get password from user interactively.
23   */   */
24  void get_password(char *user, char *serv, char *passwd)  void get_password(char *passwd, size_t pwlen)
25  {  {
26      char *c;      char *c;
27        
28      tty_store();      tty_store();
       
     printf("Enter password for %s@%s: ", user, serv);  
       
29      tty_disable_echo();      tty_disable_echo();
30        
31      if (fgets(passwd, PASSWORD_LEN, stdin))      if (fgets(passwd, pwlen, stdin))
32          if ((c = strchr(passwd, '\n')))          if ((c = strchr(passwd, '\n')))
33              *c = 0;              *c = 0;
34        
35      tty_restore();      tty_restore();
36    
37      putchar('\n');      putchar('\n');
38  }  }
39    
40    
41    #ifdef ENCRYPTED_PASSWORDS
42  /*  /*
43   * Encode in base64/radix64 a sequence of three characters.   * Encrypt and Base64 encode passwords.  Append the MD5 checksum of the passwords
44     * before encrypting them.
45   */   */
46  char *base64_encode(char *dest, char *src, int n)  int encrypt_passwords(FILE *fd, account_t *accts[])
47  {  {
48      if (n == 2)      int i;    
49          src[2] = 0;      char *c;
50      if (n == 1)      unsigned char iv[EVP_MAX_IV_LENGTH];
51          src[1] = 0;      unsigned char key[EVP_MAX_KEY_LENGTH];
52            unsigned char buf[ENCRYPTION_BUF];
53      dest[0] = base64[src[0] >> 2];      unsigned char ebuf[ENCRYPTION_BUF];
54      dest[1] = base64[((src[0] & 0x03) << 4) | (src[1] >> 4)];      unsigned char bbuf[ENCRYPTION_BUF];
55      dest[2] = base64[((src[1] & 0x0f) << 2) | (src[2] >> 6)];      unsigned char mdv[EVP_MAX_MD_SIZE];
56      dest[3] = base64[src[2] & 0x3f];      int mdl, ebufl, bbufl;
57            EVP_CIPHER_CTX ctx;
58      if (n <= 2)      EVP_MD_CTX mdctx;
59          dest[3] = '=';      EVP_ENCODE_CTX bctx;
60      if (n <= 1)  
61          dest[2] = '=';      srandom(time(NULL));
62    
63        c = ultostr(1 + random() % 100000000, 10);
64        memset(iv, '0', EVP_MAX_IV_LENGTH);
65        memcpy(iv + 8 - strlen(c), c, min(8, strlen(c)));
66    
67        fprintf(fd, "%.8s\n", iv);
68    
69        EVP_CIPHER_CTX_init(&ctx);
70    
71        EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr), 1,
72                       key, NULL);
73            
74        EVP_DigestInit(&mdctx, EVP_md5());
75        EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
76        EVP_EncodeInit(&bctx);
77    
78        for (i = 0; accts[i]; i++) {
79            snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server, accts[i]->username,
80                     accts[i]->password);
81    
82            EVP_DigestUpdate(&mdctx, buf, strlen(buf));
83            EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
84            EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
85            
86            fwrite(bbuf, sizeof(char), bbufl, fd);
87        }
88    
89        EVP_DigestFinal(&mdctx, mdv, &mdl);
90        
91        xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
92        
93        for (i = 0; i < mdl; i++)
94            snprintf(2 + buf + i * 2, ENCRYPTION_BUF - i * 2, "%02x", mdv[i]);
95        
96        EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
97        EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
98        fwrite(bbuf, sizeof(char), bbufl, fd);
99        
100        EVP_EncryptFinal(&ctx, ebuf, &ebufl);
101        EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
102        EVP_EncodeFinal(&bctx, bbuf, &bbufl);
103        
104        fwrite(bbuf, sizeof(char), bbufl, fd);
105    
106        EVP_CIPHER_CTX_cleanup(&ctx);
107            
108      return dest;      return 0;
109  }  }
110    
111    
112  /*  /*
113   * Decode from base64/radix64 a sequence of four characters.   * Decode (Base64) and decrypt passwords and verify the MD5 checksum.
114   */   */
115  int base64_decode(char *dest, char *src)  int decrypt_passwords(unsigned char *buf, FILE *fd)
116  {  {
117      int n, i, t;      int i, j = 1;
118      char tmp[4];      unsigned char iv[EVP_MAX_IV_LENGTH];
119                unsigned char key[EVP_MAX_KEY_LENGTH];
120      if (src[2] == '=') {      unsigned char *c = buf;
121          n = 1;      unsigned char ebuf[LINE_MAX];
122          src[2] = src[3] = 0;      unsigned char bbuf[LINE_MAX];
123      } else if (src[3] == '=') {      unsigned char mdv[EVP_MAX_MD_SIZE];
124          n = 2;      unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
125          src[3] = 0;      int mdl, bufl, ebufl;
126      } else      EVP_CIPHER_CTX ctx;
127          n = 3;      EVP_MD_CTX mdctx;
128        EVP_ENCODE_CTX bctx;
129        
130        fgets(bbuf, LINE_MAX, fd);
131    
132        memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
133            
134      for (i = 0; i < 4; i++) {      EVP_CIPHER_CTX_init(&ctx);
135          t = strchr(base64, src[i]) - base64;  
136          if (t == 64)      EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
137              tmp[i] = 0;                     1, key, NULL);
138          else  
139              tmp[i] = t;      EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
140        EVP_DecodeInit(&bctx);
141    
142        while (fgets(bbuf, LINE_MAX, fd)) {
143            EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
144            if (!EVP_DecryptUpdate(&ctx, c, &bufl, ebuf, ebufl)) {
145                error("Wrong master passphrase.\n");
146                return 1;
147            }
148            
149            c += bufl;
150            *c = 0;
151            
152            if (c - buf < DECRYPTION_BUF * j - 64)
153                buf = (char *) xrealloc(buf, DECRYPTION_BUF * ++j);
154        }
155    
156        EVP_DecodeFinal(&bctx, ebuf, &ebufl);
157        if (!EVP_DecryptFinal(&ctx, c, &bufl)) {
158            fprintf(stderr, "Wrong master passphrase.\n");
159            return 1;
160      }      }
161            
162      dest[0] = (tmp[0] << 2) | (tmp[1] >> 4);      c += bufl;
163      dest[1] = (tmp[1] << 4) | (tmp[2] >> 2);      *c = 0;
164      dest[2] = (tmp[2] << 6) | tmp[3];      
165        if ((c = strstr(buf, "\n.\n"))) {
166            EVP_DigestInit(&mdctx, EVP_md5());
167            EVP_DigestUpdate(&mdctx, buf, c - buf + 1);
168            EVP_DigestFinal(&mdctx, mdv, &mdl);
169            
170            for (i = 0; i < mdl; i++)
171                snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x", mdv[i]);
172            putchar('\n');
173            
174            *c = 0;
175        } else
176            return 1;
177    
178        EVP_CIPHER_CTX_cleanup(&ctx);
179            
180      return n;      return 0;
181    }
182    
183    
184    /*
185     * Interactive encrypted passwords editor.
186     */
187    void password_editor(void)
188    {
189        int i, q, n;
190        char buf[LINE_MAX];
191        char *c;
192        char p[2][PASSPHRASE_LEN];
193        account_t *a, *accts[EDITOR_PASSWORDS_MAX];
194    
195        q = 0;
196    
197        for (i = 0; i < EDITOR_PASSWORDS_MAX; i++)
198            accts[i] = NULL;
199    
200        for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX && a; a = a->next) {
201            if (a->passwdattr == PASSWORD_NONE ||
202                a->passwdattr == PASSWORD_ENCRYPTED)
203                accts[i++] = a;
204        }
205    
206        do {
207            printf("command: ");
208            fgets(buf, LINE_MAX, stdin);
209            c = buf;
210            for (;; c++) {
211                if (*c == ' ' || *c == '\t')
212                    continue;
213                else if (*c == '?' || *c == 'h')
214                    printf("c       clear a password entry\n"
215                           "e       edit a password entry\n"
216                           "h       help\n"
217                           "l       list entries\n"
218                           "p       change master password\n"
219                           "q       quit without saving\n"
220                           "x       save and exit\n");
221                else if (*c == 'q')
222                    q = 1;
223                else if (*c == 'l')
224                    for (i = 0; accts[i]; i++)
225                        printf("%d %s %s %s\n", i + 1, accts[i]->server,
226                               accts[i]->username, accts[i]->password);
227                else if (*c == 'e') {
228                    n = atoi(++c);
229                    if (!n || n < 1 || n > 128 || !accts[n - 1])
230                        break;
231                    accts[n - 1]->password[0] = 0;
232                    printf("Enter new password: ");
233                    if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
234                        if ((c = strchr(accts[n - 1]->password, '\n')))
235                            *c = 0;
236                } else if (*c == 'c') {
237                    n = atoi(++c);
238                    if (!n || n < 1 || n > 128 || !accts[n - 1])
239                        break;
240                    accts[n - 1]->password[0] = 0;
241                } else if (*c == 'p') {
242                    do {
243                        for (i = 0; i < 2; i++) {
244                            printf("Enter %snew master password: ",
245                                   i ? "again " : "");
246                            get_password(p[i], PASSPHRASE_LEN);
247                        }
248                    } while (strcmp(p[0], p[1]));
249                    xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
250                } else if (*c == 'x') {
251                    store_passwords(accts);
252                    q = 1;
253                } else
254                    break;
255            }
256        } while (!q);
257  }  }
258    #endif

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26