smbnegotiate.c 2.9 KB

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