1 From df6b82f10e53d43cfbc4cb3f52aa7e1751998fa1 Mon Sep 17 00:00:00 2001
   2 From: oracle <solaris@oracle.com>
   3 Date: Mon, 3 Aug 2015 14:35:43 -0700
   4 Subject: [PATCH 09/36] DTrace support for SFTP
   5 
   6 ---
   7  Makefile.in          | 25 +++++++++++++++---
   8  sftp-server.c        | 25 ++++++++++++++++--
   9  sftp64.d             | 56 ++++++++++++++++++++++++++++++++++++++++
  10  sftp_provider.d      | 61 +++++++++++++++++++++++++++++++++++++++++++
  11  sftp_provider_impl.h | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
  12  5 files changed, 234 insertions(+), 6 deletions(-)
  13  create mode 100644 sftp64.d
  14  create mode 100644 sftp_provider.d
  15  create mode 100644 sftp_provider_impl.h
  16 
  17 diff --git a/Makefile.in b/Makefile.in
  18 index 9f953e1..121a261 100644
  19 --- a/Makefile.in
  20 +++ b/Makefile.in
  21 @@ -26,6 +26,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
  22  SFTP_SERVER=$(libexecdir)/sftp-server
  23  SSH_KEYSIGN=$(libexecdir)/ssh-keysign
  24  SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
  25 +ROOTDLIBDIR64=$(DESTDIR)/usr/lib/dtrace/64
  26  PRIVSEP_PATH=@PRIVSEP_PATH@
  27  SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
  28  STRIP_OPT=@STRIP_OPT@
  29 @@ -85,6 +86,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
  30         atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o \
  31         monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
  32         msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
  33 +       sftp_provider.o \
  34         ssh-pkcs11.o smult_curve25519_ref.o \
  35         poly1305.o chacha.o cipher-chachapoly.o \
  36         ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \
  37 @@ -111,7 +113,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
  38         sftp-server.o sftp-common.o \
  39         roaming_common.o roaming_serv.o \
  40         sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
  41 -       sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-solaris.o
  42 +       sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-solaris.o \
  43 +       sftp_provider.o
  44  
  45  MANPAGES       = moduli.4.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.1m.out sftp-server.1m.out sftp.1.out ssh-keysign.1m.out ssh-pkcs11-helper.1m.out sshd_config.4.out ssh_config.4.out
  46  MANPAGES_IN    = moduli.4 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.1m sftp-server.1m sftp.1 ssh-keysign.1m ssh-pkcs11-helper.1m sshd_config.4 ssh_config.4
  47 @@ -188,8 +191,8 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11
  48  ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
  49         $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
  50  
  51 -sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
  52 -       $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
  53 +sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o sftp_provider.o
  54 +       $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o sftp_provider.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
  55  
  56  sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
  57         $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
  58 @@ -226,9 +229,22 @@ umac128.o: umac.c
  59             -Dumac_update=umac128_update -Dumac_final=umac128_final \
  60             -Dumac_delete=umac128_delete
  61  
  62 +# dtrace sftp
  63 +sftp_provider.h: $(srcdir)/sftp_provider.d
  64 +       /usr/sbin/dtrace -xnolibs -h -s $(srcdir)/sftp_provider.d \
  65 +           -o $(srcdir)/sftp_provider.h
  66 +
  67 +sftp_provider.o: sftp_provider.d sftp_provider.h sftp-server.o
  68 +       /usr/sbin/dtrace -G -64 -xnolibs -s $(srcdir)/sftp_provider.d \
  69 +           sftp-server.o -o sftp_provider.o
  70 +
  71 +# special case for sftp-server.o, it includes sftp_provider.h
  72 +sftp-server.o: sftp_provider.h sftp-server.c
  73 +       $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $(srcdir)/sftp-server.c
  74 +
  75  clean: regressclean
  76         rm -f *.o *.a $(TARGETS) logintest config.cache config.log
  77 -       rm -f *.out core survey
  78 +       rm -f *.out core survey sftp_provider.h
  79         rm -f regress/unittests/test_helper/*.a
  80         rm -f regress/unittests/test_helper/*.o
  81         rm -f regress/unittests/sshbuf/*.o
  82 @@ -341,6 +357,7 @@ install-files:
  83         ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
  84         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
  85         ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
  86 +       mkdir -p $(ROOTDLIBDIR64) && cp $(srcdir)/sftp64.d $(ROOTDLIBDIR64)/sftp64.d
  87  
  88  install-sysconf:
  89         if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
  90 diff --git a/sftp-server.c b/sftp-server.c
  91 index 3877c03..772a7c3 100644
  92 --- a/sftp-server.c
  93 +++ b/sftp-server.c
  94 @@ -54,6 +54,9 @@
  95  
  96  #include "sftp.h"
  97  #include "sftp-common.h"
  98 +#ifdef DTRACE_SFTP
  99 +#include "sftp_provider_impl.h"
 100 +#endif
 101  
 102  /* Our verbosity */
 103  static LogLevel log_level = SYSLOG_LEVEL_ERROR;
 104 @@ -740,14 +743,17 @@ process_read(u_int32_t id)
 105         u_int32_t len;
 106         int r, handle, fd, ret, status = SSH2_FX_FAILURE;
 107         u_int64_t off;
 108 +       char *fpath;
 109  
 110         if ((r = get_handle(iqueue, &handle)) != 0 ||
 111             (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
 112             (r = sshbuf_get_u32(iqueue, &len)) != 0)
 113                 fatal("%s: buffer error: %s", __func__, ssh_err(r));
 114  
 115 +       fpath = handle_to_name(handle);
 116 +
 117         debug("request %u: read \"%s\" (handle %d) off %llu len %d",
 118 -           id, handle_to_name(handle), handle, (unsigned long long)off, len);
 119 +           id, fpath, handle, (unsigned long long)off, len);
 120         if (len > sizeof buf) {
 121                 len = sizeof buf;
 122                 debug2("read change len %d", len);
 123 @@ -758,7 +764,13 @@ process_read(u_int32_t id)
 124                         error("process_read: seek failed");
 125                         status = errno_to_portable(errno);
 126                 } else {
 127 +#ifdef DTRACE_SFTP
 128 +                       SFTP_TRANSFER_START_OP("read", fd, fpath, len);
 129 +#endif
 130                         ret = read(fd, buf, len);
 131 +#ifdef DTRACE_SFTP
 132 +                       SFTP_TRANSFER_DONE_OP("read", fd, fpath, ret);
 133 +#endif
 134                         if (ret < 0) {
 135                                 status = errno_to_portable(errno);
 136                         } else if (ret == 0) {
 137 @@ -781,14 +793,16 @@ process_write(u_int32_t id)
 138         size_t len;
 139         int r, handle, fd, ret, status;
 140         u_char *data;
 141 +       char *fpath;
 142  
 143         if ((r = get_handle(iqueue, &handle)) != 0 ||
 144             (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
 145             (r = sshbuf_get_string(iqueue, &data, &len)) != 0)
 146                 fatal("%s: buffer error: %s", __func__, ssh_err(r));
 147  
 148 +       fpath = handle_to_name(handle);
 149         debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
 150 -           id, handle_to_name(handle), handle, (unsigned long long)off, len);
 151 +           id, fpath, handle, (unsigned long long)off, len);
 152         fd = handle_to_fd(handle);
 153  
 154         if (fd < 0)
 155 @@ -800,7 +814,14 @@ process_write(u_int32_t id)
 156                         error("process_write: seek failed");
 157                 } else {
 158  /* XXX ATOMICIO ? */
 159 +#ifdef DTRACE_SFTP
 160 +                       SFTP_TRANSFER_START_OP("write", fd, fpath, len);
 161 +#endif
 162                         ret = write(fd, data, len);
 163 +#ifdef DTRACE_SFTP
 164 +                       SFTP_TRANSFER_DONE_OP("write", fd, fpath, ret);
 165 +#endif
 166 +
 167                         if (ret < 0) {
 168                                 error("process_write: write failed");
 169                                 status = errno_to_portable(errno);
 170 diff --git a/sftp64.d b/sftp64.d
 171 new file mode 100644
 172 index 0000000..8305d0a
 173 --- /dev/null
 174 +++ b/sftp64.d
 175 @@ -0,0 +1,56 @@
 176 +/*
 177 + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
 178 + */
 179 +
 180 +#pragma D depends_on library net.d
 181 +#pragma D depends_on library io.d
 182 +#pragma D depends_on module lofs
 183 +
 184 +typedef struct sftpinfo {
 185 +       string sfi_user;                /* user name */
 186 +       string sfi_operation;           /* SFTP Operation */
 187 +       ssize_t sfi_nbytes;             /* bytes transferred, if any */
 188 +       string sfi_pathname;            /* pathname of transfer */
 189 +       string sfi_fsresource;          /* Dataset(ZFS) or resource name */
 190 +} sftpinfo_t;
 191 +
 192 +/*
 193 + * This structure must match the definition of same in sftp_provider_impl.h.
 194 + */
 195 +typedef struct sftpproto {
 196 +       int64_t sftp_nbytes;            /* bytes written or read */
 197 +       uint64_t sftp_user;             /* user name */
 198 +       uint64_t sftp_operation;        /* SFTP operation */
 199 +       uint64_t sftp_raddr;            /* remote address */
 200 +       uint64_t sftp_pathname;         /* path with file name */
 201 +       int32_t sftp_fd;                /* fd for transfer, if any */
 202 +} sftpproto_t;
 203 +
 204 +#pragma D binding "1.6.1" translator
 205 +translator conninfo_t <sftpproto_t *s> {
 206 +       ci_protocol = "tcp";
 207 +       ci_remote = copyinstr((uintptr_t)
 208 +           *(uint64_t *)copyin((uintptr_t)&s->sftp_raddr, sizeof (uint64_t)));
 209 +       ci_local = "<unknown>";
 210 +};
 211 +
 212 +#pragma D binding "1.6.1" translator
 213 +translator sftpinfo_t <sftpproto_t *s> {
 214 +       sfi_user = copyinstr((uintptr_t)
 215 +           *(uint64_t *)copyin((uintptr_t)&s->sftp_user, sizeof (uint64_t)));
 216 +       sfi_operation = copyinstr((uintptr_t)
 217 +           *(uint64_t *)copyin((uintptr_t)&s->sftp_operation,
 218 +           sizeof (uint64_t)));
 219 +       sfi_nbytes =
 220 +           *(uint64_t *)copyin((uintptr_t)&s->sftp_nbytes, sizeof (uint64_t));
 221 +       sfi_fsresource = stringof(fds[*(int32_t *)copyin((uintptr_t)&s->sftp_fd,
 222 +           sizeof (int32_t))].fi_fs) == "lofs" ? stringof(((struct loinfo *)
 223 +           curthread->t_procp->p_user.u_finfo.fi_list[*(int32_t *)copyin(
 224 +           (uintptr_t)&s->sftp_fd, sizeof (int32_t))].uf_file->f_vnode->
 225 +           v_vfsp->vfs_data)->li_realvfs->vfs_resource->rs_string) :
 226 +           stringof(curthread->t_procp->p_user.u_finfo.fi_list[
 227 +           *(int32_t *)copyin((uintptr_t)&s->sftp_fd, sizeof (int32_t))].
 228 +           uf_file->f_vnode->v_vfsp->vfs_resource->rs_string);
 229 +       sfi_pathname = copyinstr((uintptr_t)*(uint64_t *)copyin(
 230 +           (uintptr_t)&s->sftp_pathname, sizeof (uint64_t)));
 231 +};
 232 diff --git a/sftp_provider.d b/sftp_provider.d
 233 new file mode 100644
 234 index 0000000..99e9920
 235 --- /dev/null
 236 +++ b/sftp_provider.d
 237 @@ -0,0 +1,61 @@
 238 +/*
 239 + * CDDL HEADER START
 240 + *
 241 + * The contents of this file are subject to the terms of the
 242 + * Common Development and Distribution License (the "License").
 243 + * You may not use this file except in compliance with the License.
 244 + *
 245 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 246 + * or http://www.opensolaris.org/os/licensing.
 247 + * See the License for the specific language governing permissions
 248 + * and limitations under the License.
 249 + *
 250 + * When distributing Covered Code, include this CDDL HEADER in each
 251 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 252 + * If applicable, add the following below this CDDL HEADER, with the
 253 + * fields enclosed by brackets "[]" replaced with your own identifying
 254 + * information: Portions Copyright [yyyy] [name of copyright owner]
 255 + *
 256 + * CDDL HEADER END
 257 + */
 258 +/*
 259 + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
 260 + */
 261 +
 262 +/*
 263 + * We seem currently unable to depend properly on existing D libraries (like
 264 + * sftp.d). But the definitions for conninfo_t and sftpinfo_t are stored there
 265 + * (and have to be, since that's where the real translators live). So we're
 266 + * forced to define something here to satisfy dtrace(1M), but none of the
 267 + * definitions or translators here are actually used.
 268 + */
 269 +typedef struct sftpinfo {
 270 +       int dummy;
 271 +} sftpinfo_t;
 272 +
 273 +typedef struct sftpproto {
 274 +       int dummy;
 275 +} sftpproto_t;
 276 +
 277 +typedef struct conninfo {
 278 +       int dummy;
 279 +} conninfo_t;
 280 +
 281 +translator conninfo_t <sftpproto_t *dp> {
 282 +};
 283 +
 284 +translator sftpinfo_t <sftpproto_t *dp> {
 285 +};
 286 +
 287 +provider sftp {
 288 +       probe transfer__start(sftpproto_t *p) :
 289 +           (conninfo_t *p, sftpinfo_t *p);
 290 +       probe transfer__done(sftpproto_t *p) :
 291 +           (conninfo_t *p, sftpinfo_t *p);
 292 +};
 293 +
 294 +#pragma D attributes Evolving/Evolving/ISA provider sftp provider
 295 +#pragma D attributes Private/Private/Unknown provider sftp module
 296 +#pragma D attributes Private/Private/Unknown provider sftp function
 297 +#pragma D attributes Private/Private/ISA provider sftp name
 298 +#pragma D attributes Evolving/Evolving/ISA provider sftp args
 299 diff --git a/sftp_provider_impl.h b/sftp_provider_impl.h
 300 new file mode 100644
 301 index 0000000..4b18e6e
 302 --- /dev/null
 303 +++ b/sftp_provider_impl.h
 304 @@ -0,0 +1,73 @@
 305 +/*
 306 + * CDDL HEADER START
 307 + *
 308 + * The contents of this file are subject to the terms of the
 309 + * Common Development and Distribution License (the "License").
 310 + * You may not use this file except in compliance with the License.
 311 + *
 312 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 313 + * or http://www.opensolaris.org/os/licensing.
 314 + * See the License for the specific language governing permissions
 315 + * and limitations under the License.
 316 + *
 317 + * When distributing Covered Code, include this CDDL HEADER in each
 318 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 319 + * If applicable, add the following below this CDDL HEADER, with the
 320 + * fields enclosed by brackets "[]" replaced with your own identifying
 321 + * information: Portions Copyright [yyyy] [name of copyright owner]
 322 + *
 323 + * CDDL HEADER END
 324 + */
 325 +/*
 326 + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
 327 + */
 328 +
 329 +#ifndef        _SFTP_PROVIDER_IMPL_H
 330 +#define        _SFTP_PROVIDER_IMPL_H
 331 +
 332 +#ifdef __cplusplus
 333 +extern "C" {
 334 +#endif
 335 +
 336 +/*
 337 + * This structure must match the definition of same in sftp.d.
 338 + */
 339 +typedef struct sftpproto {
 340 +       int64_t sftp_nbytes;            /* bytes writtten or read */
 341 +       const char *sftp_user;          /* user name */
 342 +       const char *sftp_operation;     /* SFTP Operation */
 343 +       const char *sftp_raddr;         /* remote address */
 344 +       const char *sftp_pathname;      /* path with file name */
 345 +       int32_t sftp_fd;                /* fd for transfer, if any */
 346 +} sftpproto_t;
 347 +
 348 +#define        SFTP_TRANSFER_PROTO(proto, op, fd, path, len) \
 349 +       bzero((proto), sizeof (struct sftpproto)); \
 350 +       (proto)->sftp_user = (pw->pw_name ? pw->pw_name : "UNKNOWN"); \
 351 +       (proto)->sftp_operation = (op ? op : "UNKNOWN"); \
 352 +       (proto)->sftp_raddr = (client_addr); \
 353 +       (proto)->sftp_fd = (fd); \
 354 +       (proto)->sftp_pathname = (path ? path : "UNKNOWN"); \
 355 +       (proto)->sftp_nbytes = (len); \
 356 +
 357 +#define        SFTP_TRANSFER_START_OP(op, fd, path, len) \
 358 +       if (SFTP_TRANSFER_START_ENABLED()) { \
 359 +               sftpproto_t proto; \
 360 +               SFTP_TRANSFER_PROTO(&proto, op, fd, path, len); \
 361 +               SFTP_TRANSFER_START(&proto); \
 362 +       } \
 363 +
 364 +#define        SFTP_TRANSFER_DONE_OP(op, fd, path, len) \
 365 +       if (SFTP_TRANSFER_DONE_ENABLED()) { \
 366 +               sftpproto_t proto; \
 367 +               SFTP_TRANSFER_PROTO(&proto, op, fd, path, len); \
 368 +               SFTP_TRANSFER_DONE(&proto); \
 369 +       } \
 370 +
 371 +#include "sftp_provider.h"
 372 +
 373 +#ifdef __cplusplus
 374 +}
 375 +#endif
 376 +
 377 +#endif /* _SFTP_PROVIDER_IMPL_H */
 378 -- 
 379 2.5.4 (Apple Git-61)
 380