pushtls.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <mp.h>
  5. #include <libsec.h>
  6. enum {
  7. TLSFinishedLen = 12,
  8. HFinished = 20,
  9. };
  10. static int
  11. finished(int hand, int isclient)
  12. {
  13. int i, n;
  14. uchar buf[500], buf2[500];
  15. buf[0] = HFinished;
  16. buf[1] = TLSFinishedLen>>16;
  17. buf[2] = TLSFinishedLen>>8;
  18. buf[3] = TLSFinishedLen;
  19. n = TLSFinishedLen+4;
  20. for(i=0; i<2; i++){
  21. if(i==0)
  22. memmove(buf+4, "client finished", TLSFinishedLen);
  23. else
  24. memmove(buf+4, "server finished", TLSFinishedLen);
  25. if(isclient == 1-i){
  26. if(write(hand, buf, n) != n)
  27. return -1;
  28. }else{
  29. if(readn(hand, buf2, n) != n || memcmp(buf,buf2,n) != 0)
  30. return -1;
  31. }
  32. }
  33. return 1;
  34. }
  35. // given a plain fd and secrets established beforehand, return encrypted connection
  36. int
  37. pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir)
  38. {
  39. char buf[8];
  40. char dname[64];
  41. int n, data, ctl, hand;
  42. // open a new filter; get ctl fd
  43. data = hand = -1;
  44. // /net/tls uses decimal file descriptors to name channels, hence a
  45. // user-level file server can't stand in for #a; may as well hard-code it.
  46. ctl = open("#a/tls/clone", ORDWR);
  47. if(ctl < 0)
  48. goto error;
  49. n = read(ctl, buf, sizeof(buf)-1);
  50. if(n < 0)
  51. goto error;
  52. buf[n] = 0;
  53. if(dir)
  54. sprint(dir, "#a/tls/%s", buf);
  55. // get application fd
  56. sprint(dname, "#a/tls/%s/data", buf);
  57. data = open(dname, ORDWR);
  58. if(data < 0)
  59. goto error;
  60. // get handshake fd
  61. sprint(dname, "#a/tls/%s/hand", buf);
  62. hand = open(dname, ORDWR);
  63. if(hand < 0)
  64. goto error;
  65. // speak a minimal handshake
  66. if(fprint(ctl, "fd %d 0x301", fd) < 0 ||
  67. fprint(ctl, "version 0x301") < 0 ||
  68. fprint(ctl, "secret %s %s %d %s", hashalg, encalg, isclient, secret) < 0 ||
  69. fprint(ctl, "changecipher") < 0 ||
  70. finished(hand, isclient) < 0 ||
  71. fprint(ctl, "opened") < 0){
  72. close(hand);
  73. hand = -1;
  74. goto error;
  75. }
  76. close(ctl);
  77. close(hand);
  78. close(fd);
  79. return data;
  80. error:
  81. if(data>=0)
  82. close(data);
  83. if(ctl>=0)
  84. close(ctl);
  85. if(hand>=0)
  86. close(hand);
  87. return -1;
  88. }