smb_message.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*****************************************************************************
  2. * __________________ _________ _____ _____ .__ ._.
  3. * \______ \______ \ / _____/ / \ / _ \ |__| ____ | |
  4. * | | _/| | \ \_____ \ / \ / \ / /_\ \| _/ __ \ | |
  5. * | | \| ` \/ / Y \ / | | \ ___/ \|
  6. * |______ /_______ /_______ \____|__ / /\ \____|__ |__|\___ | __
  7. * \/ \/ \/ \/ )/ \/ \/ \/
  8. *
  9. * This file is part of liBDSM. Copyright © 2014-2016 VideoLabs SAS
  10. *
  11. * Author: Julien 'Lta' BALLET <contact@lta.io>
  12. *
  13. * liBDSM is released under LGPLv2.1 (or later) and is also available
  14. * under a commercial license.
  15. *****************************************************************************
  16. * This program is free software; you can redistribute it and/or modify it
  17. * under the terms of the GNU Lesser General Public License as published by
  18. * the Free Software Foundation; either version 2.1 of the License, or
  19. * (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU Lesser General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU Lesser General Public License
  27. * along with this program; if not, write to the Free Software Foundation,
  28. * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  29. *****************************************************************************/
  30. #ifdef HAVE_CONFIG_H
  31. # include "config.h"
  32. #endif
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <sys/types.h>
  37. #include <unistd.h>
  38. #include "bdsm_debug.h"
  39. #include "netbios_session.h"
  40. #include "smb_message.h"
  41. #include "smb_utils.h"
  42. #define PAYLOAD_BLOCK_SIZE 256
  43. static int smb_message_expand_payload(smb_message *msg, size_t cursor, size_t data_size)
  44. {
  45. if (data_size == 0 || data_size > msg->payload_size - cursor)
  46. {
  47. size_t new_size = data_size + cursor - msg->payload_size;
  48. size_t nb_blocks = (new_size / PAYLOAD_BLOCK_SIZE) + 1;
  49. size_t new_payload_size = msg->payload_size + nb_blocks * PAYLOAD_BLOCK_SIZE;
  50. void *new_packet = realloc(msg->packet, sizeof(smb_packet) + new_payload_size);
  51. if (!new_packet)
  52. return 0;
  53. msg->packet = new_packet;
  54. msg->payload_size = new_payload_size;
  55. }
  56. return 1;
  57. }
  58. smb_message *smb_message_new(uint8_t cmd)
  59. {
  60. const uint8_t magic[4] = SMB_MAGIC;
  61. smb_message *msg;
  62. msg = (smb_message *)calloc(1, sizeof(smb_message));
  63. if (!msg)
  64. return NULL;
  65. if (smb_message_expand_payload(msg, msg->cursor, 0) == 0) {
  66. free(msg);
  67. return NULL;
  68. }
  69. memset(msg->packet, 0, sizeof(smb_packet));
  70. for (unsigned i = 0; i < 4; i++)
  71. msg->packet->header.magic[i] = magic[i];
  72. msg->packet->header.command = cmd;
  73. msg->packet->header.pid = getpid();
  74. return msg;
  75. }
  76. // Duplicate a message while growing payload_size.
  77. smb_message *smb_message_grow(smb_message *msg, size_t size)
  78. {
  79. smb_message *copy;
  80. if (msg == NULL || msg->packet == NULL)
  81. return NULL;
  82. copy = malloc(sizeof(smb_message));
  83. if (!copy)
  84. return NULL;
  85. copy->cursor = msg->cursor;
  86. copy->payload_size = msg->payload_size + size;
  87. copy->packet = malloc(sizeof(smb_packet) + copy->payload_size);
  88. if (!copy->packet) {
  89. free(copy);
  90. return NULL;
  91. }
  92. memcpy((void *)copy->packet, (void *)msg->packet,
  93. msg->payload_size + sizeof(smb_packet));
  94. return copy;
  95. }
  96. void smb_message_destroy(smb_message *msg)
  97. {
  98. if (msg == NULL)
  99. return;
  100. free(msg->packet);
  101. free(msg);
  102. }
  103. int smb_message_append(smb_message *msg, const void *data,
  104. size_t data_size)
  105. {
  106. if (msg == NULL || data == NULL)
  107. return -1;
  108. if (smb_message_expand_payload(msg, msg->cursor, data_size) == 0)
  109. return 0;
  110. memcpy(msg->packet->payload + msg->cursor, data, data_size);
  111. msg->cursor += data_size;
  112. //BDSM_dbg("Cursor is at %d (append)\n", msg->cursor);
  113. return 1;
  114. }
  115. int smb_message_insert(smb_message *msg, size_t cursor,
  116. const void *data, size_t data_size)
  117. {
  118. if (msg == NULL || data == NULL)
  119. return -1;
  120. if (smb_message_expand_payload(msg, cursor, data_size) == 0)
  121. return 0;
  122. memcpy(msg->packet->payload + cursor, data, data_size);
  123. return 1;
  124. }
  125. int smb_message_advance(smb_message *msg, size_t size)
  126. {
  127. if (msg == NULL)
  128. return -1;
  129. if (smb_message_expand_payload(msg, msg->cursor, size) == 0)
  130. return 0;
  131. msg->cursor += size;
  132. //BDSM_dbg("Cursor is at %d (advance)\n", msg->cursor);
  133. return 1;
  134. }
  135. int smb_message_put8(smb_message *msg, uint8_t data)
  136. {
  137. return smb_message_append(msg, (void *)&data, 1);
  138. }
  139. int smb_message_put16(smb_message *msg, uint16_t data)
  140. {
  141. return smb_message_append(msg, (void *)&data, 2);
  142. }
  143. int smb_message_put32(smb_message *msg, uint32_t data)
  144. {
  145. return smb_message_append(msg, (void *)&data, 4);
  146. }
  147. int smb_message_put64(smb_message *msg, uint64_t data)
  148. {
  149. return smb_message_append(msg, (void *)&data, 8);
  150. }
  151. size_t smb_message_put_utf16(smb_message *msg, const char *str,
  152. size_t str_len)
  153. {
  154. char *utf_str;
  155. size_t utf_str_len;
  156. int res;
  157. utf_str_len = smb_to_utf16(str, str_len, &utf_str);
  158. res = smb_message_append(msg, utf_str, utf_str_len);
  159. free(utf_str);
  160. // BDSM_dbg("put_utf16, adds %d bytes, cursor is at %d\n",
  161. // utf_str_len, msg->cursor);
  162. if (res)
  163. return utf_str_len;
  164. return 0;
  165. }
  166. int smb_message_put_uuid(smb_message *msg, uint32_t a, uint16_t b,
  167. uint16_t c, const uint8_t d[8])
  168. {
  169. if (msg == NULL)
  170. return -1;
  171. if (!smb_message_put32(msg, a))
  172. return 0;
  173. if (!smb_message_put16(msg, b))
  174. return 0;
  175. if (!smb_message_put16(msg, c))
  176. return 0;
  177. for (int i = 0; i < 8; i++)
  178. if (!smb_message_put8(msg, d[i]))
  179. return 0;
  180. return 1;
  181. }
  182. void smb_message_flag(smb_message *msg, uint32_t flag, int value)
  183. {
  184. uint32_t *flags;
  185. if (msg == NULL || msg->packet == NULL)
  186. return;
  187. // flags + flags2 is actually 24 bit long, we have to be cautious
  188. flags = (uint32_t *)&(msg->packet->header.flags);
  189. flag &= 0x00FFFFFF;
  190. if (value)
  191. *flags |= flag;
  192. else
  193. *flags &= ~flag;
  194. }
  195. void smb_message_set_andx_members(smb_message *msg)
  196. {
  197. // This could have been any type with the 'SMB_ANDX_MEMBERS';
  198. smb_session_req *req;
  199. if (msg == NULL)
  200. return;
  201. req = (smb_session_req *)msg->packet->payload;
  202. req->andx = 0xff;
  203. req->andx_reserved = 0;
  204. req->andx_offset = 0;
  205. }