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 /* 9 * hack to allow smtp forwarding. 10 * hide the peer IP address under a rock in the ratifier FS. 11 */ 12 void 13 enableForwarding(void) 14 { 15 char buf[64], peer[64], *p; 16 static ulong last; 17 ulong now; 18 int fd; 19 20 if(remote == nil) 21 return; 22 23 now = time(0); 24 if(now < last + 5*60) 25 return; 26 last = now; 27 28 fd = open("/srv/ratify", ORDWR); 29 if(fd < 0) 30 return; 31 if(!mount(fd, -1, "/mail/ratify", MBEFORE, "")){ 32 close(fd); 33 return; 34 } 35 close(fd); 36 37 strncpy(peer, remote, sizeof(peer)); 38 peer[sizeof(peer) - 1] = '\0'; 39 p = strchr(peer, '!'); 40 if(p != nil) 41 *p = '\0'; 42 43 snprint(buf, sizeof(buf), "/mail/ratify/trusted/%s#32", peer); 44 45 /* 46 * if the address is already there and the user owns it, 47 * remove it and recreate it to give him a new time quanta. 48 */ 49 if(access(buf, 0) >= 0 && remove(buf) < 0) 50 return; 51 52 fd = create(buf, OREAD, 0666); 53 if(fd >= 0) 54 close(fd); 55 } 56 57 void 58 setupuser(AuthInfo *ai) 59 { 60 Waitmsg *w; 61 int pid; 62 63 if(ai){ 64 strecpy(username, username+sizeof username, ai->cuid); 65 66 if(auth_chuid(ai, nil) < 0) 67 bye("user auth failed: %r"); 68 auth_freeAI(ai); 69 }else 70 strecpy(username, username+sizeof username, getuser()); 71 72 if(newns(username, 0) < 0) 73 bye("user login failed: %r"); 74 75 /* 76 * hack to allow access to outgoing smtp forwarding 77 */ 78 enableForwarding(); 79 80 snprint(mboxDir, MboxNameLen, "/mail/box/%s", username); 81 if(myChdir(mboxDir) < 0) 82 bye("can't open user's mailbox"); 83 84 switch(pid = fork()){ 85 case -1: 86 bye("can't initialize mail system"); 87 break; 88 case 0: 89 execl("/bin/upas/fs", "upas/fs", "-np", nil); 90 _exits("rob1"); 91 _exits(0); 92 break; 93 default: 94 break; 95 } 96 if((w=wait()) == nil || w->pid != pid || w->msg[0] != '\0') 97 bye("can't initialize mail system"); 98 free(w); 99 } 100 101 static char* 102 authresp(void) 103 { 104 char *s, *t; 105 int n; 106 107 t = Brdline(&bin, '\n'); 108 n = Blinelen(&bin); 109 if(n < 2) 110 return nil; 111 n--; 112 if(t[n-1] == '\r') 113 n--; 114 t[n] = '\0'; 115 if(n == 0 || strcmp(t, "*") == 0) 116 return nil; 117 118 s = binalloc(&parseBin, n + 1, 0); 119 n = dec64((uchar*)s, n, t, n); 120 s[n] = '\0'; 121 return s; 122 } 123 124 /* 125 * rfc 2195 cram-md5 authentication 126 */ 127 char* 128 cramauth(void) 129 { 130 AuthInfo *ai; 131 Chalstate *cs; 132 char *s, *t; 133 int n; 134 135 if((cs = auth_challenge("proto=cram role=server")) == nil) 136 return "couldn't get cram challenge"; 137 138 n = cs->nchal; 139 s = binalloc(&parseBin, n * 2, 0); 140 n = enc64(s, n * 2, (uchar*)cs->chal, n); 141 Bprint(&bout, "+ "); 142 Bwrite(&bout, s, n); 143 Bprint(&bout, "\r\n"); 144 if(Bflush(&bout) < 0) 145 writeErr(); 146 147 s = authresp(); 148 if(s == nil) 149 return "client cancelled authentication"; 150 151 t = strchr(s, ' '); 152 if(t == nil) 153 bye("bad auth response"); 154 *t++ = '\0'; 155 strncpy(username, s, UserNameLen); 156 username[UserNameLen-1] = '\0'; 157 158 cs->user = username; 159 cs->resp = t; 160 cs->nresp = strlen(t); 161 if((ai = auth_response(cs)) == nil) 162 return "login failed"; 163 auth_freechal(cs); 164 setupuser(ai); 165 return nil; 166 } 167 168 AuthInfo* 169 passLogin(char *user, char *secret) 170 { 171 AuthInfo *ai; 172 Chalstate *cs; 173 uchar digest[MD5dlen]; 174 char response[2*MD5dlen+1]; 175 int i; 176 177 if((cs = auth_challenge("proto=cram role=server")) == nil) 178 return nil; 179 180 hmac_md5((uchar*)cs->chal, strlen(cs->chal), 181 (uchar*)secret, strlen(secret), digest, 182 nil); 183 for(i = 0; i < MD5dlen; i++) 184 snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]); 185 186 cs->user = user; 187 cs->resp = response; 188 cs->nresp = strlen(response); 189 ai = auth_response(cs); 190 auth_freechal(cs); 191 return ai; 192 } 193