pushtls.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. }
  75. close(ctl);
  76. close(hand);
  77. close(fd);
  78. return data;
  79. error:
  80. if(data>=0)
  81. close(data);
  82. if(ctl>=0)
  83. close(ctl);
  84. if(hand>=0)
  85. close(hand);
  86. return -1;
  87. }