smb_session.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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 "smb_session.h"
  24. #include "smb_session_msg.h"
  25. #include "smb_fd.h"
  26. #include "smb_ntlm.h"
  27. #include "smb_spnego.h"
  28. #include "smb_transport.h"
  29. static int smb_negotiate(smb_session *s);
  30. smb_session *smb_session_new()
  31. {
  32. smb_session *s;
  33. s = malloc(sizeof(smb_session));
  34. assert(s != NULL);
  35. memset((void *)s, 0, sizeof(smb_session));
  36. s->guest = false;
  37. // Explicitly sets pointer to NULL, insted of 0
  38. s->spnego_asn1 = NULL;
  39. s->transport.session = NULL;
  40. s->shares = NULL;
  41. s->creds.domain = NULL;
  42. s->creds.login = NULL;
  43. s->creds.password = NULL;
  44. smb_buffer_init(&s->xsec_target, NULL, 0);
  45. // Until we know more, assume server supports everything.
  46. // s->c
  47. return (s);
  48. }
  49. void smb_session_destroy(smb_session *s)
  50. {
  51. if (s != NULL)
  52. {
  53. smb_session_share_clear(s);
  54. // FIXME Free smb_share and smb_file
  55. if (s->transport.session != NULL)
  56. {
  57. s->transport.destroy(s->transport.session);
  58. s->transport.session = NULL;
  59. }
  60. if (s->spnego_asn1 != NULL)
  61. asn1_delete_structure(&s->spnego_asn1);
  62. smb_buffer_free(&s->xsec_target);
  63. // Free stored credentials.
  64. free(s->creds.domain);
  65. free(s->creds.login);
  66. free(s->creds.password);
  67. free(s);
  68. }
  69. }
  70. int smb_session_state(smb_session *s)
  71. {
  72. if (s != NULL)
  73. return (s->state);
  74. else
  75. return (SMB_STATE_ERROR);
  76. }
  77. void smb_session_set_creds(smb_session *s, const char *domain,
  78. const char *login, const char *password)
  79. {
  80. assert(s != NULL);
  81. if (domain != NULL)
  82. {
  83. if (s->creds.domain != NULL)
  84. free(s->creds.domain);
  85. s->creds.domain = strndup(domain, SMB_CREDS_MAXLEN);
  86. }
  87. if (login != NULL)
  88. {
  89. if (s->creds.login != NULL)
  90. free(s->creds.login);
  91. s->creds.login = strndup(login, SMB_CREDS_MAXLEN);
  92. }
  93. if (password != NULL)
  94. {
  95. if (s->creds.password != NULL)
  96. free(s->creds.password);
  97. s->creds.password = strndup(password, SMB_CREDS_MAXLEN);
  98. }
  99. }
  100. int smb_session_connect(smb_session *s, const char *name,
  101. uint32_t ip, int transport)
  102. {
  103. assert(s != NULL && name != NULL);
  104. if (s->transport.session != NULL)
  105. s->transport.destroy(s->transport.session);
  106. switch (transport)
  107. {
  108. case SMB_TRANSPORT_TCP:
  109. smb_transport_tcp(&s->transport);
  110. break;
  111. case SMB_TRANSPORT_NBT:
  112. smb_transport_nbt(&s->transport);
  113. break;
  114. default:
  115. goto error;
  116. }
  117. if ((s->transport.session = s->transport.new(SMB_DEFAULT_BUFSIZE)) == NULL)
  118. goto error;
  119. if (!s->transport.connect((struct in_addr *)&ip, s->transport.session, name))
  120. goto error;
  121. memcpy(s->srv.name, name, strlen(name) + 1);
  122. s->state = SMB_STATE_NETBIOS_OK;
  123. if (!smb_negotiate(s))
  124. return (0);
  125. return (1);
  126. error:
  127. s->state = SMB_STATE_ERROR;
  128. return (0);
  129. }
  130. static int smb_negotiate(smb_session *s)
  131. {
  132. const char *dialects[] = SMB_DIALECTS;
  133. smb_message *msg = NULL;
  134. smb_message answer;
  135. smb_nego_resp *nego;
  136. msg = smb_message_new(SMB_CMD_NEGOTIATE, 128);
  137. smb_message_put8(msg, 0); // wct
  138. smb_message_put16(msg, 0); // bct, will be updated later
  139. for (unsigned i = 0; dialects[i] != NULL; i++)
  140. smb_message_append(msg, dialects[i], strlen(dialects[i]) + 1);
  141. *((uint16_t *)(msg->packet->payload + 1)) = msg->cursor - 3;
  142. if (!smb_session_send_msg(s, msg))
  143. {
  144. smb_message_destroy(msg);
  145. goto error;
  146. }
  147. smb_message_destroy(msg);
  148. if (!smb_session_recv_msg(s, &answer))
  149. goto error;
  150. nego = (smb_nego_resp *)answer.packet->payload;
  151. if (answer.packet->header.status != NT_STATUS_SUCCESS && nego->wct != 0x11)
  152. goto error;
  153. s->srv.dialect = nego->dialect_index;
  154. s->srv.security_mode = nego->security_mode;
  155. s->srv.caps = nego->caps;
  156. s->srv.ts = nego->ts;
  157. s->srv.session_key = nego->session_key;
  158. // Copy SPNEGO supported mechanisms token for later usage (login_gss())
  159. if (smb_session_supports(s, SMB_SESSION_XSEC))
  160. BDSM_dbg("Server is supporting extended security\n");
  161. else
  162. s->srv.challenge = nego->challenge;
  163. // Yeah !
  164. s->state = SMB_STATE_DIALECT_OK;
  165. return (1);
  166. error:
  167. s->state = SMB_STATE_ERROR;
  168. return (0);
  169. }
  170. static int smb_session_login_ntlm(smb_session *s, const char *domain,
  171. const char *user, const char *password)
  172. {
  173. smb_message answer;
  174. smb_message *msg = NULL;
  175. smb_session_req *req = NULL;
  176. uint8_t *ntlm2 = NULL;
  177. smb_ntlmh hash_v2;
  178. uint64_t user_challenge;
  179. msg = smb_message_new(SMB_CMD_SETUP, 512);
  180. smb_message_set_andx_members(msg);
  181. req = (smb_session_req *)msg->packet->payload;
  182. req->wct = 13;
  183. req->max_buffer = SMB_SESSION_MAX_BUFFER;
  184. req->mpx_count = 16; // XXX ?
  185. req->vc_count = 1;
  186. //req->session_key = s->srv.session_key; // XXX Useless on the wire?
  187. req->caps = s->srv.caps; // XXX caps & our_caps_mask
  188. smb_message_advance(msg, sizeof(smb_session_req));
  189. user_challenge = smb_ntlm_generate_challenge();
  190. // LM2 Response
  191. smb_ntlm2_hash(user, password, domain, &hash_v2);
  192. ntlm2 = smb_lm2_response(&hash_v2, s->srv.challenge, user_challenge);
  193. smb_message_append(msg, ntlm2, 16 + 8);
  194. free(ntlm2);
  195. req->oem_pass_len = 16 + SMB_LM2_BLOB_SIZE;
  196. req->uni_pass_len = 0; //16 + blob_size; //SMB_NTLM2_BLOB_SIZE;
  197. if (msg->cursor / 2) // Padding !
  198. smb_message_put8(msg, 0);
  199. smb_message_put_utf16(msg, user, strlen(user));
  200. smb_message_put16(msg, 0);
  201. smb_message_put_utf16(msg, domain, strlen(domain));
  202. smb_message_put16(msg, 0);
  203. smb_message_put_utf16(msg, SMB_OS, strlen(SMB_OS));
  204. smb_message_put16(msg, 0);
  205. smb_message_put_utf16(msg, SMB_LANMAN, strlen(SMB_LANMAN));
  206. smb_message_put16(msg, 0);
  207. req->payload_size = msg->cursor - sizeof(smb_session_req);
  208. if (!smb_session_send_msg(s, msg))
  209. {
  210. smb_message_destroy(msg);
  211. BDSM_dbg("Unable to send Session Setup AndX message\n");
  212. return (0);
  213. }
  214. smb_message_destroy(msg);
  215. if (smb_session_recv_msg(s, &answer) == 0)
  216. {
  217. BDSM_dbg("Unable to get Session Setup AndX reply\n");
  218. return (0);
  219. }
  220. smb_session_resp *r = (smb_session_resp *)answer.packet->payload;
  221. if (answer.packet->header.status != NT_STATUS_SUCCESS)
  222. {
  223. BDSM_dbg("Session Setup AndX : failure.\n");
  224. return (0);
  225. }
  226. if (r->action & 0x0001)
  227. s->guest = true;
  228. s->srv.uid = answer.packet->header.uid;
  229. s->state = SMB_STATE_SESSION_OK;
  230. return (1);
  231. }
  232. int smb_session_login(smb_session *s)
  233. {
  234. assert(s != NULL);
  235. if (s->creds.domain == NULL
  236. || s->creds.login == NULL
  237. || s->creds.password == NULL)
  238. return (0);
  239. if (smb_session_supports(s, SMB_SESSION_XSEC))
  240. return (smb_session_login_spnego(s, s->creds.domain, s->creds.login,
  241. s->creds.password));
  242. else
  243. return (smb_session_login_ntlm(s, s->creds.domain, s->creds.login,
  244. s->creds.password));
  245. }
  246. int smb_session_is_guest(smb_session *s)
  247. {
  248. // Invalid session object
  249. if (s == NULL)
  250. return (-1);
  251. // We're not logged in yet.
  252. if (smb_session_state(s) != SMB_STATE_SESSION_OK)
  253. return (-1);
  254. // We're logged in as guest
  255. if (s->guest)
  256. return (1);
  257. // We're logged in as regular user
  258. return (0);
  259. }
  260. const char *smb_session_server_name(smb_session *s)
  261. {
  262. if (s == NULL)
  263. return (NULL);
  264. else
  265. return (s->srv.name);
  266. }
  267. int smb_session_supports(smb_session *s, int what)
  268. {
  269. if (s == NULL)
  270. return (0);
  271. switch (what)
  272. {
  273. case SMB_SESSION_XSEC:
  274. return (s->srv.caps & SMB_CAPS_XSEC);
  275. default:
  276. return (0);
  277. }
  278. }