1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <libsec.h> 5 #include <bio.h> 6 #include "imap4d.h" 7 8 void 9 setupuser(void) 10 { 11 Waitmsg w; 12 int pid; 13 14 if(newns(username, 0) < 0) 15 bye("user login failed: %r"); 16 snprint(mboxDir, 3 * NAMELEN, "/mail/box/%s", username); 17 if(myChdir(mboxDir) < 0) 18 bye("can't open user's mailbox"); 19 20 switch(pid = fork()){ 21 case -1: 22 bye("can't initialize mail system"); 23 break; 24 case 0: 25 execl("/bin/upas/fs", "upas/fs", "-np", nil); 26 _exits(0); 27 break; 28 default: 29 break; 30 } 31 if(wait(&w) != pid || w.msg[0] != '\0') 32 bye("can't initialize mail system"); 33 } 34 35 void 36 initchal(Chalstate *ch) 37 { 38 ch->afd = -1; 39 ch->asfd = -1; 40 } 41 42 void 43 closechal(Chalstate *ch) 44 { 45 if(ch->afd >= 0) 46 close(ch->afd); 47 if(ch->asfd >= 0) 48 close(ch->asfd); 49 ch->afd = -1; 50 ch->asfd = -1; 51 } 52 53 static char* 54 authresp(void) 55 { 56 char *s, *t; 57 int n; 58 59 t = Brdline(&bin, '\n'); 60 n = Blinelen(&bin); 61 if(n < 2) 62 return nil; 63 n--; 64 if(t[n-1] == '\r') 65 n--; 66 t[n] = '\0'; 67 if(n == 0 || strcmp(t, "*") == 0) 68 return nil; 69 70 s = canAlloc(&parseCan, n + 1, 0); 71 n = dec64((uchar*)s, n, t, n); 72 s[n] = '\0'; 73 return s; 74 } 75 76 /* 77 * rfc 2195 cram-md5 authentication 78 */ 79 char* 80 cramauth(void) 81 { 82 Cramchalstate acs; 83 char *s, *t; 84 int n; 85 86 if(cramchal(&acs) < 0) 87 return "couldn't get cram challenge"; 88 89 n = strlen(acs.chal); 90 s = canAlloc(&parseCan, n * 2, 0); 91 n = enc64(s, n * 2, (uchar*)acs.chal, n); 92 Bprint(&bout, "+ "); 93 Bwrite(&bout, s, n); 94 Bprint(&bout, "\r\n"); 95 if(Bflush(&bout) < 0) 96 writeErr(); 97 98 s = authresp(); 99 if(s == nil) 100 return "client cancelled authentication"; 101 102 t = strchr(s, ' '); 103 if(t == nil) 104 bye("bad auth response"); 105 *t++ = '\0'; 106 strncpy(username, s, NAMELEN); 107 username[NAMELEN-1] = '\0'; 108 109 if(cramreply(&acs, username, t) < 0) 110 return "login failed"; 111 112 setupuser(); 113 114 return nil; 115 } 116 117 static char* 118 cramLogin(char *user, char *secret) 119 { 120 Cramchalstate acs; 121 uchar digest[MD5dlen]; 122 char response[2*MD5dlen+1]; 123 int i; 124 125 if(cramchal(&acs) < 0) 126 return "couldn't get cram challenge"; 127 128 hmac_md5((uchar*)acs.chal, strlen(acs.chal), 129 (uchar*)secret, strlen(secret), digest, 130 nil); 131 for(i = 0; i < MD5dlen; i++) 132 snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]); 133 134 if(cramreply(&acs, user, response) < 0) 135 return "login failed"; 136 137 return nil; 138 } 139 140 int 141 passCheck(char *user, char *pass) 142 { 143 return cramLogin(user, pass) == nil; 144 } 145 146 147 #define USER "VXNlcg==" 148 #define PASSWORD "UGFzc3dvcmQ=" 149 150 char* 151 loginauth(void) 152 { 153 Chalstate ch; 154 char *s, *u; 155 156 Bprint(&bout, "+ %s\r\n", USER); 157 if(Bflush(&bout) < 0) 158 writeErr(); 159 160 u = authresp(); 161 if(u == nil || getchal(&ch, u) < 0) 162 return "login failed"; 163 Bprint(&bout, "* ok [ALERT] encrypt challenge, %s, as a password\r\n", ch.chal); 164 Bprint(&bout, "+ %s\r\n", PASSWORD); 165 if(Bflush(&bout) < 0) 166 writeErr(); 167 168 s = authresp(); 169 if(s == nil || chalreply(&ch, s) < 0) 170 return "login failed"; 171 172 strncpy(username, u, NAMELEN); 173 username[NAMELEN-1] = '\0'; 174 175 setupuser(); 176 return nil; 177 } 178