From 4afef59e9cfdc88092899a6abdff720d39b0ddd3 Mon Sep 17 00:00:00 2001 From: oracle Date: Mon, 3 Aug 2015 14:35:43 -0700 Subject: [PATCH 07/34] DTrace support for SFTP diff -wpruN --no-dereference '--exclude=*.orig' a~/Makefile.in a/Makefile.in --- a~/Makefile.in 1970-01-01 00:00:00 +++ a/Makefile.in 1970-01-01 00:00:00 @@ -105,6 +105,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ ssh-ed25519-sk.o ssh-rsa.o dh.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ + sftp_provider.o \ ssh-pkcs11.o smult_curve25519_ref.o \ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ @@ -139,7 +140,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rh sftp-server.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 uidswap.o $(SKOBJS) + sandbox-solaris.o uidswap.o sftp_provider.o $(SKOBJS) SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o @@ -159,7 +160,8 @@ SKHELPER_OBJS= ssh-sk-helper.o ssh-sk.o SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS) -SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o +SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o sftp_provider.o +ROOTDLIBDIR64=$(DESTDIR)/usr/lib/dtrace/64 SFTP_OBJS= sftp.o sftp-usergroup.o progressmeter.o $(SFTP_CLIENT_OBJS) @@ -275,9 +277,22 @@ $(CONFIGFILES): $(CONFIGFILES_IN) moduli: echo +# dtrace sftp +sftp_provider.h: $(srcdir)/sftp_provider.d + /usr/sbin/dtrace -xnolibs -h -s $(srcdir)/sftp_provider.d \ + -o $(srcdir)/sftp_provider.h + +sftp_provider.o: sftp_provider.d sftp_provider.h sftp-server.o + /usr/sbin/dtrace -G -64 -xnolibs -s $(srcdir)/sftp_provider.d \ + sftp-server.o -o sftp_provider.o + +# special case for sftp-server.o, it includes sftp_provider.h +sftp-server.o: sftp_provider.h sftp-server.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $(srcdir)/sftp-server.c + clean: regressclean rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log - rm -f *.out core survey + rm -f *.out core survey sftp_provider.h rm -f regress/check-perm$(EXEEXT) rm -f regress/mkdtemp$(EXEEXT) rm -f regress/unittests/test_helper/*.a @@ -440,6 +455,7 @@ install-files: $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 + mkdir -p $(ROOTDLIBDIR64) && cp $(srcdir)/sftp64.d $(ROOTDLIBDIR64)/ install-sysconf: $(MKDIR_P) $(DESTDIR)$(sysconfdir) diff -wpruN --no-dereference '--exclude=*.orig' a~/sftp-server.c a/sftp-server.c --- a~/sftp-server.c 1970-01-01 00:00:00 +++ a/sftp-server.c 1970-01-01 00:00:00 @@ -56,6 +56,9 @@ #include "sftp.h" #include "sftp-common.h" +#ifdef DTRACE_SFTP +#include "sftp_provider_impl.h" +#endif char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ @@ -801,16 +804,19 @@ process_read(u_int32_t id) static u_char *buf; static size_t buflen; u_int32_t len; - int r, handle, fd, ret, status = SSH2_FX_FAILURE; + int r, handle, fd, ret = 0, status = SSH2_FX_FAILURE; u_int64_t off; + char *fpath; if ((r = get_handle(iqueue, &handle)) != 0 || (r = sshbuf_get_u64(iqueue, &off)) != 0 || (r = sshbuf_get_u32(iqueue, &len)) != 0) fatal_fr(r, "parse"); + fpath = handle_to_name(handle); + debug("request %u: read \"%s\" (handle %d) off %llu len %u", - id, handle_to_name(handle), handle, (unsigned long long)off, len); + id, fpath, handle, (unsigned long long)off, len); if ((fd = handle_to_fd(handle)) == -1) goto out; if (len > SFTP_MAX_READ_LENGTH) { @@ -829,6 +835,9 @@ process_read(u_int32_t id) strerror(errno)); goto out; } +#ifdef DTRACE_SFTP + SFTP_TRANSFER_START_OP("read", fd, fpath, len); +#endif if (len == 0) { /* weird, but not strictly disallowed */ ret = 0; @@ -841,11 +850,18 @@ process_read(u_int32_t id) status = SSH2_FX_EOF; goto out; } +#ifdef DTRACE_SFTP + SFTP_TRANSFER_DONE_OP("read", fd, fpath, ret); +#endif send_data(id, buf, ret); handle_update_read(handle, ret); /* success */ status = SSH2_FX_OK; out: +#ifdef DTRACE_SFTP + if (status != SSH2_FX_OK) + SFTP_TRANSFER_DONE_OP("read", fd, fpath, ret); +#endif if (status != SSH2_FX_OK) send_status(id, status); } @@ -857,14 +873,17 @@ process_write(u_int32_t id) size_t len; int r, handle, fd, ret, status; u_char *data; + char *fpath; if ((r = get_handle(iqueue, &handle)) != 0 || (r = sshbuf_get_u64(iqueue, &off)) != 0 || (r = sshbuf_get_string(iqueue, &data, &len)) != 0) fatal_fr(r, "parse"); + fpath = handle_to_name(handle); + debug("request %u: write \"%s\" (handle %d) off %llu len %zu", - id, handle_to_name(handle), handle, (unsigned long long)off, len); + id, fpath, handle, (unsigned long long)off, len); fd = handle_to_fd(handle); if (fd < 0) @@ -877,7 +896,13 @@ process_write(u_int32_t id) strerror(errno)); } else { /* XXX ATOMICIO ? */ +#ifdef DTRACE_SFTP + SFTP_TRANSFER_START_OP("write", fd, fpath, len); +#endif ret = write(fd, data, len); +#ifdef DTRACE_SFTP + SFTP_TRANSFER_DONE_OP("write", fd, fpath, ret); +#endif if (ret == -1) { status = errno_to_portable(errno); error_f("write \"%.100s\": %s", diff -wpruN --no-dereference '--exclude=*.orig' a~/sftp64.d a/sftp64.d --- a~/sftp64.d 1970-01-01 00:00:00 +++ a/sftp64.d 1970-01-01 00:00:00 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + */ + +#pragma D depends_on library net.d +#pragma D depends_on library io.d +#pragma D depends_on module lofs + +typedef struct sftpinfo { + string sfi_user; /* user name */ + string sfi_operation; /* SFTP Operation */ + ssize_t sfi_nbytes; /* bytes transferred, if any */ + string sfi_pathname; /* pathname of transfer */ + string sfi_fsresource; /* Dataset(ZFS) or resource name */ +} sftpinfo_t; + +/* + * This structure must match the definition of same in sftp_provider_impl.h. + */ +typedef struct sftpproto { + int64_t sftp_nbytes; /* bytes written or read */ + uint64_t sftp_user; /* user name */ + uint64_t sftp_operation; /* SFTP operation */ + uint64_t sftp_raddr; /* remote address */ + uint64_t sftp_pathname; /* path with file name */ + int32_t sftp_fd; /* fd for transfer, if any */ +} sftpproto_t; + +#pragma D binding "1.6.1" translator +translator conninfo_t { + ci_protocol = "tcp"; + ci_remote = copyinstr((uintptr_t) + *(uint64_t *)copyin((uintptr_t)&s->sftp_raddr, sizeof (uint64_t))); + ci_local = ""; +}; + +#pragma D binding "1.6.1" translator +translator sftpinfo_t { + sfi_user = copyinstr((uintptr_t) + *(uint64_t *)copyin((uintptr_t)&s->sftp_user, sizeof (uint64_t))); + sfi_operation = copyinstr((uintptr_t) + *(uint64_t *)copyin((uintptr_t)&s->sftp_operation, + sizeof (uint64_t))); + sfi_nbytes = + *(uint64_t *)copyin((uintptr_t)&s->sftp_nbytes, sizeof (uint64_t)); + sfi_fsresource = stringof(fds[*(int32_t *)copyin((uintptr_t)&s->sftp_fd, + sizeof (int32_t))].fi_fs) == "lofs" ? stringof(((struct loinfo *) + curthread->t_procp->p_user.u_finfo.fi_list[*(int32_t *)copyin( + (uintptr_t)&s->sftp_fd, sizeof (int32_t))].uf_file->f_vnode-> + v_vfsp->vfs_data)->li_realvfs->vfs_resource->rs_string) : + stringof(curthread->t_procp->p_user.u_finfo.fi_list[ + *(int32_t *)copyin((uintptr_t)&s->sftp_fd, sizeof (int32_t))]. + uf_file->f_vnode->v_vfsp->vfs_resource->rs_string); + sfi_pathname = copyinstr((uintptr_t)*(uint64_t *)copyin( + (uintptr_t)&s->sftp_pathname, sizeof (uint64_t))); +}; diff -wpruN --no-dereference '--exclude=*.orig' a~/sftp_provider.d a/sftp_provider.d --- a~/sftp_provider.d 1970-01-01 00:00:00 +++ a/sftp_provider.d 1970-01-01 00:00:00 @@ -0,0 +1,61 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * We seem currently unable to depend properly on existing D libraries (like + * sftp.d). But the definitions for conninfo_t and sftpinfo_t are stored there + * (and have to be, since that's where the real translators live). So we're + * forced to define something here to satisfy dtrace(8), but none of the + * definitions or translators here are actually used. + */ +typedef struct sftpinfo { + int dummy; +} sftpinfo_t; + +typedef struct sftpproto { + int dummy; +} sftpproto_t; + +typedef struct conninfo { + int dummy; +} conninfo_t; + +translator conninfo_t { +}; + +translator sftpinfo_t { +}; + +provider sftp { + probe transfer__start(sftpproto_t *p) : + (conninfo_t *p, sftpinfo_t *p); + probe transfer__done(sftpproto_t *p) : + (conninfo_t *p, sftpinfo_t *p); +}; + +#pragma D attributes Evolving/Evolving/ISA provider sftp provider +#pragma D attributes Private/Private/Unknown provider sftp module +#pragma D attributes Private/Private/Unknown provider sftp function +#pragma D attributes Private/Private/ISA provider sftp name +#pragma D attributes Evolving/Evolving/ISA provider sftp args diff -wpruN --no-dereference '--exclude=*.orig' a~/sftp_provider_impl.h a/sftp_provider_impl.h --- a~/sftp_provider_impl.h 1970-01-01 00:00:00 +++ a/sftp_provider_impl.h 1970-01-01 00:00:00 @@ -0,0 +1,73 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + */ + +#ifndef _SFTP_PROVIDER_IMPL_H +#define _SFTP_PROVIDER_IMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This structure must match the definition of same in sftp.d. + */ +typedef struct sftpproto { + int64_t sftp_nbytes; /* bytes writtten or read */ + const char *sftp_user; /* user name */ + const char *sftp_operation; /* SFTP Operation */ + const char *sftp_raddr; /* remote address */ + const char *sftp_pathname; /* path with file name */ + int32_t sftp_fd; /* fd for transfer, if any */ +} sftpproto_t; + +#define SFTP_TRANSFER_PROTO(proto, op, fd, path, len) \ + bzero((proto), sizeof (struct sftpproto)); \ + (proto)->sftp_user = (pw->pw_name ? pw->pw_name : "UNKNOWN"); \ + (proto)->sftp_operation = (op ? op : "UNKNOWN"); \ + (proto)->sftp_raddr = (client_addr); \ + (proto)->sftp_fd = (fd); \ + (proto)->sftp_pathname = (path ? path : "UNKNOWN"); \ + (proto)->sftp_nbytes = (len); \ + +#define SFTP_TRANSFER_START_OP(op, fd, path, len) \ + if (SFTP_TRANSFER_START_ENABLED()) { \ + sftpproto_t proto; \ + SFTP_TRANSFER_PROTO(&proto, op, fd, path, len); \ + SFTP_TRANSFER_START(&proto); \ + } \ + +#define SFTP_TRANSFER_DONE_OP(op, fd, path, len) \ + if (SFTP_TRANSFER_DONE_ENABLED()) { \ + sftpproto_t proto; \ + SFTP_TRANSFER_PROTO(&proto, op, fd, path, len); \ + SFTP_TRANSFER_DONE(&proto); \ + } \ + +#include "sftp_provider.h" + +#ifdef __cplusplus +} +#endif + +#endif /* _SFTP_PROVIDER_IMPL_H */