smbnegotiate.c 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "headers.h"
  10. SmbProcessResult
  11. smbnegotiate(SmbSession *s, SmbHeader *h, uint8_t *l, SmbBuffer *b)
  12. {
  13. uint16_t index;
  14. int i;
  15. uint8_t bufferformat;
  16. if (!smbcheckwordcount("negotiate", h, 0))
  17. return SmbProcessResultFormat;
  18. if (s->state != SmbSessionNeedNegotiate) {
  19. /* this acts as a complete session reset */
  20. smblogprint(-1, "smbnegotiate: called when already negotiated\n");
  21. return SmbProcessResultUnimp;
  22. }
  23. i = 0;
  24. index = 0xffff;
  25. while (smbbuffergetb(b, &bufferformat)) {
  26. char *s;
  27. if (bufferformat != 0x02) {
  28. smblogprint(-1, "smbnegotiate: unrecognised buffer format 0x%.2x\n", bufferformat);
  29. return SmbProcessResultFormat;
  30. }
  31. if (!smbbuffergetstr(b, 0, &s)) {
  32. smblogprint(-1, "smbnegotiate: no null found\n");
  33. return SmbProcessResultFormat;
  34. }
  35. smblogprint(h->command, "smbnegotiate: '%s'\n", s);
  36. if (index == 0xffff && strcmp(s, "NT LM 0.12") == 0)
  37. index = i;
  38. i++;
  39. free(s);
  40. }
  41. if (index != 0xffff) {
  42. Tm *tm;
  43. uint32_t capabilities;
  44. uint32_t bytecountfixupoffset;
  45. h->wordcount = 17;
  46. if (!smbbufferputheader(s->response, h, nil)
  47. || !smbbufferputs(s->response, index)
  48. || !smbbufferputb(s->response, 3) /* user security, encrypted */
  49. || !smbbufferputs(s->response, 1) /* max mux */
  50. || !smbbufferputs(s->response, 1) /* max vc */
  51. || !smbbufferputl(s->response, smbglobals.maxreceive) /* max buffer size */
  52. || !smbbufferputl(s->response, 0x10000) /* max raw */
  53. || !smbbufferputl(s->response, threadid())) /* session key */
  54. goto die;
  55. /* <= Win2k insist upon this being set to ensure that they observe the prototol (!) */
  56. capabilities = CAP_NT_SMBS;
  57. if (smbglobals.unicode)
  58. capabilities |= CAP_UNICODE;
  59. tm = localtime(time(nil));
  60. s->tzoff = tm->tzoff;
  61. if (!smbbufferputl(s->response, capabilities)
  62. || !smbbufferputv(s->response, nsec() / 100 + (int64_t)10000000 * 11644473600LL)
  63. || !smbbufferputs(s->response, -s->tzoff / 60)
  64. || !smbbufferputb(s->response, 8)) /* crypt len */
  65. goto die;
  66. bytecountfixupoffset = smbbufferwriteoffset(s->response);
  67. if (!smbbufferputs(s->response, 0))
  68. goto die;
  69. s->cs = auth_challenge("proto=mschap role=server");
  70. if (s->cs == nil) {
  71. smblogprint(h->command, "smbnegotiate: couldn't get mschap challenge\n");
  72. return SmbProcessResultMisc;
  73. }
  74. if (s->cs->nchal != 8) {
  75. smblogprint(h->command, "smbnegotiate: nchal %d\n", s->cs->nchal);
  76. return SmbProcessResultMisc;
  77. }
  78. if (!smbbufferputbytes(s->response, s->cs->chal, s->cs->nchal)
  79. || !smbbufferputstring(s->response, nil, SMB_STRING_UNICODE, smbglobals.primarydomain)
  80. || !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
  81. goto die;
  82. }
  83. else {
  84. h->wordcount = 1;
  85. if (!smbbufferputheader(s->response, h, nil)
  86. || !smbbufferputs(s->response, index)
  87. || !smbbufferputs(s->response, 0))
  88. goto die;
  89. }
  90. s->state = SmbSessionNeedSetup;
  91. return SmbProcessResultReply;
  92. die:
  93. return SmbProcessResultDie;
  94. }