auth.c 3.4 KB

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