smb_session.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. //---------------------------------------------------------------------------
  2. // __________________ _________ _____ _____ .__ ._.
  3. // \______ \______ \ / _____/ / \ / _ \ |__| ____ | |
  4. // | | _/| | \ \_____ \ / \ / \ / /_\ \| _/ __ \ | |
  5. // | | \| ` \/ / Y \ / | | \ ___/ \|
  6. // |______ /_______ /_______ \____|__ / /\ \____|__ |__|\___ | __
  7. // \/ \/ \/ \/ )/ \/ \/ \/
  8. //
  9. // This file is part of libdsm. Copyright © 2014 VideoLabs SAS
  10. //
  11. // Author: Julien 'Lta' BALLET <contact@lta.io>
  12. //
  13. // This program is free software. It comes without any warranty, to the extent
  14. // permitted by applicable law. You can redistribute it and/or modify it under
  15. // the terms of the Do What The Fuck You Want To Public License, Version 2, as
  16. // published by Sam Hocevar. See the COPYING file for more details.
  17. //----------------------------------------------------------------------------
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <stdio.h>
  21. #include <assert.h>
  22. #include "bdsm/debug.h"
  23. #include "bdsm/smb_session.h"
  24. #include "bdsm/smb_ntlm.h"
  25. smb_session_t *smb_session_new()
  26. {
  27. smb_session_t *s;
  28. s = malloc(sizeof(smb_session_t));
  29. assert(s != NULL);
  30. memset((void *)s, 0, sizeof(smb_session_t));
  31. return (s);
  32. }
  33. void smb_session_destroy(smb_session_t *s)
  34. {
  35. if (s != NULL)
  36. {
  37. // FIXME Free smb_share and smb_file
  38. if (s->nb_session != NULL)
  39. netbios_session_destroy(s->nb_session);
  40. free(s);
  41. }
  42. }
  43. int smb_session_state(smb_session_t *s)
  44. {
  45. if (s != NULL)
  46. return (s->state);
  47. else
  48. return (SMB_STATE_ERROR);
  49. }
  50. int smb_session_connect(smb_session_t *s, const char *name,
  51. uint32_t ip)
  52. {
  53. assert(s != NULL && name != NULL);
  54. if ((s->nb_session = netbios_session_new(ip)) == NULL)
  55. goto error;
  56. if (!netbios_session_connect(s->nb_session, name))
  57. goto error;
  58. memcpy(s->srv.name, name, strlen(name) + 1);
  59. s->state = SMB_STATE_NETBIOS_OK;
  60. if (!smb_negotiate(s))
  61. return (0);
  62. return(1);
  63. error:
  64. s->state = SMB_STATE_ERROR;
  65. return (0);
  66. }
  67. int smb_session_send_msg(smb_session_t *s, smb_message_t *msg)
  68. {
  69. size_t packet_size;
  70. assert(s != NULL && s->state >= SMB_STATE_NETBIOS_OK && s->nb_session != NULL);
  71. assert(msg != NULL && msg->packet != NULL);
  72. msg->packet->header.uid = s->uid;
  73. netbios_session_packet_init(s->nb_session, NETBIOS_OP_SESSION_MSG);
  74. packet_size = sizeof(smb_packet_t) + msg->cursor;
  75. if (!netbios_session_packet_append(s->nb_session, (char *)msg->packet, packet_size))
  76. return (0);
  77. if (!netbios_session_packet_send(s->nb_session))
  78. return (0);
  79. return (1);
  80. }
  81. size_t smb_session_recv_msg(smb_session_t *s, smb_message_t *msg)
  82. {
  83. netbios_session_packet_t *nb_packet;
  84. ssize_t recv_size;
  85. size_t payload_size;
  86. assert(s != NULL && s->nb_session != NULL);
  87. recv_size = netbios_session_packet_recv(s->nb_session);
  88. if(recv_size <= 0)
  89. return (0);
  90. nb_packet = (netbios_session_packet_t *)s->nb_session->recv_buffer;
  91. if (msg != NULL)
  92. msg->packet = (smb_packet_t *)nb_packet->payload;
  93. payload_size = ntohs(nb_packet->length);
  94. payload_size |= (nb_packet->flags & 0x01) << 16; // XXX If this is the case we overran our recv_buffer
  95. if (payload_size > recv_size - sizeof(netbios_session_packet_t))
  96. {
  97. BDSM_dbg("smb_session_recv_msg: Packet size mismatch\n");
  98. return(0);
  99. }
  100. if (msg != NULL)
  101. {
  102. msg->payload_size = payload_size - sizeof(smb_header_t);
  103. msg->cursor = 0;
  104. }
  105. return (payload_size - sizeof(smb_header_t));
  106. }
  107. int smb_negotiate(smb_session_t *s)
  108. {
  109. const char *dialects[] = SMB_DIALECTS;
  110. smb_message_t *msg = NULL;
  111. smb_message_t answer;
  112. smb_negotiate_resp_t *nego;
  113. msg = smb_message_new(SMB_CMD_NEGOTIATE, 64);
  114. smb_message_set_default_flags(msg);
  115. smb_message_put8(msg, 0); // wct
  116. smb_message_put16(msg, 0); // bct, will be updated later
  117. for(unsigned i = 0; dialects[i] != NULL; i++)
  118. smb_message_append(msg, dialects[i], strlen(dialects[i]) + 1);
  119. *((uint16_t *)(msg->packet->payload + 1)) = msg->cursor - 3;
  120. if (!smb_session_send_msg(s, msg))
  121. {
  122. smb_message_destroy(msg);
  123. goto error;
  124. }
  125. smb_message_destroy(msg);
  126. if (!smb_session_recv_msg(s, &answer))
  127. goto error;
  128. nego = (smb_negotiate_resp_t *)answer.packet->payload;
  129. if (answer.packet->header.status != NT_STATUS_SUCCESS
  130. && nego->wct != 0x11 && nego->security_mode & 0x03)
  131. goto error;
  132. s->srv.dialect = nego->dialect_index;
  133. s->srv.security_mode = nego->security_mode;
  134. s->srv.caps = nego->caps;
  135. s->srv.session_key = nego->session_key;
  136. s->srv.challenge = nego->challenge;
  137. s->srv.ts = nego->ts;
  138. // Yeah !
  139. s->state = SMB_STATE_DIALECT_OK;
  140. return (1);
  141. error:
  142. s->state = SMB_STATE_ERROR;
  143. return (0);
  144. }
  145. int smb_session_login(smb_session_t *s, const char *domain,
  146. const char *user, const char *password)
  147. {
  148. smb_message_t answer;
  149. smb_message_t *msg = NULL;
  150. smb_session_req_t *req = NULL;
  151. uint8_t *ntlm2 = NULL;
  152. smb_ntlmh_t hash_v2;
  153. uint8_t *ucs;
  154. size_t ucs_len;
  155. uint64_t user_challenge;
  156. uint8_t blob[128];
  157. size_t blob_size;
  158. msg = smb_message_new(SMB_CMD_SETUP, 512);
  159. smb_message_set_default_flags(msg);
  160. smb_message_set_andx_members(msg);
  161. req = (smb_session_req_t *)msg->packet->payload;
  162. req->wct = (sizeof(smb_session_req_t) - 3) / 2;
  163. req->max_buffer = NETBIOS_SESSION_PAYLOAD;
  164. req->max_buffer -= sizeof(netbios_session_packet_t);
  165. req->max_buffer -= sizeof(smb_packet_t);
  166. req->mpx_count = 16; // XXX ?
  167. req->vc_count = 1;
  168. req->session_key = s->srv.session_key;
  169. req->caps = s->srv.caps; // XXX caps & our_caps_mask
  170. smb_message_advance(msg, sizeof(smb_session_req_t));
  171. user_challenge = smb_ntlm_generate_challenge();
  172. // LM2 Response
  173. smb_ntlm2_hash(user, password, domain, &hash_v2);
  174. ntlm2 = smb_ntlm2_response(&hash_v2, s->srv.challenge,
  175. (void *)&user_challenge, 8);
  176. smb_message_append(msg, ntlm2, 16 + 8);
  177. free(ntlm2);
  178. // NTLM2 Response
  179. blob_size = smb_ntlm_blob((smb_ntlm_blob_t *)blob, s->srv.ts,
  180. user_challenge, domain);
  181. ntlm2 = smb_ntlm2_response(&hash_v2, s->srv.challenge, blob, blob_size);
  182. //smb_message_append(msg, ntlm2, 16 + blob_size);
  183. free(ntlm2);
  184. req->oem_pass_len = 16 + SMB_LM2_BLOB_SIZE;
  185. req->uni_pass_len = 0; //16 + blob_size; //SMB_NTLM2_BLOB_SIZE;
  186. if (msg->cursor / 2) // Padding !
  187. smb_message_put8(msg, 0);
  188. smb_message_put_utf16(msg, "", user, strlen(user));
  189. smb_message_put16(msg, 0);
  190. smb_message_put_utf16(msg, "", domain, strlen(domain));
  191. smb_message_put16(msg, 0);
  192. smb_message_put_utf16(msg, "", SMB_OS, strlen(SMB_OS));
  193. smb_message_put16(msg, 0);
  194. smb_message_put_utf16(msg, "", SMB_LANMAN, strlen(SMB_OS));
  195. smb_message_put16(msg, 0);
  196. req->payload_size = msg->cursor - sizeof(smb_session_req_t);
  197. if (!smb_session_send_msg(s, msg))
  198. {
  199. smb_message_destroy(msg);
  200. BDSM_dbg("Unable to send Session Setup AndX message\n");
  201. return (0);
  202. }
  203. smb_message_destroy(msg);
  204. if (smb_session_recv_msg(s, &answer) == 0)
  205. {
  206. BDSM_dbg("Unable to get Session Setup AndX reply\n");
  207. return (0);
  208. }
  209. smb_session_resp_t *r = (smb_session_resp_t *)answer.packet->payload;
  210. if (answer.packet->header.status != NT_STATUS_SUCCESS)
  211. {
  212. BDSM_dbg("Session Setup AndX : failure.\n");
  213. return (0);
  214. }
  215. if (r->action & 0x0001)
  216. s->guest = 1;
  217. s->state = SMB_STATE_SESSION_OK;
  218. s->uid = answer.packet->header.uid;
  219. return (1);
  220. }
  221. int smb_session_is_guest(smb_session_t *s)
  222. {
  223. // Invalid session object
  224. if (s == NULL)
  225. return (-1);
  226. // We're not logged in yet.
  227. if (smb_session_state(s) != SMB_STATE_SESSION_OK)
  228. return (-1);
  229. // We're logged in as guest
  230. if (s->guest)
  231. return (1);
  232. // We're logged in as regular user
  233. return (0);
  234. }
  235. const char *smb_session_server_name(smb_session_t *s)
  236. {
  237. if (s == NULL)
  238. return (NULL);
  239. else
  240. return (s->srv.name);
  241. }