diff options
Diffstat (limited to 'usr/src/cmd')
619 files changed, 28481 insertions, 82866 deletions
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index 3fc7b894b0..1f098842b9 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -21,7 +21,7 @@ # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2015 Nexenta Systems, Inc. All rights reserved. -# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Copyright (c) 2014 Joyent, Inc. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright (c) 2013 DEY Storage Systems, Inc. All rights reserved. # Copyright 2014 Garrett D'Amore <garrett@damore.org> @@ -29,8 +29,8 @@ include ../Makefile.master # -# Note that the commands 'lp', and 'perl' are first in -# the list, violating alphabetical order. This is because they are very +# Note that if the 'lp' command were built, it would be first in +# the list, violating alphabetical order. This is because it is very # long-running and should be given the most wall-clock time for a # parallel build. # @@ -51,7 +51,6 @@ FIRST_SUBDIRS= \ COMMON_SUBDIRS= \ allocate \ availdevs \ - lp \ perl \ Adm \ abi \ @@ -94,6 +93,7 @@ COMMON_SUBDIRS= \ cmd-crypto \ cmd-inet \ col \ + column \ compress \ consadm \ coreadm \ @@ -103,6 +103,10 @@ COMMON_SUBDIRS= \ crypt \ csh \ csplit \ + ctfconvert \ + ctfdiff \ + ctfdump \ + ctfmerge \ ctrun \ ctstat \ ctwatch \ @@ -186,7 +190,6 @@ COMMON_SUBDIRS= \ groups \ grpck \ gss \ - hal \ halt \ head \ hostid \ @@ -223,7 +226,6 @@ COMMON_SUBDIRS= \ kvmstat \ last \ lastcomm \ - latencytop \ ldap \ ldapcachemgr \ lgrpinfo \ @@ -244,8 +246,8 @@ COMMON_SUBDIRS= \ look \ ls \ luxadm \ - lvm \ mach \ + machid \ mail \ mailwrapper \ mailx \ @@ -280,6 +282,7 @@ COMMON_SUBDIRS= \ news \ newtask \ nice \ + nicstat \ nl \ nlsadmin \ nohup \ @@ -312,7 +315,6 @@ COMMON_SUBDIRS= \ plockstat \ pr \ prctl \ - print \ printf \ priocntl \ profiles \ @@ -330,7 +332,6 @@ COMMON_SUBDIRS= \ pwck \ pwconv \ pwd \ - pyzfs \ raidctl \ ramdiskadm \ rcap \ @@ -381,7 +382,6 @@ COMMON_SUBDIRS= \ srchtxt \ srptadm \ srptsvc \ - ssh \ stat \ stmfadm \ stmfproxy \ @@ -433,8 +433,11 @@ COMMON_SUBDIRS= \ utmp_update \ utmpd \ valtools \ + varpd \ vgrind \ vi \ + vndadm \ + vndstat \ volcheck \ volrmmount \ vrrpadm \ @@ -500,7 +503,6 @@ sparc_SUBDIRS= \ # (see previous comment about 'lp'.) # MSGSUBDIRS= \ - lp \ abi \ acctadm \ allocate \ @@ -612,7 +614,6 @@ MSGSUBDIRS= \ logins \ ls \ luxadm \ - lvm \ mailx \ make \ man \ @@ -643,7 +644,6 @@ MSGSUBDIRS= \ power \ pr \ praudit \ - print \ profiles \ projadd \ projects \ @@ -654,7 +654,6 @@ MSGSUBDIRS= \ ptools \ pwconv \ pwd \ - pyzfs \ raidctl \ ramdiskadm \ rcap \ @@ -682,7 +681,6 @@ MSGSUBDIRS= \ sort \ split \ srptadm \ - ssh \ stat \ stmfadm \ stmsboot \ diff --git a/usr/src/cmd/Makefile.check b/usr/src/cmd/Makefile.check index 96fea6b370..d3b6dcc4a4 100644 --- a/usr/src/cmd/Makefile.check +++ b/usr/src/cmd/Makefile.check @@ -117,7 +117,6 @@ MANIFEST_SUBDIRS= \ krb5/krb5kdc \ krb5/kwarn \ krb5/slave \ - lp/cmd/lpsched \ lvm/rpc.mdcommd \ lvm/rpc.metad \ lvm/rpc.metamedd \ @@ -126,13 +125,10 @@ MANIFEST_SUBDIRS= \ lvm/util \ picl/picld \ pools/poold \ - print/bsd-sysv-commands \ - print/ppdmgr \ rcap/rcapd \ rpcsvc/rpc.bootparamd \ sendmail/lib \ smbsrv/smbd \ - ssh/etc \ svc/milestone \ tsol/labeld \ tsol/tnctl \ diff --git a/usr/src/cmd/cmd-inet/etc/services b/usr/src/cmd/cmd-inet/etc/services index 37514ac0a7..25ccc7cc43 100644 --- a/usr/src/cmd/cmd-inet/etc/services +++ b/usr/src/cmd/cmd-inet/etc/services @@ -1,6 +1,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2015 Joyent, Inc. # # CDDL HEADER START # @@ -215,6 +216,8 @@ krb5_prop 754/tcp # Kerberos V5 KDC propogation swat 901/tcp # Samba Web Adm.Tool ufsd 1008/tcp ufsd # UFS-aware server ufsd 1008/udp ufsd +portolan 1296/tcp # Portolan +svp-underlay 1339/tcp # SDC VXLAN underlay invalidation cvc 1495/tcp # Network Console ingreslock 1524/tcp www-ldap-gw 1760/tcp # HTTP to LDAP gateway diff --git a/usr/src/cmd/cmd-inet/etc/sock2path.d/system%2Fkernel b/usr/src/cmd/cmd-inet/etc/sock2path.d/system%2Fkernel index c62e339953..49151907eb 100644 --- a/usr/src/cmd/cmd-inet/etc/sock2path.d/system%2Fkernel +++ b/usr/src/cmd/cmd-inet/etc/sock2path.d/system%2Fkernel @@ -18,6 +18,7 @@ # CDDL HEADER END # # Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, Joyent, Inc. All rights reserved. # # socket configuration information # @@ -52,3 +53,6 @@ 29 4 1 /dev/spdsock 31 1 0 trill + + 33 1 0 lx_netlink + 33 4 0 lx_netlink diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile index 199f92807a..f150602cc9 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile @@ -19,13 +19,15 @@ # CDDL HEADER END # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2015 Joyent, Inc. # # Needed for ROOTFS_LIBDIR definition include ../../../../lib/Makefile.lib PROG= ipmgmtd -OBJS= ipmgmt_main.o ipmgmt_door.o ipmgmt_persist.o ipmgmt_util.o +OBJS= ipmgmt_main.o ipmgmt_door.o ipmgmt_persist.o ipmgmt_util.o \ + ipmgmt_path.o SRCS= $(OBJS:.o=.c) SVCMETHOD= net-ipmgmt MANIFEST= network-ipmgmt.xml diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c index 8e9e153b21..9f546bcad9 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014, Joyent, Inc. All rights reserved. */ /* @@ -112,7 +113,9 @@ ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp, goto fail; } - /* check for solaris.network.interface.config authorization */ + /* + * if not root, check for solaris.network.interface.config authorization + */ if (infop->idi_set) { uid_t uid; struct passwd pwd; @@ -124,24 +127,32 @@ ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp, goto fail; } uid = ucred_getruid(cred); + ucred_free(cred); if ((int)uid < 0) { err = errno; ipmgmt_log(LOG_ERR, "Could not get user id."); goto fail; } - if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == - NULL) { - err = errno; - ipmgmt_log(LOG_ERR, "Could not get password entry."); - goto fail; - } - if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH, - pwd.pw_name) != 1) { - err = EPERM; - ipmgmt_log(LOG_ERR, "Not authorized for operation."); - goto fail; + + /* + * Branded zones may have different auth, but root always + * allowed. + */ + if (uid != 0) { + if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) { + err = errno; + ipmgmt_log(LOG_ERR, + "Could not get password entry."); + goto fail; + } + if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH, + pwd.pw_name) != 1) { + err = EPERM; + ipmgmt_log(LOG_ERR, + "Not authorized for operation."); + goto fail; + } } - ucred_free(cred); } /* individual handlers take care of calling door_return */ diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h index 0d905f2ff0..32d752a6eb 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Joyent, Inc. */ #ifndef _IPMGMT_IMPL_H @@ -134,8 +135,6 @@ extern ipmgmt_aobjmap_list_t aobjmap; #define ADDROBJ_LOOKUPADD 0x00000004 #define ADDROBJ_SETLIFNUM 0x00000008 -/* Permanent data store for ipadm */ -#define IPADM_DB_FILE "/etc/ipadm/ipadm.conf" #define IPADM_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* @@ -145,20 +144,12 @@ extern ipmgmt_aobjmap_list_t aobjmap; */ #define IPADM_DB_VERSION 1 -/* - * A temporary file created in SMF volatile filesystem. This file captures the - * in-memory copy of list `aobjmap' on disk. This is done to recover from - * daemon reboot (using svcadm) or crashes. - */ -#define IPADM_TMPFS_DIR "/etc/svc/volatile/ipadm" -#define ADDROBJ_MAPPING_DB_FILE IPADM_TMPFS_DIR"/aobjmap.conf" - -/* - * A temporary copy of the ipadm configuration file might need - * to be created if write requests are encountered during boottime - * and the root filesystem is mounted read-only. - */ -#define IPADM_VOL_DB_FILE IPADM_TMPFS_DIR"/ipadm.conf" +typedef enum ipadm_path { + IPADM_PATH_TMPFS_DIR = 1, + IPADM_PATH_ADDROBJ_MAP_DB, + IPADM_PATH_DB, + IPADM_PATH_VOL_DB +} ipadm_path_t; /* SCF resources required to interact with svc.configd */ typedef struct scf_resources { @@ -188,6 +179,8 @@ extern void ipmgmt_release_scf_resources(scf_resources_t *); extern boolean_t ipmgmt_needs_upgrade(scf_resources_t *); extern void ipmgmt_update_dbver(scf_resources_t *); +extern void ipmgmt_path(ipadm_path_t, char *, size_t); + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c index 5cdc0f5697..994d1b0125 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Joyent, Inc. */ /* @@ -105,6 +106,7 @@ ipmgmt_db_init() int fd, err, scferr; scf_resources_t res; boolean_t upgrade = B_TRUE; + char aobjpath[MAXPATHLEN]; /* * Check to see if we need to upgrade the data-store. We need to @@ -134,11 +136,11 @@ ipmgmt_db_init() ipmgmt_release_scf_resources(&res); /* creates the address object data store, if it doesn't exist */ - if ((fd = open(ADDROBJ_MAPPING_DB_FILE, O_CREAT|O_RDONLY, - IPADM_FILE_MODE)) == -1) { + ipmgmt_path(IPADM_PATH_ADDROBJ_MAP_DB, aobjpath, sizeof (aobjpath)); + if ((fd = open(aobjpath, O_CREAT|O_RDONLY, IPADM_FILE_MODE)) == -1) { err = errno; - ipmgmt_log(LOG_ERR, "could not open %s: %s", - ADDROBJ_MAPPING_DB_FILE, strerror(err)); + ipmgmt_log(LOG_ERR, "could not open %s: %s", aobjpath, + strerror(err)); return (err); } (void) close(fd); @@ -152,8 +154,8 @@ ipmgmt_db_init() * representation of the mapping. That is, build `aobjmap' structure * from address object data store. */ - if ((err = ipadm_rw_db(ipmgmt_aobjmap_init, NULL, - ADDROBJ_MAPPING_DB_FILE, 0, IPADM_DB_READ)) != 0) { + if ((err = ipadm_rw_db(ipmgmt_aobjmap_init, NULL, aobjpath, 0, + IPADM_DB_READ)) != 0) { /* if there was nothing to initialize, it's fine */ if (err != ENOENT) return (err); @@ -165,17 +167,42 @@ ipmgmt_db_init() return (err); } +static const char * +ipmgmt_door_path() +{ + static char door[MAXPATHLEN]; + static boolean_t init_done = B_FALSE; + + if (!init_done) { + const char *zroot = zone_get_nroot(); + + /* + * If this is a branded zone, make sure we use the "/native" + * prefix for the door path: + */ + (void) snprintf(door, sizeof (door), "%s%s", zroot != NULL ? + zroot : "", IPMGMT_DOOR); + + init_done = B_TRUE; + } + + return (door); +} + static int ipmgmt_door_init() { int fd; int err; + const char *door = ipmgmt_door_path(); - /* create the door file for ipmgmtd */ - if ((fd = open(IPMGMT_DOOR, O_CREAT|O_RDONLY, IPADM_FILE_MODE)) == -1) { + /* + * Create the door file for ipmgmtd. + */ + if ((fd = open(door, O_CREAT | O_RDONLY, IPADM_FILE_MODE)) == -1) { err = errno; - ipmgmt_log(LOG_ERR, "could not open %s: %s", - IPMGMT_DOOR, strerror(err)); + ipmgmt_log(LOG_ERR, "could not open %s: %s", door, + strerror(err)); return (err); } (void) close(fd); @@ -186,15 +213,16 @@ ipmgmt_door_init() ipmgmt_log(LOG_ERR, "failed to create door: %s", strerror(err)); return (err); } + /* * fdetach first in case a previous daemon instance exited * ungracefully. */ - (void) fdetach(IPMGMT_DOOR); - if (fattach(ipmgmt_door_fd, IPMGMT_DOOR) != 0) { + (void) fdetach(door); + if (fattach(ipmgmt_door_fd, door) != 0) { err = errno; - ipmgmt_log(LOG_ERR, "failed to attach door to %s: %s", - IPMGMT_DOOR, strerror(err)); + ipmgmt_log(LOG_ERR, "failed to attach door to %s: %s", door, + strerror(err)); goto fail; } return (0); @@ -207,13 +235,15 @@ fail: static void ipmgmt_door_fini() { + const char *door = ipmgmt_door_path(); + if (ipmgmt_door_fd == -1) return; - (void) fdetach(IPMGMT_DOOR); + (void) fdetach(door); if (door_revoke(ipmgmt_door_fd) == -1) { ipmgmt_log(LOG_ERR, "failed to revoke access to door %s: %s", - IPMGMT_DOOR, strerror(errno)); + door, strerror(errno)); } } @@ -350,10 +380,14 @@ ipmgmt_init_privileges() { struct stat statbuf; int err; + char tmpfsdir[MAXPATHLEN]; - /* create the IPADM_TMPFS_DIR directory */ - if (stat(IPADM_TMPFS_DIR, &statbuf) < 0) { - if (mkdir(IPADM_TMPFS_DIR, (mode_t)0755) < 0) { + /* + * Create the volatile storage directory: + */ + ipmgmt_path(IPADM_PATH_TMPFS_DIR, tmpfsdir, sizeof (tmpfsdir)); + if (stat(tmpfsdir, &statbuf) < 0) { + if (mkdir(tmpfsdir, (mode_t)0755) < 0) { err = errno; goto fail; } @@ -364,8 +398,8 @@ ipmgmt_init_privileges() } } - if ((chmod(IPADM_TMPFS_DIR, 0755) < 0) || - (chown(IPADM_TMPFS_DIR, UID_NETADM, GID_NETADM) < 0)) { + if ((chmod(tmpfsdir, 0755) < 0) || + (chown(tmpfsdir, UID_NETADM, GID_NETADM) < 0)) { err = errno; goto fail; } diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c new file mode 100644 index 0000000000..0219ac1522 --- /dev/null +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c @@ -0,0 +1,84 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * Lookup functions for various file paths used by ipmgmtd. This mechanism + * primarily exists to account for a native root prefix when run within a + * branded zone (e.g. "/native"). + */ + +#include <stdio.h> +#include <zone.h> +#include "ipmgmt_impl.h" + +#define IPADM_PERM_DIR "/etc/ipadm" +#define IPADM_TMPFS_DIR "/etc/svc/volatile/ipadm" + +typedef struct ipadm_path_ent { + ipadm_path_t ipe_id; + const char *ipe_path; +} ipadm_path_ent_t; + +static ipadm_path_ent_t ipadm_paths[] = { + /* + * A temporary directory created in the SMF volatile filesystem. + */ + { IPADM_PATH_TMPFS_DIR, IPADM_TMPFS_DIR }, + + /* + * This file captures the in-memory copy of list `aobjmap' on disk. + * This allows the system to recover in the event that the daemon + * crashes or is restarted. + */ + { IPADM_PATH_ADDROBJ_MAP_DB, IPADM_TMPFS_DIR "/aobjmap.conf" }, + + /* + * The permanent data store for ipadm. + */ + { IPADM_PATH_DB, IPADM_PERM_DIR "/ipadm.conf" }, + + /* + * A temporary copy of the ipadm configuration created, if needed, to + * service write requests early in boot. This file is merged with the + * permanent data store once it is available for writes. + */ + { IPADM_PATH_VOL_DB, IPADM_TMPFS_DIR "/ipadm.conf" }, + + { 0, NULL } +}; + +/* + * Load one of the paths used by ipadm into the provided string buffer. + * Prepends the native system prefix (e.g. "/native") if one is in effect, + * such as when running within a branded zone. + */ +void +ipmgmt_path(ipadm_path_t ip, char *buf, size_t bufsz) +{ + int i; + + for (i = 0; ipadm_paths[i].ipe_path != NULL; i++) { + if (ipadm_paths[i].ipe_id == ip) { + const char *zroot = zone_get_nroot(); + + (void) snprintf(buf, bufsz, "%s%s", zroot != NULL ? + zroot : "", ipadm_paths[i].ipe_path); + + return; + } + } + + abort(); +} diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c index 73a0c621d0..5c5057a172 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Joyent, Inc. */ /* @@ -380,13 +381,18 @@ static void * ipmgmt_db_restore_thread(void *arg) { int err; + char confpath[MAXPATHLEN]; + char tmpconfpath[MAXPATHLEN]; + + ipmgmt_path(IPADM_PATH_DB, confpath, sizeof (confpath)); + ipmgmt_path(IPADM_PATH_VOL_DB, tmpconfpath, sizeof (tmpconfpath)); for (;;) { (void) sleep(5); (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock); if (!ipmgmt_rdonly_root) break; - err = ipmgmt_cpfile(IPADM_VOL_DB_FILE, IPADM_DB_FILE, B_FALSE); + err = ipmgmt_cpfile(tmpconfpath, confpath, B_FALSE); if (err == 0) { ipmgmt_rdonly_root = B_FALSE; break; @@ -418,6 +424,11 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) mode_t mode; pthread_t tid; pthread_attr_t attr; + char confpath[MAXPATHLEN]; + char tmpconfpath[MAXPATHLEN]; + + ipmgmt_path(IPADM_PATH_DB, confpath, sizeof (confpath)); + ipmgmt_path(IPADM_PATH_VOL_DB, tmpconfpath, sizeof (tmpconfpath)); writeop = (db_op != IPADM_DB_READ); if (writeop) { @@ -430,11 +441,10 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) /* * Did a previous write attempt fail? If so, don't even try to - * read/write to IPADM_DB_FILE. + * read/write to the permanent configuration file. */ if (!ipmgmt_rdonly_root) { - err = ipadm_rw_db(db_walk_func, db_warg, IPADM_DB_FILE, - mode, db_op); + err = ipadm_rw_db(db_walk_func, db_warg, confpath, mode, db_op); if (err != EROFS) goto done; } @@ -442,11 +452,11 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) /* * If we haven't already copied the file to the volatile * file system, do so. This should only happen on a failed - * writeop(i.e., we have acquired the write lock above). + * writeop (i.e., we have acquired the write lock above). */ - if (access(IPADM_VOL_DB_FILE, F_OK) != 0) { + if (access(tmpconfpath, F_OK) != 0) { assert(writeop); - err = ipmgmt_cpfile(IPADM_DB_FILE, IPADM_VOL_DB_FILE, B_TRUE); + err = ipmgmt_cpfile(confpath, tmpconfpath, B_TRUE); if (err != 0) goto done; (void) pthread_attr_init(&attr); @@ -456,7 +466,7 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) NULL); (void) pthread_attr_destroy(&attr); if (err != 0) { - (void) unlink(IPADM_VOL_DB_FILE); + (void) unlink(tmpconfpath); goto done; } ipmgmt_rdonly_root = B_TRUE; @@ -465,7 +475,7 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) /* * Read/write from the volatile copy. */ - err = ipadm_rw_db(db_walk_func, db_warg, IPADM_VOL_DB_FILE, + err = ipadm_rw_db(db_walk_func, db_warg, tmpconfpath, mode, db_op); done: (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); @@ -1233,6 +1243,9 @@ ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op) int err; ipadm_dbwrite_cbarg_t cb; nvlist_t *nvl = NULL; + char aobjpath[MAXPATHLEN]; + + ipmgmt_path(IPADM_PATH_ADDROBJ_MAP_DB, aobjpath, sizeof (aobjpath)); if (op == IPADM_DB_WRITE) { if ((err = i_ipmgmt_node2nvl(&nvl, nodep)) != 0) @@ -1243,14 +1256,14 @@ ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op) else cb.dbw_flags = 0; - err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb, - ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_WRITE); + err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb, aobjpath, + IPADM_FILE_MODE, IPADM_DB_WRITE); nvlist_free(nvl); } else { assert(op == IPADM_DB_DELETE); - err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep, - ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_DELETE); + err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep, aobjpath, + IPADM_FILE_MODE, IPADM_DB_DELETE); } return (err); } diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/net-ipmgmt b/usr/src/cmd/cmd-inet/lib/ipmgmtd/net-ipmgmt index 77b6be9f54..d5812793d4 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/net-ipmgmt +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/net-ipmgmt @@ -21,6 +21,7 @@ # # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # This daemon stores address object to logical interface number mappings # (among other things) and reads/writes from/to ipmgmtd data store. @@ -38,14 +39,16 @@ fi # When the non-global shared-IP stack zone boots, it tries to bring up this # service as well. If we don't start a background process and simply exit the # service, the service will go into maintenance mode and so will all it's -# dependents. +# dependents. Ideally we would simply exit with SMF_EXIT_NODAEMON, but since +# this method is also used in an S10C zone, where support for SMF_EXIT_NODAEMON +# does not exist, we have to stick around. # # In S10C zone (where this script is also used) smf_isnonglobalzone # function is unavailable in smf_include.sh # if [ `/sbin/zonename` != global ]; then if [ `/sbin/zonename -t` = shared ]; then - (while true ; do sleep 3600 ; done) & + (while true ; do sleep 3600 ; done) & exit $SMF_EXIT_OK fi fi diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c index 78da07aebf..9a710f9125 100644 --- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c +++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. * * REQUESTING state of the client state machine. */ @@ -38,6 +39,7 @@ #include <dhcp_hostconf.h> #include <dhcpagent_util.h> #include <dhcpmsg.h> +#include <strings.h> #include "states.h" #include "util.h" @@ -641,8 +643,24 @@ accept_v4_acknak(dhcp_smach_t *dsmp, PKT_LIST *plp) stop_pkt_retransmission(dsmp); if (*plp->opts[CD_DHCP_TYPE]->value == NAK) { - dhcpmsg(MSG_WARNING, "accept_v4_acknak: NAK on interface %s", - dsmp->dsm_name); + char saddr[18]; + + saddr[0] = '\0'; + if (plp->opts[CD_SERVER_ID] != NULL && + plp->opts[CD_SERVER_ID]->len == sizeof (struct in_addr)) { + struct in_addr t_server; + + bcopy(plp->opts[CD_SERVER_ID]->value, &t_server, + plp->opts[CD_SERVER_ID]->len); + (void) strlcpy(saddr, inet_ntoa(t_server), + sizeof (saddr)); + } + + dhcpmsg(MSG_WARNING, "accept_v4_acknak: NAK on interface %s " + "from %s %s", + dsmp->dsm_name, + inet_ntoa(plp->pktfrom.v4.sin_addr), saddr); + dsmp->dsm_bad_offers++; free_pkt_entry(plp); dhcp_restart(dsmp); diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c index ce771e3188..173a8f8325 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c @@ -1485,7 +1485,7 @@ mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *const limit ptr += sizeof(mDNSs32); nread += sizeof(mDNSs32); } - else { LogMsg("ERROR: getOptRdata - unknown opt %d", opt->opt); return mDNSNULL; } + else { return mDNSNULL; } opt++; // increment pointer into rdatabody } diff --git a/usr/src/cmd/cmd-inet/usr.lib/wanboot/p12split/Makefile b/usr/src/cmd/cmd-inet/usr.lib/wanboot/p12split/Makefile index f855d268c1..1b71e71af9 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/wanboot/p12split/Makefile +++ b/usr/src/cmd/cmd-inet/usr.lib/wanboot/p12split/Makefile @@ -25,7 +25,7 @@ include ../Makefile.com PROG= p12split -LDLIBS += -lwanboot -linetutil -lwanbootutil -lcrypto +LDLIBS += -lwanboot -linetutil -lwanbootutil -lsunw_crypto CPPFLAGS += -I$(CMNCRYPTDIR) LINTFLAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED diff --git a/usr/src/cmd/cmd-inet/usr.lib/wanboot/wanboot-cgi/Makefile b/usr/src/cmd/cmd-inet/usr.lib/wanboot/wanboot-cgi/Makefile index 16e3eb8261..9f671d4df7 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/wanboot/wanboot-cgi/Makefile +++ b/usr/src/cmd/cmd-inet/usr.lib/wanboot/wanboot-cgi/Makefile @@ -25,7 +25,7 @@ include ../Makefile.com PROG = wanboot-cgi -LDLIBS += -lgen -lnsl -lwanbootutil -lnvpair -lwanboot -lcrypto +LDLIBS += -lgen -lnsl -lwanbootutil -lnvpair -lwanboot -lsunw_crypto CPPFLAGS += -I$(CMNCRYPTDIR) LINTFLAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED diff --git a/usr/src/cmd/cmd-inet/usr.lib/wpad/Makefile b/usr/src/cmd/cmd-inet/usr.lib/wpad/Makefile index 1b82adef80..a743bed065 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/wpad/Makefile +++ b/usr/src/cmd/cmd-inet/usr.lib/wpad/Makefile @@ -33,7 +33,7 @@ include ../../../Makefile.cmd ROOTMANIFESTDIR = $(ROOTSVCNETWORK) LDLIBS += -ldladm -ldlpi -all install := LDLIBS += -lcrypto +all install := LDLIBS += -lsunw_crypto LINTFLAGS += -u diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile index 9724fff4e5..504d64b4ef 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile +++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile @@ -42,6 +42,7 @@ LDLIBS += -lxnet -lsocket -lnsl -lm -linetutil CPPFLAGS += -D_XOPEN_SOURCE=600 -D__EXTENSIONS__ C99MODE= -xc99=%all +C99LMODE= -Xc99=%all # Setting the above defines to use the UNIX98 ancillary data feature # causes lint to output warnings about lint library declarations conflicting diff --git a/usr/src/cmd/cmd-inet/usr.sbin/routeadm/routeadm.c b/usr/src/cmd/cmd-inet/usr.sbin/routeadm/routeadm.c index 71a2fc9853..be826baba2 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/routeadm/routeadm.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/routeadm/routeadm.c @@ -21,10 +21,9 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2012 Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -46,6 +45,7 @@ #include <libscf.h> #include <libscf_priv.h> #include <libuutil.h> +#include <ifaddrs.h> /* * This program moves routing management under SMF. We do this by giving @@ -2335,8 +2335,8 @@ out: /* * - * Return the number of IPv6 addresses configured. This answers the - * generic question, "is IPv6 configured?". We only start in.ndpd if IPv6 + * Return the number of non-loopback IPv6 addresses configured. This answers + * the generic question, "is IPv6 configured?". We only start in.ndpd if IPv6 * is configured, and we also only enable IPv6 routing daemons if IPv6 is * enabled. */ @@ -2344,28 +2344,24 @@ static int ra_numv6intfs(void) { static int num = -1; - int ipsock; - struct lifnum lifn; + int cnt; + struct ifaddrs *ifp_head, *ifp; if (num != -1) return (num); - if ((ipsock = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) { - (void) fprintf(stderr, - gettext("%1$s: unable to open %2$s: %3$s\n"), - myname, IP_DEV_NAME, strerror(errno)); + if (getifaddrs(&ifp_head) < 0) return (0); - } - lifn.lifn_family = AF_INET6; - lifn.lifn_flags = 0; - if (ioctl(ipsock, SIOCGLIFNUM, &lifn) == -1) { - (void) close(ipsock); - return (0); + cnt = 0; + for (ifp = ifp_head; ifp; ifp = ifp->ifa_next) { + if (!(ifp->ifa_flags & IFF_LOOPBACK) && + (ifp->ifa_flags & IFF_IPV6)) + cnt++; } - (void) close(ipsock); - return (num = lifn.lifn_count); + freeifaddrs(ifp_head); + return (num = cnt); } /* diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile index 1d408bccba..5d9ef9e64d 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile @@ -22,6 +22,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2015 Joyent, Inc. # PROG= snoop @@ -39,12 +40,14 @@ OBJS= nfs4_xdr.o snoop.o snoop_aarp.o snoop_adsp.o snoop_aecho.o \ snoop_pppoe.o snoop_rip.o snoop_rip6.o snoop_rpc.o snoop_rpcprint.o \ snoop_rpcsec.o snoop_rport.o snoop_rquota.o snoop_rstat.o snoop_rtmp.o \ snoop_sctp.o snoop_slp.o snoop_smb.o snoop_socks.o snoop_solarnet.o \ - snoop_tcp.o snoop_tftp.o snoop_trill.o snoop_udp.o snoop_zip.o + snoop_tcp.o snoop_tftp.o snoop_trill.o snoop_udp.o snoop_vxlan.o \ + snoop_zip.o SRCS= $(OBJS:.o=.c) HDRS= snoop.h snoop_mip.h at.h snoop_ospf.h snoop_ospf6.h include ../../../Makefile.cmd +include ../../../Makefile.ctf CPPFLAGS += -I. -I$(SRC)/common/net/dhcp \ -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c index 097dd6ee90..f2192df089 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c @@ -121,6 +121,7 @@ main(int argc, char **argv) char *output_area; int nbytes; char *datalink = NULL; + char *zonename = NULL; dlpi_handle_t dh; names[0] = '\0'; @@ -227,7 +228,7 @@ main(int argc, char **argv) } (void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ); - while ((c = getopt(argc, argv, "at:CPDSi:o:Nn:s:d:I:vVp:f:c:x:U?rqz")) + while ((c = getopt(argc, argv, "at:CPDSi:o:Nn:s:d:I:vVp:f:c:x:U?rqz:Z")) != EOF) { switch (c) { case 'a': @@ -348,8 +349,11 @@ main(int argc, char **argv) case 'U': Uflg = B_TRUE; break; -#ifdef DEBUG case 'z': + zonename = optarg; + break; +#ifdef DEBUG + case 'Z': zflg = B_TRUE; break; #endif /* DEBUG */ @@ -371,7 +375,7 @@ main(int argc, char **argv) * requested was chosen, but that's too hard. */ if (!icapfile) { - use_kern_pf = open_datalink(&dh, datalink); + use_kern_pf = open_datalink(&dh, datalink, zonename); } else { use_kern_pf = B_FALSE; cap_open_read(icapfile); @@ -816,6 +820,8 @@ usage(void) (void) fprintf(stderr, "\t[ -r ] # Do not resolve address to name\n"); (void) fprintf(stderr, + "\t[ -z zone ] # Open links from named zone\n"); + (void) fprintf(stderr, "\n\t[ filter expression ]\n"); (void) fprintf(stderr, "\nExample:\n"); (void) fprintf(stderr, "\tsnoop -o saved host fred\n\n"); diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h index e4f182572b..42095bcd34 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h @@ -24,6 +24,7 @@ * Use is subject to license terms. * * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. */ #ifndef _SNOOP_H @@ -182,7 +183,7 @@ extern void cap_open_read(const char *); extern void cap_open_write(const char *); extern void cap_read(int, int, int, void (*)(), int); extern void cap_close(void); -extern boolean_t open_datalink(dlpi_handle_t *, const char *); +extern boolean_t open_datalink(dlpi_handle_t *, const char *, const char *); extern void init_datalink(dlpi_handle_t, ulong_t, ulong_t, struct timeval *, struct Pf_ext_packetfilt *); extern void net_read(dlpi_handle_t, size_t, int, void (*)(), int); @@ -260,6 +261,7 @@ extern int interpret_socks_reply(int, char *, int); extern int interpret_trill(int, struct ether_header **, char *, int *); extern int interpret_isis(int, char *, int, boolean_t); extern int interpret_bpdu(int, char *, int); +extern int interpret_vxlan(int, char *, int); extern void init_ldap(void); extern boolean_t arp_for_ether(char *, struct ether_addr *); extern char *ether_ouiname(uint32_t); diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c index ab6bc292ac..8fbf3fc15f 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c @@ -29,6 +29,7 @@ #include <strings.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <setjmp.h> #include <sys/types.h> #include <sys/signal.h> @@ -114,7 +115,7 @@ select_datalink(const char *linkname, void *arg) * about the datalink useful for building the proper packet filters. */ boolean_t -open_datalink(dlpi_handle_t *dhp, const char *linkname) +open_datalink(dlpi_handle_t *dhp, const char *linkname, const char *zonename) { int retval; int flags = DLPI_PASSIVE | DLPI_RAW; @@ -122,6 +123,9 @@ open_datalink(dlpi_handle_t *dhp, const char *linkname) dlpi_info_t dlinfo; if (linkname == NULL) { + if (zonename != NULL) + pr_err("a datalink must be specified with a zone name"); + /* * Select a datalink to use by default. Prefer datalinks that * are plumbed by IP. @@ -145,7 +149,8 @@ open_datalink(dlpi_handle_t *dhp, const char *linkname) flags |= DLPI_DEVIPNET; if (Iflg || strcmp(linkname, "lo0") == 0) flags |= DLPI_IPNETINFO; - if ((retval = dlpi_open(linkname, dhp, flags)) != DLPI_SUCCESS) { + if ((retval = dlpi_open_zone(linkname, zonename, dhp, + flags)) != DLPI_SUCCESS) { pr_err("cannot open \"%s\": %s", linkname, dlpi_strerror(retval)); } @@ -614,6 +619,10 @@ cap_open_read(const char *name) if (fstat(capfile_in, &st) < 0) pr_err("couldn't stat %s: %m", name); + if (st.st_size > INT_MAX) + pr_err("input file size (%llu bytes) exceeds maximum " + "supported size (%d bytes)", + (unsigned long long)st.st_size, INT_MAX); cap_len = st.st_size; cap_buffp = mmap(0, cap_len, PROT_READ, MAP_PRIVATE, capfile_in, 0); diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ether.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ether.c index 5c6bde0cd6..029ed66116 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ether.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ether.c @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2015 Joyent, Inc. */ #include <stdio.h> @@ -54,8 +55,9 @@ static headerlen_fn_t ether_header_len, fddi_header_len, tr_header_len, ib_header_len, ipnet_header_len, ipv4_header_len, ipv6_header_len; -static interpreter_fn_t interpret_ether, interpret_fddi, interpret_tr, +static interpreter_fn_t interpret_fddi, interpret_tr, interpret_ib, interpret_ipnet, interpret_iptun; +interpreter_fn_t interpret_ether; static void addr_copy_swap(struct ether_addr *, struct ether_addr *); static int tr_machdr_len(char *, int *, int *); diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c index b84ee3c1b4..c2fcfd7c72 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c @@ -21,6 +21,7 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2015, Joyent, Inc. */ #include <stdio.h> @@ -76,6 +77,7 @@ static const struct porttable pt_udp[] = { { 560, "RMONITOR" }, { 561, "MONITOR" }, { IPPORT_SOCKS, "SOCKS" }, + { IPPORT_VXLAN, "VXLAN" }, { 0, NULL } }; @@ -428,6 +430,9 @@ interpret_reserved(int flags, int proto, in_port_t src, in_port_t dst, (void) interpret_socks_reply(flags, data, dlen); return (1); + case IPPORT_VXLAN: + (void) interpret_vxlan(flags, data, dlen); + return (1); } } diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_vxlan.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_vxlan.c new file mode 100644 index 0000000000..36025ca8f3 --- /dev/null +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_vxlan.c @@ -0,0 +1,68 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. All rights reserved. + */ + +/* + * Decode VXLAN encapsulated packets. + */ + +#include <sys/vxlan.h> +#include "snoop.h" + +int +interpret_vxlan(int flags, char *data, int fraglen) +{ + vxlan_hdr_t *vxlan = (vxlan_hdr_t *)data; + uint32_t id, vxf; + + if (fraglen < sizeof (vxlan_hdr_t)) { + if (flags & F_SUM) + (void) snprintf(get_sum_line(), MAXLINE, + "VXLAN RUNT"); + if (flags & F_DTAIL) + show_header("VXLAN RUNT: ", "Short packet", fraglen); + + return (fraglen); + } + + id = ntohl(vxlan->vxlan_id) >> VXLAN_ID_SHIFT; + vxf = ntohl(vxlan->vxlan_flags); + + if (flags & F_SUM) { + (void) snprintf(get_sum_line(), MAXLINE, + "VXLAN VNI=%d", id); + } + + if (flags & F_DTAIL) { + show_header("VXLAN: ", "VXLAN Header", sizeof (vxlan_hdr_t)); + show_space(); + (void) snprintf(get_line(0, 0), get_line_remain(), + "Flags = 0x%08x", vxf); + (void) snprintf(get_line(0, 0), get_line_remain(), " %s", + getflag(vxf >> 24, VXLAN_F_VDI >> 24, "vni present", + "vni missing")); + (void) snprintf(get_line(0, 0), get_line_remain(), + "VXLAN network id (VNI) = %d", id); + show_space(); + } + + if (flags & (F_DTAIL | F_ALLSUM)) { + fraglen -= sizeof (vxlan_hdr_t); + data += sizeof (vxlan_hdr_t); + + return (interpret_ether(flags, data, fraglen, fraglen)); + } + + return (0); +} diff --git a/usr/src/cmd/column/Makefile b/usr/src/cmd/column/Makefile new file mode 100644 index 0000000000..ab4cf3390e --- /dev/null +++ b/usr/src/cmd/column/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 2013 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +PROG=column + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/column/THIRDPARTYLICENSE b/usr/src/cmd/column/THIRDPARTYLICENSE new file mode 100644 index 0000000000..a80f56cb43 --- /dev/null +++ b/usr/src/cmd/column/THIRDPARTYLICENSE @@ -0,0 +1,26 @@ +Copyright (c) 1989, 1993, 1994 + The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + * +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/usr/src/cmd/column/THIRDPARTYLICENSE.descrip b/usr/src/cmd/column/THIRDPARTYLICENSE.descrip new file mode 100644 index 0000000000..42051a2982 --- /dev/null +++ b/usr/src/cmd/column/THIRDPARTYLICENSE.descrip @@ -0,0 +1 @@ +PORTIONS OF COLUMN COMMAND FUNCTIONALITY diff --git a/usr/src/cmd/column/column.c b/usr/src/cmd/column/column.c new file mode 100644 index 0000000000..4f9a3c81a6 --- /dev/null +++ b/usr/src/cmd/column/column.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Portions Copyright (c) 2013 Joyent, Inc. All rights reserved. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/param.h> +#include <sys/termios.h> + +#include <err.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <wchar.h> +#include <wctype.h> + +#define TAB 8 +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ + +static void c_columnate(void); +static void input(FILE *); +static void maketbl(void); +static void print(void); +static void r_columnate(void); +static void usage(void); +static int width(const wchar_t *); + +static int termwidth = 80; /* default terminal width */ + +static int entries; /* number of records */ +static int eval; /* exit value */ +static int maxlength; /* longest record */ +static wchar_t **list; /* array of pointers to records */ +static const wchar_t *separator = L"\t "; /* field separator for table option */ + +int +main(int argc, char **argv) +{ + struct winsize win; + FILE *fp; + int ch, tflag, xflag; + char *p; + const char *src; + wchar_t *newsep; + size_t seplen; + + (void) setlocale(LC_ALL, ""); + + if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) { + if ((p = getenv("COLUMNS"))) + termwidth = atoi(p); + } else + termwidth = win.ws_col; + + tflag = xflag = 0; + while ((ch = getopt(argc, argv, "c:s:tx")) != -1) + switch (ch) { + case 'c': + termwidth = atoi(optarg); + break; + case 's': + src = optarg; + seplen = mbsrtowcs(NULL, &src, 0, NULL); + if (seplen == (size_t)-1) + err(1, "bad separator"); + newsep = malloc((seplen + 1) * sizeof (wchar_t)); + if (newsep == NULL) + err(1, NULL); + (void) mbsrtowcs(newsep, &src, seplen + 1, NULL); + separator = newsep; + break; + case 't': + tflag = 1; + break; + case 'x': + xflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (!*argv) + input(stdin); + else for (; *argv; ++argv) + if ((fp = fopen(*argv, "rF"))) { + input(fp); + (void) fclose(fp); + } else { + warn("%s", *argv); + eval = 1; + } + + if (!entries) + exit(eval); + + maxlength = roundup(maxlength + 1, TAB); + if (tflag) + maketbl(); + else if (maxlength >= termwidth) + print(); + else if (xflag) + c_columnate(); + else + r_columnate(); + exit(eval); + + /*NOTREACHED*/ + return (eval); +} + +static void +c_columnate(void) +{ + int chcnt, col, cnt, endcol, numcols; + wchar_t **lp; + + numcols = termwidth / maxlength; + endcol = maxlength; + for (chcnt = col = 0, lp = list; ; ++lp) { + (void) wprintf(L"%ls", *lp); + chcnt += width(*lp); + if (!--entries) + break; + if (++col == numcols) { + chcnt = col = 0; + endcol = maxlength; + (void) putwchar('\n'); + } else { + while ((cnt = roundup(chcnt + 1, TAB)) <= endcol) { + (void) putwchar('\t'); + chcnt = cnt; + } + endcol += maxlength; + } + } + if (chcnt) + (void) putwchar('\n'); +} + +static void +r_columnate(void) +{ + int base, chcnt, cnt, col, endcol, numcols, numrows, row; + + numcols = termwidth / maxlength; + numrows = entries / numcols; + if (entries % numcols) + ++numrows; + + for (row = 0; row < numrows; ++row) { + endcol = maxlength; + for (base = row, chcnt = col = 0; col < numcols; ++col) { + (void) wprintf(L"%ls", list[base]); + chcnt += width(list[base]); + if ((base += numrows) >= entries) + break; + while ((cnt = roundup(chcnt + 1, TAB)) <= endcol) { + (void) putwchar('\t'); + chcnt = cnt; + } + endcol += maxlength; + } + (void) putwchar('\n'); + } +} + +static void +print(void) +{ + int cnt; + wchar_t **lp; + + for (cnt = entries, lp = list; cnt--; ++lp) + (void) wprintf(L"%ls\n", *lp); +} + +typedef struct _tbl { + wchar_t **list; + int cols, *len; +} TBL; +#define DEFCOLS 25 + +static void +maketbl(void) +{ + TBL *t; + int coloff, cnt; + wchar_t *p, **lp; + int *lens, maxcols; + TBL *tbl; + wchar_t **cols; + wchar_t *last; + + if ((t = tbl = calloc(entries, sizeof (TBL))) == NULL) + err(1, (char *)NULL); + if ((cols = calloc((maxcols = DEFCOLS), sizeof (*cols))) == NULL) + err(1, (char *)NULL); + if ((lens = calloc(maxcols, sizeof (int))) == NULL) + err(1, (char *)NULL); + for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) { + for (coloff = 0, p = *lp; + (cols[coloff] = wcstok(p, separator, &last)); + p = NULL) + if (++coloff == maxcols) { + if (!(cols = realloc(cols, ((uint_t)maxcols + + DEFCOLS) * sizeof (char *))) || + !(lens = realloc(lens, + ((uint_t)maxcols + DEFCOLS) * + sizeof (int)))) + err(1, NULL); + (void) memset((char *)lens + maxcols * + sizeof (int), 0, DEFCOLS * sizeof (int)); + maxcols += DEFCOLS; + } + if ((t->list = calloc(coloff, sizeof (*t->list))) == NULL) + err(1, (char *)NULL); + if ((t->len = calloc(coloff, sizeof (int))) == NULL) + err(1, (char *)NULL); + for (t->cols = coloff; --coloff >= 0; ) { + t->list[coloff] = cols[coloff]; + t->len[coloff] = width(cols[coloff]); + if (t->len[coloff] > lens[coloff]) + lens[coloff] = t->len[coloff]; + } + } + for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) { + for (coloff = 0; coloff < t->cols - 1; ++coloff) + (void) wprintf(L"%ls%*ls", t->list[coloff], + lens[coloff] - t->len[coloff] + 2, L" "); + (void) wprintf(L"%ls\n", t->list[coloff]); + } +} + +#define DEFNUM 1000 +#define MAXLINELEN (LINE_MAX + 1) + +static void +input(FILE *fp) +{ + static int maxentry; + int len; + wchar_t *p, buf[MAXLINELEN]; + + if (!list) + if ((list = calloc((maxentry = DEFNUM), sizeof (*list))) == + NULL) + err(1, (char *)NULL); + while (fgetws(buf, MAXLINELEN, fp)) { + for (p = buf; *p && iswspace(*p); ++p) + ; + if (!*p) + continue; + if (!(p = wcschr(p, L'\n'))) { + warnx("line too long"); + eval = 1; + continue; + } + *p = L'\0'; + len = width(buf); + if (maxlength < len) + maxlength = len; + if (entries == maxentry) { + maxentry += DEFNUM; + if (!(list = realloc(list, + (uint_t)maxentry * sizeof (*list)))) + err(1, NULL); + } + list[entries] = malloc((wcslen(buf) + 1) * sizeof (wchar_t)); + if (list[entries] == NULL) + err(1, NULL); + (void) wcscpy(list[entries], buf); + entries++; + } +} + +/* Like wcswidth(), but ignores non-printing characters. */ +static int +width(const wchar_t *wcs) +{ + int w, cw; + + for (w = 0; *wcs != L'\0'; wcs++) + if ((cw = wcwidth(*wcs)) > 0) + w += cw; + return (w); +} + +static void +usage(void) +{ + + (void) fprintf(stderr, + "usage: column [-tx] [-c columns] [-s sep] [file ...]\n"); + exit(1); +} diff --git a/usr/src/cmd/coreadm/coreadm.xml b/usr/src/cmd/coreadm/coreadm.xml index 46a4cda17a..28f1e27240 100644 --- a/usr/src/cmd/coreadm/coreadm.xml +++ b/usr/src/cmd/coreadm/coreadm.xml @@ -48,14 +48,6 @@ <service_fmri value='svc:/system/filesystem/minimal' /> </dependency> - <dependency - name='coreadm_manifest-import' - type='service' - grouping='require_all' - restart_on='none'> - <service_fmri value='svc:/system/manifest-import:default' /> - </dependency> - <instance name='default' enabled='false'> <exec_method type='method' diff --git a/usr/src/cmd/cron/Makefile b/usr/src/cmd/cron/Makefile index c9ffeadffe..fb05e292a3 100644 --- a/usr/src/cmd/cron/Makefile +++ b/usr/src/cmd/cron/Makefile @@ -26,6 +26,7 @@ DEFAULTFILES = cron.dfl include ../Makefile.cmd +include ../Makefile.ctf MANIFEST = cron.xml @@ -96,20 +97,20 @@ XPG4ATOBJS= $(ATOBJS:%=objs.xpg4/%) $(XPG4OBJS:%=objs.xpg4/%) XPG6COMMONOBJS= $(COMMONOBJS:%=objs.xpg6/%) XPG6CTOBJS= $(CRONTABOBJS:%=objs.xpg6/%) -cron := POBJS = $(CRONOBJS) $(COMMONOBJ2) -at := POBJS = $(ATOBJS) $(COMMONOBJS) -at.xpg4 := POBJS = $(XPG4ATOBJS) $(XPG4COMMONOBJS) -atrm := POBJS = $(ATRMOBJS) $(COMMONOBJS) -atq := POBJS = $(ATQOBJS) $(COMMONOBJS) -crontab := POBJS = $(CRONTABOBJS) $(COMMONOBJS) -crontab.xpg4 := POBJS = $(XPG4CTOBJS) $(XPG4COMMONOBJS) -crontab.xpg6 := POBJS = $(XPG6CTOBJS) $(XPG6COMMONOBJS) +cron := OBJS = $(CRONOBJS) $(COMMONOBJ2) +at := OBJS = $(ATOBJS) $(COMMONOBJS) +at.xpg4 := OBJS = $(XPG4ATOBJS) $(XPG4COMMONOBJS) +atrm := OBJS = $(ATRMOBJS) $(COMMONOBJS) +atq := OBJS = $(ATQOBJS) $(COMMONOBJS) +crontab := OBJS = $(CRONTABOBJS) $(COMMONOBJS) +crontab.xpg4 := OBJS = $(XPG4CTOBJS) $(XPG4COMMONOBJS) +crontab.xpg6 := OBJS = $(XPG6CTOBJS) $(XPG6COMMONOBJS) CFLAGS += $(CCVERBOSE) NOBJS= $(CRONOBJS) $(ATOBJS) $(ATRMOBJS1) $(ATQOBJS) $(CRONTABOBJS1) \ $(COMMONOBJS) -OBJS = $(NOBJS) $(XPG4COMMONOBJS) $(XPG4ATOBJS) $(XPG4CTOBJS) \ +COBJS = $(NOBJS) $(XPG4COMMONOBJS) $(XPG4ATOBJS) $(XPG4CTOBJS) \ $(XPG6COMMONOBJS) $(XPG6CTOBJS) $(GETRESPOBJ) SRCS = $(NOBJS:%.o=%.c) $(GETRESPSRC) @@ -157,32 +158,35 @@ all : $(PROG) $(XPG4) $(XPG6) $(SCRIPT) $(XPG4SCRIPT) $(FILES) install : all $(ROOTPROG) $(ROOTETCDEFAULTFILES) $(ROOTSYMLINK) \ $(ROOTMANIFEST) $(ROOTMETHOD) -$(PROG) : $$(POBJS) - $(LINK.c) $(POBJS) -o $@ $(LDLIBS) +$(PROG) : $$(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) -$(XPG4) : objs.xpg4 $$(POBJS) - $(LINK.c) $(POBJS) -o $@ $(LDLIBS) +$(XPG4) : objs.xpg4 $$(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) -$(XPG6) : objs.xpg6 $$(POBJS) - $(LINK.c) $(POBJS) -o $@ $(LDLIBS) +$(XPG6) : objs.xpg6 $$(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) objs.xpg6/%.o: %.c $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) objs.xpg6: -@mkdir -p $@ objs.xpg4/%.o: %.c $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) objs.xpg4: -@mkdir -p $@ objs.xpg4/values-xpg4.o: ../../lib/common/common/values-xpg4.c $(COMPILE.c) -o $@ ../../lib/common/common/values-xpg4.c + $(POST_PROCESS_O) %.o: $(SRC)/common/util/%.c $(COMPILE.c) $(OUTPUT_OPTION) $< @@ -219,7 +223,7 @@ $(POFILE): $(POFILES) $(RM) $@; cat $(POFILES) > $@ clean : - $(RM) $(OBJS) att1.h att1.c att2.c + $(RM) $(COBJS) att1.h att1.c att2.c lint : lint_SRCS diff --git a/usr/src/cmd/cron/cron.c b/usr/src/cmd/cron/cron.c index ab36d09037..33a7373f1e 100644 --- a/usr/src/cmd/cron/cron.c +++ b/usr/src/cmd/cron/cron.c @@ -23,7 +23,7 @@ * Use is subject to license terms. * * Copyright 2013 Joshua M. Clulow <josh@sysmgr.org> - * + * Copyright 2013 Joyent, Inc. All rights reserved. * Copyright (c) 2014 Gary Mills */ @@ -315,7 +315,8 @@ static int ex(struct event *e); static void read_dirs(int); static void mail(char *, char *, int); static char *next_field(int, int); -static void readcron(struct usr *, time_t); +static void readcron(char *, struct usr *, time_t); +static void readcronfile(FILE *, struct usr *, time_t); static int next_ge(int, char *); static void free_if_unused(struct usr *); static void del_atjob(char *, char *); @@ -420,7 +421,7 @@ extern void el_delete(void); static int valid_entry(char *, int); static struct usr *create_ulist(char *, int); -static void init_cronevent(char *, int); +static void init_cronevent(char *, char *); static void init_atevent(char *, time_t, int, int); static void update_atevent(struct usr *, char *, time_t, int); @@ -759,6 +760,18 @@ read_dirs(int first) time_t tim; + if (chdir(SYSCRONDIR) != -1) { + cwd = CRON; + if ((dir = opendir(".")) != NULL) { + while ((dp = readdir(dir)) != NULL) { + if (!valid_entry(dp->d_name, CRONEVENT)) + continue; + init_cronevent(SYSCRONDIR, dp->d_name); + } + (void) closedir(dir); + } + } + if (chdir(CRONDIR) == -1) crabort(BADCD, REMOVE_FIFO|CONSOLE_MSG); cwd = CRON; @@ -767,7 +780,7 @@ read_dirs(int first) while ((dp = readdir(dir)) != NULL) { if (!valid_entry(dp->d_name, CRONEVENT)) continue; - init_cronevent(dp->d_name, first); + init_cronevent(CRONDIR, dp->d_name); } (void) closedir(dir); @@ -853,23 +866,18 @@ create_ulist(char *name, int type) } void -init_cronevent(char *name, int first) +init_cronevent(char *basedir, char *name) { struct usr *u; - if (first) { + if ((u = find_usr(name)) == NULL) { u = create_ulist(name, CRONEVENT); - readcron(u, 0); + readcron(basedir, u, 0); } else { - if ((u = find_usr(name)) == NULL) { - u = create_ulist(name, CRONEVENT); - readcron(u, 0); - } else { - u->ctexists = TRUE; - rm_ctevents(u); - el_remove(u->ctid, 0); - readcron(u, 0); - } + u->ctexists = TRUE; + rm_ctevents(u); + el_remove(u->ctid, 0); + readcron(basedir, u, 0); } } @@ -950,7 +958,7 @@ mod_ctab(char *name, time_t reftime) (void) strcpy(u->home, pw->pw_dir); u->uid = pw->pw_uid; u->gid = pw->pw_gid; - readcron(u, reftime); + readcron(CRONDIR, u, reftime); } else { u->uid = pw->pw_uid; u->gid = pw->pw_gid; @@ -973,7 +981,7 @@ mod_ctab(char *name, time_t reftime) /* user didnt have a crontab last time */ u->ctid = ecid++; u->ctevents = NULL; - readcron(u, reftime); + readcron(CRONDIR, u, reftime); return; } #ifdef DEBUG @@ -981,7 +989,7 @@ mod_ctab(char *name, time_t reftime) #endif rm_ctevents(u); el_remove(u->ctid, 0); - readcron(u, reftime); + readcron(CRONDIR, u, reftime); } } @@ -1116,8 +1124,94 @@ update_atevent(struct usr *u, char *name, time_t tim, int jobtype) static char line[CTLINESIZE]; /* holds a line from a crontab file */ static int cursor; /* cursor for the above line */ +static int +copyfile(char *name, FILE *dp) +{ + FILE *tf; + + if ((tf = fopen(name, "r")) == NULL) { + (void) fclose(dp); + return (1); + } + + while (fgets(line, CTLINESIZE, tf) != NULL) { + if (fputs(line, dp) == EOF) { + (void) fclose(tf); + (void) fclose(dp); + return (1); + } + } + (void) fclose(tf); + + return (0); +} + +static void +readcron(char *basedir, struct usr *u, time_t reftime) +{ + char *altpath; + struct stat sb; + FILE *cf; /* cf will be a user's crontab file */ + char altnamebuf[PATH_MAX]; + char namebuf[PATH_MAX]; + + if (strcmp(basedir, SYSCRONDIR) == 0) + altpath = CRONDIR; + else + altpath = SYSCRONDIR; + + if (snprintf(altnamebuf, sizeof (altnamebuf), "%s/%s", altpath, + u->name) >= sizeof (altnamebuf)) + return; + + if (snprintf(namebuf, sizeof (namebuf), "%s/%s", basedir, u->name) >= + sizeof (namebuf)) + return; + + if (stat(altnamebuf, &sb) != -1) { + /* + * There is a secondary crontab for this user. We need to + * merge the two crontabs into a temporary file for loading. + */ + int fd; + char tmpfile[PATH_MAX]; + + (void) strlcpy(tmpfile, "/tmp/cronXXXXXX", sizeof (tmpfile)); + if ((fd = mkstemp(tmpfile)) == -1) + return; + + unlink(tmpfile); + if ((cf = fdopen(fd, "w+")) == NULL) { + close(fd); + return; + } + + if (copyfile(namebuf, cf) != 0) + return; + + if (copyfile(altnamebuf, cf) != 0) + return; + + (void) fflush(cf); + rewind(cf); + + } else { + /* + * Only one crontab, open it directly. + */ + if ((cf = fopen(namebuf, "r")) == NULL) { + mail(u->name, NOREAD, ERR_UNIXERR); + return; + } + } + + readcronfile(cf, u, reftime); + + (void) fclose(cf); +} + static void -readcron(struct usr *u, time_t reftime) +readcronfile(FILE *cf, struct usr *u, time_t reftime) { /* * readcron reads in a crontab file for a user (u). The list of @@ -1125,12 +1219,9 @@ readcron(struct usr *u, time_t reftime) * this list. Each event is also entered into the main event * list. */ - FILE *cf; /* cf will be a user's crontab file */ struct event *e; int start; unsigned int i; - char namebuf[PATH_MAX]; - char *pname; struct shared *tz = NULL; struct shared *home = NULL; struct shared *shell = NULL; @@ -1138,19 +1229,6 @@ readcron(struct usr *u, time_t reftime) /* read the crontab file */ cte_init(); /* Init error handling */ - if (cwd != CRON) { - if (snprintf(namebuf, sizeof (namebuf), "%s/%s", - CRONDIR, u->name) >= sizeof (namebuf)) { - return; - } - pname = namebuf; - } else { - pname = u->name; - } - if ((cf = fopen(pname, "r")) == NULL) { - mail(u->name, NOREAD, ERR_UNIXERR); - return; - } while (fgets(line, CTLINESIZE, cf) != NULL) { char *tmp; /* process a line of a crontab file */ @@ -1279,7 +1357,6 @@ again: #endif } cte_sendmail(u->name); /* mail errors if any to user */ - (void) fclose(cf); rel_shared(tz); rel_shared(shell); rel_shared(home); @@ -2442,6 +2519,9 @@ ex(struct event *e) } else { r = audit_cron_session(e->u->name, CRONDIR, e->u->uid, e->u->gid, NULL); + if (r != 0) + r = audit_cron_session(e->u->name, SYSCRONDIR, + e->u->uid, e->u->gid, NULL); } if (r != 0) { msg("cron audit problem. job failed (%s) for user %s", diff --git a/usr/src/cmd/cron/cron.h b/usr/src/cmd/cron/cron.h index a76016299c..93e21e7b41 100644 --- a/usr/src/cmd/cron/cron.h +++ b/usr/src/cmd/cron/cron.h @@ -71,6 +71,9 @@ struct message { char logname[LLEN]; }; +/* anything below here can be changed */ + +#define SYSCRONDIR "/etc/cron.d/crontabs" #define CRONDIR "/var/spool/cron/crontabs" #define ATDIR "/var/spool/cron/atjobs" #define ACCTFILE "/var/cron/log" diff --git a/usr/src/cmd/cron/crontab.c b/usr/src/cmd/cron/crontab.c index 327a71388b..cdb4e1e394 100644 --- a/usr/src/cmd/cron/crontab.c +++ b/usr/src/cmd/cron/crontab.c @@ -71,7 +71,7 @@ "usage:\n" \ "\tcrontab [file]\n" \ "\tcrontab -e [username]\n" \ - "\tcrontab -l [username]\n" \ + "\tcrontab -l [-g] [username]\n" \ "\tcrontab -r [username]" #define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)." #define NOTALLOWED "you are not authorized to use cron. Sorry." @@ -120,6 +120,7 @@ main(int argc, char **argv) int c, r; int rflag = 0; int lflag = 0; + int gflag = 0; int eflag = 0; int errflg = 0; char *pp; @@ -151,11 +152,14 @@ main(int argc, char **argv) exit(1); } - while ((c = getopt(argc, argv, "elr")) != EOF) + while ((c = getopt(argc, argv, "eglr")) != EOF) switch (c) { case 'e': eflag++; break; + case 'g': + gflag++; + break; case 'l': lflag++; break; @@ -170,6 +174,9 @@ main(int argc, char **argv) if (eflag + lflag + rflag > 1) errflg++; + if (gflag && !lflag) + errflg++; + argc -= optind; argv += optind; if (errflg || argc > 1) @@ -236,12 +243,27 @@ main(int argc, char **argv) exit(0); } if (lflag) { - if ((fp = fopen(cf, "r")) == NULL) - crabort(BADOPEN); - while (fgets(line, CTLINESIZE, fp) != NULL) - fputs(line, stdout); - fclose(fp); - exit(0); + char sysconf[PATH_MAX]; + + if (gflag) { + if (snprintf(sysconf, sizeof (sysconf), "%s/%s", + SYSCRONDIR, login) < sizeof (sysconf) && + (fp = fopen(sysconf, "r")) != NULL) { + while (fgets(line, CTLINESIZE, fp) != NULL) + fputs(line, stdout); + fclose(fp); + exit(0); + } else { + crabort(BADOPEN); + } + } else { + if ((fp = fopen(cf, "r")) == NULL) + crabort(BADOPEN); + while (fgets(line, CTLINESIZE, fp) != NULL) + fputs(line, stdout); + fclose(fp); + exit(0); + } } if (eflag) { if ((fp = fopen(cf, "r")) == NULL) { diff --git a/usr/src/cmd/ctfconvert/Makefile b/usr/src/cmd/ctfconvert/Makefile new file mode 100644 index 0000000000..688addd9d1 --- /dev/null +++ b/usr/src/cmd/ctfconvert/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +PROG= ctfconvert + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf -lelf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfconvert/ctfconvert.c b/usr/src/cmd/ctfconvert/ctfconvert.c new file mode 100644 index 0000000000..dd3d40c6cc --- /dev/null +++ b/usr/src/cmd/ctfconvert/ctfconvert.c @@ -0,0 +1,389 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Create CTF from extant debugging information + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <libelf.h> +#include <libctf.h> +#include <string.h> +#include <libgen.h> +#include <limits.h> +#include <strings.h> +#include <sys/debug.h> + +#define CTFCONVERT_OK 0 +#define CTFCONVERT_FATAL 1 +#define CTFCONVERT_USAGE 2 + +#define CTFCONVERT_DEFAULT_NTHREADS 4 + +#define CTFCONVERT_ALTEXEC "CTFCONVERT_ALTEXEC" + +static char *ctfconvert_progname; + +static void +ctfconvert_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", ctfconvert_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(CTFCONVERT_FATAL); +} + + +static void +ctfconvert_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + + (void) fprintf(stderr, "%s: ", ctfconvert_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-is] [-j nthrs] [-l label | " + "-L labelenv] [-o outfile] input\n" + "\n" + "\t-i ignore files not built partially from C sources\n" + "\t-j use nthrs threads to perform the merge\n" + "\t-k keep around original input file on failure\n" + "\t-o copy input to outfile and add CTF\n" + "\t-l set output container's label to specified value\n" + "\t-L set output container's label to value from environment\n", + ctfconvert_progname); +} + +/* + * This is a bit unfortunate. Traditionally we do type uniquification across all + * modules in the kernel, including ip and unix against genunix. However, when + * _MACHDEP is defined, then the cpu_t ends up having an additional member + * (cpu_m), thus changing the ability for us to uniquify against it. This in + * turn causes a lot of type sprawl, as there's a lot of things that end up + * referring to the cpu_t and it chains out from there. + * + * So, if we find that a cpu_t has been defined and it has a couple of useful + * sentinel members and it does *not* have the cpu_m member, then we will try + * and lookup or create a forward declaration to the machcpu, append it to the + * end, and update the file. + * + * This currently is only invoked if an undocumented option -X is passed. This + * value is private to illumos and it can be changed at any time inside of it, + * so if -X wants to be used for something, it should be. The ability to rely on + * -X for others is strictly not an interface in any way, shape, or form. + * + * The following struct contains most of the information that we care about and + * that we want to validate exists before we decide what to do. + */ + +typedef struct ctfconvert_fixup { + boolean_t cf_cyclic; /* Do we have a cpu_cyclic member */ + boolean_t cf_mcpu; /* We have a cpu_m member */ + boolean_t cf_lastpad; /* Is the pad member the last entry */ + ulong_t cf_padoff; /* offset of the pad */ +} ctfconvert_fixup_t; + +/* ARGSUSED */ +static int +ctfconvert_fixup_genunix_cb(const char *name, ctf_id_t tid, ulong_t off, + void *arg) +{ + ctfconvert_fixup_t *cfp = arg; + + cfp->cf_lastpad = B_FALSE; + if (strcmp(name, "cpu_cyclic") == 0) { + cfp->cf_cyclic = B_TRUE; + return (0); + } + + if (strcmp(name, "cpu_m") == 0) { + cfp->cf_mcpu = B_TRUE; + return (0); + } + + if (strcmp(name, "cpu_m_pad") == 0) { + cfp->cf_lastpad = B_TRUE; + cfp->cf_padoff = off; + return (0); + } + + return (0); +} + +static void +ctfconvert_fixup_genunix(ctf_file_t *fp) +{ + ctf_id_t cpuid, mcpu; + ssize_t sz; + ctfconvert_fixup_t cf; + int model, ptrsz; + + cpuid = ctf_lookup_by_name(fp, "struct cpu"); + if (cpuid == CTF_ERR) + return; + + if (ctf_type_kind(fp, cpuid) != CTF_K_STRUCT) + return; + + if ((sz = ctf_type_size(fp, cpuid)) == CTF_ERR) + return; + + model = ctf_getmodel(fp); + VERIFY(model == CTF_MODEL_ILP32 || model == CTF_MODEL_LP64); + ptrsz = model == CTF_MODEL_ILP32 ? 4 : 8; + + bzero(&cf, sizeof (ctfconvert_fixup_t)); + if (ctf_member_iter(fp, cpuid, ctfconvert_fixup_genunix_cb, &cf) == + CTF_ERR) + return; + + /* + * Finally, we want to verify that the cpu_m is actually the last member + * that we have here. + */ + if (cf.cf_cyclic == B_FALSE || cf.cf_mcpu == B_TRUE || + cf.cf_lastpad == B_FALSE) { + return; + } + + if (cf.cf_padoff + ptrsz * NBBY != sz * NBBY) { + return; + } + + /* + * Okay, we're going to do this, try to find a struct machcpu. We either + * want a forward or a struct. If we find something else, error. If we + * find nothing, add a forward and then add the member. + */ + mcpu = ctf_lookup_by_name(fp, "struct machcpu"); + if (mcpu == CTF_ERR) { + mcpu = ctf_add_forward(fp, CTF_ADD_NONROOT, "struct machcpu", + CTF_K_STRUCT); + if (mcpu == CTF_ERR) { + ctfconvert_fatal("failed to add 'struct machcpu' " + "forward: %s", ctf_errmsg(ctf_errno(fp))); + } + } else { + int kind; + if ((kind = ctf_type_kind(fp, mcpu)) == CTF_ERR) { + ctfconvert_fatal("failed to get the type kind for " + "the struct machcpu: %s", + ctf_errmsg(ctf_errno(fp))); + } + + if (kind != CTF_K_STRUCT && kind != CTF_K_FORWARD) + ctfconvert_fatal("encountered a struct machcpu of the " + "wrong type, found type kind %d\n", kind); + } + + if (ctf_update(fp) == CTF_ERR) { + ctfconvert_fatal("failed to update output file: %s\n", + ctf_errmsg(ctf_errno(fp))); + } + + if (ctf_add_member(fp, cpuid, "cpu_m", mcpu, sz * NBBY) == CTF_ERR) { + ctfconvert_fatal("failed to add the m_cpu member: %s\n", + ctf_errmsg(ctf_errno(fp))); + } + + if (ctf_update(fp) == CTF_ERR) { + ctfconvert_fatal("failed to update output file: %s\n", + ctf_errmsg(ctf_errno(fp))); + } + + VERIFY(ctf_type_size(fp, cpuid) == sz); +} + +static void +ctfconvert_altexec(char **argv) +{ + const char *alt; + char *altexec; + + alt = getenv(CTFCONVERT_ALTEXEC); + if (alt == NULL || *alt == '\0') + return; + + altexec = strdup(alt); + if (altexec == NULL) + ctfconvert_fatal("failed to allocate memory for altexec\n"); + if (unsetenv(CTFCONVERT_ALTEXEC) != 0) + ctfconvert_fatal("failed to unset %s from environment: %s\n", + CTFCONVERT_ALTEXEC, strerror(errno)); + + (void) execv(altexec, argv); + ctfconvert_fatal("failed to execute alternate program %s: %s", + altexec, strerror(errno)); +} + +int +main(int argc, char *argv[]) +{ + int c, ifd, err; + boolean_t keep = B_FALSE; + uint_t flags = 0; + uint_t nthreads = CTFCONVERT_DEFAULT_NTHREADS; + const char *outfile = NULL; + const char *label = NULL; + const char *infile = NULL; + char *tmpfile; + ctf_file_t *ofp; + long argj; + char *eptr; + char buf[4096]; + boolean_t optx = B_FALSE; + + ctfconvert_progname = basename(argv[0]); + + ctfconvert_altexec(argv); + + while ((c = getopt(argc, argv, ":j:kl:L:o:iX")) != -1) { + switch (c) { + case 'k': + keep = B_TRUE; + break; + case 'l': + label = optarg; + break; + case 'L': + label = getenv(optarg); + break; + case 'j': + errno = 0; + argj = strtol(optarg, &eptr, 10); + if (errno != 0 || argj == LONG_MAX || + argj == LONG_MIN || argj <= 0 || + argj > UINT_MAX || *eptr != '\0') { + ctfconvert_fatal("invalid argument for -j: " + "%s\n", optarg); + } + nthreads = (uint_t)argj; + break; + case 'o': + outfile = optarg; + break; + case 'i': + flags |= CTF_CONVERT_F_IGNNONC; + break; + case 'X': + optx = B_TRUE; + break; + case ':': + ctfconvert_usage("Option -%c requires an operand\n", + optopt); + return (CTFCONVERT_USAGE); + case '?': + ctfconvert_usage("Unknown option: -%c\n", optopt); + return (CTFCONVERT_USAGE); + } + } + + argv += optind; + argc -= optind; + + if (argc < 1) { + ctfconvert_usage("Missing required input file\n"); + return (CTFCONVERT_USAGE); + } + infile = argv[0]; + + if (elf_version(EV_CURRENT) == EV_NONE) + ctfconvert_fatal("failed to initialize libelf: library is " + "out of date\n"); + + ifd = open(infile, O_RDONLY); + if (ifd < 0) { + ctfconvert_fatal("failed to open input file %s: %s\n", infile, + strerror(errno)); + } + + /* + * By default we remove the input file on failure unless we've been + * given an output file or -k has been specified. + */ + if (outfile != NULL && strcmp(infile, outfile) != 0) + keep = B_TRUE; + + ofp = ctf_fdconvert(ifd, label, nthreads, flags, &err, buf, + sizeof (buf)); + if (ofp == NULL) { + /* + * -i says that we shouldn't concern ourselves with source files + * that weren't built from C source code in part. Because this + * has been traditionally used across all of illumos, we still + * honor it. + */ + if ((flags & CTF_CONVERT_F_IGNNONC) != 0 && + err == ECTF_CONVNOCSRC) { + exit(CTFCONVERT_OK); + } + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("CTF conversion failed: %s\n", + err == ECTF_CONVBKERR ? buf : ctf_errmsg(err)); + } + + if (optx == B_TRUE) + ctfconvert_fixup_genunix(ofp); + + tmpfile = NULL; + if (outfile == NULL || strcmp(infile, outfile) == 0) { + if (asprintf(&tmpfile, "%s.ctf", infile) == -1) { + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("failed to allocate memory for " + "temporary file: %s\n", strerror(errno)); + } + outfile = tmpfile; + } + err = ctf_elfwrite(ofp, infile, outfile, CTF_ELFWRITE_F_COMPRESS); + if (err == CTF_ERR) { + (void) unlink(outfile); + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("failed to write CTF section to output file: " + "%s", ctf_errmsg(ctf_errno(ofp))); + } + ctf_close(ofp); + + if (tmpfile != NULL) { + if (rename(tmpfile, infile) != 0) { + int e = errno; + (void) unlink(outfile); + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("failed to rename temporary file: " + "%s\n", strerror(e)); + } + } + free(tmpfile); + + return (CTFCONVERT_OK); +} diff --git a/usr/src/cmd/ctfdiff/Makefile b/usr/src/cmd/ctfdiff/Makefile new file mode 100644 index 0000000000..268bf9f3ed --- /dev/null +++ b/usr/src/cmd/ctfdiff/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015, Joyent, Inc. +# + +PROG= ctfdiff + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfdiff/ctfdiff.c b/usr/src/cmd/ctfdiff/ctfdiff.c new file mode 100644 index 0000000000..8018761257 --- /dev/null +++ b/usr/src/cmd/ctfdiff/ctfdiff.c @@ -0,0 +1,518 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * diff two CTF containers + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <strings.h> +#include <libctf.h> +#include <libgen.h> +#include <stdarg.h> + +#define CTFDIFF_NAMELEN 256 + +#define CTFDIFF_EXIT_SIMILAR 0 +#define CTFDIFF_EXIT_DIFFERENT 1 +#define CTFDIFF_EXIT_USAGE 2 +#define CTFDIFF_EXIT_ERROR 3 + +typedef enum ctf_diff_cmd { + CTF_DIFF_TYPES = 0x01, + CTF_DIFF_FUNCS = 0x02, + CTF_DIFF_OBJS = 0x04, + CTF_DIFF_DEFAULT = 0x07, + CTF_DIFF_LABEL = 0x08, + CTF_DIFF_ALL = 0x0f +} ctf_diff_cmd_t; + +typedef struct { + int dil_next; + const char **dil_labels; +} ctfdiff_label_t; + +static char *g_progname; +static const char *g_iname; +static ctf_file_t *g_ifp; +static const char *g_oname; +static ctf_file_t *g_ofp; +static char **g_typelist = NULL; +static int g_nexttype = 0; +static int g_ntypes = 0; +static char **g_objlist = NULL; +static int g_nextfunc = 0; +static int g_nfuncs = 0; +static char **g_funclist = NULL; +static int g_nextobj = 0; +static int g_nobjs = 0; +static boolean_t g_onlydiff = B_FALSE; +static boolean_t g_different = B_FALSE; +static ctf_diff_cmd_t g_flag = 0; + +static void +ctfdiff_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(CTFDIFF_EXIT_ERROR); +} + +static const char * +ctfdiff_fp_to_name(ctf_file_t *fp) +{ + if (fp == g_ifp) + return (g_iname); + if (fp == g_ofp) + return (g_oname); + return (NULL); +} + +/* ARGSUSED */ +static void +ctfdiff_func_cb(ctf_file_t *ifp, ulong_t iidx, boolean_t similar, + ctf_file_t *ofp, ulong_t oidx, void *arg) +{ + char namebuf[CTFDIFF_NAMELEN]; + + if (similar == B_TRUE) + return; + + if (ctf_symbol_name(ifp, iidx, namebuf, sizeof (namebuf)) == NULL) { + if (g_nextfunc != 0) + return; + (void) printf("ctf container %s function %ld is different\n", + ctfdiff_fp_to_name(ifp), iidx); + } else { + if (g_nextfunc != 0) { + int i; + for (i = 0; i < g_nextfunc; i++) { + if (strcmp(g_funclist[i], namebuf) == 0) + break; + } + if (i == g_nextfunc) + return; + } + (void) printf("ctf container %s function %s (%ld) is " + "different\n", ctfdiff_fp_to_name(ifp), namebuf, iidx); + } + + g_different = B_TRUE; +} + +/* ARGSUSED */ +static void +ctfdiff_obj_cb(ctf_file_t *ifp, ulong_t iidx, ctf_id_t iid, boolean_t similar, + ctf_file_t *ofp, ulong_t oidx, ctf_id_t oid, void *arg) +{ + char namebuf[CTFDIFF_NAMELEN]; + + if (similar == B_TRUE) + return; + + if (ctf_symbol_name(ifp, iidx, namebuf, sizeof (namebuf)) == NULL) { + if (g_nextobj != 0) + return; + (void) printf("ctf container %s object %ld is different\n", + ctfdiff_fp_to_name(ifp), iidx); + } else { + if (g_nextobj != 0) { + int i; + for (i = 0; i < g_nextobj; i++) { + if (strcmp(g_objlist[i], namebuf) == 0) + break; + } + if (i == g_nextobj) + return; + } + (void) printf("ctf container %s object %s (%ld) is different\n", + ctfdiff_fp_to_name(ifp), namebuf, iidx); + } + + g_different = B_TRUE; +} + +/* ARGSUSED */ +static void +ctfdiff_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t similar, ctf_file_t *ofp, + ctf_id_t oid, void *arg) +{ + if (similar == B_TRUE) + return; + + if (ctf_type_kind(ifp, iid) == CTF_K_UNKNOWN) + return; + + /* + * Check if it's the type the user cares about. + */ + if (g_nexttype != 0) { + int i; + char namebuf[CTFDIFF_NAMELEN]; + + if (ctf_type_name(ifp, iid, namebuf, sizeof (namebuf)) == + NULL) { + ctfdiff_fatal("failed to obtain the name " + "of type %ld from %s: %s\n", + iid, ctfdiff_fp_to_name(ifp), + ctf_errmsg(ctf_errno(ifp))); + } + + for (i = 0; i < g_nexttype; i++) { + if (strcmp(g_typelist[i], namebuf) == 0) + break; + } + + if (i == g_nexttype) + return; + } + + g_different = B_TRUE; + + if (g_onlydiff == B_TRUE) + return; + + (void) printf("ctf container %s type %ld is different\n", + ctfdiff_fp_to_name(ifp), iid); +} + +/* ARGSUSED */ +static int +ctfdiff_labels_count(const char *name, const ctf_lblinfo_t *li, void *arg) +{ + uint32_t *count = arg; + *count = *count + 1; + + return (0); +} + +/* ARGSUSED */ +static int +ctfdiff_labels_fill(const char *name, const ctf_lblinfo_t *li, void *arg) +{ + ctfdiff_label_t *dil = arg; + + dil->dil_labels[dil->dil_next] = name; + dil->dil_next++; + + return (0); +} + +static int +ctfdiff_labels(ctf_file_t *ifp, ctf_file_t *ofp) +{ + int ret; + uint32_t nilabel, nolabel, i, j; + ctfdiff_label_t idl, odl; + const char **ilptr, **olptr; + + nilabel = nolabel = 0; + ret = ctf_label_iter(ifp, ctfdiff_labels_count, &nilabel); + if (ret == CTF_ERR) + return (ret); + ret = ctf_label_iter(ofp, ctfdiff_labels_count, &nolabel); + if (ret == CTF_ERR) + return (ret); + + if (nilabel != nolabel) { + (void) printf("ctf container %s labels differ from ctf " + "container %s\n", ctfdiff_fp_to_name(ifp), + ctfdiff_fp_to_name(ofp)); + g_different = B_TRUE; + return (0); + } + + if (nilabel == 0) + return (0); + + ilptr = malloc(sizeof (char *) * nilabel); + olptr = malloc(sizeof (char *) * nolabel); + if (ilptr == NULL || olptr == NULL) { + ctfdiff_fatal("failed to allocate memory for label " + "comparison\n"); + } + + idl.dil_next = 0; + idl.dil_labels = ilptr; + odl.dil_next = 0; + odl.dil_labels = olptr; + + if ((ret = ctf_label_iter(ifp, ctfdiff_labels_fill, &idl)) != 0) + goto out; + if ((ret = ctf_label_iter(ofp, ctfdiff_labels_fill, &odl)) != 0) + goto out; + + for (i = 0; i < nilabel; i++) { + for (j = 0; j < nolabel; j++) { + if (strcmp(ilptr[i], olptr[j]) == 0) + break; + } + + if (j == nolabel) { + (void) printf("ctf container %s labels differ from ctf " + "container %s\n", ctfdiff_fp_to_name(ifp), + ctfdiff_fp_to_name(ofp)); + g_different = B_TRUE; + break; + } + } + + ret = 0; +out: + free(ilptr); + free(olptr); + return (ret); +} + +static void +ctfdiff_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-afIloqt] [-F function] [-O object]" + "[-p parent] [-P parent]\n" + "\t[-T type] file1 file2\n" + "\n" + "\t-a diff label, types, objects, and functions\n" + "\t-f diff function type information\n" + "\t-F when diffing functions, only consider those named\n" + "\t-I ignore the names of integral types\n" + "\t-l diff CTF labels\n" + "\t-o diff global object type information\n" + "\t-O when diffing objects, only consider those named\n" + "\t-p set the CTF parent for file1\n" + "\t-P set the CTF parent for file2\n" + "\t-q set quiet mode (no diff information sent to stdout)\n" + "\t-t diff CTF type information\n" + "\t-T when diffing types, only consider those named\n", + g_progname); +} + +int +main(int argc, char *argv[]) +{ + ctf_diff_flag_t flags = 0; + int err, c; + ctf_file_t *ifp, *ofp; + ctf_diff_t *cdp; + ctf_file_t *pifp = NULL; + ctf_file_t *pofp = NULL; + + g_progname = basename(argv[0]); + + while ((c = getopt(argc, argv, ":aqtfolIp:F:O:P:T:")) != -1) { + switch (c) { + case 'a': + g_flag |= CTF_DIFF_ALL; + break; + case 't': + g_flag |= CTF_DIFF_TYPES; + break; + case 'f': + g_flag |= CTF_DIFF_FUNCS; + break; + case 'o': + g_flag |= CTF_DIFF_OBJS; + break; + case 'l': + g_flag |= CTF_DIFF_LABEL; + break; + case 'q': + g_onlydiff = B_TRUE; + break; + case 'p': + pifp = ctf_open(optarg, &err); + if (pifp == NULL) { + ctfdiff_fatal("failed to open parent input " + "container %s: %s\n", optarg, + ctf_errmsg(err)); + } + break; + case 'F': + if (g_nextfunc == g_nfuncs) { + if (g_nfuncs == 0) + g_nfuncs = 16; + else + g_nfuncs *= 2; + g_funclist = realloc(g_funclist, + sizeof (char *) * g_nfuncs); + if (g_funclist == NULL) { + ctfdiff_fatal("failed to allocate " + "memory for the %dth -F option: " + "%s\n", g_nexttype + 1, + strerror(errno)); + } + } + g_funclist[g_nextfunc] = optarg; + g_nextfunc++; + break; + case 'O': + if (g_nextobj == g_nobjs) { + if (g_nobjs == 0) + g_nobjs = 16; + else + g_nobjs *= 2; + g_objlist = realloc(g_objlist, + sizeof (char *) * g_nobjs); + if (g_objlist == NULL) { + ctfdiff_fatal("failed to allocate " + "memory for the %dth -F option: " + "%s\n", g_nexttype + 1, + strerror(errno)); + return (CTFDIFF_EXIT_ERROR); + } + } + g_objlist[g_nextobj] = optarg; + g_nextobj++; + break; + case 'I': + flags |= CTF_DIFF_F_IGNORE_INTNAMES; + break; + case 'P': + pofp = ctf_open(optarg, &err); + if (pofp == NULL) { + ctfdiff_fatal("failed to open parent output " + "container %s: %s\n", optarg, + ctf_errmsg(err)); + } + break; + case 'T': + if (g_nexttype == g_ntypes) { + if (g_ntypes == 0) + g_ntypes = 16; + else + g_ntypes *= 2; + g_typelist = realloc(g_typelist, + sizeof (char *) * g_ntypes); + if (g_typelist == NULL) { + ctfdiff_fatal("failed to allocate " + "memory for the %dth -T option: " + "%s\n", g_nexttype + 1, + strerror(errno)); + } + } + g_typelist[g_nexttype] = optarg; + g_nexttype++; + break; + case ':': + ctfdiff_usage("Option -%c requires an operand\n", + optopt); + return (CTFDIFF_EXIT_USAGE); + case '?': + ctfdiff_usage("Unknown option: -%c\n", optopt); + return (CTFDIFF_EXIT_USAGE); + } + } + + argc -= optind - 1; + argv += optind - 1; + + if (g_flag == 0) + g_flag = CTF_DIFF_DEFAULT; + + if (argc != 3) { + ctfdiff_usage(NULL); + return (CTFDIFF_EXIT_USAGE); + } + + if (g_nexttype != 0 && !(g_flag & CTF_DIFF_TYPES)) { + ctfdiff_usage("-T cannot be used if not diffing types\n"); + return (CTFDIFF_EXIT_USAGE); + } + + if (g_nextfunc != 0 && !(g_flag & CTF_DIFF_FUNCS)) { + ctfdiff_usage("-F cannot be used if not diffing functions\n"); + return (CTFDIFF_EXIT_USAGE); + } + + if (g_nextobj != 0 && !(g_flag & CTF_DIFF_OBJS)) { + ctfdiff_usage("-O cannot be used if not diffing objects\n"); + return (CTFDIFF_EXIT_USAGE); + } + + ifp = ctf_open(argv[1], &err); + if (ifp == NULL) { + ctfdiff_fatal("failed to open %s: %s\n", argv[1], + ctf_errmsg(err)); + } + if (pifp != NULL) { + err = ctf_import(ifp, pifp); + if (err != 0) { + ctfdiff_fatal("failed to set parent container: %s\n", + ctf_errmsg(ctf_errno(pifp))); + } + } + g_iname = argv[1]; + g_ifp = ifp; + + ofp = ctf_open(argv[2], &err); + if (ofp == NULL) { + ctfdiff_fatal("failed to open %s: %s\n", argv[2], + ctf_errmsg(err)); + } + + if (pofp != NULL) { + err = ctf_import(ofp, pofp); + if (err != 0) { + ctfdiff_fatal("failed to set parent container: %s\n", + ctf_errmsg(ctf_errno(pofp))); + } + } + g_oname = argv[2]; + g_ofp = ofp; + + if (ctf_diff_init(ifp, ofp, &cdp) != 0) { + ctfdiff_fatal("failed to initialize libctf diff engine: %s\n", + ctf_errmsg(ctf_errno(ifp))); + } + + if (ctf_diff_setflags(cdp, flags) != 0) { + ctfdiff_fatal("failed to set ctfdiff flags: %s\n", + ctf_errmsg(ctf_errno(ifp))); + } + + err = 0; + if ((g_flag & CTF_DIFF_TYPES) && err != CTF_ERR) + err = ctf_diff_types(cdp, ctfdiff_cb, NULL); + if ((g_flag & CTF_DIFF_FUNCS) && err != CTF_ERR) + err = ctf_diff_functions(cdp, ctfdiff_func_cb, NULL); + if ((g_flag & CTF_DIFF_OBJS) && err != CTF_ERR) + err = ctf_diff_objects(cdp, ctfdiff_obj_cb, NULL); + if ((g_flag & CTF_DIFF_LABEL) && err != CTF_ERR) + err = ctfdiff_labels(ifp, ofp); + + ctf_diff_fini(cdp); + if (err == CTF_ERR) { + ctfdiff_fatal("encountered a libctf error: %s!\n", + ctf_errmsg(ctf_errno(ifp))); + } + + return (g_different == B_TRUE ? CTFDIFF_EXIT_DIFFERENT : + CTFDIFF_EXIT_SIMILAR); +} diff --git a/usr/src/cmd/ctfdump/Makefile b/usr/src/cmd/ctfdump/Makefile new file mode 100644 index 0000000000..962ca43a8f --- /dev/null +++ b/usr/src/cmd/ctfdump/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +PROG= ctfdump + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfdump/ctfdump.c b/usr/src/cmd/ctfdump/ctfdump.c new file mode 100644 index 0000000000..d0ff63a02a --- /dev/null +++ b/usr/src/cmd/ctfdump/ctfdump.c @@ -0,0 +1,815 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Dump information about CTF containers. This was inspired by the original + * ctfdump written in tools/ctf, but this has been reimplemented in terms of + * libctf. + */ + +#include <stdio.h> +#include <unistd.h> +#include <libctf.h> +#include <libgen.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stddef.h> +#include <sys/sysmacros.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> + +typedef enum ctfdump_arg { + CTFDUMP_OBJECTS = 0x01, + CTFDUMP_FUNCTIONS = 0x02, + CTFDUMP_HEADER = 0x04, + CTFDUMP_LABELS = 0x08, + CTFDUMP_STRINGS = 0x10, + CTFDUMP_STATS = 0x20, + CTFDUMP_TYPES = 0x40, + CTFDUMP_DEFAULT = 0x7f, + CTFDUMP_OUTPUT = 0x80, + CTFDUMP_ALL = 0xff +} ctfdump_arg_t; + +typedef struct ctfdump_stat { + ulong_t cs_ndata; /* number of data objects */ + ulong_t cs_nfuncs; /* number of functions */ + ulong_t cs_nfuncargs; /* number of function args */ + ulong_t cs_nfuncmax; /* largest number of args */ + ulong_t cs_ntypes[CTF_K_MAX]; /* number of types */ + ulong_t cs_nsmembs; /* number of struct members */ + ulong_t cs_nsmax; /* largest number of members */ + ulong_t cs_structsz; /* sum of structures sizes */ + ulong_t cs_sszmax; /* largest structure */ + ulong_t cs_numembs; /* number of union members */ + ulong_t cs_numax; /* largest number of members */ + ulong_t cs_unionsz; /* sum of unions sizes */ + ulong_t cs_uszmax; /* largest union */ + ulong_t cs_nemembs; /* number of enum members */ + ulong_t cs_nemax; /* largest number of members */ + ulong_t cs_nstrings; /* number of strings */ + ulong_t cs_strsz; /* string size */ + ulong_t cs_strmax; /* longest string */ +} ctfdump_stat_t; + +static const char *g_progname; +static ctfdump_arg_t g_dump; +static ctf_file_t *g_fp; +static ctfdump_stat_t g_stats; +static ctf_id_t *g_fargc; +static int g_nfargc; + +static int g_exit = 0; + +static const char *ctfdump_fpenc[] = { + NULL, + "SINGLE", + "DOUBLE", + "COMPLEX", + "DCOMPLEX", + "LDCOMPLEX", + "LDOUBLE", + "INTERVAL", + "DINTERVAL", + "LDINTERVAL", + "IMAGINARY", + "DIMAGINARY", + "LDIMAGINARY" +}; + +/* + * When stats are requested, we have to go through everything. To make our lives + * easier, we'll just always allow the code to print everything out, but only + * output it if we have actually enabled that section. + */ +static void +ctfdump_printf(ctfdump_arg_t arg, const char *fmt, ...) +{ + va_list ap; + + if ((arg & g_dump) == 0) + return; + + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); +} + +static void +ctfdump_warn(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static void +ctfdump_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(1); +} + +static void +ctfdump_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-dfhlsSt] [-p parent] [-u outfile] " + "file\n" + "\n" + "\t-d dump object data\n" + "\t-f dump function data\n" + "\t-h dump the CTF header\n" + "\t-l dump the label table\n" + "\t-p use parent to supply additional information\n" + "\t-s dump the string table\n" + "\t-S dump statistics about the CTF container\n" + "\t-t dump type information\n" + "\t-u dump uncompressed CTF data to outfile\n", + g_progname); +} + +static void +ctfdump_title(ctfdump_arg_t arg, const char *header) +{ + static const char line[] = "----------------------------------------" + "----------------------------------------"; + ctfdump_printf(arg, "\n- %s %.*s\n\n", header, (int)78 - strlen(header), + line); +} + +static int +ctfdump_objects_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg) +{ + int len; + + len = snprintf(NULL, 0, " [%u] %u", g_stats.cs_ndata, id); + ctfdump_printf(CTFDUMP_OBJECTS, " [%u] %u %*s%s (%u)\n", + g_stats.cs_ndata, id, MAX(15 - len, 0), "", name, symidx); + g_stats.cs_ndata++; + return (0); +} + +static void +ctfdump_objects(void) +{ + ctfdump_title(CTFDUMP_OBJECTS, "Data Objects"); + if (ctf_object_iter(g_fp, ctfdump_objects_cb, NULL) == CTF_ERR) { + ctfdump_warn("failed to dump objects: %s\n", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_fargs_grow(int nargs) +{ + if (g_nfargc < nargs) { + g_fargc = realloc(g_fargc, sizeof (ctf_id_t) * nargs); + if (g_fargc == NULL) + ctfdump_fatal("failed to get memory for %d " + "ctf_id_t's\n", nargs); + g_nfargc = nargs; + } +} + +static int +ctfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc, + void *arg) +{ + int i; + + if (ctc->ctc_argc != 0) { + ctfdump_fargs_grow(ctc->ctc_argc); + if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR) + ctfdump_fatal("failed to get arguments for function " + "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + } + + ctfdump_printf(CTFDUMP_FUNCTIONS, + " [%lu] %s (%lu) returns: %u args: (", g_stats.cs_nfuncs, name, + symidx, ctc->ctc_return); + for (i = 0; i < ctc->ctc_argc; i++) + ctfdump_printf(CTFDUMP_FUNCTIONS, "%lu%s", g_fargc[i], + i + 1 == ctc->ctc_argc ? "" : ", "); + if (ctc->ctc_flags & CTF_FUNC_VARARG) + ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...", + ctc->ctc_argc == 0 ? "" : ", "); + ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n"); + + g_stats.cs_nfuncs++; + g_stats.cs_nfuncargs += ctc->ctc_argc; + g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax); + + return (0); +} + +static void +ctfdump_functions(void) +{ + ctfdump_title(CTFDUMP_FUNCTIONS, "Functions"); + + if (ctf_function_iter(g_fp, ctfdump_functions_cb, NULL) == CTF_ERR) { + ctfdump_warn("failed to dump functions: %s\n", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_header(void) +{ + const ctf_header_t *hp; + const char *parname, *parlabel; + + ctfdump_title(CTFDUMP_HEADER, "CTF Header"); + ctf_dataptr(g_fp, (const void **)&hp, NULL); + ctfdump_printf(CTFDUMP_HEADER, " cth_magic = 0x%04x\n", + hp->cth_magic); + ctfdump_printf(CTFDUMP_HEADER, " cth_version = %u\n", + hp->cth_version); + ctfdump_printf(CTFDUMP_HEADER, " cth_flags = 0x%02x\n", + ctf_flags(g_fp)); + parname = ctf_parent_name(g_fp); + parlabel = ctf_parent_label(g_fp); + ctfdump_printf(CTFDUMP_HEADER, " cth_parlabel = %s\n", + parlabel == NULL ? "(anon)" : parlabel); + ctfdump_printf(CTFDUMP_HEADER, " cth_parname = %s\n", + parname == NULL ? "(anon)" : parname); + ctfdump_printf(CTFDUMP_HEADER, " cth_lbloff = %u\n", + hp->cth_lbloff); + ctfdump_printf(CTFDUMP_HEADER, " cth_objtoff = %u\n", + hp->cth_objtoff); + ctfdump_printf(CTFDUMP_HEADER, " cth_funcoff = %u\n", + hp->cth_funcoff); + ctfdump_printf(CTFDUMP_HEADER, " cth_typeoff = %u\n", + hp->cth_typeoff); + ctfdump_printf(CTFDUMP_HEADER, " cth_stroff = %u\n", + hp->cth_stroff); + ctfdump_printf(CTFDUMP_HEADER, " cth_strlen = %u\n", + hp->cth_strlen); +} + +static int +ctfdump_labels_cb(const char *name, const ctf_lblinfo_t *li, void *arg) +{ + ctfdump_printf(CTFDUMP_LABELS, " %5lu %s\n", li->ctb_typeidx, name); + return (0); +} + +static void +ctfdump_labels(void) +{ + ctfdump_title(CTFDUMP_LABELS, "Label Table"); + if (ctf_label_iter(g_fp, ctfdump_labels_cb, NULL) == CTF_ERR) { + ctfdump_warn("failed to dump labels: %s\n", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static int +ctfdump_strings_cb(const char *s, void *arg) +{ + size_t len = strlen(s) + 1; + ulong_t *stroff = arg; + ctfdump_printf(CTFDUMP_STRINGS, " [%lu] %s\n", *stroff, + *s == '\0' ? "\\0" : s); + *stroff = *stroff + len; + g_stats.cs_nstrings++; + g_stats.cs_strsz += len; + g_stats.cs_strmax = MAX(g_stats.cs_strmax, len); + return (0); +} + +static void +ctfdump_strings(void) +{ + ulong_t stroff = 0; + + ctfdump_title(CTFDUMP_STRINGS, "String Table"); + if (ctf_string_iter(g_fp, ctfdump_strings_cb, &stroff) == CTF_ERR) { + ctfdump_warn("failed to dump strings: %s\n", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_stat_int(const char *name, ulong_t value) +{ + ctfdump_printf(CTFDUMP_STATS, " %-36s= %lu\n", name, value); +} + +static void +ctfdump_stat_fp(const char *name, float value) +{ + ctfdump_printf(CTFDUMP_STATS, " %-36s= %.2f\n", name, value); +} + +static void +ctfdump_stats(void) +{ + int i; + ulong_t sum; + + ctfdump_title(CTFDUMP_STATS, "CTF Statistics"); + + ctfdump_stat_int("total number of data objects", g_stats.cs_ndata); + ctfdump_printf(CTFDUMP_STATS, "\n"); + ctfdump_stat_int("total number of functions", g_stats.cs_nfuncs); + ctfdump_stat_int("total number of function arguments", + g_stats.cs_nfuncargs); + ctfdump_stat_int("maximum argument list length", g_stats.cs_nfuncmax); + if (g_stats.cs_nfuncs != 0) + ctfdump_stat_fp("average argument list length", + (float)g_stats.cs_nfuncargs / (float)g_stats.cs_nfuncs); + ctfdump_printf(CTFDUMP_STATS, "\n"); + + sum = 0; + for (i = 0; i < CTF_K_MAX; i++) + sum += g_stats.cs_ntypes[i]; + ctfdump_stat_int("total number of types", sum); + ctfdump_stat_int("total number of integers", + g_stats.cs_ntypes[CTF_K_INTEGER]); + ctfdump_stat_int("total number of floats", + g_stats.cs_ntypes[CTF_K_FLOAT]); + ctfdump_stat_int("total number of pointers", + g_stats.cs_ntypes[CTF_K_POINTER]); + ctfdump_stat_int("total number of arrays", + g_stats.cs_ntypes[CTF_K_ARRAY]); + ctfdump_stat_int("total number of func types", + g_stats.cs_ntypes[CTF_K_FUNCTION]); + ctfdump_stat_int("total number of structs", + g_stats.cs_ntypes[CTF_K_STRUCT]); + ctfdump_stat_int("total number of unions", + g_stats.cs_ntypes[CTF_K_UNION]); + ctfdump_stat_int("total number of enums", + g_stats.cs_ntypes[CTF_K_ENUM]); + ctfdump_stat_int("total number of forward tags", + g_stats.cs_ntypes[CTF_K_FORWARD]); + ctfdump_stat_int("total number of typedefs", + g_stats.cs_ntypes[CTF_K_TYPEDEF]); + ctfdump_stat_int("total number of volatile types", + g_stats.cs_ntypes[CTF_K_VOLATILE]); + ctfdump_stat_int("total number of const types", + g_stats.cs_ntypes[CTF_K_CONST]); + ctfdump_stat_int("total number of restrict types", + g_stats.cs_ntypes[CTF_K_RESTRICT]); + ctfdump_stat_int("total number of unknowns (holes)", + g_stats.cs_ntypes[CTF_K_UNKNOWN]); + + ctfdump_printf(CTFDUMP_STATS, "\n"); + ctfdump_stat_int("total number of struct members", g_stats.cs_nsmembs); + ctfdump_stat_int("maximum number of struct members", g_stats.cs_nsmax); + ctfdump_stat_int("total size of all structs", g_stats.cs_structsz); + ctfdump_stat_int("maximum size of a struct", g_stats.cs_sszmax); + if (g_stats.cs_ntypes[CTF_K_STRUCT] != 0) { + ctfdump_stat_fp("average number of struct members", + (float)g_stats.cs_nsmembs / + (float)g_stats.cs_ntypes[CTF_K_STRUCT]); + ctfdump_stat_fp("average size of a struct", + (float)g_stats.cs_structsz / + (float)g_stats.cs_ntypes[CTF_K_STRUCT]); + } + ctfdump_printf(CTFDUMP_STATS, "\n"); + ctfdump_stat_int("total number of union members", g_stats.cs_numembs); + ctfdump_stat_int("maximum number of union members", g_stats.cs_numax); + ctfdump_stat_int("total size of all unions", g_stats.cs_unionsz); + ctfdump_stat_int("maximum size of a union", g_stats.cs_uszmax); + if (g_stats.cs_ntypes[CTF_K_UNION] != 0) { + ctfdump_stat_fp("average number of union members", + (float)g_stats.cs_numembs / + (float)g_stats.cs_ntypes[CTF_K_UNION]); + ctfdump_stat_fp("average size of a union", + (float)g_stats.cs_unionsz / + (float)g_stats.cs_ntypes[CTF_K_UNION]); + } + ctfdump_printf(CTFDUMP_STATS, "\n"); + + ctfdump_stat_int("total number of enum members", g_stats.cs_nemembs); + ctfdump_stat_int("maximum number of enum members", g_stats.cs_nemax); + if (g_stats.cs_ntypes[CTF_K_ENUM] != 0) { + ctfdump_stat_fp("average number of enum members", + (float)g_stats.cs_nemembs / + (float)g_stats.cs_ntypes[CTF_K_ENUM]); + } + ctfdump_printf(CTFDUMP_STATS, "\n"); + + ctfdump_stat_int("total number of strings", g_stats.cs_nstrings); + ctfdump_stat_int("bytes of string data", g_stats.cs_strsz); + ctfdump_stat_int("maximum string length", g_stats.cs_strmax); + if (g_stats.cs_nstrings != 0) + ctfdump_stat_fp("average string length", + (float)g_stats.cs_strsz / (float)g_stats.cs_nstrings); + ctfdump_printf(CTFDUMP_STATS, "\n"); +} + +static void +ctfdump_intenc_name(ctf_encoding_t *cte, char *buf, int len) +{ + int off = 0; + boolean_t space = B_FALSE; + + if (cte->cte_format == 0 || (cte->cte_format & + ~(CTF_INT_SIGNED | CTF_INT_CHAR | CTF_INT_BOOL | + CTF_INT_VARARGS)) != 0) { + (void) snprintf(buf, len, "0x%x", cte->cte_format); + return; + } + + if (cte->cte_format & CTF_INT_SIGNED) { + off += snprintf(buf + off, MAX(len - off, 0), "%sSIGNED", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } + + if (cte->cte_format & CTF_INT_CHAR) { + off += snprintf(buf + off, MAX(len - off, 0), "%sCHAR", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } + + if (cte->cte_format & CTF_INT_BOOL) { + off += snprintf(buf + off, MAX(len - off, 0), "%sBOOL", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } + + if (cte->cte_format & CTF_INT_VARARGS) { + off += snprintf(buf + off, MAX(len - off, 0), "%sVARARGS", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } +} + +static int +ctfdump_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg) +{ + int *count = arg; + ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%lu off=%lu\n", member, type, + off); + *count = *count + 1; + return (0); +} + +static int +ctfdump_enum_cb(const char *name, int value, void *arg) +{ + int *count = arg; + ctfdump_printf(CTFDUMP_TYPES, "\t%s = %d\n", name, value); + *count = *count + 1; + return (0); +} + +static int +ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg) +{ + int kind, i, count; + ctf_id_t ref; + char name[512], ienc[128]; + const char *encn; + ctf_funcinfo_t ctc; + ctf_arinfo_t ar; + ctf_encoding_t cte; + ssize_t size; + + if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) + ctfdump_fatal("encountered malformed ctf, type %s does not " + "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + + if (ctf_type_name(g_fp, id, name, sizeof (name)) == NULL) { + if (ctf_errno(g_fp) != ECTF_NOPARENT) + ctfdump_fatal("type %lu missing name: %s\n", id, + ctf_errmsg(ctf_errno(g_fp))); + (void) snprintf(name, sizeof (name), "(unknown %s)", + ctf_kind_name(g_fp, kind)); + } + + g_stats.cs_ntypes[kind]++; + if (root == B_TRUE) + ctfdump_printf(CTFDUMP_TYPES, " <%lu> ", id); + else + ctfdump_printf(CTFDUMP_TYPES, " [%lu] ", id); + + switch (kind) { + case CTF_K_UNKNOWN: + break; + case CTF_K_INTEGER: + if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR) + ctfdump_fatal("failed to get encoding information " + "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_intenc_name(&cte, ienc, sizeof (ienc)); + ctfdump_printf(CTFDUMP_TYPES, + "%s encoding=%s offset=%u bits=%u", + name, ienc, cte.cte_offset, cte.cte_bits); + break; + case CTF_K_FLOAT: + if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR) + ctfdump_fatal("failed to get encoding information " + "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + if (cte.cte_format < 1 || cte.cte_format > 12) + encn = "unknown"; + else + encn = ctfdump_fpenc[cte.cte_format]; + ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u " + "bits=%u", name, encn, cte.cte_offset, cte.cte_bits); + break; + case CTF_K_POINTER: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, + ref); + break; + case CTF_K_ARRAY: + if (ctf_array_info(g_fp, id, &ar) == CTF_ERR) + ctfdump_fatal("failed to get array information for " + "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s contents: %lu, index: %lu", + name, ar.ctr_contents, ar.ctr_index); + break; + case CTF_K_FUNCTION: + if (ctf_func_info_by_id(g_fp, id, &ctc) == CTF_ERR) + ctfdump_fatal("failed to get function info for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + if (ctc.ctc_argc > 0) { + ctfdump_fargs_grow(ctc.ctc_argc); + if (ctf_func_args_by_id(g_fp, id, g_nfargc, g_fargc) == + CTF_ERR) + ctfdump_fatal("failed to get function " + "arguments for %s: %s\n", name, + ctf_errmsg(ctf_errno(g_fp))); + } + ctfdump_printf(CTFDUMP_TYPES, + "%s returns: %lu args: (", name, ctc.ctc_return); + for (i = 0; i < ctc.ctc_argc; i++) { + ctfdump_printf(CTFDUMP_TYPES, "%lu%s", g_fargc[i], + i + 1 == ctc.ctc_argc ? "" : ", "); + } + if (ctc.ctc_flags & CTF_FUNC_VARARG) + ctfdump_printf(CTFDUMP_TYPES, "%s...", + ctc.ctc_argc == 0 ? "" : ", "); + ctfdump_printf(CTFDUMP_TYPES, ")"); + break; + case CTF_K_STRUCT: + case CTF_K_UNION: + size = ctf_type_size(g_fp, id); + if (size == CTF_ERR) + ctfdump_fatal("failed to get size of %s: %s\n", name, + ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s (%d bytes)\n", name, size); + count = 0; + if (ctf_member_iter(g_fp, id, ctfdump_member_cb, &count) != 0) + ctfdump_fatal("failed to iterate members of %s: %s\n", + name, ctf_errmsg(ctf_errno(g_fp))); + if (kind == CTF_K_STRUCT) { + g_stats.cs_nsmembs += count; + g_stats.cs_nsmax = MAX(count, g_stats.cs_nsmax); + g_stats.cs_structsz += size; + g_stats.cs_sszmax = MAX(size, g_stats.cs_sszmax); + } else { + g_stats.cs_numembs += count; + g_stats.cs_numax = MAX(count, g_stats.cs_numax); + g_stats.cs_unionsz += size; + g_stats.cs_uszmax = MAX(count, g_stats.cs_uszmax); + } + break; + case CTF_K_ENUM: + ctfdump_printf(CTFDUMP_TYPES, "%s\n", name); + count = 0; + if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0) + ctfdump_fatal("failed to iterate enumerators of %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + g_stats.cs_nemembs += count; + g_stats.cs_nemax = MAX(g_stats.cs_nemax, count); + break; + case CTF_K_FORWARD: + ctfdump_printf(CTFDUMP_TYPES, "forward %s\n", name); + break; + case CTF_K_TYPEDEF: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "typedef %s refers to %lu", name, + ref); + break; + case CTF_K_VOLATILE: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, + ref); + break; + case CTF_K_CONST: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, + ref); + break; + case CTF_K_RESTRICT: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, + ref); + break; + default: + ctfdump_fatal("encountered unknown kind for type %s: %d\n", + name, kind); + } + + ctfdump_printf(CTFDUMP_TYPES, "\n"); + + return (0); +} + +static void +ctfdump_types(void) +{ + ctfdump_title(CTFDUMP_TYPES, "Types"); + + if (ctf_type_iter(g_fp, B_TRUE, ctfdump_types_cb, NULL) == CTF_ERR) { + ctfdump_warn("failed to dump labels: %s\n", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_output(const char *out) +{ + int fd, ret; + const void *data; + size_t len; + + ctf_dataptr(g_fp, &data, &len); + if ((fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) + ctfdump_fatal("failed to open output file %s: %s\n", out, + strerror(errno)); + + while (len > 0) { + ret = write(fd, data, len); + if (ret == -1 && errno == EINTR) + continue; + else if (ret == -1 && (errno == EFAULT || errno == EBADF)) + abort(); + else if (ret == -1) + ctfdump_fatal("failed to write to %s: %s\n", out, + strerror(errno)); + data += ret; + len -= ret; + } + + do { + ret = close(fd); + } while (ret == -1 && errno == EINTR); + if (ret != 0 && errno == EBADF) + abort(); + if (ret != 0) + ctfdump_fatal("failed to close %s: %s\n", out, strerror(errno)); +} + +int +main(int argc, char *argv[]) +{ + int c, fd, err; + const char *ufile = NULL, *parent = NULL; + + g_progname = basename(argv[0]); + while ((c = getopt(argc, argv, ":dfhlp:sStu:")) != -1) { + switch (c) { + case 'd': + g_dump |= CTFDUMP_OBJECTS; + break; + case 'f': + g_dump |= CTFDUMP_FUNCTIONS; + break; + case 'h': + g_dump |= CTFDUMP_HEADER; + break; + case 'l': + g_dump |= CTFDUMP_LABELS; + break; + case 'p': + parent = optarg; + break; + case 's': + g_dump |= CTFDUMP_STRINGS; + break; + case 'S': + g_dump |= CTFDUMP_STATS; + break; + case 't': + g_dump |= CTFDUMP_TYPES; + break; + case 'u': + g_dump |= CTFDUMP_OUTPUT; + ufile = optarg; + break; + case '?': + ctfdump_usage("Unknown option: -%c\n", optopt); + return (2); + case ':': + ctfdump_usage("Option -%c requires an operand\n", + optopt); + return (2); + } + } + + argc -= optind; + argv += optind; + + /* + * Dump all information by default. + */ + if (g_dump == 0) + g_dump = CTFDUMP_DEFAULT; + + if (argc != 1) { + ctfdump_usage("no file to dump\n"); + return (2); + } + + if ((fd = open(argv[0], O_RDONLY)) < 0) + ctfdump_fatal("failed to open file %s: %s\n", argv[0], + strerror(errno)); + + g_fp = ctf_fdopen(fd, &err); + if (g_fp == NULL) + ctfdump_fatal("failed to open file %s: %s\n", argv[0], + ctf_errmsg(err)); + + if (parent != NULL) { + ctf_file_t *pfp = ctf_open(parent, &err); + + if (pfp == NULL) + ctfdump_fatal("failed to open parent file %s: %s\n", + parent, ctf_errmsg(err)); + if (ctf_import(g_fp, pfp) != 0) + ctfdump_fatal("failed to import parent %s: %s\n", + parent, ctf_errmsg(ctf_errno(g_fp))); + } + + /* + * If stats is set, we must run through everything exect CTFDUMP_OUTPUT. + * We also do CTFDUMP_STATS last as a result. + */ + if (g_dump & CTFDUMP_HEADER) + ctfdump_header(); + + if (g_dump & (CTFDUMP_LABELS | CTFDUMP_STATS)) + ctfdump_labels(); + + if (g_dump & (CTFDUMP_OBJECTS | CTFDUMP_STATS)) + ctfdump_objects(); + + if (g_dump & (CTFDUMP_FUNCTIONS | CTFDUMP_STATS)) + ctfdump_functions(); + + if (g_dump & (CTFDUMP_TYPES | CTFDUMP_STATS)) + ctfdump_types(); + + if (g_dump & (CTFDUMP_STRINGS | CTFDUMP_STATS)) + ctfdump_strings(); + + if (g_dump & CTFDUMP_STATS) + ctfdump_stats(); + + if (g_dump & CTFDUMP_OUTPUT) + ctfdump_output(ufile); + + return (g_exit); +} diff --git a/usr/src/cmd/ctfmerge/Makefile b/usr/src/cmd/ctfmerge/Makefile new file mode 100644 index 0000000000..02ead98687 --- /dev/null +++ b/usr/src/cmd/ctfmerge/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +PROG= ctfmerge + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf -lelf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfmerge/ctfmerge.c b/usr/src/cmd/ctfmerge/ctfmerge.c new file mode 100644 index 0000000000..5dea32b3aa --- /dev/null +++ b/usr/src/cmd/ctfmerge/ctfmerge.c @@ -0,0 +1,538 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * merge CTF containers + */ + +#include <stdio.h> +#include <libctf.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <unistd.h> +#include <sys/fcntl.h> +#include <stdlib.h> +#include <libelf.h> +#include <gelf.h> +#include <sys/mman.h> +#include <libgen.h> +#include <stdarg.h> +#include <limits.h> + +static char *g_progname; +static char *g_unique; +static char *g_outfile; +static boolean_t g_req; +static uint_t g_nctf; + +#define CTFMERGE_OK 0 +#define CTFMERGE_FATAL 1 +#define CTFMERGE_USAGE 2 + +#define CTFMERGE_DEFAULT_NTHREADS 8 +#define CTFMERGE_ALTEXEC "CTFMERGE_ALTEXEC" + +static void +ctfmerge_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + if (g_outfile != NULL) + (void) unlink(g_outfile); + + exit(CTFMERGE_FATAL); +} + +static boolean_t +ctfmerge_expect_ctf(const char *name, Elf *elf) +{ + Elf_Scn *scn, *strscn; + Elf_Data *data, *strdata; + GElf_Shdr shdr; + ulong_t i; + + if (g_req == B_FALSE) + return (B_FALSE); + + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) { + ctfmerge_fatal("failed to get section header for file " + "%s: %s\n", name, elf_errmsg(elf_errno())); + } + + if (shdr.sh_type == SHT_SYMTAB) + break; + } + + if (scn == NULL) + return (B_FALSE); + + if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) + ctfmerge_fatal("failed to get section header for file %s: %s\n", + name, elf_errmsg(elf_errno())); + + if ((data = elf_getdata(scn, NULL)) == NULL) + ctfmerge_fatal("failed to read symbol table for %s: %s\n", + name, elf_errmsg(elf_errno())); + + if ((strdata = elf_getdata(strscn, NULL)) == NULL) + ctfmerge_fatal("failed to read string table for %s: %s\n", + name, elf_errmsg(elf_errno())); + + for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { + GElf_Sym sym; + const char *file; + size_t len; + + if (gelf_getsym(data, i, &sym) == NULL) + ctfmerge_fatal("failed to read symbol table entry %d " + "for %s: %s\n", i, name, elf_errmsg(elf_errno())); + + if (GELF_ST_TYPE(sym.st_info) != STT_FILE) + continue; + + file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name); + len = strlen(file); + if (len < 2 || name[len - 2] != '.') + continue; + + if (name[len - 1] == 'c') + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * Go through and construct enough information for this Elf Object to try and do + * a ctf_bufopen(). + */ +static void +ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh) +{ + GElf_Ehdr ehdr; + GElf_Shdr shdr; + Elf_Scn *scn; + Elf_Data *ctf_data, *str_data, *sym_data; + ctf_sect_t ctfsect, symsect, strsect; + ctf_file_t *fp; + int err; + + if (gelf_getehdr(elf, &ehdr) == NULL) + ctfmerge_fatal("failed to get ELF header for %s: %s\n", + name, elf_errmsg(elf_errno())); + + bzero(&ctfsect, sizeof (ctf_sect_t)); + bzero(&symsect, sizeof (ctf_sect_t)); + bzero(&strsect, sizeof (ctf_sect_t)); + + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + const char *sname; + + if (gelf_getshdr(scn, &shdr) == NULL) + ctfmerge_fatal("failed to get section header for " + "file %s: %s\n", name, elf_errmsg(elf_errno())); + + sname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); + if (shdr.sh_type == SHT_PROGBITS && + strcmp(sname, ".SUNW_ctf") == 0) { + ctfsect.cts_name = sname; + ctfsect.cts_type = shdr.sh_type; + ctfsect.cts_flags = shdr.sh_flags; + ctfsect.cts_size = shdr.sh_size; + ctfsect.cts_entsize = shdr.sh_entsize; + ctfsect.cts_offset = (off64_t)shdr.sh_offset; + + ctf_data = elf_getdata(scn, NULL); + if (ctf_data == NULL) + ctfmerge_fatal("failed to get ELF CTF " + "data section for %s: %s\n", name, + elf_errmsg(elf_errno())); + ctfsect.cts_data = ctf_data->d_buf; + } else if (shdr.sh_type == SHT_SYMTAB) { + Elf_Scn *strscn; + GElf_Shdr strhdr; + + symsect.cts_name = sname; + symsect.cts_type = shdr.sh_type; + symsect.cts_flags = shdr.sh_flags; + symsect.cts_size = shdr.sh_size; + symsect.cts_entsize = shdr.sh_entsize; + symsect.cts_offset = (off64_t)shdr.sh_offset; + + if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL || + gelf_getshdr(strscn, &strhdr) == NULL) + ctfmerge_fatal("failed to get " + "string table for file %s: %s\n", name, + elf_errmsg(elf_errno())); + + strsect.cts_name = elf_strptr(elf, ehdr.e_shstrndx, + strhdr.sh_name); + strsect.cts_type = strhdr.sh_type; + strsect.cts_flags = strhdr.sh_flags; + strsect.cts_size = strhdr.sh_size; + strsect.cts_entsize = strhdr.sh_entsize; + strsect.cts_offset = (off64_t)strhdr.sh_offset; + + sym_data = elf_getdata(scn, NULL); + if (sym_data == NULL) + ctfmerge_fatal("failed to get ELF CTF " + "data section for %s: %s\n", name, + elf_errmsg(elf_errno())); + symsect.cts_data = sym_data->d_buf; + + str_data = elf_getdata(strscn, NULL); + if (str_data == NULL) + ctfmerge_fatal("failed to get ELF CTF " + "data section for %s: %s\n", name, + elf_errmsg(elf_errno())); + strsect.cts_data = str_data->d_buf; + } + } + + if (ctfsect.cts_type == SHT_NULL) { + if (ctfmerge_expect_ctf(name, elf) == B_FALSE) + return; + ctfmerge_fatal("failed to open %s: %s\n", name, + ctf_errmsg(ECTF_NOCTFDATA)); + } + + if (symsect.cts_type != SHT_NULL && strsect.cts_type != SHT_NULL) { + fp = ctf_bufopen(&ctfsect, &symsect, &strsect, &err); + } else { + fp = ctf_bufopen(&ctfsect, NULL, NULL, &err); + } + + if (fp == NULL) { + if (ctfmerge_expect_ctf(name, elf) == B_TRUE) { + ctfmerge_fatal("failed to open file %s: %s\n", + name, ctf_errmsg(err)); + } + } else { + if ((err = ctf_merge_add(cmh, fp)) != 0) { + ctfmerge_fatal("failed to add input %s: %s\n", + name, ctf_errmsg(err)); + } + g_nctf++; + } +} + +static void +ctfmerge_read_archive(const char *name, int fd, Elf *elf, + ctf_merge_t *cmh) +{ + Elf *aelf; + Elf_Cmd cmd = ELF_C_READ; + int cursec = 1; + char *nname; + + while ((aelf = elf_begin(fd, cmd, elf)) != NULL) { + Elf_Arhdr *arhdr; + boolean_t leakelf = B_FALSE; + + if ((arhdr = elf_getarhdr(aelf)) == NULL) + ctfmerge_fatal("failed to get archive header %d for " + "%s: %s\n", cursec, name, elf_errmsg(elf_errno())); + + if (*(arhdr->ar_name) == '/') + goto next; + + if (asprintf(&nname, "%s.%s.%d", name, arhdr->ar_name, + cursec) < 0) + ctfmerge_fatal("failed to allocate memory for archive " + "%d of file %s\n", cursec, name); + + switch (elf_kind(aelf)) { + case ELF_K_AR: + ctfmerge_read_archive(nname, fd, aelf, cmh); + free(nname); + break; + case ELF_K_ELF: + ctfmerge_elfopen(nname, aelf, cmh); + free(nname); + leakelf = B_TRUE; + break; + default: + ctfmerge_fatal("unknown elf kind (%d) in archive %d " + "for %s\n", elf_kind(aelf), cursec, name); + } + +next: + cmd = elf_next(aelf); + if (leakelf == B_FALSE) + (void) elf_end(aelf); + cursec++; + } +} + +static void +ctfmerge_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-gt] [-d uniqfile] [-l label] " + "[-L labelenv] [-j nthrs] -o outfile file ...\n" + "\n" + "\t-d uniquify merged output against uniqfile\n" + "\t-g do not remove source debug information (STABS, DWARF)\n" + "\t-j use nthrs threads to perform the merge\n" + "\t-l set output container's label to specified value\n" + "\t-L set output container's label to value from environment\n" + "\t-o file to add CTF data to\n" + "\t-t require CTF data from all inputs built from C sources\n", + g_progname); +} + +static void +ctfmerge_altexec(char **argv) +{ + const char *alt; + char *altexec; + + alt = getenv(CTFMERGE_ALTEXEC); + if (alt == NULL || *alt == '\0') + return; + + altexec = strdup(alt); + if (altexec == NULL) + ctfmerge_fatal("failed to allocate memory for altexec\n"); + if (unsetenv(CTFMERGE_ALTEXEC) != 0) + ctfmerge_fatal("failed to unset %s from environment: %s\n", + CTFMERGE_ALTEXEC, strerror(errno)); + + (void) execv(altexec, argv); + ctfmerge_fatal("failed to execute alternate program %s: %s", + altexec, strerror(errno)); +} + +int +main(int argc, char *argv[]) +{ + int err, i, c, ofd; + uint_t nthreads = CTFMERGE_DEFAULT_NTHREADS; + char *tmpfile = NULL, *label = NULL; + int wflags = CTF_ELFWRITE_F_COMPRESS; + ctf_file_t *ofp; + ctf_merge_t *cmh; + long argj; + char *eptr; + + g_progname = basename(argv[0]); + + ctfmerge_altexec(argv); + + /* + * We support a subset of the old CTF merge flags, mostly for + * compatability. + */ + while ((c = getopt(argc, argv, ":d:fgj:L:o:t")) != -1) { + switch (c) { + case 'd': + g_unique = optarg; + break; + case 'f': + /* Silently ignored for compatibility */ + break; + case 'g': + /* Silently ignored for compatibility */ + break; + case 'j': + errno = 0; + argj = strtol(optarg, &eptr, 10); + if (errno != 0 || argj == LONG_MAX || + argj == LONG_MIN || argj <= 0 || + argj > UINT_MAX || *eptr != '\0') { + ctfmerge_fatal("invalid argument for -j: %s\n", + optarg); + } + nthreads = (uint_t)argj; + break; + case 'l': + label = optarg; + break; + case 'L': + label = getenv(optarg); + break; + case 'o': + g_outfile = optarg; + break; + case 't': + g_req = B_TRUE; + break; + case ':': + ctfmerge_usage("Option -%c requires an operand\n", + optopt); + return (CTFMERGE_USAGE); + case '?': + ctfmerge_usage("Unknown option: -%c\n", optopt); + return (CTFMERGE_USAGE); + } + } + + if (g_outfile == NULL) { + ctfmerge_usage("missing required -o output file\n"); + return (CTFMERGE_USAGE); + } + + (void) elf_version(EV_CURRENT); + + /* + * Obviously this isn't atomic, but at least gives us a good starting + * point. + */ + if ((ofd = open(g_outfile, O_RDWR)) < 0) + ctfmerge_fatal("cannot open output file %s: %s\n", g_outfile, + strerror(errno)); + + argc -= optind; + argv += optind; + + if (argc < 1) { + ctfmerge_usage("no input files specified"); + return (CTFMERGE_USAGE); + } + + cmh = ctf_merge_init(ofd, &err); + if (cmh == NULL) + ctfmerge_fatal("failed to create merge handle: %s\n", + ctf_errmsg(err)); + + if ((err = ctf_merge_set_nthreads(cmh, nthreads)) != 0) + ctfmerge_fatal("failed to set parallelism to %d: %s\n", + nthreads, ctf_errmsg(err)); + + for (i = 0; i < argc; i++) { + ctf_file_t *ifp; + int fd; + + if ((fd = open(argv[i], O_RDONLY)) < 0) + ctfmerge_fatal("failed to open file %s: %s\n", + argv[i], strerror(errno)); + ifp = ctf_fdopen(fd, &err); + if (ifp == NULL) { + Elf *e; + + if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + (void) close(fd); + ctfmerge_fatal("failed to open %s: %s\n", + argv[i], ctf_errmsg(err)); + } + + /* + * It's an ELF file, check if we have an archive or if + * we're expecting CTF here. + */ + switch (elf_kind(e)) { + case ELF_K_AR: + break; + case ELF_K_ELF: + if (ctfmerge_expect_ctf(argv[i], e) == B_TRUE) { + (void) elf_end(e); + (void) close(fd); + ctfmerge_fatal("failed to " + "open %s: file was built from C " + "sources, but missing CTF\n", + argv[i]); + } + (void) elf_end(e); + (void) close(fd); + continue; + default: + (void) elf_end(e); + (void) close(fd); + ctfmerge_fatal("failed to open %s: " + "unsupported ELF file type", argv[i]); + } + + ctfmerge_read_archive(argv[i], fd, e, cmh); + (void) elf_end(e); + (void) close(fd); + continue; + } + (void) close(fd); + if ((err = ctf_merge_add(cmh, ifp)) != 0) + ctfmerge_fatal("failed to add input %s: %s\n", + argv[i], ctf_errmsg(err)); + g_nctf++; + } + + if (g_nctf == 0) { + ctf_merge_fini(cmh); + return (0); + } + + if (g_unique != NULL) { + ctf_file_t *ufp; + char *base; + + ufp = ctf_open(g_unique, &err); + if (ufp == NULL) { + ctfmerge_fatal("failed to open uniquify file %s: %s\n", + g_unique, ctf_errmsg(err)); + } + + base = basename(g_unique); + (void) ctf_merge_uniquify(cmh, ufp, base); + } + + if (label != NULL) { + if ((err = ctf_merge_label(cmh, label)) != 0) + ctfmerge_fatal("failed to add label %s: %s\n", label, + ctf_errmsg(err)); + } + + err = ctf_merge_merge(cmh, &ofp); + if (err != 0) + ctfmerge_fatal("failed to merge types: %s\n", ctf_errmsg(err)); + ctf_merge_fini(cmh); + + if (asprintf(&tmpfile, "%s.ctf", g_outfile) == -1) + ctfmerge_fatal("ran out of memory for temporary file name\n"); + err = ctf_elfwrite(ofp, g_outfile, tmpfile, wflags); + if (err == CTF_ERR) { + (void) unlink(tmpfile); + free(tmpfile); + ctfmerge_fatal("encountered a libctf error: %s!\n", + ctf_errmsg(ctf_errno(ofp))); + } + + if (rename(tmpfile, g_outfile) != 0) { + (void) unlink(tmpfile); + free(tmpfile); + ctfmerge_fatal("failed to rename temporary file: %s\n", + strerror(errno)); + } + free(tmpfile); + + return (CTFMERGE_OK); +} diff --git a/usr/src/cmd/devfsadm/Makefile.com b/usr/src/cmd/devfsadm/Makefile.com index 4df3b00585..1585db2894 100644 --- a/usr/src/cmd/devfsadm/Makefile.com +++ b/usr/src/cmd/devfsadm/Makefile.com @@ -67,7 +67,6 @@ LINK_OBJS_CMN = \ fssnap_link.o \ sgen_link.o \ smp_link.o \ - md_link.o \ dtrace_link.o \ vscan_link.o \ zfs_link.o \ diff --git a/usr/src/cmd/devfsadm/devlink.tab.sh b/usr/src/cmd/devfsadm/devlink.tab.sh index 6724fcb573..0267efeb9f 100644 --- a/usr/src/cmd/devfsadm/devlink.tab.sh +++ b/usr/src/cmd/devfsadm/devlink.tab.sh @@ -22,8 +22,7 @@ # # Copyright (c) 1998, 2000 by Sun Microsystems, Inc. # All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 2012 Joyent, Inc. All rights reserved. # # This is the script that generates the devlink.tab file. It is # architecture-aware, and dumps different stuff for x86 and sparc. @@ -34,8 +33,6 @@ # cat <<EOM -#ident "%Z%%M% %I% %E% SMI" -# # Copyright (c) 1998 by Sun Microsystems, Inc. # # diff --git a/usr/src/cmd/devfsadm/i386/Makefile b/usr/src/cmd/devfsadm/i386/Makefile index 1f14c93dad..75f2da3436 100644 --- a/usr/src/cmd/devfsadm/i386/Makefile +++ b/usr/src/cmd/devfsadm/i386/Makefile @@ -24,8 +24,11 @@ LINK_OBJS_i386 = \ misc_link_i386.o \ + lx_link_i386.o \ xen_link.o +lx_link_i386.o lx_link_i386.po lx_link_i386.ln := CPPFLAGS += -I$(UTSBASE)/common/brand/lx + xen_link.o xen_link.ln xen_link.po := CPPFLAGS += -I$(UTSBASE)/i86xpv include ../Makefile.com diff --git a/usr/src/cmd/devfsadm/i386/lx_link_i386.c b/usr/src/cmd/devfsadm/i386/lx_link_i386.c new file mode 100644 index 0000000000..855f4f7383 --- /dev/null +++ b/usr/src/cmd/devfsadm/i386/lx_link_i386.c @@ -0,0 +1,86 @@ +/* + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <devfsadm.h> +#include <strings.h> +#include <stdio.h> +#include <sys/lx_ptm.h> +#include <sys/lx_audio.h> + +static int lx_ptm(di_minor_t minor, di_node_t node); +static int lx_audio(di_minor_t minor, di_node_t node); +static int lx_systrace(di_minor_t minor, di_node_t node); + +static devfsadm_create_t lx_create_cbt[] = { + { "pseudo", "ddi_pseudo", LX_PTM_DRV, + TYPE_EXACT | DRV_EXACT, ILEVEL_0, lx_ptm }, + { "pseudo", "ddi_pseudo", LX_AUDIO_DRV, + TYPE_EXACT | DRV_EXACT, ILEVEL_0, lx_audio }, + { "pseudo", "ddi_pseudo", "lx_systrace", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, lx_systrace }, +}; + +DEVFSADM_CREATE_INIT_V0(lx_create_cbt); + +static int +lx_ptm(di_minor_t minor, di_node_t node) +{ + char *mname = di_minor_name(minor); + + if (strcmp(LX_PTM_MINOR_NODE, mname) == 0) + (void) devfsadm_mklink("brand/lx/ptmx", node, minor, 0); + + return (DEVFSADM_CONTINUE); +} + +static int +lx_audio(di_minor_t minor, di_node_t node) +{ + char *mname = di_minor_name(minor); + + if (strcmp(LXA_MINORNAME_DEVCTL, mname) == 0) + (void) devfsadm_mklink("brand/lx/audio_devctl", node, minor, 0); + if (strcmp(LXA_MINORNAME_DSP, mname) == 0) + (void) devfsadm_mklink("brand/lx/dsp", node, minor, 0); + if (strcmp(LXA_MINORNAME_MIXER, mname) == 0) + (void) devfsadm_mklink("brand/lx/mixer", node, minor, 0); + + return (DEVFSADM_CONTINUE); +} + +static int +lx_systrace(di_minor_t minor, di_node_t node) +{ + char *mname = di_minor_name(minor); + char path[MAXPATHLEN]; + + (void) snprintf(path, sizeof (path), "dtrace/provider/%s", mname); + (void) devfsadm_mklink(path, node, minor, 0); + + return (DEVFSADM_CONTINUE); +} diff --git a/usr/src/cmd/devfsadm/misc_link.c b/usr/src/cmd/devfsadm/misc_link.c index abb133bc6d..55aff1e4f7 100644 --- a/usr/src/cmd/devfsadm/misc_link.c +++ b/usr/src/cmd/devfsadm/misc_link.c @@ -21,7 +21,7 @@ /* * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #include <regex.h> @@ -32,6 +32,7 @@ #include <limits.h> #include <sys/zone.h> #include <sys/zcons.h> +#include <sys/zfd.h> #include <sys/cpuid_drv.h> static int display(di_minor_t minor, di_node_t node); @@ -53,6 +54,7 @@ static int av_create(di_minor_t minor, di_node_t node); static int tsalarm_create(di_minor_t minor, di_node_t node); static int ntwdt_create(di_minor_t minor, di_node_t node); static int zcons_create(di_minor_t minor, di_node_t node); +static int zfd_create(di_minor_t minor, di_node_t node); static int cpuid(di_minor_t minor, di_node_t node); static int glvc(di_minor_t minor, di_node_t node); static int ses_callback(di_minor_t minor, di_node_t node); @@ -92,6 +94,9 @@ static devfsadm_create_t misc_cbt[] = { { "pseudo", "ddi_pseudo", "eventfd", TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name }, + { "pseudo", "ddi_pseudo", "signalfd", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + }, { "pseudo", "ddi_pseudo", "rsm", TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name }, @@ -111,6 +116,9 @@ static devfsadm_create_t misc_cbt[] = { "(^nca$)|(^rds$)|(^sdp$)|(^ipnet$)|(^dlpistub$)|(^bpf$)", TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name }, + { "pseudo", "ddi_pseudo", "inotify", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + }, { "pseudo", "ddi_pseudo", "ipd", TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name }, @@ -126,6 +134,9 @@ static devfsadm_create_t misc_cbt[] = { "(^kdmouse$)|(^rootprop$)", TYPE_EXACT | DRV_RE, ILEVEL_0, node_name }, + { "pseudo", "ddi_pseudo", "timerfd", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + }, { "pseudo", "ddi_pseudo", "tod", TYPE_EXACT | DRV_EXACT, ILEVEL_0, node_name }, @@ -174,6 +185,9 @@ static devfsadm_create_t misc_cbt[] = { { "pseudo", "ddi_pseudo", "zcons", TYPE_EXACT | DRV_EXACT, ILEVEL_0, zcons_create, }, + { "pseudo", "ddi_pseudo", "zfd", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, zfd_create, + }, { "pseudo", "ddi_pseudo", CPUID_DRIVER_NAME, TYPE_EXACT | DRV_EXACT, ILEVEL_0, cpuid, }, @@ -198,6 +212,9 @@ static devfsadm_create_t misc_cbt[] = { { "pseudo", "ddi_pseudo", "tpm", TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name }, + { "pseudo", "ddi_pseudo", "overlay", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + } }; DEVFSADM_CREATE_INIT_V0(misc_cbt); @@ -222,6 +239,9 @@ static devfsadm_remove_t misc_remove_cbt[] = { ZCONS_SLAVE_NAME ")$", RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all }, + { "pseudo", "^zfd/" ZONENAME_REGEXP "/(master|slave)/[0-9]+$", + RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all + }, { "pseudo", "^" CPUID_SELF_NAME "$", RM_ALWAYS | RM_PRE | RM_HOT, ILEVEL_0, devfsadm_rm_all }, @@ -669,6 +689,35 @@ zcons_create(di_minor_t minor, di_node_t node) return (DEVFSADM_CONTINUE); } +static int +zfd_create(di_minor_t minor, di_node_t node) +{ + char *minor_str; + char *zonename; + int *id; + char path[MAXPATHLEN]; + + minor_str = di_minor_name(minor); + + if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname", + &zonename) == -1) + return (DEVFSADM_CONTINUE); + + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "zfd_id", &id) == -1) + return (DEVFSADM_CONTINUE); + + if (strncmp(minor_str, "slave", 5) == 0) { + (void) snprintf(path, sizeof (path), "zfd/%s/slave/%d", + zonename, id[0]); + } else { + (void) snprintf(path, sizeof (path), "zfd/%s/master/%d", + zonename, id[0]); + } + (void) devfsadm_mklink(path, node, minor, 0); + + return (DEVFSADM_CONTINUE); +} + /* * /dev/cpu/self/cpuid -> /devices/pseudo/cpuid@0:self */ diff --git a/usr/src/cmd/dladm/Makefile b/usr/src/cmd/dladm/Makefile index 143086e26a..1f07bbd714 100644 --- a/usr/src/cmd/dladm/Makefile +++ b/usr/src/cmd/dladm/Makefile @@ -21,6 +21,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2015 Joyent, Inc. # PROG= dladm @@ -35,7 +36,7 @@ include ../Makefile.cmd XGETFLAGS += -a -x $(PROG).xcl LDLIBS += -L$(ROOT)/lib -lsocket LDLIBS += -ldladm -ldlpi -lkstat -lsecdb -lbsm -linetutil -ldevinfo -LDLIBS += $(ZLAZYLOAD) -lrstp $(ZNOLAZYLOAD) +LDLIBS += $(ZLAZYLOAD) -lrstp $(ZNOLAZYLOAD) -lnsl -lumem -lcmdutils CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-unused-label diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c index 904eca536d..8e4f61fae0 100644 --- a/usr/src/cmd/dladm/dladm.c +++ b/usr/src/cmd/dladm/dladm.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015 Joyent, Inc. All rights reserved. */ #include <stdio.h> @@ -59,6 +60,7 @@ #include <libdliptun.h> #include <libdlsim.h> #include <libdlbridge.h> +#include <libdloverlay.h> #include <libinetutil.h> #include <libvrrpadm.h> #include <bsm/adt.h> @@ -74,6 +76,7 @@ #include <stddef.h> #include <stp_in.h> #include <ofmt.h> +#include <libcmdutils.h> #define MAXPORT 256 #define MAXVNIC 256 @@ -154,6 +157,7 @@ typedef struct show_vnic_state { dladm_status_t vs_status; uint32_t vs_flags; ofmt_handle_t vs_ofmt; + char *vs_zonename; } show_vnic_state_t; typedef struct show_part_state { @@ -192,6 +196,7 @@ static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb; static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb; static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb; static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb; +static ofmt_cb_t print_overlay_cb, print_overlay_fma_cb, print_overlay_targ_cb; static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); typedef void cmdfunc_t(int, char **, const char *); @@ -219,6 +224,8 @@ static cmdfunc_t do_create_bridge, do_modify_bridge, do_delete_bridge; static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge; static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun; static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun; +static cmdfunc_t do_create_overlay, do_delete_overlay, do_modify_overlay; +static cmdfunc_t do_show_overlay; static void do_up_vnic_common(int, char **, const char *, boolean_t); @@ -254,8 +261,11 @@ static void die(const char *, ...); static void die_optdup(int); static void die_opterr(int, int, const char *); static void die_dlerr(dladm_status_t, const char *, ...); +static void die_dlerrlist(dladm_status_t, dladm_errlist_t *, + const char *, ...); static void warn(const char *, ...); static void warn_dlerr(dladm_status_t, const char *, ...); +static void warn_dlerrlist(dladm_errlist_t *); typedef struct cmd { char *c_name; @@ -265,7 +275,7 @@ typedef struct cmd { static cmd_t cmds[] = { { "rename-link", do_rename_link, - " rename-link <oldlink> <newlink>" }, + " rename-link [-z zonename] <oldlink> <newlink>" }, { "show-link", do_show_link, " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] " "[<link>]\n" }, @@ -300,12 +310,13 @@ static cmd_t cmds[] = { { "show-wifi", do_show_wifi, " show-wifi [-p] [-o <field>,...] [<link>]\n" }, { "set-linkprop", do_set_linkprop, - " set-linkprop [-t] -p <prop>=<value>[,...] <name>" }, + " set-linkprop [-t] [-z zonename] -p <prop>=<value>[,...] " + "<name>" }, { "reset-linkprop", do_reset_linkprop, - " reset-linkprop [-t] [-p <prop>,...] <name>" }, + " reset-linkprop [-t] [-z zonename] [-p <prop>,...] <name>"}, { "show-linkprop", do_show_linkprop, - " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] " - "<name>\n" }, + " show-linkprop [-cP] [-o <field>,...] [-z zonename] " + "[-p <prop>,...] <name>\n" }, { "show-ether", do_show_ether, " show-ether [-px][-o <field>,...] <link>\n" }, { "create-secobj", do_create_secobj, @@ -347,10 +358,10 @@ static cmd_t cmds[] = { "\t\t {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n" "\t\t [-p <prop>=<value>[,...]] <vnic-link>" }, { "delete-vnic", do_delete_vnic, - " delete-vnic [-t] <vnic-link>" }, + " delete-vnic [-t] [-z zonename] <vnic-link>" }, { "show-vnic", do_show_vnic, - " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] " - "[<link>]\n" }, + " show-vnic [-pP] [-l <link>] [-z zonename] " + "[-s [-i <interval>]] [<link>]\n" }, { "up-vnic", do_up_vnic, NULL }, { "create-part", do_create_part, " create-part [-t] [-f] -l <link> [-P <pkey>]\n" @@ -401,6 +412,17 @@ static cmd_t cmds[] = { " <bridge>\n" " show-bridge -t [-p] [-o <field>,...] [-s [-i <interval>]]" " <bridge>\n" }, + { "create-overlay", do_create_overlay, + " create-overlay [-t] -e <encap> -s <search> -v <vnetid>\n" + "\t\t [ -p <prop>=<value>[,...]] <overlay>" }, + { "delete-overlay", do_delete_overlay, + " delete-overlay <overlay>" }, + { "modify-overlay", do_modify_overlay, + " modify-overlay -d mac | -f | -s mac=ip:port " + "<overlay>" }, + { "show-overlay", do_show_overlay, + " show-overlay [-f | -t] [[-p] -o <field>,...] " + "[<overlay>]\n" }, { "show-usage", do_show_usage, " show-usage [-a] [-d | -F <format>] " "[-s <DD/MM/YYYY,HH:MM:SS>]\n" @@ -959,6 +981,7 @@ typedef struct show_linkprop_state { char ls_link[MAXLINKNAMELEN]; char *ls_line; char **ls_propvals; + char *ls_zonename; dladm_arg_list_t *ls_proplist; boolean_t ls_parsable; boolean_t ls_persist; @@ -1011,21 +1034,24 @@ typedef struct vnic_fields_buf_s char vnic_macaddr[18]; char vnic_macaddrtype[19]; char vnic_vid[6]; + char vnic_zone[ZONENAME_MAX]; } vnic_fields_buf_t; static const ofmt_field_t vnic_fields[] = { { "LINK", 13, offsetof(vnic_fields_buf_t, vnic_link), print_default_cb}, -{ "OVER", 13, +{ "OVER", 11, offsetof(vnic_fields_buf_t, vnic_over), print_default_cb}, -{ "SPEED", 7, +{ "SPEED", 6, offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb}, { "MACADDRESS", 18, offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb}, -{ "MACADDRTYPE", 20, +{ "MACADDRTYPE", 12, offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb}, -{ "VID", 7, +{ "VID", 5, offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb}, +{ "ZONE", 20, + offsetof(vnic_fields_buf_t, vnic_zone), print_default_cb}, { NULL, 0, 0, NULL}} ; @@ -1425,6 +1451,82 @@ static ofmt_field_t bridge_trill_fields[] = { offsetof(bridge_trill_fields_buf_t, bridget_nexthop), print_default_cb }, { NULL, 0, 0, NULL}}; +static const struct option overlay_create_lopts[] = { + { "encap", required_argument, NULL, 'e' }, + { "prop", required_argument, NULL, 'p' }, + { "search", required_argument, NULL, 's' }, + { "temporary", no_argument, NULL, 't' }, + { "vnetid", required_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } +}; + +static const struct option overlay_modify_lopts[] = { + { "delete-entry", required_argument, NULL, 'd' }, + { "flush-table", no_argument, NULL, 'f' }, + { "set-entry", required_argument, NULL, 's' }, + { NULL, 0, NULL, 0 } +}; + +static const struct option overlay_show_lopts[] = { + { "fma", no_argument, NULL, 'f' }, + { "target", no_argument, NULL, 't' }, + { "parsable", no_argument, NULL, 'p' }, + { "parseable", no_argument, NULL, 'p' }, + { "output", required_argument, NULL, 'o' }, + { NULL, 0, NULL, 0 } +}; + +/* + * Structures for dladm show-overlay + */ +typedef enum { + OVERLAY_LINK, + OVERLAY_PROPERTY, + OVERLAY_PERM, + OVERLAY_REQ, + OVERLAY_VALUE, + OVERLAY_DEFAULT, + OVERLAY_POSSIBLE +} overlay_field_index_t; + +static const ofmt_field_t overlay_fields[] = { +/* name, field width, index */ +{ "LINK", 19, OVERLAY_LINK, print_overlay_cb }, +{ "PROPERTY", 19, OVERLAY_PROPERTY, print_overlay_cb }, +{ "PERM", 5, OVERLAY_PERM, print_overlay_cb }, +{ "REQ", 4, OVERLAY_REQ, print_overlay_cb }, +{ "VALUE", 11, OVERLAY_VALUE, print_overlay_cb }, +{ "DEFAULT", 10, OVERLAY_DEFAULT, print_overlay_cb }, +{ "POSSIBLE", 10, OVERLAY_POSSIBLE, print_overlay_cb }, +{ NULL, 0, 0, NULL } +}; + +typedef enum { + OVERLAY_FMA_LINK, + OVERLAY_FMA_STATUS, + OVERLAY_FMA_DETAILS +} overlay_fma_field_index_t; + +static const ofmt_field_t overlay_fma_fields[] = { +{ "LINK", 20, OVERLAY_FMA_LINK, print_overlay_fma_cb }, +{ "STATUS", 8, OVERLAY_FMA_STATUS, print_overlay_fma_cb }, +{ "DETAILS", 52, OVERLAY_FMA_DETAILS, print_overlay_fma_cb }, +{ NULL, 0, 0, NULL } +}; + +typedef enum { + OVERLAY_TARG_LINK, + OVERLAY_TARG_TARGET, + OVERLAY_TARG_DEST +} overlay_targ_field_index_t; + +static const ofmt_field_t overlay_targ_fields[] = { +{ "LINK", 20, OVERLAY_TARG_LINK, print_overlay_targ_cb }, +{ "TARGET", 18, OVERLAY_TARG_TARGET, print_overlay_targ_cb }, +{ "DESTINATION", 42, OVERLAY_TARG_DEST, print_overlay_targ_cb }, +{ NULL, 0, 0, NULL } +}; + static char *progname; static sig_atomic_t signalled; @@ -1434,6 +1536,12 @@ static sig_atomic_t signalled; */ static dladm_handle_t handle = NULL; +/* + * Global error list that all routines can use. It's initialized by the main + * code. + */ +static dladm_errlist_t errlist; + #define DLADM_ETHERSTUB_NAME "etherstub" #define DLADM_IS_ETHERSTUB(id) (id == DATALINK_INVALID_LINKID) @@ -1484,6 +1592,8 @@ main(int argc, char *argv[]) "could not open /dev/dld"); } + dladm_errlist_init(&errlist); + cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage); dladm_close(handle); @@ -2495,13 +2605,17 @@ do_rename_link(int argc, char *argv[], const char *use) char *link1, *link2; char *altroot = NULL; dladm_status_t status; + char *zonename = NULL; opterr = 0; - while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { + while ((option = getopt_long(argc, argv, ":R:z:", lopts, NULL)) != -1) { switch (option) { case 'R': altroot = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); break; @@ -2517,7 +2631,7 @@ do_rename_link(int argc, char *argv[], const char *use) link1 = argv[optind++]; link2 = argv[optind]; - if ((status = dladm_rename_link(handle, link1, link2)) != + if ((status = dladm_rename_link(handle, zonename, link1, link2)) != DLADM_STATUS_OK) die_dlerr(status, "rename operation failed"); } @@ -3407,11 +3521,12 @@ do_show_link(int argc, char *argv[], const char *use) ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":pPsSi:o:", + while ((option = getopt_long(argc, argv, ":pPsSi:o:z:", show_lopts, NULL)) != -1) { switch (option) { case 'p': @@ -3450,6 +3565,9 @@ do_show_link(int argc, char *argv[], const char *use) if (!dladm_str2interval(optarg, &interval)) die("invalid interval value '%s'", optarg); break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); break; @@ -3475,8 +3593,8 @@ do_show_link(int argc, char *argv[], const char *use) if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long"); - if ((status = dladm_name2info(handle, linkname, &linkid, &f, - NULL, NULL)) != DLADM_STATUS_OK) { + if ((status = dladm_zname2info(handle, zonename, linkname, + &linkid, &f, NULL, NULL)) != DLADM_STATUS_OK) { die_dlerr(status, "link %s is not valid", linkname); } @@ -4741,6 +4859,12 @@ do_create_vnic(int argc, char *argv[], const char *use) if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) die("-f option can only be used with -v"); + /* + * If creating a transient VNIC for a zone, mark it in the kernel. + */ + if (strstr(propstr, "zone=") != NULL && !(flags & DLADM_OPT_PERSIST)) + flags |= DLADM_OPT_TRANSIENT; + if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) usage(); @@ -4785,7 +4909,7 @@ do_create_vnic(int argc, char *argv[], const char *use) status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, mac_addr, maclen, &mac_slot, mac_prefix_len, vid, vrid, af, - &linkid, proplist, flags); + &linkid, proplist, &errlist, flags); switch (status) { case DLADM_STATUS_OK: break; @@ -4796,7 +4920,8 @@ do_create_vnic(int argc, char *argv[], const char *use) break; default: - die_dlerr(status, "vnic creation over %s failed", devname); + die_dlerrlist(status, &errlist, "vnic creation over %s failed", + devname); } dladm_free_props(proplist); @@ -4832,9 +4957,10 @@ do_delete_vnic_common(int argc, char *argv[], const char *use, datalink_id_t linkid; char *altroot = NULL; dladm_status_t status; + char *zonename = NULL; opterr = 0; - while ((option = getopt_long(argc, argv, ":R:t", lopts, + while ((option = getopt_long(argc, argv, ":R:tz:", lopts, NULL)) != -1) { switch (option) { case 't': @@ -4843,6 +4969,9 @@ do_delete_vnic_common(int argc, char *argv[], const char *use, case 'R': altroot = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); } @@ -4855,8 +4984,8 @@ do_delete_vnic_common(int argc, char *argv[], const char *use, if (altroot != NULL) altroot_cmd(altroot, argc, argv); - status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, - NULL); + status = dladm_zname2info(handle, zonename, argv[optind], &linkid, NULL, + NULL, NULL); if (status != DLADM_STATUS_OK) die("invalid link name '%s'", argv[optind]); @@ -4988,6 +5117,9 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid) char vnic_name[MAXLINKNAMELEN]; char mstr[MAXMACADDRLEN * 3]; vnic_fields_buf_t vbuf; + uint_t valcnt = 1; + char zonename[DLADM_PROP_VAL_MAX + 1]; + char *valptr[1]; if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != DLADM_STATUS_OK) @@ -5017,6 +5149,18 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid) NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) (void) sprintf(devname, "?"); + + zonename[0] = '\0'; + if (!is_etherstub) { + valptr[0] = zonename; + (void) dladm_get_linkprop(handle, linkid, + DLADM_PROP_VAL_CURRENT, "zone", (char **)valptr, &valcnt); + } + + if (state->vs_zonename != NULL && + strcmp(state->vs_zonename, zonename) != 0) + return (DLADM_STATUS_OK); + state->vs_found = B_TRUE; if (state->vs_stats) { /* print vnic statistics */ @@ -5092,6 +5236,13 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid) (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), "%d", vnic->va_vid); + + if (zonename[0] != '\0') + (void) snprintf(vbuf.vnic_zone, + sizeof (vbuf.vnic_zone), "%s", zonename); + else + (void) strlcpy(vbuf.vnic_zone, "--", + sizeof (vbuf.vnic_zone)); } ofmt_print(state->vs_ofmt, &vbuf); @@ -5130,10 +5281,11 @@ do_show_vnic_common(int argc, char *argv[], const char *use, ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, + while ((option = getopt_long(argc, argv, ":pPl:si:o:z:", lopts, NULL)) != -1) { switch (option) { case 'p': @@ -5172,6 +5324,9 @@ do_show_vnic_common(int argc, char *argv[], const char *use, o_arg = B_TRUE; fields_str = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); } @@ -5182,8 +5337,8 @@ do_show_vnic_common(int argc, char *argv[], const char *use, /* get vnic ID (optional last argument) */ if (optind == (argc - 1)) { - status = dladm_name2info(handle, argv[optind], &linkid, NULL, - NULL, NULL); + status = dladm_zname2info(handle, zonename, argv[optind], + &linkid, NULL, NULL, NULL); if (status != DLADM_STATUS_OK) { die_dlerr(status, "invalid vnic name '%s'", argv[optind]); @@ -5194,8 +5349,8 @@ do_show_vnic_common(int argc, char *argv[], const char *use, } if (l_arg) { - status = dladm_name2info(handle, state.vs_link, &dev_linkid, - NULL, NULL, NULL); + status = dladm_zname2info(handle, zonename, state.vs_link, + &dev_linkid, NULL, NULL, NULL); if (status != DLADM_STATUS_OK) { die_dlerr(status, "invalid link name '%s'", state.vs_link); @@ -5207,6 +5362,7 @@ do_show_vnic_common(int argc, char *argv[], const char *use, state.vs_etherstub = etherstub; state.vs_found = B_FALSE; state.vs_flags = flags; + state.vs_zonename = zonename; if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { if (etherstub) @@ -5295,7 +5451,7 @@ do_create_etherstub(int argc, char *argv[], const char *use) status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, - VRRP_VRID_NONE, AF_UNSPEC, NULL, NULL, flags); + VRRP_VRID_NONE, AF_UNSPEC, NULL, NULL, &errlist, flags); if (status != DLADM_STATUS_OK) die_dlerr(status, "etherstub creation failed"); } @@ -6695,6 +6851,7 @@ do_show_linkprop(int argc, char **argv, const char *use) ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(propstr, DLADM_STRSIZE); opterr = 0; @@ -6705,7 +6862,7 @@ do_show_linkprop(int argc, char **argv, const char *use) state.ls_header = B_TRUE; state.ls_retstatus = DLADM_STATUS_OK; - while ((option = getopt_long(argc, argv, ":p:cPo:", + while ((option = getopt_long(argc, argv, ":p:cPo:z:", prop_longopts, NULL)) != -1) { switch (option) { case 'p': @@ -6724,6 +6881,9 @@ do_show_linkprop(int argc, char **argv, const char *use) case 'o': fields_str = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); break; @@ -6731,8 +6891,8 @@ do_show_linkprop(int argc, char **argv, const char *use) } if (optind == (argc - 1)) { - if ((status = dladm_name2info(handle, argv[optind], &linkid, - NULL, NULL, NULL)) != DLADM_STATUS_OK) { + if ((status = dladm_zname2info(handle, zonename, argv[optind], + &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) { die_dlerr(status, "link %s is not valid", argv[optind]); } } else if (optind != argc) { @@ -6743,6 +6903,7 @@ do_show_linkprop(int argc, char **argv, const char *use) != DLADM_STATUS_OK) die("invalid link properties specified"); state.ls_proplist = proplist; + state.ls_zonename = zonename; state.ls_status = DLADM_STATUS_OK; if (state.ls_parsable) @@ -6787,6 +6948,17 @@ show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) return (DLADM_WALK_CONTINUE); } + if (statep->ls_zonename != NULL) { + datalink_id_t tlinkid; + + if (dladm_zname2info(hdl, statep->ls_zonename, statep->ls_link, + &tlinkid, NULL, NULL, NULL) != DLADM_STATUS_OK || + linkid != tlinkid) { + statep->ls_status = DLADM_STATUS_NOTFOUND; + return (DLADM_WALK_CONTINUE); + } + } + if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { statep->ls_status = DLADM_STATUS_BADARG; @@ -6869,11 +7041,12 @@ set_linkprop(int argc, char **argv, boolean_t reset, const char *use) dladm_status_t status = DLADM_STATUS_OK; char propstr[DLADM_STRSIZE]; dladm_arg_list_t *proplist = NULL; + char *zonename = NULL; opterr = 0; bzero(propstr, DLADM_STRSIZE); - while ((option = getopt_long(argc, argv, ":p:R:t", + while ((option = getopt_long(argc, argv, ":p:R:tz:", prop_longopts, NULL)) != -1) { switch (option) { case 'p': @@ -6888,6 +7061,9 @@ set_linkprop(int argc, char **argv, boolean_t reset, const char *use) case 'R': altroot = optarg; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, use); @@ -6910,8 +7086,8 @@ set_linkprop(int argc, char **argv, boolean_t reset, const char *use) altroot_cmd(altroot, argc, argv); } - status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, - NULL); + status = dladm_zname2info(handle, zonename, argv[optind], &linkid, + NULL, NULL, NULL); if (status != DLADM_STATUS_OK) die_dlerr(status, "link %s is not valid", argv[optind]); @@ -8934,6 +9110,21 @@ warn_dlerr(dladm_status_t err, const char *format, ...) (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); } +static void +warn_dlerrlist(dladm_errlist_t *errlist) +{ + if (errlist != NULL && errlist->el_count > 0) { + int i; + for (i = 0; i < errlist->el_count; i++) { + (void) fprintf(stderr, gettext("%s: warning: "), + progname); + + (void) fprintf(stderr, "%s\n", + gettext(errlist->el_errs[i])); + } + } +} + /* * Also closes the dladm handle if it is not NULL. */ @@ -8959,6 +9150,34 @@ die_dlerr(dladm_status_t err, const char *format, ...) exit(EXIT_FAILURE); } +/* + * Like die_dlerr, but uses the errlist for additional information. + */ +/* PRINTFLIKE3 */ +static void +die_dlerrlist(dladm_status_t err, dladm_errlist_t *errlist, + const char *format, ...) +{ + va_list alist; + char errmsg[DLADM_STRSIZE]; + + warn_dlerrlist(errlist); + format = gettext(format); + (void) fprintf(stderr, "%s: ", progname); + + va_start(alist, format); + (void) vfprintf(stderr, format, alist); + va_end(alist); + (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); + + /* close dladm handle if it was opened */ + if (handle != NULL) + dladm_close(handle); + + exit(EXIT_FAILURE); + +} + /* PRINTFLIKE1 */ static void die(const char *format, ...) @@ -9689,3 +9908,673 @@ do_up_part(int argc, char *argv[], const char *use) (void) dladm_part_up(handle, partid, 0); } + +static void +do_create_overlay(int argc, char *argv[], const char *use) +{ + int opt; + char *encap = NULL, *endp, *search = NULL; + char name[MAXLINKNAMELEN]; + dladm_status_t status; + uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; + uint64_t vid; + boolean_t havevid = B_FALSE; + char propstr[DLADM_STRSIZE]; + dladm_arg_list_t *proplist = NULL; + + bzero(propstr, sizeof (propstr)); + while ((opt = getopt_long(argc, argv, ":te:v:p:s:", + overlay_create_lopts, NULL)) != -1) { + switch (opt) { + case 'e': + encap = optarg; + break; + case 's': + search = optarg; + break; + case 't': + flags &= ~DLADM_OPT_PERSIST; + break; + case 'p': + (void) strlcat(propstr, optarg, DLADM_STRSIZE); + if (strlcat(propstr, ",", DLADM_STRSIZE) >= + DLADM_STRSIZE) + die("property list too long '%s'", propstr); + break; + case 'v': + vid = strtoul(optarg, &endp, 10); + if (*endp != '\0' || (vid == 0 && errno == EINVAL)) + die("couldn't parse virtual networkd id: %s", + optarg); + if (vid == ULONG_MAX && errno == ERANGE) + die("virtual networkd id too large: %s", + optarg); + havevid = B_TRUE; + break; + default: + die_opterr(optopt, opt, use); + } + } + + if (havevid == B_FALSE) + die("missing required virtual network id"); + + if (encap == NULL) + die("missing required encapsulation plugin"); + + if (encap == NULL) + die("missing required search plugin"); + + if (optind != (argc - 1)) + die("missing device name"); + + if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) + die("link name too long '%s'", argv[optind]); + + if (!dladm_valid_linkname(name)) + die("invalid link name '%s'", argv[optind]); + + if (strlen(encap) + 1 > MAXLINKNAMELEN) + die("encapsulation plugin name too long '%s'", encap); + + if (strlen(search) + 1 > MAXLINKNAMELEN) + die("search plugin name too long '%s'", encap); + + if (dladm_parse_link_props(propstr, &proplist, B_FALSE) + != DLADM_STATUS_OK) + die("invalid overlay property"); + + status = dladm_overlay_create(handle, name, encap, search, vid, + proplist, &errlist, flags); + dladm_free_props(proplist); + if (status != DLADM_STATUS_OK) { + die_dlerrlist(status, &errlist, "overlay creation failed"); + } +} + +/* ARGSUSED */ +static void +do_delete_overlay(int argc, char *argv[], const char *use) +{ + datalink_id_t linkid = DATALINK_ALL_LINKID; + dladm_status_t status; + + if (argc != 2) { + usage(); + } + + status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, NULL); + if (status != DLADM_STATUS_OK) + die_dlerr(status, "failed to delete %s", argv[1]); + + status = dladm_overlay_delete(handle, linkid); + if (status != DLADM_STATUS_OK) + die_dlerr(status, "failed to delete %s", argv[1]); +} + +typedef struct showoverlay_state { + ofmt_handle_t sho_ofmt; + const char *sho_linkname; + dladm_overlay_propinfo_handle_t sho_info; + uint8_t sho_value[DLADM_OVERLAY_PROP_SIZEMAX]; + uint32_t sho_size; +} showoverlay_state_t; + +typedef struct showoverlay_fma_state { + ofmt_handle_t shof_ofmt; + const char *shof_linkname; + dladm_overlay_status_t *shof_status; +} showoverlay_fma_state_t; + +typedef struct showoverlay_targ_state { + ofmt_handle_t shot_ofmt; + const char *shot_linkname; + const struct ether_addr *shot_key; + const dladm_overlay_point_t *shot_point; +} showoverlay_targ_state_t; + +static void +print_overlay_value(char *outbuf, uint_t bufsize, uint_t type, const void *pbuf, + const size_t psize) +{ + const struct in6_addr *ipv6; + struct in_addr ip; + + switch (type) { + case OVERLAY_PROP_T_INT: + if (psize != 1 && psize != 2 && psize != 4 && psize != 8) { + (void) snprintf(outbuf, bufsize, "?"); + break; + } + if (psize == 1) + (void) snprintf(outbuf, bufsize, "%d", *(int8_t *)pbuf); + if (psize == 2) + (void) snprintf(outbuf, bufsize, "%d", + *(int16_t *)pbuf); + if (psize == 4) + (void) snprintf(outbuf, bufsize, "%d", + *(int32_t *)pbuf); + if (psize == 8) + (void) snprintf(outbuf, bufsize, "%d", + *(int64_t *)pbuf); + break; + case OVERLAY_PROP_T_UINT: + if (psize != 1 && psize != 2 && psize != 4 && psize != 8) { + (void) snprintf(outbuf, bufsize, "?"); + break; + } + if (psize == 1) + (void) snprintf(outbuf, bufsize, "%d", + *(uint8_t *)pbuf); + if (psize == 2) + (void) snprintf(outbuf, bufsize, "%d", + *(uint16_t *)pbuf); + if (psize == 4) + (void) snprintf(outbuf, bufsize, "%d", + *(uint32_t *)pbuf); + if (psize == 8) + (void) snprintf(outbuf, bufsize, "%d", + *(uint64_t *)pbuf); + break; + case OVERLAY_PROP_T_IP: + if (psize != sizeof (struct in6_addr)) { + warn("malformed overlay IP property: %d bytes\n", + psize); + (void) snprintf(outbuf, bufsize, "--"); + break; + } + + ipv6 = pbuf; + if (IN6_IS_ADDR_V4MAPPED(ipv6)) { + IN6_V4MAPPED_TO_INADDR(ipv6, &ip); + if (inet_ntop(AF_INET, &ip, outbuf, bufsize) == NULL) { + warn("malformed overlay IP property\n"); + (void) snprintf(outbuf, bufsize, "--"); + break; + } + } else { + if (inet_ntop(AF_INET6, ipv6, outbuf, bufsize) == + NULL) { + warn("malformed overlay IP property\n"); + (void) snprintf(outbuf, bufsize, "--"); + break; + } + } + + break; + case OVERLAY_PROP_T_STRING: + (void) snprintf(outbuf, bufsize, "%s", pbuf); + break; + default: + abort(); + } + + return; + +} + +static boolean_t +print_overlay_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) +{ + dladm_status_t status; + showoverlay_state_t *sp = ofarg->ofmt_cbarg; + dladm_overlay_propinfo_handle_t infop = sp->sho_info; + const char *pname; + uint_t type, prot; + const void *def; + uint32_t defsize; + const mac_propval_range_t *rangep; + + if ((status = dladm_overlay_prop_info(infop, &pname, &type, &prot, &def, + &defsize, &rangep)) != DLADM_STATUS_OK) { + warn_dlerr(status, "failed to get get property info"); + return (B_TRUE); + } + + switch (ofarg->ofmt_id) { + case OVERLAY_LINK: + (void) snprintf(buf, bufsize, "%s", sp->sho_linkname); + break; + case OVERLAY_PROPERTY: + (void) snprintf(buf, bufsize, "%s", pname); + break; + case OVERLAY_PERM: + if ((prot & OVERLAY_PROP_PERM_RW) == OVERLAY_PROP_PERM_RW) { + (void) snprintf(buf, bufsize, "%s", "rw"); + } else if ((prot & OVERLAY_PROP_PERM_RW) == + OVERLAY_PROP_PERM_READ) { + (void) snprintf(buf, bufsize, "%s", "r-"); + } else { + (void) snprintf(buf, bufsize, "%s", "--"); + } + break; + case OVERLAY_REQ: + (void) snprintf(buf, bufsize, "%s", + prot & OVERLAY_PROP_PERM_REQ ? "y" : "-"); + break; + case OVERLAY_VALUE: + if (sp->sho_size == 0) { + (void) snprintf(buf, bufsize, "%s", "--"); + } else { + print_overlay_value(buf, bufsize, type, sp->sho_value, + sp->sho_size); + } + break; + case OVERLAY_DEFAULT: + if (defsize == 0) { + (void) snprintf(buf, bufsize, "%s", "--"); + } else { + print_overlay_value(buf, bufsize, type, def, defsize); + } + break; + case OVERLAY_POSSIBLE: { + int i; + char **vals, *ptr, *lim; + if (rangep->mpr_count == 0) { + (void) snprintf(buf, bufsize, "%s", "--"); + break; + } + + vals = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * + rangep->mpr_count); + if (vals == NULL) + die("insufficient memory"); + for (i = 0; i < rangep->mpr_count; i++) { + vals[i] = (char *)vals + sizeof (char *) * + rangep->mpr_count + i * DLADM_MAX_PROP_VALCNT; + } + + if (dladm_range2strs(rangep, vals) != 0) { + free(vals); + (void) snprintf(buf, bufsize, "%s", "?"); + break; + } + + ptr = buf; + lim = buf + bufsize; + for (i = 0; i < rangep->mpr_count; i++) { + ptr += snprintf(ptr, lim - ptr, "%s,", vals[i]); + if (ptr >= lim) + break; + } + if (rangep->mpr_count > 0) + buf[strlen(buf) - 1] = '\0'; + free(vals); + break; + } + default: + abort(); + } + return (B_TRUE); +} + +static int +dladm_overlay_show_one(dladm_handle_t handle, datalink_id_t linkid, + dladm_overlay_propinfo_handle_t phdl, void *arg) +{ + showoverlay_state_t *sp = arg; + sp->sho_info = phdl; + + sp->sho_size = sizeof (sp->sho_value); + if (dladm_overlay_get_prop(handle, linkid, phdl, &sp->sho_value, + &sp->sho_size) != DLADM_STATUS_OK) + return (DLADM_WALK_CONTINUE); + + ofmt_print(sp->sho_ofmt, sp); + return (DLADM_WALK_CONTINUE); +} + +static int +show_one_overlay(dladm_handle_t hdl, datalink_id_t linkid, void *arg) +{ + char buf[MAXLINKNAMELEN]; + showoverlay_state_t state; + datalink_class_t class; + + if (dladm_datalink_id2info(hdl, linkid, NULL, &class, NULL, buf, + MAXLINKNAMELEN) != DLADM_STATUS_OK || + class != DATALINK_CLASS_OVERLAY) + return (DLADM_WALK_CONTINUE); + + state.sho_linkname = buf; + state.sho_ofmt = arg; + + dladm_errlist_reset(&errlist); + (void) dladm_overlay_walk_prop(handle, linkid, dladm_overlay_show_one, + &state, &errlist); + warn_dlerrlist(&errlist); + + return (DLADM_WALK_CONTINUE); +} + +static boolean_t +print_overlay_targ_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) +{ + char keybuf[ETHERADDRSTRL]; + const showoverlay_targ_state_t *shot = ofarg->ofmt_cbarg; + const dladm_overlay_point_t *point = shot->shot_point; + char macbuf[ETHERADDRSTRL]; + char ipbuf[INET6_ADDRSTRLEN]; + custr_t *cus; + + switch (ofarg->ofmt_id) { + case OVERLAY_TARG_LINK: + (void) snprintf(buf, bufsize, shot->shot_linkname); + break; + case OVERLAY_TARG_TARGET: + if ((point->dop_flags & DLADM_OVERLAY_F_DEFAULT) != 0) { + (void) snprintf(buf, bufsize, "*:*:*:*:*:*"); + } else { + if (ether_ntoa_r(shot->shot_key, keybuf) == NULL) { + warn("encountered malformed mac address key\n"); + return (B_FALSE); + } + (void) snprintf(buf, bufsize, "%s", keybuf); + } + break; + case OVERLAY_TARG_DEST: + if (custr_alloc_buf(&cus, buf, bufsize) != 0) { + die("ran out of memory for printing the overlay " + "target destination"); + } + + if (point->dop_dest & OVERLAY_PLUGIN_D_ETHERNET) { + if (ether_ntoa_r(&point->dop_mac, macbuf) == NULL) { + warn("encountered malformed mac address target " + "for key %s\n", keybuf); + return (B_FALSE); + } + (void) custr_append(cus, macbuf); + } + + if (point->dop_dest & OVERLAY_PLUGIN_D_IP) { + if (IN6_IS_ADDR_V4MAPPED(&point->dop_ip)) { + struct in_addr v4; + IN6_V4MAPPED_TO_INADDR(&point->dop_ip, &v4); + if (inet_ntop(AF_INET, &v4, ipbuf, + sizeof (ipbuf)) == NULL) + abort(); + } else if (inet_ntop(AF_INET6, &point->dop_ip, ipbuf, + sizeof (ipbuf)) == NULL) { + /* + * The only failrues we should get are + * EAFNOSUPPORT and ENOSPC because of buffer + * exhaustion. In either of these cases, that + * means something has gone horribly wrong. + */ + abort(); + } + if (point->dop_dest & OVERLAY_PLUGIN_D_ETHERNET) + (void) custr_appendc(cus, ','); + (void) custr_append(cus, ipbuf); + } + + if (point->dop_dest & OVERLAY_PLUGIN_D_PORT) { + if (point->dop_dest & OVERLAY_PLUGIN_D_IP) + (void) custr_appendc(cus, ':'); + else if (point->dop_dest & OVERLAY_PLUGIN_D_ETHERNET) + (void) custr_appendc(cus, ','); + (void) custr_append_printf(cus, "%u", point->dop_port); + } + + custr_free(cus); + + break; + } + return (B_TRUE); +} + +/* ARGSUSED */ +static int +show_one_overlay_table_entry(dladm_handle_t handle, datalink_id_t linkid, + const struct ether_addr *key, const dladm_overlay_point_t *point, void *arg) +{ + showoverlay_targ_state_t *shot = arg; + + shot->shot_key = key; + shot->shot_point = point; + ofmt_print(shot->shot_ofmt, shot); + + return (DLADM_WALK_CONTINUE); +} + +/* ARGSUSED */ +static int +show_one_overlay_table(dladm_handle_t handle, datalink_id_t linkid, void *arg) +{ + char linkbuf[MAXLINKNAMELEN]; + showoverlay_targ_state_t shot; + datalink_class_t class; + + if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, linkbuf, + MAXLINKNAMELEN) != DLADM_STATUS_OK || + class != DATALINK_CLASS_OVERLAY) + return (DLADM_WALK_CONTINUE); + + shot.shot_ofmt = arg; + shot.shot_linkname = linkbuf; + + (void) dladm_overlay_walk_cache(handle, linkid, + show_one_overlay_table_entry, &shot); + + return (DLADM_WALK_CONTINUE); +} + +static boolean_t +print_overlay_fma_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) +{ + showoverlay_fma_state_t *shof = ofarg->ofmt_cbarg; + dladm_overlay_status_t *st = shof->shof_status; + + switch (ofarg->ofmt_id) { + case OVERLAY_FMA_LINK: + (void) snprintf(buf, bufsize, "%s", shof->shof_linkname); + break; + case OVERLAY_FMA_STATUS: + (void) snprintf(buf, bufsize, st->dos_degraded == B_TRUE ? + "DEGRADED": "ONLINE"); + break; + case OVERLAY_FMA_DETAILS: + (void) snprintf(buf, bufsize, "%s", st->dos_degraded == B_TRUE ? + st->dos_fmamsg : "-"); + break; + default: + abort(); + } + return (B_TRUE); +} + +/* ARGSUSED */ +static void +show_one_overlay_fma_cb(dladm_handle_t handle, datalink_id_t linkid, + dladm_overlay_status_t *stat, void *arg) +{ + showoverlay_fma_state_t *shof = arg; + shof->shof_status = stat; + ofmt_print(shof->shof_ofmt, shof); +} + + +static int +show_one_overlay_fma(dladm_handle_t handle, datalink_id_t linkid, void *arg) +{ + dladm_status_t status; + char linkbuf[MAXLINKNAMELEN]; + datalink_class_t class; + showoverlay_fma_state_t shof; + + if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, linkbuf, + MAXLINKNAMELEN) != DLADM_STATUS_OK || + class != DATALINK_CLASS_OVERLAY) { + die("datalink %s is not an overlay device\n", linkbuf); + } + + shof.shof_ofmt = arg; + shof.shof_linkname = linkbuf; + + status = dladm_overlay_status(handle, linkid, + show_one_overlay_fma_cb, &shof); + if (status != DLADM_STATUS_OK) + die_dlerr(status, "failed to obtain device status for %s", + linkbuf); + + return (DLADM_WALK_CONTINUE); +} + +static void +do_show_overlay(int argc, char *argv[], const char *use) +{ + int i, opt; + datalink_id_t linkid = DATALINK_ALL_LINKID; + dladm_status_t status; + int (*funcp)(dladm_handle_t, datalink_id_t, void *); + char *fields_str = NULL; + const ofmt_field_t *fieldsp; + ofmt_status_t oferr; + boolean_t parse; + ofmt_handle_t ofmt; + uint_t ofmtflags; + int err; + + + funcp = show_one_overlay; + fieldsp = overlay_fields; + parse = B_FALSE; + ofmtflags = OFMT_WRAP; + while ((opt = getopt_long(argc, argv, ":o:pft", overlay_show_lopts, + NULL)) != -1) { + switch (opt) { + case 'f': + funcp = show_one_overlay_fma; + fieldsp = overlay_fma_fields; + break; + case 'o': + fields_str = optarg; + break; + case 'p': + parse = B_TRUE; + ofmtflags = OFMT_PARSABLE; + break; + case 't': + funcp = show_one_overlay_table; + fieldsp = overlay_targ_fields; + break; + default: + die_opterr(optopt, opt, use); + } + } + + if (fields_str != NULL && strcasecmp(fields_str, "all") == 0) + fields_str = NULL; + + oferr = ofmt_open(fields_str, fieldsp, ofmtflags, 0, &ofmt); + dladm_ofmt_check(oferr, parse, ofmt); + + err = 0; + if (argc > optind) { + for (i = optind; i < argc; i++) { + status = dladm_name2info(handle, argv[i], &linkid, + NULL, NULL, NULL); + if (status != DLADM_STATUS_OK) { + warn_dlerr(status, "failed to find %s", + argv[i]); + err = 1; + continue; + } + funcp(handle, linkid, ofmt); + } + } else { + (void) dladm_walk_datalink_id(funcp, handle, ofmt, + DATALINK_CLASS_OVERLAY, DATALINK_ANY_MEDIATYPE, + DLADM_OPT_ACTIVE); + } + ofmt_close(ofmt); + + exit(err); +} + +static void +do_modify_overlay(int argc, char *argv[], const char *use) +{ + int opt, ocnt = 0; + boolean_t flush, set, delete; + struct ether_addr e; + char *dest; + datalink_id_t linkid = DATALINK_ALL_LINKID; + dladm_status_t status; + + flush = set = delete = B_FALSE; + while ((opt = getopt_long(argc, argv, ":fd:s:", overlay_modify_lopts, + NULL)) != -1) { + switch (opt) { + case 'd': + if (delete == B_TRUE) + die_optdup('d'); + delete = B_TRUE; + ocnt++; + if (ether_aton_r(optarg, &e) == NULL) + die("invalid mac address: %s\n", optarg); + break; + case 'f': + if (flush == B_TRUE) + die_optdup('f'); + flush = B_TRUE; + ocnt++; + break; + case 's': + if (set == B_TRUE) + die_optdup('s'); + set = B_TRUE; + ocnt++; + dest = strchr(optarg, '='); + *dest = '\0'; + dest++; + if (dest == NULL) + die("malformed value, expected mac=dest, " + "got: %s\n", optarg); + if (ether_aton_r(optarg, &e) == NULL) + die("invalid mac address: %s\n", optarg); + break; + default: + die_opterr(optopt, opt, use); + } + } + + if (ocnt == 0) + die("need to specify one of -d, -f, or -s"); + if (ocnt > 1) + die("only one of -d, -f, or -s may be used"); + + if (argv[optind] == NULL) + die("missing required overlay device\n"); + if (argc > optind + 1) + die("only one overlay device may be specified\n"); + + status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, + NULL); + if (status != DLADM_STATUS_OK) { + die_dlerr(status, "failed to find overlay %s", argv[optind]); + } + + if (flush == B_TRUE) { + status = dladm_overlay_cache_flush(handle, linkid); + if (status != DLADM_STATUS_OK) + die_dlerr(status, "failed to flush target cache for " + "overlay %s", argv[optind]); + } + + if (delete == B_TRUE) { + status = dladm_overlay_cache_delete(handle, linkid, &e); + if (status != DLADM_STATUS_OK) + die_dlerr(status, "failed to flush target %s from " + "overlay target cache %s", optarg, argv[optind]); + } + + if (set == B_TRUE) { + status = dladm_overlay_cache_set(handle, linkid, &e, dest); + if (status != DLADM_STATUS_OK) + die_dlerr(status, "failed to set target %s for overlay " + "target cache %s", optarg, argv[optind]); + } + +} diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_db.c b/usr/src/cmd/dlmgmtd/dlmgmt_db.c index 99307dbc03..8eecc807e5 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_db.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_db.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent Inc. */ #include <assert.h> @@ -43,6 +44,8 @@ #include <libcontract.h> #include <libcontract_priv.h> #include <sys/contract/process.h> +#include <sys/vnic.h> +#include <zone.h> #include "dlmgmt_impl.h" typedef enum dlmgmt_db_op { @@ -552,6 +555,10 @@ dlmgmt_db_update(dlmgmt_db_op_t op, const char *entryname, dlmgmt_link_t *linkp, linkp->ll_zoneid, flags, &err)) == NULL) return (err); + /* If transient op and onloan, use the global zone cache file. */ + if (flags == DLMGMT_ACTIVE && linkp->ll_onloan) + req->ls_zoneid = GLOBAL_ZONEID; + /* * If the return error is EINPROGRESS, this request is handled * asynchronously; return success. @@ -714,11 +721,13 @@ parse_linkprops(char *buf, dlmgmt_link_t *linkp) char attr_name[MAXLINKATTRLEN]; size_t attr_buf_len = 0; void *attr_buf = NULL; + boolean_t rename; curr = buf; len = strlen(buf); attr_name[0] = '\0'; for (i = 0; i < len; i++) { + rename = B_FALSE; char c = buf[i]; boolean_t match = (c == '=' || (c == ',' && !found_type) || c == ';'); @@ -768,6 +777,21 @@ parse_linkprops(char *buf, dlmgmt_link_t *linkp) goto parse_fail; linkp->ll_media = (uint32_t)*(int64_t *)attr_buf; + } else if (strcmp(attr_name, "zone") == 0) { + if (read_str(curr, &attr_buf) == 0) + goto parse_fail; + linkp->ll_zoneid = getzoneidbyname(attr_buf); + if (linkp->ll_zoneid == -1) { + if (errno == EFAULT) + abort(); + /* + * If we can't find the zone, assign the + * link to the GZ and mark it for being + * renamed. + */ + linkp->ll_zoneid = 0; + rename = B_TRUE; + } } else { attr_buf_len = translators[type].read_func(curr, &attr_buf); @@ -811,6 +835,16 @@ parse_linkprops(char *buf, dlmgmt_link_t *linkp) (void) snprintf(attr_name, MAXLINKATTRLEN, "%s", curr); } + + /* + * The zone that this link belongs to has died, we are + * reparenting it to the GZ and renaming it to avoid name + * collisions. + */ + if (rename == B_TRUE) { + (void) snprintf(linkp->ll_link, MAXLINKNAMELEN, + "SUNWorphan%u", (uint16_t)(gethrtime() / 1000)); + } curr = buf + i + 1; } @@ -1222,12 +1256,19 @@ generate_link_line(dlmgmt_link_t *linkp, boolean_t persist, char *buf) ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", linkp->ll_link); if (!persist) { + char zname[ZONENAME_MAX]; /* - * We store the linkid in the active database so that dlmgmtd - * can recover in the event that it is restarted. + * We store the linkid and the zone name in the active database + * so that dlmgmtd can recover in the event that it is + * restarted. */ u64 = linkp->ll_linkid; ptr += write_uint64(ptr, BUFLEN(lim, ptr), "linkid", &u64); + + if (getzonenamebyid(linkp->ll_zoneid, zname, + sizeof (zname)) != -1) { + ptr += write_str(ptr, BUFLEN(lim, ptr), "zone", zname); + } } u64 = linkp->ll_class; ptr += write_uint64(ptr, BUFLEN(lim, ptr), "class", &u64); @@ -1382,38 +1423,88 @@ dlmgmt_db_walk(zoneid_t zoneid, datalink_class_t class, db_walk_func_t *func) } /* + * Attempt to mitigate one of the deadlocks in the dlmgmtd architecture. + * + * dlmgmt_db_init() calls dlmgmt_process_db_req() which eventually gets to + * dlmgmt_zfop() which tries to fork, enter the zone and read the file. + * Because of the upcall architecture of dlmgmtd this can lead to deadlock + * with the following scenario: + * a) the thread preparing to fork will have acquired the malloc locks + * then attempt to suspend every thread in preparation to fork. + * b) all of the upcalls will be blocked in door_ucred() trying to malloc() + * and get the credentials of their caller. + * c) we can't suspend the in-kernel thread making the upcall. + * + * Thus, we cannot serve door requests because we're blocked in malloc() + * which fork() owns, but fork() is in turn blocked on the in-kernel thread + * making the door upcall. This is a fundamental architectural problem with + * any server handling upcalls and also trying to fork(). + * + * To minimize the chance of this deadlock occuring, we check ahead of time to + * see if the file we want to read actually exists in the zone (which it almost + * never does), so we don't need fork in that case (i.e. rarely to never). + */ +static boolean_t +zone_file_exists(char *zoneroot, char *filename) +{ + struct stat sb; + char fname[MAXPATHLEN]; + + (void) snprintf(fname, sizeof (fname), "%s/%s", zoneroot, filename); + + if (stat(fname, &sb) == -1) + return (B_FALSE); + + return (B_TRUE); +} + +/* * Initialize the datalink <link name, linkid> mapping and the link's * attributes list based on the configuration file /etc/dladm/datalink.conf * and the active configuration cache file * /etc/svc/volatile/dladm/datalink-management:default.cache. */ int -dlmgmt_db_init(zoneid_t zoneid) +dlmgmt_db_init(zoneid_t zoneid, char *zoneroot) { dlmgmt_db_req_t *req; int err; boolean_t boot = B_FALSE; + char tdir[MAXPATHLEN]; + char *path = cachefile; if ((req = dlmgmt_db_req_alloc(DLMGMT_DB_OP_READ, NULL, DATALINK_INVALID_LINKID, zoneid, DLMGMT_ACTIVE, &err)) == NULL) return (err); - if ((err = dlmgmt_process_db_req(req)) != 0) { - /* - * If we get back ENOENT, that means that the active - * configuration file doesn't exist yet, and is not an error. - * We'll create it down below after we've loaded the - * persistent configuration. - */ - if (err != ENOENT) - goto done; + /* Handle running in a non-native branded zone (i.e. has /native) */ + if (zone_file_exists(zoneroot, "/native" DLMGMT_TMPFS_DIR)) { + (void) snprintf(tdir, sizeof (tdir), "/native%s", cachefile); + path = tdir; + } + + if (zone_file_exists(zoneroot, path)) { + if ((err = dlmgmt_process_db_req(req)) != 0) { + /* + * If we get back ENOENT, that means that the active + * configuration file doesn't exist yet, and is not an + * error. We'll create it down below after we've + * loaded the persistent configuration. + */ + if (err != ENOENT) + goto done; + boot = B_TRUE; + } + } else { boot = B_TRUE; } - req->ls_flags = DLMGMT_PERSIST; - err = dlmgmt_process_db_req(req); - if (err != 0 && err != ENOENT) - goto done; + if (zone_file_exists(zoneroot, DLMGMT_PERSISTENT_DB_PATH)) { + req->ls_flags = DLMGMT_PERSIST; + err = dlmgmt_process_db_req(req); + if (err != 0 && err != ENOENT) + goto done; + } err = 0; if (rewrite_needed) { /* @@ -1442,6 +1533,11 @@ done: /* * Remove all links in the given zoneid. + * + * We do this work in two different passes. In the first pass, we remove any + * entry that hasn't been loaned and mark every entry that has been loaned as + * something that is going to be tombstomed. In the second pass, we drop the + * table lock for every entry and remove the tombstombed entry for our zone. */ void dlmgmt_db_fini(zoneid_t zoneid) @@ -1451,9 +1547,66 @@ dlmgmt_db_fini(zoneid_t zoneid) while (linkp != NULL) { next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); if (linkp->ll_zoneid == zoneid) { - (void) dlmgmt_destroy_common(linkp, - DLMGMT_ACTIVE | DLMGMT_PERSIST); + boolean_t onloan = linkp->ll_onloan; + + /* + * Cleanup any VNICs that were loaned to the zone + * before the zone goes away and we can no longer + * refer to the VNIC by the name/zoneid. + */ + if (onloan) { + (void) dlmgmt_delete_db_entry(linkp, + DLMGMT_ACTIVE); + linkp->ll_tomb = B_TRUE; + } else { + (void) dlmgmt_destroy_common(linkp, + DLMGMT_ACTIVE | DLMGMT_PERSIST); + } + } linkp = next_linkp; } + +again: + linkp = avl_first(&dlmgmt_name_avl); + while (linkp != NULL) { + vnic_ioc_delete_t ioc; + + next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); + + if (linkp->ll_zoneid != zoneid) { + linkp = next_linkp; + continue; + } + ioc.vd_vnic_id = linkp->ll_linkid; + if (linkp->ll_tomb != B_TRUE) + abort(); + + /* + * We have to drop the table lock while going up into the + * kernel. If we hold the table lock while deleting a vnic, we + * may get blocked on the mac perimeter and the holder of it may + * want something from dlmgmtd. + */ + dlmgmt_table_unlock(); + + if (ioctl(dladm_dld_fd(dld_handle), + VNIC_IOC_DELETE, &ioc) < 0) + dlmgmt_log(LOG_WARNING, "dlmgmt_db_fini " + "delete VNIC ioctl failed %d %d", + ioc.vd_vnic_id, errno); + + /* + * Even though we've dropped the lock, we know that nothing else + * could have removed us. Therefore, it should be safe to go + * through and delete ourselves, but do nothing else. We'll have + * to restart iteration from the beginning. This can be painful. + */ + dlmgmt_table_lock(B_TRUE); + + (void) dlmgmt_destroy_common(linkp, + DLMGMT_ACTIVE | DLMGMT_PERSIST); + goto again; + } + } diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_door.c b/usr/src/cmd/dlmgmtd/dlmgmt_door.c index 11e4329669..137c2a6fb3 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_door.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_door.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -58,6 +59,10 @@ #include <libsysevent.h> #include <libdlmgmt.h> #include <librcm.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> #include "dlmgmt_impl.h" typedef void dlmgmt_door_handler_t(void *, void *, size_t *, zoneid_t, @@ -379,6 +384,11 @@ dlmgmt_upcall_destroy(void *argp, void *retp, size_t *sz, zoneid_t zoneid, if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0) goto done; + if (linkp->ll_tomb == B_TRUE) { + err = EINPROGRESS; + goto done; + } + if (((linkp->ll_flags & flags) & DLMGMT_ACTIVE) != 0) { if ((err = dlmgmt_delete_db_entry(linkp, DLMGMT_ACTIVE)) != 0) goto done; @@ -439,6 +449,10 @@ dlmgmt_getlinkid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, dlmgmt_link_t *linkp; int err = 0; + /* Enable the global zone to lookup links it has given away. */ + if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1) + zoneid = getlinkid->ld_zoneid; + /* * Hold the reader lock to access the link */ @@ -648,6 +662,12 @@ dlmgmt_remapid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0) goto done; + if (linkp->ll_tomb == B_TRUE) { + err = EBUSY; + goto done; + } + + if (link_by_name(remapid->ld_link, linkp->ll_zoneid) != NULL) { err = EEXIST; goto done; @@ -709,6 +729,11 @@ dlmgmt_upid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0) goto done; + if (linkp->ll_tomb == B_TRUE) { + err = EBUSY; + goto done; + } + if (linkp->ll_flags & DLMGMT_ACTIVE) { err = EINVAL; goto done; @@ -1216,6 +1241,11 @@ dlmgmt_setzoneid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0) goto done; + if (linkp->ll_tomb == B_TRUE) { + err = EBUSY; + goto done; + } + /* We can only assign an active link to a zone. */ if (!(linkp->ll_flags & DLMGMT_ACTIVE)) { err = EINVAL; @@ -1245,7 +1275,19 @@ dlmgmt_setzoneid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, "zone %d: %s", linkid, oldzoneid, strerror(err)); goto done; } - avl_remove(&dlmgmt_loan_avl, linkp); + + if (newzoneid == GLOBAL_ZONEID && linkp->ll_onloan) { + /* + * We can only reassign a loaned VNIC back to the + * global zone when the zone is shutting down, since + * otherwise the VNIC is in use by the zone and will be + * busy. Leave the VNIC assigned to the zone so we can + * still see it and delete it when dlmgmt_zonehalt() + * runs. + */ + goto done; + } + linkp->ll_onloan = B_FALSE; } if (newzoneid != GLOBAL_ZONEID) { @@ -1256,7 +1298,6 @@ dlmgmt_setzoneid(void *argp, void *retp, size_t *sz, zoneid_t zoneid, (void) zone_add_datalink(oldzoneid, linkid); goto done; } - avl_add(&dlmgmt_loan_avl, linkp); linkp->ll_onloan = B_TRUE; } @@ -1309,6 +1350,10 @@ dlmgmt_zonehalt(void *argp, void *retp, size_t *sz, zoneid_t zoneid, int err = 0; dlmgmt_door_zonehalt_t *zonehalt = argp; dlmgmt_zonehalt_retval_t *retvalp = retp; + static char my_pid[10]; + + if (my_pid[0] == NULL) + (void) snprintf(my_pid, sizeof (my_pid), "%d\n", getpid()); if ((err = dlmgmt_checkprivs(0, cred)) == 0) { if (zoneid != GLOBAL_ZONEID) { @@ -1316,9 +1361,26 @@ dlmgmt_zonehalt(void *argp, void *retp, size_t *sz, zoneid_t zoneid, } else if (zonehalt->ld_zoneid == GLOBAL_ZONEID) { err = EINVAL; } else { + /* + * dls and mac don't honor the locking rules defined in + * mac. In order to try and make that case less likely + * to happen, we try to serialize some of the zone + * activity here between dlmgmtd and the brands on + * /etc/dladm/zone.lck + */ + int fd; + + while ((fd = open(ZONE_LOCK, O_WRONLY | + O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0) + (void) sleep(1); + (void) write(fd, my_pid, sizeof (my_pid)); + (void) close(fd); + dlmgmt_table_lock(B_TRUE); dlmgmt_db_fini(zonehalt->ld_zoneid); dlmgmt_table_unlock(); + + (void) unlink(ZONE_LOCK); } } retvalp->lr_err = err; diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_impl.h b/usr/src/cmd/dlmgmtd/dlmgmt_impl.h index cdfd0d8a4d..dde27ef66e 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_impl.h +++ b/usr/src/cmd/dlmgmtd/dlmgmt_impl.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -67,6 +68,7 @@ typedef struct dlmgmt_link_s { avl_node_t ll_loan_node; uint32_t ll_flags; uint32_t ll_gen; /* generation number */ + boolean_t ll_tomb; /* tombstombed */ } dlmgmt_link_t; /* @@ -84,6 +86,8 @@ typedef struct dlmgmt_dlconf_s { avl_node_t ld_node; } dlmgmt_dlconf_t; +#define ZONE_LOCK "/etc/dladm/zone.lck" + extern boolean_t debug; extern const char *progname; extern char cachefile[]; @@ -138,7 +142,7 @@ void dlmgmt_handler(void *, char *, size_t, door_desc_t *, uint_t); void dlmgmt_log(int, const char *, ...); int dlmgmt_write_db_entry(const char *, dlmgmt_link_t *, uint32_t); int dlmgmt_delete_db_entry(dlmgmt_link_t *, uint32_t); -int dlmgmt_db_init(zoneid_t); +int dlmgmt_db_init(zoneid_t, char *); void dlmgmt_db_fini(zoneid_t); #ifdef __cplusplus diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_main.c b/usr/src/cmd/dlmgmtd/dlmgmt_main.c index c02610bb5f..d8397cc0e6 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_main.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_main.c @@ -22,6 +22,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2014 Joyent, Inc. All rights reserved. */ /* @@ -125,15 +126,24 @@ dlmgmt_door_fini(void) dlmgmt_door_fd = -1; } -int +static int dlmgmt_door_attach(zoneid_t zoneid, char *rootdir) { int fd; int err = 0; char doorpath[MAXPATHLEN]; + struct stat statbuf; - (void) snprintf(doorpath, sizeof (doorpath), "%s%s", rootdir, - DLMGMT_DOOR); + /* Handle running in a non-native branded zone (i.e. has /native) */ + (void) snprintf(doorpath, sizeof (doorpath), "%s/native%s", + rootdir, DLMGMT_TMPFS_DIR); + if (stat(doorpath, &statbuf) == 0) { + (void) snprintf(doorpath, sizeof (doorpath), "%s/native%s", + rootdir, DLMGMT_DOOR); + } else { + (void) snprintf(doorpath, sizeof (doorpath), "%s%s", + rootdir, DLMGMT_DOOR); + } /* * Create the door file for dlmgmtd. @@ -192,8 +202,16 @@ dlmgmt_zone_init(zoneid_t zoneid) (void) snprintf(tmpfsdir, sizeof (tmpfsdir), "%s%s", rootdir, DLMGMT_TMPFS_DIR); if (stat(tmpfsdir, &statbuf) < 0) { - if (mkdir(tmpfsdir, (mode_t)0755) < 0) - return (errno); + if (mkdir(tmpfsdir, (mode_t)0755) < 0) { + /* + * Handle running in a non-native branded zone + * (i.e. has /native) + */ + (void) snprintf(tmpfsdir, sizeof (tmpfsdir), + "%s/native%s", rootdir, DLMGMT_TMPFS_DIR); + if (mkdir(tmpfsdir, (mode_t)0755) < 0) + return (errno); + } } else if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { return (ENOTDIR); } @@ -203,7 +221,7 @@ dlmgmt_zone_init(zoneid_t zoneid) return (EPERM); } - if ((err = dlmgmt_db_init(zoneid)) != 0) + if ((err = dlmgmt_db_init(zoneid, rootdir)) != 0) return (err); return (dlmgmt_door_attach(zoneid, rootdir)); } @@ -214,7 +232,7 @@ dlmgmt_zone_init(zoneid_t zoneid) static int dlmgmt_allzones_init(void) { - int err, i; + int i; zoneid_t *zids = NULL; uint_t nzids, nzids_saved; @@ -235,11 +253,37 @@ again: } for (i = 0; i < nzids; i++) { - if ((err = dlmgmt_zone_init(zids[i])) != 0) - break; + int res; + zone_status_t status; + + /* + * Skip over zones that have gone away or are going down + * since we got the list. Process all zones in the list, + * logging errors for any that failed. + */ + if (zone_getattr(zids[i], ZONE_ATTR_STATUS, &status, + sizeof (status)) < 0) + continue; + switch (status) { + case ZONE_IS_SHUTTING_DOWN: + case ZONE_IS_EMPTY: + case ZONE_IS_DOWN: + case ZONE_IS_DYING: + case ZONE_IS_DEAD: + /* FALLTHRU */ + continue; + default: + break; + } + if ((res = dlmgmt_zone_init(zids[i])) != 0) { + (void) fprintf(stderr, "zone (%ld) init error %s", + zids[i], strerror(res)); + dlmgmt_log(LOG_ERR, "zone (%d) init error %s", + zids[i], strerror(res)); + } } free(zids); - return (err); + return (0); } static int @@ -262,6 +306,8 @@ dlmgmt_init(void) return (err); } + (void) unlink(ZONE_LOCK); + /* * First derive the name of the cache file from the FMRI name. This * cache name is used to keep active datalink configuration. diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_util.c b/usr/src/cmd/dlmgmtd/dlmgmt_util.c index afcfbed37b..7493ee3577 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_util.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_util.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -45,13 +46,10 @@ /* * There are three datalink AVL tables. The dlmgmt_name_avl tree contains all * datalinks and is keyed by zoneid and link name. The dlmgmt_id_avl also - * contains all datalinks, and it is keyed by link ID. The dlmgmt_loan_avl is - * keyed by link name, and contains the set of global-zone links that are - * currently on loan to non-global zones. + * contains all datalinks, and it is keyed by link ID. */ avl_tree_t dlmgmt_name_avl; avl_tree_t dlmgmt_id_avl; -avl_tree_t dlmgmt_loan_avl; avl_tree_t dlmgmt_dlconf_avl; @@ -162,8 +160,6 @@ dlmgmt_linktable_init(void) offsetof(dlmgmt_link_t, ll_name_node)); avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t), offsetof(dlmgmt_link_t, ll_id_node)); - avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t), - offsetof(dlmgmt_link_t, ll_loan_node)); avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id, sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node)); dlmgmt_nextlinkid = 1; @@ -181,7 +177,6 @@ dlmgmt_linktable_fini(void) avl_destroy(&dlmgmt_dlconf_avl); avl_destroy(&dlmgmt_name_avl); - avl_destroy(&dlmgmt_loan_avl); avl_destroy(&dlmgmt_id_avl); } @@ -385,7 +380,6 @@ link_activate(dlmgmt_link_t *linkp) linkp->ll_zoneid = zoneid; avl_add(&dlmgmt_name_avl, linkp); - avl_add(&dlmgmt_loan_avl, linkp); linkp->ll_onloan = B_TRUE; } } else if (linkp->ll_zoneid != GLOBAL_ZONEID) { @@ -430,10 +424,6 @@ link_by_name(const char *name, zoneid_t zoneid) (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); link.ll_zoneid = zoneid; linkp = avl_find(&dlmgmt_name_avl, &link, NULL); - if (linkp == NULL && zoneid == GLOBAL_ZONEID) { - /* The link could be on loan to a non-global zone? */ - linkp = avl_find(&dlmgmt_loan_avl, &link, NULL); - } return (linkp); } @@ -461,6 +451,7 @@ dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media, linkp->ll_linkid = dlmgmt_nextlinkid; linkp->ll_zoneid = zoneid; linkp->ll_gen = 0; + linkp->ll_tomb = B_FALSE; if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL || avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) { @@ -511,8 +502,6 @@ dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags) if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) { (void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid); - if (linkp->ll_onloan) - avl_remove(&dlmgmt_loan_avl, linkp); } if (linkp->ll_flags == 0) { diff --git a/usr/src/cmd/dlmgmtd/svc-dlmgmtd b/usr/src/cmd/dlmgmtd/svc-dlmgmtd index 7559207535..a75e71f9b3 100644 --- a/usr/src/cmd/dlmgmtd/svc-dlmgmtd +++ b/usr/src/cmd/dlmgmtd/svc-dlmgmtd @@ -23,17 +23,16 @@ # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2012 Joyent, Inc. All rights reserved. # -# ident "%Z%%M% %I% %E% SMI" . /lib/svc/share/smf_include.sh -# The real daemon is not started in a non-global zone. But we need to -# create a dummy background process to preserve contract lifetime. +# The real daemon is not started in a non-global zone. Exit to leave +# an empty contract. if smf_is_nonglobalzone; then - (while true ; do sleep 3600 ; done) & - exit $SMF_EXIT_OK + exit $SMF_EXIT_NODAEMON fi # Start the dlmgmtd daemon. diff --git a/usr/src/cmd/dlstat/dlstat.c b/usr/src/cmd/dlstat/dlstat.c index a931ba82ff..2615fdbb12 100644 --- a/usr/src/cmd/dlstat/dlstat.c +++ b/usr/src/cmd/dlstat/dlstat.c @@ -62,7 +62,7 @@ typedef struct link_chain_s { struct link_chain_s *lc_next; } link_chain_t; -typedef void * (*stats2str_t)(const char *, void *, +typedef void * (*stats2str_t)(const char *, const char *, void *, char, boolean_t); typedef struct show_state { @@ -141,6 +141,7 @@ typedef struct total_fields_buf_s { char t_rbytes[MAXSTATLEN]; char t_opackets[MAXSTATLEN]; char t_obytes[MAXSTATLEN]; + char t_zone[ZONENAME_MAX]; } total_fields_buf_t; static ofmt_field_t total_s_fields[] = { @@ -154,6 +155,8 @@ static ofmt_field_t total_s_fields[] = { offsetof(total_fields_buf_t, t_opackets), print_default_cb}, { "OBYTES", 8, offsetof(total_fields_buf_t, t_obytes), print_default_cb}, +{ "ZONE", 20, + offsetof(total_fields_buf_t, t_zone), print_default_cb}, { NULL, 0, 0, NULL}}; /* @@ -957,8 +960,8 @@ cleanup_removed_links(show_state_t *state) } void * -print_total_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_total_stats(const char *linkname, const char *zonename, void *statentry, + char unit, boolean_t parsable) { total_stat_entry_t *sentry = statentry; total_stat_t *link_stats = &sentry->tse_stats; @@ -970,6 +973,7 @@ print_total_stats(const char *linkname, void *statentry, char unit, (void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s", linkname); + (void) snprintf(buf->t_zone, sizeof (buf->t_zone), "%s", zonename); map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets), link_stats->ts_ipackets, unit, parsable); @@ -988,8 +992,8 @@ done: } void * -print_rx_generic_ring_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_rx_generic_ring_stats(const char *linkname, const char *zonename, + void *statentry, char unit, boolean_t parsable) { ring_stat_entry_t *sentry = statentry; ring_stat_t *link_stats = &sentry->re_stats; @@ -1022,8 +1026,8 @@ done: } void * -print_tx_generic_ring_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_tx_generic_ring_stats(const char *linkname, const char *zonename, + void *statentry, char unit, boolean_t parsable) { ring_stat_entry_t *sentry = statentry; ring_stat_t *link_stats = &sentry->re_stats; @@ -1056,8 +1060,8 @@ done: } void * -print_rx_ring_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_rx_ring_stats(const char *linkname, const char *zonename, void *statentry, + char unit, boolean_t parsable) { ring_stat_entry_t *sentry = statentry; ring_stat_t *link_stats = &sentry->re_stats; @@ -1090,8 +1094,8 @@ done: } void * -print_tx_ring_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_tx_ring_stats(const char *linkname, const char *zonename, void *statentry, + char unit, boolean_t parsable) { ring_stat_entry_t *sentry = statentry; ring_stat_t *link_stats = &sentry->re_stats; @@ -1124,8 +1128,8 @@ done: } void * -print_rx_generic_lane_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_rx_generic_lane_stats(const char *linkname, const char *zonename, + void *statentry, char unit, boolean_t parsable) { rx_lane_stat_entry_t *sentry = statentry; rx_lane_stat_t *link_stats = &sentry->rle_stats; @@ -1172,8 +1176,8 @@ done: } void * -print_tx_generic_lane_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_tx_generic_lane_stats(const char *linkname, const char *zonename, + void *statentry, char unit, boolean_t parsable) { tx_lane_stat_entry_t *sentry = statentry; tx_lane_stat_t *link_stats = &sentry->tle_stats; @@ -1217,8 +1221,8 @@ done: } void * -print_rx_lane_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_rx_lane_stats(const char *linkname, const char *zonename, void *statentry, + char unit, boolean_t parsable) { rx_lane_stat_entry_t *sentry = statentry; rx_lane_stat_t *link_stats = &sentry->rle_stats; @@ -1283,9 +1287,8 @@ done: } void * -print_tx_lane_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) -{ +print_tx_lane_stats(const char *linkname, const char *zonename, void *statentry, + char unit, boolean_t parsable) { tx_lane_stat_entry_t *sentry = statentry; tx_lane_stat_t *link_stats = &sentry->tle_stats; tx_lane_fields_buf_t *buf = NULL; @@ -1338,8 +1341,8 @@ done: } void * -print_fanout_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_fanout_stats(const char *linkname, const char *zonename, void *statentry, + char unit, boolean_t parsable) { fanout_stat_entry_t *sentry = statentry; fanout_stat_t *link_stats = &sentry->fe_stats; @@ -1392,8 +1395,8 @@ done: } void * -print_aggr_port_stats(const char *linkname, void *statentry, char unit, - boolean_t parsable) +print_aggr_port_stats(const char *linkname, const char *zonename, + void *statentry, char unit, boolean_t parsable) { aggr_port_stat_entry_t *sentry = statentry; aggr_port_stat_t *link_stats = &sentry->ape_stats; @@ -1470,7 +1473,8 @@ done: void walk_dlstat_stats(show_state_t *state, const char *linkname, - dladm_stat_type_t stattype, dladm_stat_chain_t *diff_stat) + const char *zonename, dladm_stat_type_t stattype, + dladm_stat_chain_t *diff_stat) { dladm_stat_chain_t *curr; @@ -1480,7 +1484,8 @@ walk_dlstat_stats(show_state_t *state, const char *linkname, /* Format the raw numbers for printing */ fields_buf = state->ls_stats2str[stattype](linkname, - curr->dc_statentry, state->ls_unit, state->ls_parsable); + zonename, curr->dc_statentry, state->ls_unit, + state->ls_parsable); /* Print the stats */ if (fields_buf != NULL) ofmt_print(state->ls_ofmt, fields_buf); @@ -1495,12 +1500,20 @@ show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) int i; dladm_stat_chain_t *diff_stat; char linkname[DLPI_LINKNAME_MAX]; + char zonename[DLADM_PROP_VAL_MAX + 1]; + char *valptr[1]; + uint_t valcnt = 1; if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname, DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { goto done; } + valptr[0] = zonename; + if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, "zone", + (char **)valptr, &valcnt) != 0) + zonename[0] = '\0'; + for (i = 0; i < DLADM_STAT_NUM_STATS; i++) { if (state->ls_stattype[i]) { /* @@ -1508,7 +1521,8 @@ show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) * Stats are returned as chain of raw numbers */ diff_stat = query_link_stats(handle, linkid, arg, i); - walk_dlstat_stats(state, linkname, i, diff_stat); + walk_dlstat_stats(state, linkname, zonename, i, + diff_stat); dladm_link_stat_free(diff_stat); } } @@ -1628,7 +1642,7 @@ do_show(int argc, char *argv[], const char *use) char *o_fields_str = NULL; char *total_stat_fields = - "link,ipkts,rbytes,opkts,obytes"; + "link,ipkts,rbytes,opkts,obytes,zone"; char *rx_total_stat_fields = "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50"; char *tx_total_stat_fields = diff --git a/usr/src/cmd/dtrace/test/cmd/jdtrace/Makefile b/usr/src/cmd/dtrace/test/cmd/jdtrace/Makefile index 66479e77bc..ee93b7a258 100644 --- a/usr/src/cmd/dtrace/test/cmd/jdtrace/Makefile +++ b/usr/src/cmd/dtrace/test/cmd/jdtrace/Makefile @@ -75,7 +75,7 @@ $(PROG): $(SRCS) $(POST_PROCESS) ; $(STRIP_STABS) JFLAGS= -g -cp $(CLASSPATH) -d $(CLASSDIR) -JFLAGS += -source 1.5 -target 1.6 -Xlint:all,-options +JFLAGS += -source 1.5 -target 1.6 -Xlint:all,-options,-path COMPILE.java=$(JAVAC) $(JFLAGS) JAVASRC= JDTrace.java Getopt.java diff --git a/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl b/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl index d6f1c8c277..e7f9189822 100644 --- a/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl +++ b/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl @@ -566,7 +566,7 @@ $defdir = -d $dt_tst ? $dt_tst : '.'; $bindir = -d $dt_bin ? $dt_bin : '.'; if (!$opt_F) { - my @dependencies = ("gcc", "make", "java", "perl"); + my @dependencies = ("gcc", "cc", "make", "java", "perl", "printenv"); for my $dep (@dependencies) { if (!inpath($dep)) { diff --git a/usr/src/cmd/dtrace/test/tst/common/Makefile b/usr/src/cmd/dtrace/test/tst/common/Makefile index fa3a8b17c0..95ada26513 100644 --- a/usr/src/cmd/dtrace/test/tst/common/Makefile +++ b/usr/src/cmd/dtrace/test/tst/common/Makefile @@ -152,6 +152,14 @@ usdt/tst.forker.o: usdt/forker.h usdt/forker.h: usdt/forker.d $(DTRACE) -h -s usdt/forker.d -o usdt/forker.h +ustack/tst.unpriv.exe: ustack/tst.unpriv.o ustack/unpriv_helper.o + $(LINK.c) -o ustack/tst.unpriv.exe \ + ustack/tst.unpriv.o ustack/unpriv_helper.o $(LDLIBS) + $(POST_PROCESS) ; $(STRIP_STABS) + +ustack/unpriv_helper.o: ustack/unpriv_helper.d + $(COMPILE.d) -o ustack/unpriv_helper.o -s ustack/unpriv_helper.d + usdt/tst.lazyprobe.exe: usdt/tst.lazyprobe.o usdt/lazyprobe.o $(LINK.c) -o usdt/tst.lazyprobe.exe \ usdt/tst.lazyprobe.o usdt/lazyprobe.o $(LDLIBS) diff --git a/usr/src/cmd/dtrace/test/tst/common/java_api/Makefile b/usr/src/cmd/dtrace/test/tst/common/java_api/Makefile index 43daede8e8..04e6cca7b4 100644 --- a/usr/src/cmd/dtrace/test/tst/common/java_api/Makefile +++ b/usr/src/cmd/dtrace/test/tst/common/java_api/Makefile @@ -60,7 +60,7 @@ lint: install: all $(PROTO_TEST_JAR) JFLAGS= -g -cp $(CLASSPATH) -d $(CLASSDIR) -JFLAGS += -source 1.5 -target 1.6 -Xlint:all,-options,-rawtypes +JFLAGS += -source 1.5 -target 1.6 -Xlint:all,-options,-rawtypes,-path COMPILE.java=$(JAVAC) $(JFLAGS) $(TEST_JAR): $(SRCDIR)/*.java diff --git a/usr/src/cmd/dtrace/test/tst/common/llquantize/tst.range.d b/usr/src/cmd/dtrace/test/tst/common/llquantize/tst.range.d index e2882b3f8e..a9138d2f54 100644 --- a/usr/src/cmd/dtrace/test/tst/common/llquantize/tst.range.d +++ b/usr/src/cmd/dtrace/test/tst/common/llquantize/tst.range.d @@ -19,10 +19,6 @@ * CDDL HEADER END */ -/* - * Copyright (c) 2011, Joyent, Inc. All rights reserved. - */ - #pragma D option quiet BEGIN diff --git a/usr/src/cmd/ssh/sftp/Makefile b/usr/src/cmd/dtrace/test/tst/common/mdb/tst.postmort.ksh index 8bd8bb4ac3..c5921b8d28 100644 --- a/usr/src/cmd/ssh/sftp/Makefile +++ b/usr/src/cmd/dtrace/test/tst/common/mdb/tst.postmort.ksh @@ -18,43 +18,52 @@ # # CDDL HEADER END # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/sftp/Makefile - -PROG = sftp -OBJS = \ - sftp.o \ - sftp-client.o \ - sftp-glob.o +# +# Copyright (c) 2011, Joyent, Inc. All rights reserved. +# -SRCS = $(OBJS:.o=.c) +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi -include ../../Makefile.cmd -include ../Makefile.ssh-common +dtrace=$1 +DIR=/var/tmp/dtest.$$ -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto -ltecla +mkdir $DIR +cd $DIR -POFILE_DIR = .. +expected=`od -t u8 -N 8 /dev/urandom | head -1 | cut -d ' ' -f2` -.KEEP_STATE: +$dtrace -x bufpolicy=ring -x bufsize=10k -qs /dev/stdin > /dev/null 2>&1 <<EOF & + tick-1ms + /i < 10000/ + { + printf("%d: expected is $expected!\n", i++); + } -.PARALLEL: $(OBJS) + tick-1ms + /i >= 10000/ + { + exit(0); + } +EOF -all: $(PROG) +background=$! -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) +# +# Give some time for the enabling to get there... +# +sleep 2 -install: all $(ROOTPROG) +echo "::walk dtrace_state | ::dtrace" | mdb -k | tee test.out +grep "expected is $expected" test.out 2> /dev/null 1>&2 +status=$? -clean: - $(RM) -f $(OBJS) $(PROG) +kill $background -lint: lint_SRCS +cd / +/usr/bin/rm -rf $DIR -include ../Makefile.msg.targ -include ../../Makefile.targ +exit $status diff --git a/usr/src/cmd/dtrace/test/tst/common/ustack/tst.unpriv.c b/usr/src/cmd/dtrace/test/tst/common/ustack/tst.unpriv.c new file mode 100644 index 0000000000..43ba244444 --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/ustack/tst.unpriv.c @@ -0,0 +1,7 @@ +int +main(int argc, char *argv[]) +{ + for (;;) + ; + return (0); +} diff --git a/usr/src/cmd/ssh/Makefile.msg.targ b/usr/src/cmd/dtrace/test/tst/common/ustack/tst.unpriv.ksh index df56774c25..26c430bff7 100644 --- a/usr/src/cmd/ssh/Makefile.msg.targ +++ b/usr/src/cmd/dtrace/test/tst/common/ustack/tst.unpriv.ksh @@ -18,22 +18,51 @@ # # CDDL HEADER END # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -POFILE = _messages.po -XGETFLAGS = -o $(POFILE_DIR)/$(POFILE) --foreign-user --strict -j -n -E \ - --width=72 \ - --omit-header \ - --keyword=fatal \ - --keyword=error \ - --keyword=verbose \ - --keyword=packet_send_debug \ - --keyword=packet_disconnect - -$(POFILE): - $(RM) $@ - $(COMPILE.cpp) $(SRCS) > $(POFILE).i.c - $(XGETTEXT) $(XGETFLAGS) $(POFILE).i.c - $(RM) $(POFILE).i.c +# +# Copyright (c) 2011, Joyent, Inc. All rights reserved. +# + +ppriv -s A=basic,dtrace_user,dtrace_proc $$ + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +file=out.$$ +dtrace=$1 + +rm -f $file + +dir=`/bin/dirname $tst` + +$dtrace -o $file -c $dir/tst.unpriv.exe -ws /dev/stdin <<EOF + profile-1234hz + /pid == \$target/ + { + @[ustack(20, 8192)] = count(); + } + + tick-1s + { + secs++; + } + + tick-1s + /secs > 10/ + { + trace("test timed out"); + exit(1); + } + + profile-1234hz + /pid == \$target && secs > 5/ + { + raise(SIGINT); + exit(0); + } +EOF + +status=$? +exit $status diff --git a/usr/src/cmd/dtrace/test/tst/common/ustack/unpriv_helper.d b/usr/src/cmd/dtrace/test/tst/common/ustack/unpriv_helper.d new file mode 100644 index 0000000000..eb7b0e9e9d --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/ustack/unpriv_helper.d @@ -0,0 +1,4 @@ +dtrace:helper:ustack: +{ + this->otherstr = "doogle"; +} diff --git a/usr/src/cmd/flowadm/flowadm.c b/usr/src/cmd/flowadm/flowadm.c index 374fa1675c..34e597dc78 100644 --- a/usr/src/cmd/flowadm/flowadm.c +++ b/usr/src/cmd/flowadm/flowadm.c @@ -21,6 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ #include <stdio.h> @@ -233,9 +234,9 @@ usage(void) (void) fprintf(stderr, gettext("usage: flowadm <subcommand>" " <args>...\n" " add-flow [-t] -l <link> -a <attr>=<value>[,...]\n" - "\t\t [-p <prop>=<value>,...] <flow>\n" - " remove-flow [-t] {-l <link> | <flow>}\n" - " show-flow [-p] [-l <link>] " + "\t\t [-p <prop>=<value>,...] [-z zonename] <flow>\n" + " remove-flow [-t] [-z zonename] {-l <link> | <flow>}\n" + " show-flow [-p] [-l <link>] [-z zonename] " "[<flow>]\n\n" " set-flowprop [-t] -p <prop>=<value>[,...] <flow>\n" " reset-flowprop [-t] [-p <prop>,...] <flow>\n" @@ -333,11 +334,12 @@ do_add_flow(int argc, char *argv[]) dladm_arg_list_t *proplist = NULL; dladm_arg_list_t *attrlist = NULL; dladm_status_t status; + char *zonename = NULL; bzero(propstr, DLADM_STRSIZE); bzero(attrstr, DLADM_STRSIZE); - while ((option = getopt_long(argc, argv, "tR:l:a:p:", + while ((option = getopt_long(argc, argv, "tR:l:a:p:z:", prop_longopts, NULL)) != -1) { switch (option) { case 't': @@ -351,9 +353,6 @@ do_add_flow(int argc, char *argv[]) MAXLINKNAMELEN) >= MAXLINKNAMELEN) { die("link name too long"); } - if (dladm_name2info(handle, devname, &linkid, NULL, - NULL, NULL) != DLADM_STATUS_OK) - die("invalid link '%s'", devname); l_arg = B_TRUE; break; case 'a': @@ -368,6 +367,9 @@ do_add_flow(int argc, char *argv[]) DLADM_STRSIZE) die("property list too long '%s'", propstr); break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option); } @@ -376,6 +378,10 @@ do_add_flow(int argc, char *argv[]) die("link is required"); } + if (dladm_zname2info(handle, zonename, devname, &linkid, NULL, + NULL, NULL) != DLADM_STATUS_OK) + die("invalid link '%s'", devname); + opterr = 0; index = optind; @@ -414,11 +420,12 @@ do_remove_flow(int argc, char *argv[]) boolean_t l_arg = B_FALSE; remove_flow_state_t state; dladm_status_t status; + char *zonename = NULL; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":tR:l:", + while ((option = getopt_long(argc, argv, ":tR:l:z:", longopts, NULL)) != -1) { switch (option) { case 't': @@ -432,12 +439,11 @@ do_remove_flow(int argc, char *argv[]) MAXLINKNAMELEN) >= MAXLINKNAMELEN) { die("link name too long"); } - if (dladm_name2info(handle, linkname, &linkid, NULL, - NULL, NULL) != DLADM_STATUS_OK) { - die("invalid link '%s'", linkname); - } l_arg = B_TRUE; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option); break; @@ -458,6 +464,12 @@ do_remove_flow(int argc, char *argv[]) /* if link is specified then flow name should not be there */ if (optind == argc-1) usage(); + + if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL, + NULL, NULL) != DLADM_STATUS_OK) { + die("invalid link '%s'", linkname); + } + /* walk the link to find flows and remove them */ state.fs_tempop = t_arg; state.fs_altroot = altroot; @@ -597,11 +609,12 @@ do_show_flow(int argc, char *argv[]) ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; + char *zonename = NULL; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":pPl:o:", + while ((option = getopt_long(argc, argv, ":pPl:o:z:", longopts, NULL)) != -1) { switch (option) { case 'p': @@ -622,17 +635,23 @@ do_show_flow(int argc, char *argv[]) if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long\n"); - if (dladm_name2info(handle, linkname, &linkid, NULL, - NULL, NULL) != DLADM_STATUS_OK) - die("invalid link '%s'", linkname); l_arg = B_TRUE; break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option); break; } } + if (l_arg) { + if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL, + NULL, NULL) != DLADM_STATUS_OK) + die("invalid link '%s'", linkname); + } + /* get flow name (optional last argument */ if (optind == (argc-1)) { if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN) diff --git a/usr/src/cmd/flowstat/flowstat.c b/usr/src/cmd/flowstat/flowstat.c index 3ddff9e34f..781ce6b0f0 100644 --- a/usr/src/cmd/flowstat/flowstat.c +++ b/usr/src/cmd/flowstat/flowstat.c @@ -21,6 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ #include <stdio.h> @@ -190,9 +191,9 @@ static char *progname; static dladm_handle_t handle = NULL; const char *usage_ermsg = "flowstat [-r | -t] [-i interval] " - "[-l link] [flow]\n" + "[-l link] [-z zonename] [flow]\n" " flowstat [-S] [-A] [-i interval] [-p] [ -o field[,...]]\n" - " [-u R|K|M|G|T|P] [-l link] [flow]\n" + " [-u R|K|M|G|T|P] [-l link] [-z zonename] [flow]\n" " flowstat -h [-a] [-d] [-F format]" " [-s <DD/MM/YYYY,HH:MM:SS>]\n" " [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> " @@ -556,6 +557,7 @@ main(int argc, char *argv[]) show_flow_state_t state; char *fields_str = NULL; char *o_fields_str = NULL; + char *zonename = NULL; char *total_stat_fields = "flow,ipkts,rbytes,ierrs,opkts,obytes,oerrs"; @@ -582,10 +584,11 @@ main(int argc, char *argv[]) if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) die_dlerr(status, "could not open /dev/dld"); + linkname[0] = '\0'; bzero(&state, sizeof (state)); opterr = 0; - while ((option = getopt_long(argc, argv, ":rtApSi:o:u:l:h", + while ((option = getopt_long(argc, argv, ":rtApSi:o:u:l:hz:", NULL, NULL)) != -1) { switch (option) { case 'r': @@ -642,9 +645,6 @@ main(int argc, char *argv[]) if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long\n"); - if (dladm_name2info(handle, linkname, &linkid, NULL, - NULL, NULL) != DLADM_STATUS_OK) - die("invalid link '%s'", linkname); break; case 'h': if (r_arg || t_arg || p_arg || o_arg || u_arg || @@ -655,6 +655,9 @@ main(int argc, char *argv[]) do_show_history(argc, argv); return (0); break; + case 'z': + zonename = optarg; + break; default: die_opterr(optopt, option, usage_ermsg); break; @@ -683,6 +686,12 @@ main(int argc, char *argv[]) die("the option -A is not compatible with " "-r, -t, -p, -o, -u, -i"); + if (linkname[0] != '\0') { + if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL, + NULL, NULL) != DLADM_STATUS_OK) + die("invalid link '%s'", linkname); + } + /* get flow name (optional last argument) */ if (optind == (argc-1)) { if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN) diff --git a/usr/src/cmd/fs.d/Makefile b/usr/src/cmd/fs.d/Makefile index 8e8faaa643..6cf7642d17 100644 --- a/usr/src/cmd/fs.d/Makefile +++ b/usr/src/cmd/fs.d/Makefile @@ -19,6 +19,7 @@ # CDDL HEADER END # # Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, Joyent, Inc. All rights reserved. # # The filesystem independent utilities clri, fsdb, dcopy, labelit, and mkfs @@ -38,8 +39,8 @@ DEFAULTFILES= fs.dfl include ../Makefile.cmd -SUBDIR1= lofs zfs -SUBDIR2= dev fd pcfs nfs hsfs proc ctfs udfs ufs tmpfs cachefs \ +SUBDIR1= bootfs hyprlofs lofs zfs +SUBDIR2= dev fd pcfs nfs hsfs lxproc proc ctfs udfs ufs tmpfs cachefs \ autofs mntfs objfs sharefs smbclnt reparsed SUBDIRS= $(SUBDIR1) $(SUBDIR2) I18NDIRS= $(SUBDIR2) diff --git a/usr/src/cmd/fs.d/bootfs/Makefile b/usr/src/cmd/fs.d/bootfs/Makefile new file mode 100644 index 0000000000..d0ac4311f4 --- /dev/null +++ b/usr/src/cmd/fs.d/bootfs/Makefile @@ -0,0 +1,21 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +FSTYPE= bootfs +LIBPROG= mount + +include ../Makefile.fstype +include ../Makefile.mount +include ../Makefile.mount.targ diff --git a/usr/src/cmd/fs.d/bootfs/mount.c b/usr/src/cmd/fs.d/bootfs/mount.c new file mode 100644 index 0000000000..5363a4f872 --- /dev/null +++ b/usr/src/cmd/fs.d/bootfs/mount.c @@ -0,0 +1,139 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> +#include <errno.h> +#include <sys/fstyp.h> +#include <sys/fsid.h> +#include <sys/mntent.h> +#include <sys/mnttab.h> +#include <sys/mount.h> +#include <sys/signal.h> +#include <sys/stat.h> +#include <fslib.h> + +#define MNTTYPE_BOOTFS "bootfs" + +static char optbuf[MAX_MNTOPT_STR] = { '\0', }; +static int optsize = 0; + +static void +usage(void) +{ + (void) fprintf(stderr, + "Usage: mount [-Ormq] [-o options] special mountpoint\n"); + exit(2); +} + +/* + * usage: mount [-Ormq] [-o options] special mountp + * + * This mount program is exec'ed by /usr/sbin/mount if '-F bootfs' is + * specified. + */ +int +main(int argc, char *argv[]) +{ + int c; + char *special; /* Entity being mounted */ + char *mountp; /* Entity being mounted on */ + char *savedoptbuf; + char *myname; + char typename[64]; + int flags = 0; + int errflag = 0; + int qflg = 0; + + myname = strrchr(argv[0], '/'); + myname = myname ? myname+1 : argv[0]; + (void) snprintf(typename, sizeof (typename), "%s %s", MNTTYPE_BOOTFS, + myname); + argv[0] = typename; + + while ((c = getopt(argc, argv, "o:rmOq")) != EOF) { + switch (c) { + case '?': + errflag++; + break; + + case 'o': + if (strlcpy(optbuf, optarg, sizeof (optbuf)) >= + sizeof (optbuf)) { + (void) fprintf(stderr, + gettext("%s: Invalid argument: %s\n"), + myname, optarg); + return (2); + } + optsize = strlen(optbuf); + break; + case 'O': + flags |= MS_OVERLAY; + break; + case 'r': + flags |= MS_RDONLY; + break; + + case 'm': + flags |= MS_NOMNTTAB; + break; + + case 'q': + qflg = 1; + break; + + default: + usage(); + } + } + if ((argc - optind != 2) || errflag) { + usage(); + } + special = argv[argc - 2]; + mountp = argv[argc - 1]; + + if ((savedoptbuf = strdup(optbuf)) == NULL) { + (void) fprintf(stderr, gettext("%s: out of memory\n"), + myname); + exit(2); + } + + if (mount(special, mountp, flags | MS_OPTIONSTR, MNTTYPE_BOOTFS, NULL, + 0, optbuf, MAX_MNTOPT_STR)) { + (void) fprintf(stderr, "mount: "); + perror(special); + exit(2); + } + if (optsize && !qflg) { + cmp_requested_to_actual_options(savedoptbuf, optbuf, + special, mountp); + } + + return (0); +} diff --git a/usr/src/cmd/fs.d/hyprlofs/Makefile b/usr/src/cmd/fs.d/hyprlofs/Makefile new file mode 100644 index 0000000000..1a3aaf18d3 --- /dev/null +++ b/usr/src/cmd/fs.d/hyprlofs/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 2012, Joyent, Inc. All rights reserved +# + +SUBDIRS= hlcfg mount + +all:= TARGET= all +install:= TARGET= install +clean:= TARGET= clean +clobber:= TARGET= clobber +lint:= TARGET= lint + +.KEEP_STATE: + +.PARALLEL: $(SUBDIRS) + +all install clean clobber lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/cmd/fs.d/hyprlofs/hlcfg/Makefile b/usr/src/cmd/fs.d/hyprlofs/hlcfg/Makefile new file mode 100644 index 0000000000..d2ae22e9fd --- /dev/null +++ b/usr/src/cmd/fs.d/hyprlofs/hlcfg/Makefile @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2012, Joyent, Inc. All rights reserved. +# + +FSTYPE= hyprlofs +LIBPROG= hlcfg + +include ../../Makefile.fstype +include ../../Makefile.mount +include ../../Makefile.mount.targ diff --git a/usr/src/cmd/fs.d/hyprlofs/hlcfg/hlcfg.c b/usr/src/cmd/fs.d/hyprlofs/hlcfg/hlcfg.c new file mode 100644 index 0000000000..16e8e32b1c --- /dev/null +++ b/usr/src/cmd/fs.d/hyprlofs/hlcfg/hlcfg.c @@ -0,0 +1,244 @@ +/* + * 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 2012, Joyent, Inc. All rights reserved. + */ + +/* + * This is a simple test program to exercise the hyprlofs ioctls. This is + * not designed as a full featured CLI and only does minimal error checking + * and reporting. + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <libgen.h> +#include <strings.h> +#include <sys/errno.h> +#include <sys/fs/hyprlofs.h> + +extern int errno; + +char *usage = "usage: <fs path> add [<file name> <alias>]+\n" + " <fs path> addl [<file name>]+\n" + " <fs path> rm [<alias>]+\n" + " <fs path> clear" + " <fs path> get"; + +typedef enum { + CMD_ADD, + CMD_RM, + CMD_CLR, + CMD_ADDL, + CMD_GET +} cmd_t; + +static int +get_entries(int fd) +{ + int err; + int i; + hyprlofs_curr_entries_t e; + hyprlofs_curr_entry_t *ep; + + e.hce_cnt = 0; + e.hce_entries = NULL; + + err = ioctl(fd, HYPRLOFS_GET_ENTRIES, &e); + if (err != 0 && errno != E2BIG) { + perror("ioctl"); + return (1); + } + + if (err == 0) { + (void) printf("success, but no entries\n"); + return (0); + } + + /* + * E2BIG is what we expect when there are existing mappings + * since the current cnt is still returned in that case. + */ + (void) printf("cnt: %d\n", e.hce_cnt); + + /* alloc array and call again, then print array */ + if ((ep = (hyprlofs_curr_entry_t *) + malloc(sizeof (hyprlofs_curr_entry_t) * e.hce_cnt)) == NULL) { + (void) fprintf(stderr, "out of memory\n"); + exit(1); + } + + e.hce_entries = ep; + errno = 0; + if (ioctl(fd, HYPRLOFS_GET_ENTRIES, &e) != 0) { + /* + * Not handling an increase here. We would need to free and + * start over to do that, but ok for a test program. + */ + perror("ioctl"); + free(ep); + return (1); + } + for (i = 0; i < e.hce_cnt; i++) + (void) printf("%s %s\n", ep[i].hce_path, ep[i].hce_name); + + free(ep); + return (0); +} + +int +main(int argc, char **argv) +{ + int i, ap; + cmd_t cmd; + int cnt = 0; + int fd; + int rv = 0; + hyprlofs_entry_t *e = NULL; + hyprlofs_entries_t ents; + + if (argc < 3) { + (void) fprintf(stderr, "%s\n", usage); + exit(1); + } + + if ((fd = open(argv[1], O_RDONLY)) < 0) { + perror("can't open hyprlofs mount"); + exit(1); + } + + if (strcmp(argv[2], "add") == 0) { + cmd = CMD_ADD; + } else if (strcmp(argv[2], "rm") == 0) { + cmd = CMD_RM; + } else if (strcmp(argv[2], "clear") == 0) { + cmd = CMD_CLR; + } else if (strcmp(argv[2], "addl") == 0) { + cmd = CMD_ADDL; + } else if (strcmp(argv[2], "get") == 0) { + cmd = CMD_GET; + } else { + (void) fprintf(stderr, "%s\n", usage); + exit(1); + } + + /* Count up the number of parameters. The arg format varies w/ cmd */ + switch (cmd) { + case CMD_ADD: + for (i = 3; i < argc; i++) { + /* argv[i] is the file path */ + + /* The next arg is the alias */ + if (++i >= argc) { + (void) fprintf(stderr, "missing alias for %s\n", + argv[i - 1]); + exit(1); + } + + cnt++; + } + break; + case CMD_ADDL: + cnt = argc - 3; + break; + case CMD_RM: + cnt = argc - 3; + break; + case CMD_CLR: /*FALLTHRU*/ + case CMD_GET: + if (argc > 3) { + (void) fprintf(stderr, "%s\n", usage); + exit(1); + } + break; + } + + if (cnt > 0) { + if ((e = (hyprlofs_entry_t *)malloc(sizeof (hyprlofs_entry_t) * + cnt)) == NULL) { + (void) fprintf(stderr, "out of memory\n"); + exit(1); + } + } + + /* + * Format up the args. + * We only setup the path member for the add cmd. + * We won't run this loop for the clear cmd. + * The addl command is special since we use basename to get the alias. + */ + for (i = 0, ap = 3; i < cnt; i++, ap++) { + if (cmd == CMD_ADDL) { + e[i].hle_path = argv[ap]; + e[i].hle_plen = strlen(e[i].hle_path); + + e[i].hle_name = basename(argv[ap]); + e[i].hle_nlen = strlen(e[i].hle_name); + + continue; + } + + if (cmd == CMD_ADD) { + e[i].hle_path = argv[ap++]; + e[i].hle_plen = strlen(e[i].hle_path); + } + + e[i].hle_name = argv[ap]; + e[i].hle_nlen = strlen(e[i].hle_name); + } + + ents.hle_entries = e; + ents.hle_len = cnt; + + switch (cmd) { + case CMD_ADD: /*FALLTHRU*/ + case CMD_ADDL: + if (ioctl(fd, HYPRLOFS_ADD_ENTRIES, &ents) < 0) { + perror("ioctl"); + rv = 1; + } + break; + case CMD_RM: + if (ioctl(fd, HYPRLOFS_RM_ENTRIES, &ents) < 0) { + perror("ioctl"); + rv = 1; + } + break; + case CMD_CLR: + if (ioctl(fd, HYPRLOFS_RM_ALL) < 0) { + perror("ioctl"); + rv = 1; + } + break; + case CMD_GET: + rv = get_entries(fd); + break; + } + + (void) close(fd); + if (cnt > 0) + free(e); + return (rv); +} diff --git a/usr/src/cmd/fs.d/hyprlofs/mount/Makefile b/usr/src/cmd/fs.d/hyprlofs/mount/Makefile new file mode 100644 index 0000000000..a0b63d211c --- /dev/null +++ b/usr/src/cmd/fs.d/hyprlofs/mount/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2012 Joyent, Inc. All rights reserved. +# + +FSTYPE= hyprlofs +LIBPROG= mount + +include ../../Makefile.fstype +include ../../Makefile.mount +include ../../Makefile.mount.targ diff --git a/usr/src/cmd/fs.d/hyprlofs/mount/mount.c b/usr/src/cmd/fs.d/hyprlofs/mount/mount.c new file mode 100644 index 0000000000..a95c9ca3c2 --- /dev/null +++ b/usr/src/cmd/fs.d/hyprlofs/mount/mount.c @@ -0,0 +1,148 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright 2012 Joyent, Inc. All rights reserved. + */ + +#define HLFS +#define MNTTYPE_HYFS "hyprlofs" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> +#include <errno.h> +#include <sys/fstyp.h> +#include <sys/fsid.h> +#include <sys/mntent.h> +#include <sys/mnttab.h> +#include <sys/mount.h> +#include <sys/signal.h> +#include <sys/stat.h> +#include <fslib.h> + +#define RET_OK 0 +/* + * /sbin/mount and the fs-local method understand this exit code to + * mean that all the mount failures were related to hyprlofs mounts. Since + * this program only attempts to mount hyfs file systems, when it fails + * it returns this exit status. + */ +#define RET_ERR 111 + +static void usage(void); + +static char optbuf[MAX_MNTOPT_STR] = { '\0', }; +static int optsize = 0; + +static char fstype[] = MNTTYPE_HYFS; + +/* + * usage: mount [-Ormq] [-o options] special mountp + * + * This mount program is exec'ed by /usr/sbin/mount if '-F hyprlofs' is + * specified. + */ +int +main(int argc, char *argv[]) +{ + int c; + char *special; /* Entity being mounted */ + char *mountp; /* Entity being mounted on */ + char *savedoptbuf; + char *myname; + char typename[64]; + int flags = 0; + int errflag = 0; + int qflg = 0; + + myname = strrchr(argv[0], '/'); + myname = myname ? myname+1 : argv[0]; + (void) snprintf(typename, sizeof (typename), "%s %s", fstype, myname); + argv[0] = typename; + + while ((c = getopt(argc, argv, "o:rmOq")) != EOF) { + switch (c) { + case '?': + errflag++; + break; + + case 'o': + if (strlcpy(optbuf, optarg, sizeof (optbuf)) >= + sizeof (optbuf)) { + (void) fprintf(stderr, + gettext("%s: Invalid argument: %s\n"), + myname, optarg); + return (2); + } + optsize = strlen(optbuf); + break; + case 'O': + flags |= MS_OVERLAY; + break; + case 'r': + flags |= MS_RDONLY; + break; + + case 'm': + flags |= MS_NOMNTTAB; + break; + + case 'q': + qflg = 1; + break; + + default: + usage(); + } + } + if ((argc - optind != 2) || errflag) { + usage(); + } + special = argv[argc - 2]; + mountp = argv[argc - 1]; + + if ((savedoptbuf = strdup(optbuf)) == NULL) { + (void) fprintf(stderr, gettext("%s: out of memory\n"), + myname); + exit(2); + } + if (mount(special, mountp, flags | MS_OPTIONSTR, fstype, NULL, 0, + optbuf, MAX_MNTOPT_STR)) { + (void) fprintf(stderr, "mount: "); + perror(special); + exit(RET_ERR); + } + if (optsize && !qflg) + cmp_requested_to_actual_options(savedoptbuf, optbuf, + special, mountp); + return (0); +} + +void +usage(void) +{ + (void) fprintf(stderr, + "Usage: mount [-Ormq] [-o options] special mountpoint\n"); + exit(RET_ERR); +} diff --git a/usr/src/cmd/ssh/libssh/sparc/Makefile b/usr/src/cmd/fs.d/lxproc/Makefile index fde6250470..77075ef1dd 100644 --- a/usr/src/cmd/ssh/libssh/sparc/Makefile +++ b/usr/src/cmd/fs.d/lxproc/Makefile @@ -19,12 +19,14 @@ # # CDDL HEADER END # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # -include ../Makefile.com +FSTYPE= lxproc +LIBPROG= mount -install: all +include ../Makefile.fstype +include ../Makefile.mount +include ../Makefile.mount.targ diff --git a/usr/src/cmd/fs.d/lxproc/mount.c b/usr/src/cmd/fs.d/lxproc/mount.c new file mode 100644 index 0000000000..5a000997bd --- /dev/null +++ b/usr/src/cmd/fs.d/lxproc/mount.c @@ -0,0 +1,140 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright 2012 Joyent, Inc. All rights reserved. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> +#include <errno.h> +#include <sys/fstyp.h> +#include <sys/fsid.h> +#include <sys/mntent.h> +#include <sys/mnttab.h> +#include <sys/mount.h> +#include <sys/signal.h> +#include <sys/stat.h> +#include <fslib.h> + +#define RET_OK 0 +#define RET_ERR 33 + +static void usage(void); + +static char optbuf[MAX_MNTOPT_STR] = { '\0', }; +static int optsize = 0; + +static char fstype[] = "lxproc"; + +/* + * usage: mount [-Ormq] [-o options] special mountp + * + * This mount program is exec'ed by /usr/sbin/mount if '-F lxproc' is + * specified. + */ +int +main(int argc, char *argv[]) +{ + int c; + char *special; /* Entity being mounted */ + char *mountp; /* Entity being mounted on */ + char *savedoptbuf; + char *myname; + char typename[64]; + int flags = 0; + int errflag = 0; + int qflg = 0; + + myname = strrchr(argv[0], '/'); + myname = myname ? myname+1 : argv[0]; + (void) snprintf(typename, sizeof (typename), "%s %s", fstype, myname); + argv[0] = typename; + + while ((c = getopt(argc, argv, "o:rmOq")) != EOF) { + switch (c) { + case '?': + errflag++; + break; + + case 'o': + if (strlcpy(optbuf, optarg, sizeof (optbuf)) >= + sizeof (optbuf)) { + (void) fprintf(stderr, + gettext("%s: Invalid argument: %s\n"), + myname, optarg); + return (2); + } + optsize = strlen(optbuf); + break; + case 'O': + flags |= MS_OVERLAY; + break; + case 'r': + flags |= MS_RDONLY; + break; + + case 'm': + flags |= MS_NOMNTTAB; + break; + + case 'q': + qflg = 1; + break; + + default: + usage(); + } + } + if ((argc - optind != 2) || errflag) { + usage(); + } + special = argv[argc - 2]; + mountp = argv[argc - 1]; + + if ((savedoptbuf = strdup(optbuf)) == NULL) { + (void) fprintf(stderr, gettext("%s: out of memory\n"), + myname); + exit(2); + } + if (mount(special, mountp, flags | MS_OPTIONSTR, fstype, NULL, 0, + optbuf, MAX_MNTOPT_STR)) { + (void) fprintf(stderr, "mount: "); + perror(special); + exit(RET_ERR); + } + if (optsize && !qflg) + cmp_requested_to_actual_options(savedoptbuf, optbuf, + special, mountp); + return (0); +} + +void +usage(void) +{ + (void) fprintf(stderr, + "Usage: mount [-Ormq] [-o options] special mountpoint\n"); + exit(RET_ERR); +} diff --git a/usr/src/cmd/fs.d/nfs/lib/smfcfg.c b/usr/src/cmd/fs.d/nfs/lib/smfcfg.c index ba2420362a..b79fff4125 100644 --- a/usr/src/cmd/fs.d/nfs/lib/smfcfg.c +++ b/usr/src/cmd/fs.d/nfs/lib/smfcfg.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <stdio.h> #include <stdlib.h> @@ -344,8 +345,23 @@ fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf, } else { ret = scf_error(); } - if ((ret != 0) && scf_error() != SCF_ERROR_NONE) - fprintf(stdout, gettext("%s\n"), scf_strerror(ret)); + if ((ret != 0) && scf_error() != SCF_ERROR_NONE) { + /* + * This is a workaround for the NFS service manifests not + * containing the proper properties in local zones. + * + * When in a local zone and the property doesn't exist on an NFS + * service (most likely nfs/server or nfs/client), don't print + * the error. The caller will still see the correct error code, + * but a user creating a delegated dataset or mounting an NFS + * share won't see this spurious error. + */ + if (getzoneid() == GLOBAL_ZONEID || + scf_error() != SCF_ERROR_NOT_FOUND) { + fprintf(stdout, gettext("%s\n"), scf_strerror(ret)); + } + } + out: fs_smf_fini(phandle); return (ret); diff --git a/usr/src/cmd/fs.d/nfs/lib/smfcfg.h b/usr/src/cmd/fs.d/nfs/lib/smfcfg.h index c06327d801..f0b70907aa 100644 --- a/usr/src/cmd/fs.d/nfs/lib/smfcfg.h +++ b/usr/src/cmd/fs.d/nfs/lib/smfcfg.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #ifndef _SMFCFG_H @@ -42,6 +43,7 @@ #include <locale.h> #include <errno.h> #include <sys/types.h> +#include <zone.h> #ifdef __cplusplus extern "C" { diff --git a/usr/src/cmd/fs.d/nfs/mount/Makefile b/usr/src/cmd/fs.d/nfs/mount/Makefile index dad33922a3..c2485208a8 100644 --- a/usr/src/cmd/fs.d/nfs/mount/Makefile +++ b/usr/src/cmd/fs.d/nfs/mount/Makefile @@ -19,18 +19,12 @@ # CDDL HEADER END # # Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2014, Joyent, Inc. All rights reserved. # # cmd/fs.d/nfs/mount/Makefile FSTYPE= nfs LIBPROG= mount -ROOTFS_PROG= $(LIBPROG) - -# duplicate ROOTLIBFSTYPE value needed for installation rule -# we must define this before including Makefile.fstype -ROOTLIBFSTYPE = $(ROOT)/usr/lib/fs/$(FSTYPE) -$(ROOTLIBFSTYPE)/%: $(ROOTLIBFSTYPE) % - $(RM) $@; $(SYMLINK) ../../../../etc/fs/$(FSTYPE)/$(LIBPROG) $@ include ../../Makefile.fstype @@ -65,7 +59,7 @@ CLOBBERFILES += $(LIBPROG) .KEEP_STATE: -all: $(ROOTFS_PROG) +all: $(LIBPROG) $(LIBPROG): webnfs.h $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) @@ -114,7 +108,9 @@ $(POFILE): $(SRCS) sed "/^domain/d" messages.po > $@ $(RM) $(POFILE).i messages.po -install: $(ROOTETCPROG) +install: all $(FSTYPEPROG) + $(RM) $(ROOTETCPROG) + $(SYMLINK) ../../../usr/lib/fs/$(FSTYPE)/$(LIBPROG) $(ROOTETCPROG) lint: webnfs.h webnfs_xdr.c webnfs_client.c lint_SRCS diff --git a/usr/src/cmd/fs.d/nfs/mount/mount.c b/usr/src/cmd/fs.d/nfs/mount/mount.c index c228a91d05..b3b255d098 100644 --- a/usr/src/cmd/fs.d/nfs/mount/mount.c +++ b/usr/src/cmd/fs.d/nfs/mount/mount.c @@ -2104,7 +2104,7 @@ get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp, } while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers, - vers_min, vers_to_try, "datagram_v")) == NULL) { + vers_min, vers_to_try, NULL)) == NULL) { if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) { pr_err(gettext("%s: %s\n"), fshost, clnt_spcreateerror("")); diff --git a/usr/src/cmd/fs.d/nfs/mountd/mountd.c b/usr/src/cmd/fs.d/nfs/mountd/mountd.c index 0d9ac76d30..666ad427d5 100644 --- a/usr/src/cmd/fs.d/nfs/mountd/mountd.c +++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.c @@ -22,6 +22,7 @@ /* * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Joyent, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -419,6 +420,13 @@ main(int argc, char *argv[]) exit(1); } + /* Mountd cannot run in a non-global zone. */ + if (getzoneid() != GLOBAL_ZONEID) { + (void) fprintf(stderr, "%s: can only run in the global zone\n", + argv[0]); + exit(1); + } + if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { syslog(LOG_ERR, "getrlimit failed"); } else { diff --git a/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c b/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c index 6c0e0bda5e..c34c39a13e 100644 --- a/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c +++ b/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -176,6 +177,13 @@ main(int ac, char *av[]) exit(1); } + /* Nfsd cannot run in a non-global zone. */ + if (getzoneid() != GLOBAL_ZONEID) { + (void) fprintf(stderr, "%s: can only run in the global zone\n", + av[0]); + exit(1); + } + (void) enable_extended_FILE_stdio(-1, -1); /* diff --git a/usr/src/cmd/fs.d/nfs/svc/nfs-server b/usr/src/cmd/fs.d/nfs/svc/nfs-server index 1c7391b8df..c15fabd8eb 100644 --- a/usr/src/cmd/fs.d/nfs/svc/nfs-server +++ b/usr/src/cmd/fs.d/nfs/svc/nfs-server @@ -51,13 +51,13 @@ configure_ipfilter() # # Nothing to do if: + # - service's policy is 'use_global' # - ipfilter isn't online # - global policy is 'custom' - # - service's policy is 'use_global' # + [ "`get_policy $SMF_FMRI`" = "use_global" ] && return 0 service_check_state $IPF_FMRI $SMF_ONLINE || return 0 [ "`get_global_def_policy`" = "custom" ] && return 0 - [ "`get_policy $SMF_FMRI`" = "use_global" ] && return 0 svcadm restart $IPF_FMRI } diff --git a/usr/src/cmd/fs.d/nfs/umount/umount.c b/usr/src/cmd/fs.d/nfs/umount/umount.c index aabdc8a592..66d280bcdb 100644 --- a/usr/src/cmd/fs.d/nfs/umount/umount.c +++ b/usr/src/cmd/fs.d/nfs/umount/umount.c @@ -297,7 +297,7 @@ retry: */ timep = (quick ? &create_timeout : NULL); cl = clnt_create_timed(list[i].host, MOUNTPROG, vers, - "datagram_n", timep); + NULL, timep); /* * Do not print any error messages in case of forced * unmount. diff --git a/usr/src/cmd/halt/halt.c b/usr/src/cmd/halt/halt.c index 36867c88dc..3b57e02c64 100644 --- a/usr/src/cmd/halt/halt.c +++ b/usr/src/cmd/halt/halt.c @@ -21,6 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. @@ -1236,6 +1237,17 @@ do_archives_update(int do_fast_reboot) pid_t pid; char *cmd_argv[MAXARGS]; +#if defined(__i386) + { + /* + * bootadm will complain and exit if not a grub root, so + * just skip running it. + */ + struct stat sb; + if (stat("/boot/grub/stage2", &sb) == -1) + return; + } +#endif /* __i386 */ cmd_argv[i++] = "/sbin/bootadm"; cmd_argv[i++] = "-ea"; @@ -1300,7 +1312,7 @@ main(int argc, char *argv[]) optstring = "dlnqfp"; usage = gettext("usage: %s [ -dlnq(p|f) ] [ boot args ]\n"); #endif - cmd = A_SHUTDOWN; + cmd = A_REBOOT; fcn = AD_BOOT; } else { (void) fprintf(stderr, @@ -1498,7 +1510,8 @@ main(int argc, char *argv[]) * check_zone_haltedness later on. */ if (zoneid == GLOBAL_ZONEID && cmd != A_DUMP) { - need_check_zones = halt_zones(); + if (!qflag) + need_check_zones = halt_zones(); } #if defined(__i386) @@ -1598,7 +1611,7 @@ main(int argc, char *argv[]) (void) signal(SIGINT, SIG_IGN); - if (!qflag && !nosync) { + if (!nosync) { struct utmpx wtmpx; bzero(&wtmpx, sizeof (struct utmpx)); diff --git a/usr/src/cmd/ibd_upgrade/ibd_delete_link.c b/usr/src/cmd/ibd_upgrade/ibd_delete_link.c index b9d10a56cd..f63630207d 100644 --- a/usr/src/cmd/ibd_upgrade/ibd_delete_link.c +++ b/usr/src/cmd/ibd_upgrade/ibd_delete_link.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <stdio.h> @@ -86,6 +87,7 @@ ibd_delete_link(dladm_handle_t dlh, char *link) getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); + getlinkid.ld_zoneid = -1; if ((status = ibd_dladm_door_call(dlh, &getlinkid, sizeof (getlinkid), &retval, sizeof (retval))) != DLADM_STATUS_OK) { diff --git a/usr/src/cmd/init/Makefile b/usr/src/cmd/init/Makefile index a867a0e780..b4b857882b 100644 --- a/usr/src/cmd/init/Makefile +++ b/usr/src/cmd/init/Makefile @@ -25,11 +25,13 @@ # PROG= init +OBJS= init.o ROOTFS_PROG= $(PROG) DEFAULTFILES= init.dfl include ../Makefile.cmd +include ../Makefile.ctf LDLIBS += -lpam -lbsm -lcontract -lscf CERRWARN += -_gcc=-Wno-parentheses @@ -41,6 +43,10 @@ CLOBBERFILES= $(STATIC) all: $(ROOTFS_PROG) +$(ROOTFS_PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + install: all $(ROOTETCDEFAULTFILES) $(ROOTSBINPROG) $(RM) $(ROOTETCPROG) $(RM) $(ROOTUSRSBINPROG) @@ -58,4 +64,8 @@ clean: lint: lint_PROG +%.o: %.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + include ../Makefile.targ diff --git a/usr/src/cmd/init/init.c b/usr/src/cmd/init/init.c index 031a053b65..f6f8bccdbb 100644 --- a/usr/src/cmd/init/init.c +++ b/usr/src/cmd/init/init.c @@ -23,6 +23,7 @@ * Copyright (c) 2013 Gary Mills * * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -144,6 +145,8 @@ #define UT_USER_SZ 32 /* Size of a utmpx ut_user field */ #define UT_LINE_SZ 32 /* Size of a utmpx ut_line field */ +#define CHECK_SVC SCF_INSTANCE_FS_MINIMAL + /* * SLEEPTIME The number of seconds "init" sleeps between wakeups if * nothing else requires this "init" wakeup. @@ -696,9 +699,8 @@ main(int argc, char *argv[]) console(B_FALSE, "\n\n%s Release %s Version %s %d-bit\r\n", un.sysname, un.release, un.version, bits); - console(B_FALSE, - "Copyright (c) 1983, 2010, Oracle and/or its affiliates." - " All rights reserved.\r\n"); + console(B_FALSE, "Copyright (c) 2010-2012, " + "Joyent Inc. All rights reserved.\r\n"); } /* @@ -3509,6 +3511,28 @@ bail: } /* + * Attempt to confirm that svc.startd is ready to accept a user-initiated + * run-level change. startd is not ready until it has started its + * _scf_notify_wait thread to watch for events from svc.configd. This is + * inherently racy. To workaround this, we check the status of a file that + * startd will create once it has started the _scf_notify_wait thread. + * If we don't see this file after one minute, then charge ahead. + */ +static void +verify_startd_ready() +{ + struct stat64 buf; + int i; + + for (i = 0; i < 60; i++) { + if (stat64("/etc/svc/volatile/startd.ready", &buf) == 0) + return; + sleep(1); + } + console(B_TRUE, "verify startd timeout\n"); +} + +/* * Function to handle requests from users to main init running as process 1. */ static void @@ -3596,6 +3620,12 @@ userinit(int argc, char **argv) (void) audit_put_record(ADT_SUCCESS, ADT_SUCCESS, argv[1]); /* + * Before we tell init to start a run-level change, we need to be + * sure svc.startd is ready to accept that. + */ + verify_startd_ready(); + + /* * Signal init; init will take care of telling svc.startd. */ if (kill(init_pid, init_signal) == FAILURE) { @@ -4305,9 +4335,7 @@ contract_event(struct pollfd *poll) if (ret == 0) { if (cookie == STARTD_COOKIE && do_restart_startd) { - if (smf_debug) - console(B_TRUE, "Restarting " - "svc.startd.\n"); + console(B_TRUE, "Restarting svc.startd.\n"); /* * Account for the failure. If the failure rate diff --git a/usr/src/cmd/initpkg/mountall.sh b/usr/src/cmd/initpkg/mountall.sh index 56f2798e18..38693dd8da 100644 --- a/usr/src/cmd/initpkg/mountall.sh +++ b/usr/src/cmd/initpkg/mountall.sh @@ -28,6 +28,8 @@ # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T # All Rights Reserved # +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# usage () { if [ -n "$1" ]; then @@ -148,6 +150,9 @@ isremote() { # Get list of remote FS types (just once) RemoteFSTypes=`while read t junk; do echo $t; done < /etc/dfs/fstypes` +# Ensure nfs/smbfs are remote FS types even if not delivered from fstypes +isremote "nfs" || set -A RemoteFSTypes "nfs" +isremote "smbfs" || set -A RemoteFSTypes "smbfs" # # Process command line args diff --git a/usr/src/cmd/initpkg/shutdown.sh b/usr/src/cmd/initpkg/shutdown.sh index e65224c632..820d50310c 100644 --- a/usr/src/cmd/initpkg/shutdown.sh +++ b/usr/src/cmd/initpkg/shutdown.sh @@ -41,7 +41,7 @@ usage() { } notify() { - /usr/sbin/wall -a <<-! + /usr/sbin/wall -Za <<-! $* ! if [ -x /usr/sbin/showmount -a -x /usr/sbin/rwall ] diff --git a/usr/src/cmd/initpkg/umountall.sh b/usr/src/cmd/initpkg/umountall.sh index c9a94fd8f1..4a45e19e18 100644 --- a/usr/src/cmd/initpkg/umountall.sh +++ b/usr/src/cmd/initpkg/umountall.sh @@ -25,6 +25,7 @@ # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T # All Rights Reserved # +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # usage () { @@ -98,6 +99,9 @@ isremote() { # Get list of remote FS types (just once) RemoteFSTypes=`while read t junk; do echo $t; done < /etc/dfs/fstypes` +# Ensure nfs/smbfs are remote FS types even if not delivered from fstypes +isremote "nfs" || set -A RemoteFSTypes "nfs" +isremote "smbfs" || set -A RemoteFSTypes "smbfs" # # Process command line args diff --git a/usr/src/cmd/ipf/tools/Makefile.tools b/usr/src/cmd/ipf/tools/Makefile.tools index 7c1e151762..ce0db79970 100644 --- a/usr/src/cmd/ipf/tools/Makefile.tools +++ b/usr/src/cmd/ipf/tools/Makefile.tools @@ -23,7 +23,6 @@ # Use is subject to license terms. # # Copyright 2013 Nexenta Systems, Inc. All rights reserved. -# # Copyright (c) 2012, Joyent Inc. All rights reserved. # diff --git a/usr/src/cmd/ipf/tools/ipfstat.c b/usr/src/cmd/ipf/tools/ipfstat.c index fd39556465..f50b722bde 100644 --- a/usr/src/cmd/ipf/tools/ipfstat.c +++ b/usr/src/cmd/ipf/tools/ipfstat.c @@ -165,6 +165,10 @@ static int sort_dstip __P((const void *, const void *)); static int sort_dstpt __P((const void *, const void *)); #endif +#if SOLARIS +#include "ipfzone.h" +#endif + static void usage(name) char *name; diff --git a/usr/src/cmd/krb5/kadmin/Makefile b/usr/src/cmd/krb5/kadmin/Makefile index de893f05a4..8d0dbdc93f 100644 --- a/usr/src/cmd/krb5/kadmin/Makefile +++ b/usr/src/cmd/krb5/kadmin/Makefile @@ -25,7 +25,7 @@ include ../../Makefile.cmd -SUBDIRS= cli dbutil ktutil kpasswd server kclient kdcmgr gui +SUBDIRS= cli dbutil ktutil kpasswd server kclient kdcmgr all := TARGET= all clean := TARGET= clean diff --git a/usr/src/cmd/ksh/Makefile.com b/usr/src/cmd/ksh/Makefile.com index 8716f4eb9d..e5615cb407 100644 --- a/usr/src/cmd/ksh/Makefile.com +++ b/usr/src/cmd/ksh/Makefile.com @@ -36,11 +36,13 @@ LIBSHELLBASE=../../../lib/libshell LIBSHELLSRC=$(LIBSHELLBASE)/common/sh SRCS= $(OBJECTS:%.o=$(LIBSHELLSRC)/%.c) +OBJS= $(OBJECTS) LDLIBS += -lshell # Set common AST build flags (e.g., needed to support the math stuff). include ../../../Makefile.ast +include ../../Makefile.ctf # 1. Make sure that the -D/-U defines in CFLAGS below are in sync # with usr/src/lib/libshell/Makefile.com diff --git a/usr/src/cmd/lofiadm/main.c b/usr/src/cmd/lofiadm/main.c index 0740bce1b7..0c32b69323 100644 --- a/usr/src/cmd/lofiadm/main.c +++ b/usr/src/cmd/lofiadm/main.c @@ -349,7 +349,8 @@ out: * DO NOT use this function if the filename is actually the device name. */ static int -lofi_map_file(int lfd, struct lofi_ioctl li, const char *filename) +lofi_map_file(int lfd, struct lofi_ioctl li, const char *filename, + boolean_t no_devlink_flag) { int minor; @@ -362,7 +363,8 @@ lofi_map_file(int lfd, struct lofi_ioctl li, const char *filename) "unsupported")); die(gettext("could not map file %s"), filename); } - wait_until_dev_complete(minor); + if (!no_devlink_flag) + wait_until_dev_complete(minor); return (minor); } @@ -372,7 +374,8 @@ lofi_map_file(int lfd, struct lofi_ioctl li, const char *filename) */ static void add_mapping(int lfd, const char *devicename, const char *filename, - mech_alias_t *cipher, const char *rkey, size_t rksz, boolean_t rdonly) + mech_alias_t *cipher, const char *rkey, size_t rksz, + boolean_t rdonly, boolean_t no_devlink_flag) { struct lofi_ioctl li; @@ -408,7 +411,7 @@ add_mapping(int lfd, const char *devicename, const char *filename, int minor; /* pick one via the driver */ - minor = lofi_map_file(lfd, li, filename); + minor = lofi_map_file(lfd, li, filename, no_devlink_flag); /* if mapping succeeds, print the one picked */ (void) printf("/dev/%s/%d\n", LOFI_BLOCK_NAME, minor); return; @@ -429,7 +432,8 @@ add_mapping(int lfd, const char *devicename, const char *filename, die(gettext("could not map file %s to %s"), filename, devicename); } - wait_until_dev_complete(li.li_minor); + if (!no_devlink_flag) + wait_until_dev_complete(li.li_minor); } /* @@ -1311,7 +1315,7 @@ lofi_uncompress(int lfd, const char *filename) if (statbuf.st_size == 0) return; - minor = lofi_map_file(lfd, li, filename); + minor = lofi_map_file(lfd, li, filename, B_FALSE); (void) snprintf(devicename, sizeof (devicename), "/dev/%s/%d", LOFI_BLOCK_NAME, minor); @@ -1817,6 +1821,7 @@ main(int argc, char *argv[]) boolean_t ephflag = B_FALSE; boolean_t compressflag = B_FALSE; boolean_t uncompressflag = B_FALSE; + boolean_t no_devlink_flag = B_FALSE; /* the next two work together for -c, -k, -T, -e options only */ boolean_t need_crypto = B_FALSE; /* if any -c, -k, -T, -e */ boolean_t cipher_only = B_TRUE; /* if -c only */ @@ -1832,7 +1837,7 @@ main(int argc, char *argv[]) (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); - while ((c = getopt(argc, argv, "a:c:Cd:efk:o:rs:T:U")) != EOF) { + while ((c = getopt(argc, argv, "a:c:Cd:efk:o:rs:T:UX")) != EOF) { switch (c) { case 'a': addflag = B_TRUE; @@ -1910,6 +1915,13 @@ main(int argc, char *argv[]) case 'U': uncompressflag = B_TRUE; break; + case 'X': + /* + * Private flag to skip the wait for the /dev links to + * be created. + */ + no_devlink_flag = B_TRUE; + break; case '?': default: errflag = B_TRUE; @@ -2038,7 +2050,7 @@ main(int argc, char *argv[]) */ if (addflag) add_mapping(lfd, devicename, filename, cipher, rkey, rksz, - rdflag); + rdflag, no_devlink_flag); else if (compressflag) lofi_compress(&lfd, filename, compress_index, segsize); else if (uncompressflag) diff --git a/usr/src/cmd/ssh/ssh-http-proxy-connect/Makefile b/usr/src/cmd/lp/terminfo/40.ti index 0c717f2155..2e08ece1ca 100644 --- a/usr/src/cmd/ssh/ssh-http-proxy-connect/Makefile +++ b/usr/src/cmd/lp/terminfo/40.ti @@ -19,49 +19,50 @@ # # CDDL HEADER END # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -PROG= ssh-http-proxy-connect +# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved -DIRS= $(ROOTLIBSSH) -OBJS= ssh-http-proxy-connect.o +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.4 */ -SRCS= $(OBJS:.o=.c) - -POFILE_DIR= .. +###################################################################### +# +# Entries for the AT&T Model 40 line printers +# -.KEEP_STATE: -.PARALLEL: $(OBJS) -all: $(PROG) +40-80-6|att40-80-6|AT&T Model 40 line printer 80 cloumn 6 line per inch, -include ../../Makefile.cmd -include ../Makefile.ssh-common + daisy, + bufsz#160, + cols#80, + lines#66, + orc#1, + orhi#10, + orl#1, + orvi#6, + cps#400, -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket + cr=^M, + cuf1=\s, + ff=^L, -install: all $(DIRS) $(ROOTLIBSSHPROG) $(ROOTLIBSSH) +40-80-8|att40-80-8|AT&T Model 40 line printer 80 cloumn 8 line per inch, -$(ROOTLIBSSHPROG)/%: % - $(INS.file) + lines#88, + orvi#8, + use=40-80-6, -$(DIRS): - $(INS.dir) +40-132-6|att40-132-6|AT&T Model 40 line printer 132 cloumn 6 line per inch, -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) - $(POST_PROCESS) + bufsz#264, + cols#132, + use=40-80-6, -clean: - $(RM) -f $(OBJS) $(PROG) +40-132-8|att40-132-8|AT&T Model 40 line printer 132 cloumn 8 line per inch, -lint: lint_SRCS + lines#88, + orvi#8, + use=40-132-6, -include ../../Makefile.targ -include ../Makefile.msg.targ diff --git a/usr/src/cmd/lp/terminfo/44x.ti b/usr/src/cmd/lp/terminfo/44x.ti new file mode 100644 index 0000000000..d932bf441e --- /dev/null +++ b/usr/src/cmd/lp/terminfo/44x.ti @@ -0,0 +1,57 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +###################################################################### +# +# Entries for the AT&T 440 seris line printers +# + + +442|att442|AT&T 442 line printer, + + bufsz#2048, + cols#132, + lines#66, + orc#1, + orhi#10, + orl#1, + orvi#6, + cps#440, + + cr=^M, + cuf1=\s, + ff=^L, + +444|att444|AT&T 444 line printer, + + use=442, + +446|att446|AT&T 446 line printer, + + cps#1100, + use=442, + diff --git a/usr/src/cmd/lp/terminfo/45x.ti b/usr/src/cmd/lp/terminfo/45x.ti new file mode 100644 index 0000000000..e4a6c5ab92 --- /dev/null +++ b/usr/src/cmd/lp/terminfo/45x.ti @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +###################################################################### +# +# Entries for the AT&T 455, 457, 459 printers +# + +455|att455|AT&T 455 Daisywheel printer, + + use=Gdaisy+basic, + +457|att457|458|att458|AT&T 457 Daisy printer, + + bufsz#1024, + use=455, + + diff --git a/usr/src/cmd/lp/terminfo/477.ti b/usr/src/cmd/lp/terminfo/477.ti new file mode 100644 index 0000000000..51b808b2ce --- /dev/null +++ b/usr/src/cmd/lp/terminfo/477.ti @@ -0,0 +1,181 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.7 */ + +###################################################################### +# +# Entries for the AT&T 477 printer +# + +# +# Basic capabilities (all emulations): +# +att477+basic1, + + bufsz#8192, + cps#80, + +###################################################################### +# +# Particular printers: +# + +477-470|att477-470|AT&T 477; 470 emulation, + + cols#136, + cpix, + + orc#10, + orhi#100, + orl#30, + orvi#180, + + csnm=%?%p1%{0}%=%tamerican%e%p1%{1}%=%tbritish%e%p1%{2}%=%tswedish%e%p1%{3}%=%tgerman%e%p1%{4}%=%tfrench%e%p1%{5}%=%titalian%e%p1%{6}%=%tspanish%;, + scs=%?%p1%{0}%=%t\EZ^O@\ED^B@%e%p1%{1}%=%t\EZ^O@\ED^C@%e%p1%{2}%=%t\EZ^O@\ED^E@%e%p1%{3}%=%t\EZ^O@\ED^D@%e%p1%{4}%=%t\EZ^O@\ED^A@%e%p1%{5}%=%t\EZ^O@\ED^F@%e%p1%{6}%=%t\EZ^O@\ED^G@%;, + + use=470, + +477ibmc|att477ibmc|AT&T 477 IBM Color printer emulation, + + cols#135, + + orc#15, + orhi#150, + + orl#10, + orvi#60, + + cvr=%?%p1%{0}%>%p1%{256}%<%&%t\EA%p1%c\E2%; + + cpi=%?%p1%{10}%=%t^R%e%p1%{12}%=%t\E:%e%p1%{17}%=%t^O%;, + + + smglp=\EX%p1%{1}%+%c%p2%{2}%+%c, + smgt=\E4, + + + use=att477+basic1, use=Gibmc+basic, use=Gibmc+low+5x6, + use=Gibmc+color, + +477ibmg|att477ibmg|AT&T 477 IBM Graphics printer emulation, + + cols#136, + + orc#10, + orhi#100, + orl#10, + orvi#60, + + is2=\E@, + + smglp=%?%p1%{256}%<%t\El%p1%{1}%+%c, + smgrp=%?%p1%{256}%<%t\EQ%p1%{2}%+%c, + + + use=att477+basic1, use=Gibmg+basic, use=Gibmg+low, + +477qume|att477qume|477-455|att477-455|AT&T 477 qume emulation, + + + cols#136, + + + is2=\E\rP\EW\E.\EL08\EY, + + use=att477+basic1, use=Gdaisy+basic, use=Gdaisy+lowres, + +###################################################################### +# +# In Fujitsu DPL24C mode. This seems to be more like the Epson LQ-2500 +# than the IBM Proprinter XL. +# + +# +# Basic capabilities (Fujitsu emulation only): +# +att477+basic2, + + orc#18, + orhi#180, + orl#30, + orvi#180, + + +# +# The following is not redundant with the cpi capability, because +# the cpi changes the character size as well, so that printing +# looks balanced, while this leaves the character size alone. + chr=%?%p1%{256}%<%t\Eh%p1%c%;, + + + is2=\E@, + + csnm=%?%p1%{0}%=%tcharacter_set_1%e%p1%{1}%=%tcharacter_set_2%e%p1%{2}%=%tusa%e%p1%{3}%=%tfrench%e%p1%{4}%=%tgerman%e%p1%{5}%=%tuk%e%p1%{6}%=%tdanish%e%p1%{7}%=%tswedish%e%p1%{8}%=%titalian%e%p1%{9}%=%tspanish%;, + scs=%?%p1%{0}%=%t\E7%e%p1%{1}%=%t\E6%e%p1%{3}%=%t\ER0%e%p1%{3}%=%t\ER1%e%p1%{4}%=%t\ER2%e%p1%{5}%=%t\ER3%e%p1%{6}%=%t\ER4%e%p1%{7}%=%t\ER5%e%p1%{8}%=%t\ER6%e%p1%{9}%=%t\ER7%;, + + +477-5x6|att477-5x6|AT&T 477 as Fujitsu DPL24C; 5:6 aspect ratio, + + spinh#50, + +# defbi= +# Like the defbi for the epson2500, except: +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 50 dots per inch horizontally this means 5 +# dots per character. +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\E3\030^R\EP\EB%p2%{8}%/%c$<>\ED%p1%{6}%/%c$<>\013\r\t%;, + +# +# Note that the epson2500 drives a real Epson LQ-2500 at +# 60 dots per inch horizontally; the same control sequences +# drive the Fujitsu DPL24C at 50 dots per inch horixontally. + use=att477+basic1, use=att477+basic2, use=Gep2500+basic, + use=Gep2500+low, use=Gep2500+color, + +477|att477|AT&T 477 as Fujitsu DPL24C; 1:1; low res, + + is1@, + +# +# This mode differs from the 5x6 mode only in sbim and defbi +# (and spinh, of course). However, it is even closer to the +# epson2500, so we use that. + + sdrfq=\EH, + snlq=\EG, + snrmq@, + + sbim=\E*\005%p1%{256}%m%c%p1%{256}%/%c, + + use=att477+basic1, use=att477+basic2, use=Gep2500+basic, + use=Gep2500+low, use=Gep2500+color, + +477-hi|att477-hi|AT&T 477 as Fujitsu DPL24C; 1:1; high res, + + use=att477+basic1, use=att477+basic2, use=Gep2500+basic, + use=Gep2500+high, use=Gep2500+color, diff --git a/usr/src/cmd/lp/terminfo/47x.ti b/usr/src/cmd/lp/terminfo/47x.ti new file mode 100644 index 0000000000..a5db8850de --- /dev/null +++ b/usr/src/cmd/lp/terminfo/47x.ti @@ -0,0 +1,134 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Entries for the AT&T 470, 471, 473, 474, 475, 476, 478, 479 printers +# + +# +# C.Itoh derived printers: +# + +470|att470|AT&T 470; C.Itoh 8510; 8"; parallel matrix printer, + + bufsz#4096, + + cols#80, + cpix, + + sdrfq@, + snlq@, + snrmq@, + ssubm@, + ssupm@, + rsubm@, + rsupm@, + + sgr0=\E"\EY, + +# Reset command does not reset form length + + is2=\Ec1\Ev66, + + csnm=%?%p1%{0}%=%tusa%e%p1%{1}%=%tbritish%e%p1%{2}%=%tdanish%e%p1%{3}%=%tjapanese%e%p1%{4}%=%tnorwegian%e%p1%{5}%=%tswedish%e%p1%{6}%=%tgerman%e%p1%{7}%=%tfrench%e%p1%{8}%=%tfrench2%e%p1%{9}%=%titalian%e%p1%{10}%=%tspanish%e%p1%{11}%=%tnetherland%e%p1%{12}%=%tafrikaans%e%p1%{13}%=%tbritish2%;, + scs=%?%p1%{0}%=%t\EZ^O@\ED^B@%e%p1%{1}%=%t\EZ^O@\ED^C@%e%p1%{2}%=%t\EZ^O@\ED\b@%e%p1%{3}%=%t\EZ^O@%e%p1%{4}%=%t\EZ^O@\ED\t@%e%p1%{5}%=%t\EZ^O@\ED^E@%e%p1%{6}%=%t\EZ^O@\ED^D@%e%p1%{7}%=%t\EZ^O@\ED^A@%e%p1%{8}%=%t\EZ^O@\ED^N@%e%p1%{9}%=%t\EZ^O@\ED^F@%e%p1%{10}%=%t\EZ^O@\ED^G@%e%p1%{11}%=%t\EZ^O@\ED\n@%e%p1%{12}%=%t\EZ^O@\ED^K@%e%p1%{13}%=%t\ED^O@%;, + + + use=Gcitoh+basic, use=Gcitoh+low, + +471|att471|AT&T 471; C.Itoh 1550; 14"; parallel matrix printer, + + cols#136, + + use=470, + +475|att475|AT&T 475; C.Itoh 8510; 8"; serial matrix printer, + + use=470, + +476|att476|AT&T 475; C.Itoh 1550; 14"; serial matrix printer, + + use=471, + +# +# IBM derived printers: +# + +473|att473|AT&T 473; 8"; C.Itoh 8510EP; IBM Graphics, + + bufsz#4096, + cps#120, + +# +# FIX: The AT&T 473 doesn't seem to have fine-scale horizontal +# motion--the only motion is by columns. + orc#10, + orhi#100, + + + + + use=Gibmg+basic, use=Gibmg+low, + +474|att474|AT&T 474; 14"; C.Itoh 1550EP; IBM Graphics, + + cols#132, + + use=473, + +478|att478|AT&T 478; 8"; parallel matrix printer, + + bufsz#16384, + cps#120, + +# +# FIX: The AT&T 478 doesn't seem to have fine-scale horizontal +# motion--the only motion is by columns. + orc#10, + orhi#100, + + cpi=%?%p1%{10}%=%t^R%e%p1%{12}%=%t\E:%e%p1%{13}%=%p1%{14}%=%O%t\Eh%e%p1%{16}%=%p1%{17}%=%O%t\Em%e%p1%{18}%=%t^O%;, + + is2=^R\EW0\E-0\E_0\EF\EH\EI\ET\EA\014\E2\ER\El\001\Er\120\Et\001\EC\102\E7\EU0\EO, + + sdrfq=\EI^D, + snlq=\EI^B, + + smglp=\El%{1}%p1%+%c, + smgrp=\Er%{1}%p1%+%c, + smgtp=\Et%{1}%p1%+%c, + + use=Gibmg+basic, use=Gibmg+low, + +479|att479|AT&T 479; 14"; IBM parallel; matrix printer, + + cols#132, + is2=^R\EW0\E-0\E_0\EF\EH\EI\004\ET\EA\014\E2\ER\El\001\Er\204\Et\001\EC\102\E7\EU0\EO, + + + use=478, diff --git a/usr/src/cmd/lp/terminfo/495.ti b/usr/src/cmd/lp/terminfo/495.ti new file mode 100644 index 0000000000..562c62b6be --- /dev/null +++ b/usr/src/cmd/lp/terminfo/495.ti @@ -0,0 +1,78 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +###################################################################### +# +# Entries for the AT&T 495 printer +# + +495ibm|att495ibm|AT&T 495 IBM Graphics emulation, + + bufsz#1024, + cps#800, + + + orc#12, + orhi#120, + + lines#63, + + cpi=%?%p1%{10}%=%t^R%e%p1%{17}%=%t^O%;, + +# Reset defaults, enter IBM Graphics emulation mode + is2=\E[0~\E[12~, + + use=Gibmg+basic, use=Gibmg+low, + +495qume|att495qume|AT&T 495 Qume emulation, + + daisy@, + + bufsz#1024, + cps#800, + + cols#80, + lines#63, + + + chr=%?%p1%{0}%>%p1%{127}%<%&%t\E^_%p1%{1}%+%c%;, + cvr=%?%p1%{0}%>%p1%{127}%<%&%t\E^^%p1%{1}%+%c%;, + + is2=\E[0~\E[11~\E^_\r, + + u9=%?%p1%{128}%<%t\EF%p1%02d%;, + + use=Gdaisy+basic, use=Gdaisy+lowres, + +495hp|att495hp|AT&T 495 HP Laserjet I emulation, + + bufsz#1024, + cps#800, + + is2=\E[0~\E[10~\E&k0S, + + use=Ghplaser+basic, use=Ghplaser+high, diff --git a/usr/src/cmd/lp/terminfo/53x0.ti b/usr/src/cmd/lp/terminfo/53x0.ti new file mode 100644 index 0000000000..fc6fb2cef9 --- /dev/null +++ b/usr/src/cmd/lp/terminfo/53x0.ti @@ -0,0 +1,81 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Entries for the AT&T 5310, 5320 printers +# + +53x0+high, + + spinv#72, + spinh#150, + + bitwin#2, + u1=2, + +# defbi= +# X is in 1/150 increments; set char spacing to 1/16.7 +# increments to allow us to get close; column is X*16.7/150. +# Y is in 1/144 increments; set line spacing to 1/12 +# increments to allow us to get close; line is Y/12. +# Note: The 5310/5320 won't move upward with the absolute +# addressing control sequence, so we use the relative motion. +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\E[4w\E[%p1%{167}%*%{1500}%/%d`\E[w\E[3z\E[%p2%{12}%/%de\E[z\EP\035q%;, + defbi=%?%p5%{1}%=%t\E[4w\E[%p1%{167}%*%{1500}%/%d`\E[w\E[3z\E[%p2%{12}%/%de\E[z\EP\035q%;, + + use=Gdec+low, + +5320|att5320|AT&T Model 5320 printer (EMUL set to ANSI), + + bufsz#8192, + cps#120, + + +# +# FIX: The AT&T 5320 doesn't seem to have fine-scale horizontal +# motion--the only motion is by columns. + orc#10, + orhi#100, + +# +# FIX: The AT&T 5320 seems to only have half-line vertical motion +# at best. + orl#12, + orvi#72, + + + + use=53x0+high, use=Gdec+basic, use=Gdec+low, + +5310|att5310|AT&T 5310 matrix printer (EMUL set to ANSI), + + cols#80, + + use=5320, diff --git a/usr/src/cmd/lp/terminfo/57x.ti b/usr/src/cmd/lp/terminfo/57x.ti new file mode 100644 index 0000000000..677090111e --- /dev/null +++ b/usr/src/cmd/lp/terminfo/57x.ti @@ -0,0 +1,105 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Entries for the AT&T 570 series printers +# + +570eps|att570eps|AT&T 570 Epson emulation, + + bufsz#10000, + cps#250, + cols#80, + orl#36, + orvi#216, + + use=Gepson+basic, + use=Gepson+low, + +570ibm|att570ibm|AT&T 570 IBM ProPrinter emulation, + + bufsz#10000, + cps#250, + + use=Gibmg+basic, + use=Gibmg+low, + +571eps|att571eps|AT&T 571 Epson emulation, + + cols#136, + + use=570eps, + +571ibm|att571ibm|AT&T 571 IBM ProPrinter emulation, + + cols#136, + use=570ibm, + +572|att572|AT&T 572 9-wire Matrix Printer, + + bufsz#10000, + cps#250, + cols#80, + xhpa@, + xvpa@, + + csnm=%?%p1%{0}%=%tusascii%e%p1%{1}%=%tbritish%e%p1%{2}%=%tfinnish%e%p1%{3}%=%tjapanese%e%p1%{4}%=%tnorwegian%e%p1%{5}%=%tswedish%e%p1%{6}%=%tgerman%e%p1%{7}%=%tfrench%e%p1%{8}%=%tfrench_canadian%e%p1%{9}%=%titalian%e%p1%{10}%=%tspanish%e%p1%{11}%=%tline_drawing%e%p1%{12}%=%tdanish%e%p1%{13}%=%tebcdic%e%p1%{14}%=%tmulti_national%;, + scs=%?%p1%{0}%=%t\E(B%e%p1%{1}%=%t\E(A%e%p1%{2}%=%t\E(C%e%p1%{3}%=%t\E(J%e%p1%{4}%=%t\E(E%e%p1%{5}%=%t\E(H%e%p1%{6}%=%t\E(K%e%p1%{7}%=%t\E(R%e%p1%{8}%=%t\E(Q%e%p1%{9}%=%t\E(Y%e%p1%{10}%=%t\E(Z%e%p1%{11}%=%t\E(O%e%p1%{12}%=%t\E(E%e%p1%{13}%=%t\E(3%e%p1%{14}%=%t\E(<%;, + + is3=\E[0"z, + + snlq=\E[2"z, + snrmq=\E[3"z, + sdrfq=\E[0"z, + sshm=\E[1m, + rshm=\E[22m, + smul=\E[4m, + rmul=\E[24m, + +# The following are not supported by 572/573 + + smgbp@, + smgtp@, + smglp@, + smgrp@, + cud@, + cuf@, + cuu1@, + hpa@, + vpa@, + nel@, + + use=Gdec+basic, + use=Gdec+low, + +573|att573|AT&T 573 9-wire Matrix Printer, + + cols#132, + + use=572, diff --git a/usr/src/cmd/lp/terminfo/58x.ti b/usr/src/cmd/lp/terminfo/58x.ti new file mode 100644 index 0000000000..bd5b65c663 --- /dev/null +++ b/usr/src/cmd/lp/terminfo/58x.ti @@ -0,0 +1,103 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Generic entry: +# + +att583+basic, + + bufsz#16384, + cps#200, + +###################################################################### +# +# Specific printers: +# + +583ibm|att583ibm|AT&T 583 as IBM Proprinter XL, + + cols#136, + is3=\EX\210, + + use=att583+basic, use=Gibmxl+basic, use=Gibmxl+low+5x6, use=Gibmc+color, + + +583ibm-80|att583ibm-80|AT&T 583 as IBM Proprinter XL;80-col, + + use=att583+basic, use=Gibmxl+basic, use=Gibmxl+low+5x6, use=Gibmc+color, + + +583eps|att583eps|AT&T 583 as Epson LQ-2500; low resolution, + + use=att583+basic, use=Gep2500+basic, use=Gep2500+low, use=Gep2500+color, + +583eps-hi|att583eps-hi|AT&T 583 as Epson LQ-2500; high resolution, + + use=att583+basic, use=Gep2500+basic, use=Gep2500+high, use=Gep2500+color, + +583eps-80|att583eps-80|AT&T 583 as Epson LQ-2500; low resolution; 80-col, + + cols#80, + use=att583+basic, use=Gep2500+basic, use=Gep2500+low, use=Gep2500+color, + +583eps-hi-80|att583eps-hi-80|AT&T 583 as Epson LQ-2500; high resolution; 80-col, + + cols#80, + use=att583+basic, use=Gep2500+basic, use=Gep2500+high, use=Gep2500+color, + + +580ibm|att580ibm|AT&T 580 as IBM Proprinter XL, + + use=att583+basic, use=Gibmxl+basic, use=Gibmxl+low+5x6, + +581ibm|att581ibm|AT&T 581 as IBM Proprinter XL, + + cols#136, + is3=\EX\210, + + use=580ibm, + + +581eps|att581eps|AT&T 581 as Epson LQ-2500; low resolution, + + use=att583+basic, use=Gep2500+basic, use=Gep2500+low, + +581eps-hi|att581eps-hi|AT&T 581 as Epson LQ-2500; high resolution, + + use=att583+basic, use=Gep2500+basic, use=Gep2500+high, + +580eps|att580eps|AT&T 580 as Epson LQ-2500; low resolution, + + cols#80, + use=att583+basic, use=Gep2500+basic, use=Gep2500+low, + +580eps-hi|att580eps-hi|AT&T 580 as Epson LQ-2500; high resolution, + + cols#80, + use=att583+basic, use=Gep2500+basic, use=Gep2500+high, diff --git a/usr/src/cmd/ssh/ssh-socks5-proxy-connect/Makefile b/usr/src/cmd/lp/terminfo/593.ti index 765aca9af0..3d2a592c47 100644 --- a/usr/src/cmd/ssh/ssh-socks5-proxy-connect/Makefile +++ b/usr/src/cmd/lp/terminfo/593.ti @@ -19,49 +19,55 @@ # # CDDL HEADER END # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# +# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved -PROG= ssh-socks5-proxy-connect -DIRS= $(ROOTLIBSSH) +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ -OBJS= ssh-socks5-proxy-connect.o +###################################################################### +# +# Entries for the AT&T 593 printer +# -SRCS= $(OBJS:.o=.c) +593eps|att593eps|AT&T 593 Epson FX86e emulation, -POFILE_DIR= .. + bufsz#2000, + cps#480, + cols#80, + lines#62, + orl#36, + orvi#216, -.KEEP_STATE: +# Only letter quality for laser printer + snlq@, + snrmq@, + sdrfq@, -.PARALLEL: $(OBJS) + use=Gep2500+basic, + use=Gepson+low, -all: $(PROG) +593ibm|att593ibm|AT&T 593 IBM ProPrinter XL emulation, -include ../../Makefile.cmd -include ../Makefile.ssh-common + bufsz#2000, + cps#480, -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket + lines#62, -install: all $(DIRS) $(ROOTLIBSSHPROG) $(ROOTLIBSSH) +# Only letter quality for laser printer + snlq@, + sdrfq@, -$(ROOTLIBSSHPROG)/%: % - $(INS.file) + smglp=\EX%p1%{1}%+%c%p2%{1}%+%c, -$(DIRS): - $(INS.dir) + use=Gibmxl+basic, + use=Gibmxl+low+1x1, -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) - $(POST_PROCESS) -clean: - $(RM) -f $(OBJS) $(PROG) +593hp|att593hp|AT&T 593 HP Laserjet II emulation, -lint: lint_SRCS + bufsz#2000, + cps#480, -include ../../Makefile.targ -include ../Makefile.msg.targ + + use=Ghplaser+II, diff --git a/usr/src/cmd/lp/terminfo/Makefile b/usr/src/cmd/lp/terminfo/Makefile new file mode 100644 index 0000000000..b94f821b6b --- /dev/null +++ b/usr/src/cmd/lp/terminfo/Makefile @@ -0,0 +1,77 @@ +# +# 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 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# cmd/lp/terminfo/Makefile +# + +include ../Makefile.lp + +ROOTTERMINFO = $(ROOT)/usr/share/lib/terminfo + +TIC = tic + +SRCS = PS.ti 40.ti 477.ti 53x0.ti 593.ti daisy.ti hplaser.ti \ + 44x.ti 47x.ti 57x.ti dec.ti ibm.ti 45x.ti 495.ti \ + 58x.ti citoh.ti epson.ti unknown.ti + + +TMPSRC = terminfo.src + +DIRMODE= 755 +FILEMODE= 644 + +.KEEP_STATE: + +all : $(TMPSRC) + +$(TMPSRC) : $(SRCS) + $(RM) $@; cat $(SRCS) > $@ + +# +# Since all entries are created at once, we simply choose one of the +# target files and assume everything will be made at one time. This +# has holes (like if somebody removes P/PSR but not P/PS), but those +# are the breaks. +# +install : all $(ROOTTERMINFO) $(ROOTTERMINFO)/P/PS + +$(ROOTTERMINFO)/P/PS: $(TMPSRC) + TERMINFO=$(ROOTTERMINFO) 2>&1 $(TIC) -v $(TMPSRC) > errs + @$(ECHO) "\n`2>/dev/null cat errs|wc -l` entries have been compiled\n" + @-( 2>/dev/null cat errs|grep -iv "^mkdir"|grep -iv "^create"|grep -iv "^link"|grep -vi $(TMPSRC)|grep -vi touch|grep -vi "working"; \ + if [ $$? -ne 0 ] ; \ + then \ + $(ECHO) "\tNo errors\n"; \ + else \ + $(ECHO) "\n\tErrors can be found in `pwd`/errs\n"; \ + fi \ + ) + +$(ROOTTERMINFO) : + $(INS.dir) + +clean clobber: + $(RM) $(TMPSRC) + +strip lint : + diff --git a/usr/src/cmd/lp/terminfo/PS.ti b/usr/src/cmd/lp/terminfo/PS.ti new file mode 100644 index 0000000000..28a83e988b --- /dev/null +++ b/usr/src/cmd/lp/terminfo/PS.ti @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +# ident "%Z%%M% %I% %E% SMI" /* SVr4 1.1 */ + +PS|PSR|PS-b|PS-r|PS-br|Fake PostScript entry, + slines=\004, + u9=\004, + csnm=\004, + scs=\004, + cpi=null, + lpi=null, + cols#80, + lines#66, diff --git a/usr/src/cmd/lp/terminfo/citoh.ti b/usr/src/cmd/lp/terminfo/citoh.ti new file mode 100644 index 0000000000..c2b584b7c6 --- /dev/null +++ b/usr/src/cmd/lp/terminfo/citoh.ti @@ -0,0 +1,127 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +###################################################################### +# +# Generic entry for the C.Itoh 8510 printer and emulations: +# + +Gcitoh+basic, + +# The 8510 I use only allows 79 columns! + cols#79, + + lines#66, + it#8, + + orc#1, + orhi#10, + orl#24, + orvi#144, + + cr=\r, + cud1=\n, + cuf1=\s, + ff=\f, + ht=\t, + + cpi=%?%p1%{10}%=%t\EN%e%p1%{12}%=%t\EE%e%p1%{16}%=%p1%{17}%=%O%t\EQ%;, + cvr=%?%p1%{0}%>%p1%{100}%<%&%t\ET%p1%02d%;, + + is1=^Q^X, + is2=\Ec1\Ev66., + + smso=\E!, + rmso=\E", + smul=\EX, + rmul=\EY, + bold=\E!, + ssubm=\Es2, + rsubm=\Es0, + ssupm=\Es1, + rsupm=\Es0, + swidm=^N, + rwidm=^O, + sgr0=\E"\EY\Es0^O, + sgr=%?%p1%p6%|%t\E!%e\E"%;%?%p2%t\EX%e\EY%;, + + rep=\ER%p2%03d%p1%c, + + snlq=\Em2, + snrmq=\Em1, + sdrfq=\Em0, + + smglp=\EL%p1%03d, + smgrp=\E/%{1}%p1%+%03d, + +# slines= + u9=\Ev%p1%02d., + slines=\Ev%p1%02d., + +Gcitoh+low, + + npins#8, + spinv#68, + spinh#136, + + porder=8\,7\,6\,5\,4\,3\,2\,1;0, + + sbim=\ES%p1%04d, + +# birep= + u4=\EV%p2%04d%p3%c, + birep=\EV%p2%04d%p3%c, + + bitwin#1, + u1=1, + bitype#1, + u2=1, + +# defbi= +# Set the line spacing to 17/144 inch to get (almost) 68 dots +# per inch vertically (8 * 144/17). +# Set the character spacing to compressed (1/17 inch or 17 +# characters per inch); at 136 dots per inch horizontally this +# means 8 dots per character. +# Set the left margin at the left edge of the image. +# The C.Itoh doesn't have parameterized vertical motion, +# so we simulate it with linefeeds. Assume we never need +# to move more than 63 lines (at 17/144 LPI). +# Set uni-directional motion; bi-directional causes a wavy +# image. +# defbi= + u6=%?%p5%{1}%=%t\ET17\EQ\EL%p1%{8}%/%03d%p2%{8}%/%Py%?%gy%{31}%>%t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n%gy%{32}%-%Py%;%?%gy%{15}%>%t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n%gy%{16}%-%Py%;%?%gy%{7}%>%t\n\n\n\n\n\n\n\n%gy%{8}%-%Py%;%?%gy%{3}%>%t\n\n\n\n%gy%{4}%-%Py%;%?%gy%{1}%>%t\n\n%gy%{2}%-%Py%;%?%gy%{0}%>%t\n%;\E>%;, + defbi=%?%p5%{1}%=%t\ET17\EQ\EL%p1%{8}%/%03d%p2%{8}%/%Py%?%gy%{31}%>%t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n%gy%{32}%-%Py%;%?%gy%{15}%>%t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n%gy%{16}%-%Py%;%?%gy%{7}%>%t\n\n\n\n\n\n\n\n%gy%{8}%-%Py%;%?%gy%{3}%>%t\n\n\n\n%gy%{4}%-%Py%;%?%gy%{1}%>%t\n\n%gy%{2}%-%Py%;%?%gy%{0}%>%t\n%;\E>%;, + +# endbi= + u7=\EA\EP\EL001\E<, + endbi=\EA\EP\EL001\E<, + +# binel= + u5=\n\r\EL%p1%{8}%/%03d, + binel=\n\r\EL%p1%{8}%/%03d, + diff --git a/usr/src/cmd/lp/terminfo/daisy.ti b/usr/src/cmd/lp/terminfo/daisy.ti new file mode 100644 index 0000000000..26c7b31d9f --- /dev/null +++ b/usr/src/cmd/lp/terminfo/daisy.ti @@ -0,0 +1,126 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Generic entry for the daisy wheel printers and emulations: +# + +# +# Basic capabilities: +# +Gdaisy+basic, + + daisy, + + cols#132, + lines#66, + + bufsz#500, + cps#55, + orc#12, + orhi#120, + orl#8, + orvi#48, + + cr=^M, + cud1=^J, + cuf1=\s, + ff=^L, + ht=^I, + hpa=%?%p1%{100}%<%t\EC%p1%02d%e%p1%{110}%<%t\ECA%p1%{100}%-%d%e%p1%{120}%<%t\ECB%p1%{110}%-%d%e%p1%{130}%<%t\ECC%p1%{120}%-%d%e%p1%{140}%<%t\ECD%p1%{130}%-%d%e%p1%{150}%<%t\ECE%p1%{140}%-%d%e%p1%{160}%<%t\ECF%p1%{150}%-%d%;, + vpa=%?%p1%{100}%<%t\EP%p1%02d%e%p1%{110}%<%t\EPA%p1%{100}%-%d%e%p1%{120}%<%t\EPB%p1%{110}%-%d%e%p1%{130}%<%t\EPC%p1%{120}%-%d%e%p1%{140}%<%t\EPD%p1%{130}%-%d%e%p1%{150}%<%t\EPE%p1%{140}%-%d%e%p1%{160}%<%t\EPF%p1%{150}%-%d%;, + + chr=%?%p1%{100}%<%t\EE%p1%02d%e%p1%{110}%<%t\EEA%p1%{100}%-%d%e%p1%{120}%<%t\EEB%p1%{110}%-%d%e%p1%{130}%<%t\EEC%p1%{120}%-%d%e%p1%{140}%<%t\EED%p1%{130}%-%d%e%p1%{150}%<%t\EEE%p1%{140}%-%d%e%p1%{160}%<%t\EEF%p1%{150}%-%d%;, + cvr=%?%p1%{100}%<%t\EL%p1%02d%e%p1%{110}%<%t\ELA%p1%{100}%-%d%e%p1%{120}%<%t\ELB%p1%{110}%-%d%e%p1%{130}%<%t\ELC%p1%{120}%-%d%e%p1%{140}%<%t\ELD%p1%{130}%-%d%e%p1%{150}%<%t\ELE%p1%{140}%-%d%e%p1%{160}%<%t\ELF%p1%{150}%-%d%;, + + + is2=\E\015P\EW\E.\EL08\EE12\E%\E<, + + smso=\EQ, + rmso=\ER, + smul=\EI, + rmul=\EJ, + bold=\EK3, + sshm=\EQ, + rshm=\ER, + sgr0=\ER\EM\EJ, + sgr=%?%p1%t\EQ%e\ER%;%?%p2%t\EI%e\EJ%;%?%p6%t\EK3%e\EM%;, + + smgb=\E-, + smgl=\E9, + smgr=\E0, + smgt=\E+, + +# slines=, + u9=\EF%p1%02d, + +# +# Graphics capabilities: +# +Gdaisy+lowres, + +# +# We could use the graphics on/graphics off control sequences +# (ESC G/ESC 4) but for these problems: +# +# - graphics mode gets turned off when a \r is received; +# - printing a character doesn't cause motion, which +# means that each ``cell'' must be followed by a space; +# - to get the best aspect ratio, three horizontal dots +# must be sent per ``cell'' (using the ESC 3 graphics mode +# (1/60 instead of 1/120) alleviates this problem but +# gives a worse aspect ratio). +# +# So instead we set the HMI and VMI to 1/40 and 1/48 inch, +# respectively. +# + npins#1, + spinv#48, + spinh#40, + + porder=o\,o\,o\,o\,1\,1\,1\,o;32, + +# bitwin# + u1=1, +# bitype# + u2=1, + +# birep= + u4=%?%p3%{32}%=%t\EH%p2%{3}%*%Px%gx%{256}%/%{64}%+%c%gx%{256}%m%{16}%/%{64}%+%c%gx%{16}%m%{64}%+%c%;, + +# defbi= +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\EL01\EE03%p1%{3}%*%Px\r\EH%gx%{256}%/%{64}%+%c%gx%{256}%m%{16}%/%{64}%+%c%gx%{16}%m%{64}%+%c\EV%p2%{256}%/%{64}%+%c%p2%{256}%m%{16}%/%{64}%+%c%p2%{16}%m%{64}%+%c\E>%;, + +# endbi= + u7=\EL08\EE12\E<, + +# binel= + u5=\n\r%p1%{3}%*%Px\EH%gx%{256}%/%{64}%+%c%gx%{256}%m%{16}%/%{64}%+%c%gx%{16}%m%{64}%+%c, + diff --git a/usr/src/cmd/lp/terminfo/dec.ti b/usr/src/cmd/lp/terminfo/dec.ti new file mode 100644 index 0000000000..5cc0ae6d55 --- /dev/null +++ b/usr/src/cmd/lp/terminfo/dec.ti @@ -0,0 +1,130 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +###################################################################### +# +# Generic entries for the various DEC printers and emulations. +# +# The Gdec+... entries are really for any ANSI X3.64 printer, +# but "ansi" is already used for terminals. It would be more +# work to do "use=ansi" because there are too many screen +# oriented caps that would have to be removed. +# + +# +# Basic capabilities: +# +Gdec+basic, + + cols#132, + lines#66, + it#8, + + cpix, + orc#1, + orhi#10, + orl#2, + orvi#12, + +# +# FIX? Are xhpa and xvpa really needed? + xhpa, + xvpa, + + cr=^M, + ff=^L, + ht=^I, + cud1=^J, + cuf1=\s, + cuu1=\EM, + cud=\E[%p1%de, + cuf=\E[%p1%da, + hpa=\E[%p1%d`, + vpa=\E[%p1%dd, + nel=\EE, + + is1=\Ec, + is2=\E[20l, + + cpi=%?%p1%{10}%=%t\E[w%e%p1%{12}%=%t\E[2w%e%p1%{5}%=%t\E[5w%e%p1%{13}%=%p1%{14}%=%O%t\E[3w%e%p1%{16}%=%p1%{17}%=%O%t\E[4w%e%p1%{6}%=%t\E[6w%e%p1%{7}%=%t\E[7w%e%p1%{8}%=%t\E[8w%;, + lpi=%?%p1%{2}%=%t\E[4z%e%p1%{3}%=%t\E[5z%e%p1%{4}%=%t\E[6z%e%p1%{6}%=%t\E[z%e%p1%{8}%=%t\E[2z%e%p1%{12}%=%t\E[3z%;, + + csnm=%?%p1%{0}%=%tusascii%e%p1%{1}%=%tenglish%e%p1%{2}%=%tfinnish%e%p1%{3}%=%tjapanese%e%p1%{4}%=%tnorwegian%e%p1%{5}%=%tswedish%e%p1%{6}%=%tgermanic%e%p1%{7}%=%tfrench%e%p1%{8}%=%tcanadian_french%e%p1%{9}%=%titalian%e%p1%{10}%=%tspanish%e%p1%{11}%=%tline%e%p1%{12}%=%tsecurity%e%p1%{13}%=%tebcdic%e%p1%{14}%=%tapl%e%p1%{15}%=%tmosaic%;, + scs=%?%p1%{0}%=%t\E(B%e%p1%{1}%=%t\E(A%e%p1%{2}%=%t\E(C%e%p1%{3}%=%t\E(D%e%p1%{4}%=%t\E(E%e%p1%{5}%=%t\E(H%e%p1%{6}%=%t\E(K%e%p1%{7}%=%t\E(R%e%p1%{8}%=%t\E(Q%e%p1%{9}%=%t\E(Y%e%p1%{10}%=%t\E(Z%e%p1%{11}%=%t\E(0%e%p1%{12}%=%t\E(1%e%p1%{13}%=%t\E(3%e%p1%{14}%=%t\E(8%e%p1%{15}%=%t\E(}%;, + + sshm=\E[5m, + rshm=\E[m, + + smgtp=\E[%p1%dr, + smgbp=\E[;%p1%dr, + smglp=\E[%{1}%p1%+%ds, + smgrp=\E[;%{1}%p1%+%ds, + +# slines= + u9=\E[%p1%dt, + slines=\E[%p1%dt, + +# +# Graphics capabilities (low resolution, 6-pin): +# +Gdec+low, + + npins#6, + spinv#72, + spinh#75, + + porder=o\,o\,6\,5\,4\,3\,2\,1;63, + + bitwin#1, + u1=1, + bitype#1, + u2=1, + +# birep= + u4=!%p2%d%p3%c, + birep=!%p2%d%p3%c, + +# defbi= +# X is in 1/75 increments; set char spacing to 1/16.7 +# increments to allow us to get close; column is X*16.7/75. +# Y is in 1/72 increments; set line spacing to 1/12 +# increments to allow us to get close; line is Y/6. + u6=%?%p5%{1}%=%t\E[4w\E[%p1%{167}%*%{750}%/%d`\E[w\E[3z\E[%p2%{6}%/%dd\E[z\EP0q%;, + defbi=%?%p5%{1}%=%t\E[4w\E[%p1%{167}%*%{750}%/%d`\E[w\E[3z\E[%p2%{6}%/%dd\E[z\EP0q%;, + +# endbi= + u7=^X, + endbi=^X, + +# binel= + u5=-, + binel=-, + +# bicr= + u3=$, + bicr=$, + diff --git a/usr/src/cmd/lp/terminfo/epson.ti b/usr/src/cmd/lp/terminfo/epson.ti new file mode 100644 index 0000000000..8beceb1e74 --- /dev/null +++ b/usr/src/cmd/lp/terminfo/epson.ti @@ -0,0 +1,301 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Epson +# + +# +# Basic capabilities: +# +Gepson+basic, + + cols#80, + lines#66, + it#8, + + cpix, + orc#6, + orhi#60, + orl#30, + orvi#180, + + cr=^M, + cud1=^J, + cuf1=\s, + cub1=\b, + ff=^L, + ht=^I, + + cpi=%?%p1%{10}%=%t^R\EP%e%p1%{12}%=%t^R\EM%e%p1%{20}%=%t^O\EM%e%p1%{17}%=%t^O\EP%;, + cvr=%?%p1%{0}%>%p1%{256}%<%&%t\E3%p1%c%;, + + is1=^Q^X, + is2=\E@\E%0\EO, + + csnm=%?%p1%{0}%=%tusa%e%p1%{1}%=%tfrench%e%p1%{2}%=%tgerman%e%p1%{3}%=%tbritish%e%p1%{4}%=%tdanish%e%p1%{5}%=%tswedish%e%p1%{6}%=%titalian%e%p1%{7}%=%tspanish%e%p1%{8}%=%tjapanese%e%p1%{9}%=%tnorwegian%e%p1%{10}%=%tdanish2%e%p1%{11}%=%tspanish2%e%p1%{12}%=%tlatin_american%e%p1%{13}%=%tafrikaans%e%p1%{14}%=%tdutch%e%p1%{15}%=%tfrench_canadian%e%p1%{16}%=%tfrench2%e%p1%{17}%=%tbritish2%e%p1%{18}%=%tmulti_national%e%p1%{19}%=%tibmgraphics%;, + scs=%?%p1%{0}%=%t\ER\200%e%p1%{1}%=%t\ER\001%e%p1%{2}%=%t\ER\002%e%p1%{3}%=%t\ER\003%e%p1%{4}%=%t\ER\004%e%p1%{5}%=%t\ER\005%e%p1%{6}%=%t\ER\006%e%p1%{7}%=%t\ER\007%e%p1%{8}%=%t\ER\010%e%p1%{9}%=%t\ER\011%e%p1%{10}%=%t\ER\012%e%p1%{11}%=%t\ER\013%e%p1%{12}%=%t\ER\014%e%p1%{13}%=%t\ER\100%e%p1%{14}%=%t\ERA%e%p1%{15}%=%t\ERB%e%p1%{16}%=%t\ERC%e%p1%{17}%=%t\ERD%e%p1%{18}%=%t\E6%e%p1%{19}%=%t\Et1%;, + + smso=\EE, + rmso=\EF, + smul=\E-1, + rmul=\E-0, + bold=\EG, + sshm=\EE, + rshm=\EF, + ssubm=\ES1, + rsubm=\ET, + ssupm=\ES0, + rsupm=\ET, + swidm=\EW1, + rwidm=\EW0, + sitm=\E4, + ritm=\E5, + sgr0=\EF\E-0\EH\ET\EW0\E5, + sgr=%?%p1%t\EE%e\EF%;%?%p2%t\E-1%e\E-0%;%?%p6%t\EG%e\EH%;, + +# +# For now we can't set the margin in the first (0th) column +# due to limitations in the Curses code. This should be changed +# in the future. For now, shift right 1. Note that the right +# margin is the last USEABLE column in Terminfo, but is 1 +# PAST that for the Epson. + smglp=%?%p1%{256}%<%t\El%p1%{1}%+%c%;, + smgrp=%?%p1%{256}%<%t\EQ%p1%{2}%+%c%;, + +# slines= u9 used for svr3.2 + u9=%?%p1%{0}%>%p1%{128}%<%&%t\EC%p1%c%;, + slines=%?%p1%{0}%>%p1%{128}%<%&%t\EC%p1%d%;, + + sdrfq=\Ex0, + snlq=\Ex1, + snrmq=\Ek1, + +# +# Graphics capabilities: +# +Gepson+low, + + npins#8, + spinv#60, + spinh#60, + + porder=1\,2\,3\,4\,5\,6\,7\,8;0, + + sbim=\EK%p1%{256}%m%c%p1%{256}%/%c, + +# u1 - u8 used for svr3.2 + bitwin#1, + u1=1, + bitype#1, + u2=1, + +# defbi= +# Set the line spacing to 8/60 inch (7.5 lines per inch) +# to get 60 dots per inch vertically (7.5 lines/" * 8 pins/line). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 60 dots per inch horizontally this means 6 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + defbi=%?%p5%{1}%=%t\E3\030^R\EP\EB%p2%{8}%/%c$<>\ED%p1%{6}%/%c$<>\013\r\t%;, + +# endbi= + u7=\E3\036, + endbi=\E3\036, + +# binel= + u5=\n\r\t, + binel=\n\r\t, + +# bicr= + u3=\r\t, + bicr=\r\t, + +###################################################################### +# +# Epson LQ-2500 +# + +# +# Basic capabilities: +# +Gep2500+basic, + + cols#136, + lines#66, + it#8, + + cpix, + orc#6, + orhi#60, + orl#30, + orvi#180, + + cr=^M, + cud1=^J, + cuf1=\s, + cub1=\b, + ff=^L, + ht=^I, + + cpi=%?%p1%{10}%=%t^R\EP%e%p1%{12}%=%t^R\EM%e%p1%{20}%=%t^O\EM%e%p1%{17}%=%t^O\EP%;, + cvr=%?%p1%{0}%>%p1%{256}%<%&%t\E3%p1%c%;, + + is1=^Q^X, + is2=\E@\E%0\EO, + + + csnm=%?%p1%{0}%=%tusa%e%p1%{1}%=%tfrench%e%p1%{2}%=%tgerman%e%p1%{3}%=%tbritish%e%p1%{4}%=%tdanish%e%p1%{5}%=%tswedish%e%p1%{6}%=%titalian%e%p1%{7}%=%tspanish%e%p1%{8}%=%tjapanese%e%p1%{9}%=%tnorwegian%e%p1%{10}%=%tdanish2%e%p1%{11}%=%tspanish2%e%p1%{12}%=%tlatin_american%e%p1%{13}%=%tibmgraphics%;, + scs=%?%p1%{0}%=%t\ER\200%e%p1%{1}%=%t\ER\001%e%p1%{2}%=%t\ER\002%e%p1%{3}%=%t\ER\003%e%p1%{4}%=%t\ER\004%e%p1%{5}%=%t\ER\005%e%p1%{6}%=%t\ER\006%e%p1%{7}%=%t\ER\007%e%p1%{8}%=%t\ER\010%e%p1%{9}%=%t\ER\011%e%p1%{10}%=%t\ER\012%e%p1%{11}%=%t\ER\013%e%p1%{12}%=%t\ER\014%e%p1%{13}%=%t\Et1%;, + + smso=\EE, + rmso=\EF, + smul=\E-1, + rmul=\E-0, + bold=\EG, + sshm=\EE, + rshm=\EF, + ssubm=\ES1, + rsubm=\ET, + ssupm=\ES0, + rsupm=\ET, + swidm=\EW1, + rwidm=\EW0, + sitm=\E4, + ritm=\E5, + sgr0=\EF\E-0\EH\ET\EW0\E5, + sgr=%?%p1%t\EE%e\EF%;%?%p2%t\E-1%e\E-0%;%?%p6%t\EG%e\EH%;, + +# +# For now we can't set the margin in the first (0th) column +# due to limitations in the Curses code. This should be changed +# in the future. For now, shift right 1. Note that the right +# margin is the last USEABLE column in Terminfo, but is 1 +# PAST that for the Epson. + smglp=%?%p1%{256}%<%t\El%p1%{1}%+%c%;, + smgrp=%?%p1%{256}%<%t\EQ%p1%{2}%+%c%;, + +# slines= + u9=%?%p1%{0}%>%p1%{128}%<%&%t\EC%p1%c%;, + slines=%?%p1%{0}%>%p1%{128}%<%&%t\EC%p1%c%;, + + sdrfq=\Ex0, + snlq=\Ex1, + snrmq=\Ek1, + +# +# Graphics capabilities: +# +Gep2500+low, + + npins#8, + spinv#60, + spinh#60, + + porder=1\,2\,3\,4\,5\,6\,7\,8;0, + + sbim=\EK%p1%{256}%m%c%p1%{256}%/%c, + + bitwin#1, + u1=1, + bitype#1, + u2=1, + +# defbi= +# Set the line spacing to 8/60 inch (7.5 lines per inch) +# to get 60 dots per inch vertically (7.5 lines/" * 8 pins/line). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 60 dots per inch horizontally this means 6 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\E3\030^R\EP\EB%p2%{8}%/%c$<>\ED%p1%{6}%/%c$<>\013\r\t%;, + defbi=%?%p5%{1}%=%t\E3\030^R\EP\EB%p2%{8}%/%c$<>\ED%p1%{6}%/%c$<>\013\r\t%;, + +# endbi= + u7=\E3\036, + endbi=\E3\036, + +# binel= + u5=\n\r\t, + binel=\n\r\t, + +# bicr= + u3=\r\t, + bicr=\r\t, + +# +# Graphics capabilities: +# +Gep2500+high, + + npins#24, + spinv#180, + spinh#180, + + porder=1\,2\,3\,4\,5\,6\,7\,8\,9\,10\,11\,12\,13\,14\,15\,16\,17\,18\,19\,20\,21\,22\,23\,24;0, + + sbim=\E*\047%p1%{256}%m%c%p1%{256}%/%c, + +# defbi= +# Set the line spacing to 8/60 inch (7.5 lines per inch) +# to get 180 dots per inch vertically (7.5 lines/" * 24 pins/line). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 180 dots per inch horizontally this means 18 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\E3\030^R\EP\EB%p2%{24}%/%c$<>\ED%p1%{18}%/%c$<>\013\r\t%;, + defbi=%?%p5%{1}%=%t\E3\030^R\EP\EB%p2%{24}%/%c$<>\ED%p1%{18}%/%c$<>\013\r\t%;, + + use=Gep2500+low, + +# +# Color capability: +# +Gep2500+color, + + colors#3, + +# setcolor= + initc=%?%p1%{0}%=%t\Er0%;%?%p1%{1}%=%t\Er2%;%?%p1%{2}%=%t\Er1%;%?%p1%{3}%=%t\Er4%;, + +# colornm= + u8=%?%p1%{0}%=%tblack%;%?%p1%{1}%=%tcyan%;%?%p1%{2}%=%tmagenta%;%?%p1%{3}%=%tyellow%;%?%p1%{4}%=%torange=yellow+magenta%;%?%p1%{5}%=%tgreen=yellow+cyan%;%?%p1%{6}%=%tviolet=magenta+cyan%;%?%p1%{7}%=%tbrown=magenta+black%;, + colornm=%?%p1%{0}%=%tblack%;%?%p1%{1}%=%tcyan%;%?%p1%{2}%=%tmagenta%;%?%p1%{3}%=%tyellow%;%?%p1%{4}%=%torange=yellow+magenta%;%?%p1%{5}%=%tgreen=yellow+cyan%;%?%p1%{6}%=%tviolet=magenta+cyan%;%?%p1%{7}%=%tbrown=magenta+black%;, + diff --git a/usr/src/cmd/lp/terminfo/hplaser.ti b/usr/src/cmd/lp/terminfo/hplaser.ti new file mode 100644 index 0000000000..4d887f99ab --- /dev/null +++ b/usr/src/cmd/lp/terminfo/hplaser.ti @@ -0,0 +1,122 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +###################################################################### +# +# Generic entry for the HP Laserjet printers and emulations: +# + +# +# Basic capabilities: +# +Ghplaser+basic, + + cols#80, + lines#60, + + orc#12, + orhi#120, + orl#8, + orvi#48, + + cr=^M, + cud1=^J, + cuf1=\s, + cud=\E&a+%p1%dR, + cuf=\E&a+%p1%dC, + ff=^L, + hpa=\E&a%p1%dC, + vpa=\E&a%p1%dR, + + cpi=%?%p1%{10}%=%t\E&k0S%e%p1%{17}%=%t\E&k2S%;, + chr=%?%p1%{0}%>%p1%{127}%<%t\E&k%p1%dH%;, + cvr=%?%p1%{0}%>%p1%{127}%<%t\E&l%p1%dC%;, + lpi=%?%p1%{1}%=%t\E&l1D%e%p1%{2}%=%t\E&l2D%e%p1%{3}%=%t\E&l3D%e%p1%{4}%=%t\E&l4D%e%p1%{6}%=%t\E&l6D%e%p1%{8}%=%t\E&l8D%e%p1%{12}%=%t\E&l12D%e%p1%{16}%=%t\E&l16D%e%p1%{24}%=%t\E&l24D%e%p1%{48}%=%t\E&l48D%;, + + is2=\EE\E&k0G, + mgc=\E9, + + rmul=\E&d\100, + ritm=\E(s0S, + smul=\E&dD, + sitm=\E(s1S, + smgtp=\E&l%p1%{1}%+%dE, + smgbp=\E&l%p1%{1}%+%dF, + smglp=\E&a%p1%dL, + smgrp=\E&a%p1%dM, + +#Set top margin at +2 offset + smgtp=\E&l%p1%dE, + +#Set page length u9 used for 3.2 slines for 4.0 + u9=\E&l%p1P, + slines=\E&l%p1%dF, + +# +# Graphics capabilities: +# +Ghplaser+high, + + npins#8, + spinv#300, + spinh#300, + + porder=1\,2\,3\,4\,5\,6\,7\,8;0, + + sbim=\E*b%p1%dW, + +# u1 - u7 used for svr3.2 +# bitwin#, + u1=1, + bitwin#1, +# bitype# + u2=2, + bitype#2, + +# defbi= +# X (or Y) * scale * 12/5 == pos in decipoints (12/5 == 720/300) + u6=%?%p5%{0}%>%p5%{5}%<%&%t\E&a%p1%p5%*%{12}%*%{5}%/%dH\E&a%p2%p5%*%{12}%*%{5}%/%dV\E*t%{300}%p5%/%dR\E*r1A%;, + defbi=%?%p5%{0}%>%p5%{5}%<%&%t\E&a%p1%p5%*%{12}%*%{5}%/%dH\E&a%p2%p5%*%{12}%*%{5}%/%dV\E*t%{300}%p5%/%dR\E*r1A%;, + +# endbi= + u7=\E*rB, + endbi=\E*rB, + +Ghplaser+II, + + cpi=%?%p1%{10}%=%t\E(s10H%e%p1%{16}%=%p1%{17}%=%O%t\E(s16.66H%e%;, + + csnm=%?%p1%{0}%=%troman-8%e%p1%{1}%=%tibm-us%e%p1%{2}%=%tibm-dn%e%p1%{3}%=%tgerman%e%p1%{4}%=%tspanish%e%p1%{5}%=%tecma-94%e%p1%{6}%=%tiso2%e%p1%{7}%=%tiso4%e%p1%{8}%=%tiso6%e%p1%{9}%=%tiso10%e%p1%{10}%=%tiso11%e%p1%{11}%=%tiso14%e%p1%{12}%=%tiso15%e%p1%{13}%=%tiso16%e%p1%{14}%=%tiso17%e%p1%{15}%=%tiso21%e%p1%{16}%=%tiso25%e%p1%{17}%=%tiso57%e%p1%{18}%=%tiso60%e%p1%{19}%=%tiso61%e%p1%{20}%=%tiso69%e%p1%{21}%=%tiso84%e%p1%{22}%=%tiso85%;, + + scs=%?%p1%{0}%=%t\E(8U%e%p1%{1}%=%t\E(10U%e%p1%{2}%=%t\E(11U%e%p1%{3}%=%t\E(0G%e%p1%{4}%=%t\E(1S%e%p1%{5}%=%t\E(0N%e%p1%{6}%=%t\E(2U%e%p1%{7}%=%t\E(1E%e%p1%{8}%=%t\E(0U%e%p1%{9}%=%t\E(3S%e%p1%{10}%=%t\E(0S%e%p1%{11}%=%t\E(0K%e%p1%{12}%=%t\E(0I%e%p1%{13}%=%t\E(4S%e%p1%{14}%=%t\E(2S%e%p1%{15}%=%t\E(1G%e%p1%{16}%=%t\E(0F%e%p1%{17}%=%t\E(2K%e%p1%{18}%=%t\E(0D%e%p1%{19}%=%t\E(1D%e%p1%{20}%=%t\E(1F%e%p1%{21}%=%t\E(5S%e%p1%{22}%=%t\E(6S%;, + + use=Ghplaser+basic, use=Ghplaser+high, + diff --git a/usr/src/cmd/lp/terminfo/ibm.ti b/usr/src/cmd/lp/terminfo/ibm.ti new file mode 100644 index 0000000000..e58aca21eb --- /dev/null +++ b/usr/src/cmd/lp/terminfo/ibm.ti @@ -0,0 +1,353 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ + +###################################################################### +# +# Generic entries for the various IBM printers and emulations. +# + +################################### +# +# IBM Graphics +# + +# +# Basic capabilities: +# +Gibmg+basic, + + cols#80, + lines#66, + it#8, + + cpix, + orc#1, + orhi#10, + orl#12, + orvi#72, + + cr=^M, + ff=^L, + ht=^I, + cud1=^J, + cuf1=\s, + + cpi=%?%p1%{10}%=%t^R%e%p1%{16}%=%p1%{17}%=%O%t^O%;, + cvr=%?%p1%{0}%>%p1%{256}%<%&%t\EA%p1%c\E2%;, + + is1=^X, + is2=^R\EA\014\E2\EF\EH\EW0\ET\E-0\E7\EO\ECB, + + csnm=%?%p1%{0}%=%tcharacter_set_1%e%p1%{1}%=%tcharacter_set_2%;, + scs=%?%p1%{0}%=%t\E7%e%p1%{2}%=%t\E6%;, + + smso=\EE, + rmso=\EF, + smul=\E-1, + rmul=\E-0, + bold=\EG, + smacs=\E6, + rmacs=\E7, + sshm=\EE, + rshm=\EF, + ssubm=\ES1, + rsubm=\ET, + ssupm=\ES0, + rsupm=\ET, + swidm=\EW1, + rwidm=\EW0, + sgr0=\EF\E-0\EH\E7\ET\EW0, + sgr=%?%p1%t\EE%e\EF%;%?%p2%t\E-1%e\E-0%;%?%p6%t\EG%e\EH%;%?%p9%t\E6%e\E7%;, + sdrfq=\EH, + snlq=\EG, + +# slines= u9 used for svr3.2 + u9=%?%p1%{0}%>%p1%{128}%<%&%t\EC%p1%c%;, + slines=%?%p1%{0}%>%p1%{128}%<%&%t\EC%p1%c%;, + +# +# Graphics capabilities (low resolution, 9-pin): +# +Gibmg+low, + + npins#8, + spinv#72, + spinh#60, + + porder=1\,2\,3\,4\,5\,6\,7\,8;0, + + sbim=\EK%p1%{256}%m%c%p1%{256}%/%c, + + bitwin#1, + u1=1, + bitype#1, + u2=1, + +# defbi= +# Set the line spacing to 8/72 inch (9 lines per inch) +# to get 72 dots per inch vertically (9 lines/inch * 8 pins/line). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 60 dots per inch horizontally this means 6 +# dots per character. +# The IBM Graphics doesn't have parameterized motion, +# so we simulate it with linefeeds and spaces. +# Assume we never need to move across more than 63 colums +# or down more than 31 lines. +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\EA\010\E2^R%p2%{8}%/%Py%?%gy%{15}%>%t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n%gy%{16}%-%Py%;%?%gy%{7}%>%t\n\n\n\n\n\n\n\n%gy%{8}%-%Py%;%?%gy%{3}%>%t\n\n\n\n%gy%{4}%-%Py%;%?%gy%{1}%>%t\n\n%gy%{2}%-%Py%;%?%gy%{0}%>%t\n%;\r%p1%{6}%/%Px%?%gx%{31}%>%t %gx%{32}%-%Px%;%?%gx%{15}%>%t %gx%{16}%-%Px%;%?%gx%{7}%>%t %gx%{8}%-%Px%;%?%gx%{3}%>%t %gx%{4}%-%Px%;%?%gx%{1}%>%t %gx%{2}%-%Px%;%?%gx%{0}%>%t %;%;, + defbi=%?%p5%{1}%=%t\EA\010\E2^R%p2%{8}%/%Py%?%gy%{15}%>%t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n%gy%{16}%-%Py%;%?%gy%{7}%>%t\n\n\n\n\n\n\n\n%gy%{8}%-%Py%;%?%gy%{3}%>%t\n\n\n\n%gy%{4}%-%Py%;%?%gy%{1}%>%t\n\n%gy%{2}%-%Py%;%?%gy%{0}%>%t\n%;\r%p1%{6}%/%Px%?%gx%{31}%>%t %gx%{32}%-%Px%;%?%gx%{15}%>%t %gx%{16}%-%Px%;%?%gx%{7}%>%t %gx%{8}%-%Px%;%?%gx%{3}%>%t %gx%{4}%-%Px%;%?%gx%{1}%>%t %gx%{2}%-%Px%;%?%gx%{0}%>%t %;%;, + +# endbi= + u7=\EA\014\E2, + endbi=\EA\014\E2, + +# binel= + u5=\n\r%p1%{6}%/%Px%?%gx%{31}%>%t %gx%{32}%-%Px%;%?%gx%{15}%>%t %gx%{16}%-%Px%;%?%gx%{7}%>%t %gx%{8}%-%Px%;%?%gx%{3}%>%t %gx%{4}%-%Px%;%?%gx%{1}%>%t %gx%{2}%-%Px%;%?%gx%{0}%>%t %;, + binel=\n\r%p1%{6}%/%Px%?%gx%{31}%>%t %gx%{32}%-%Px%;%?%gx%{15}%>%t %gx%{16}%-%Px%;%?%gx%{7}%>%t %gx%{8}%-%Px%;%?%gx%{3}%>%t %gx%{4}%-%Px%;%?%gx%{1}%>%t %gx%{2}%-%Px%;%?%gx%{0}%>%t %;, + +# bicr= + u3=\r%p1%{6}%/%Px%?%gx%{31}%>%t %gx%{32}%-%Px%;%?%gx%{15}%>%t %gx%{16}%-%Px%;%?%gx%{7}%>%t %gx%{8}%-%Px%;%?%gx%{3}%>%t %gx%{4}%-%Px%;%?%gx%{1}%>%t %gx%{2}%-%Px%;%?%gx%{0}%>%t %;, + bicr=\r%p1%{6}%/%Px%?%gx%{31}%>%t %gx%{32}%-%Px%;%?%gx%{15}%>%t %gx%{16}%-%Px%;%?%gx%{7}%>%t %gx%{8}%-%Px%;%?%gx%{3}%>%t %gx%{4}%-%Px%;%?%gx%{1}%>%t %gx%{2}%-%Px%;%?%gx%{0}%>%t %;, + +################################### +# +# IBM Color +# + +# +# Basic capabilities: +# +Gibmc+basic, + + cub1=\b, + + is1=^Q^X, + is2=^R\EA\014\E2\EF\EH\EW0\ET\E-0\E7\EO\ER\E50\EM0\EX^A\210\Eb\ECB, + + cvr=%?%p1%{0}%>%p1%{256}%<%&%t\E3%p1%c%;, + + smglp=\EX%p1%{1}%+%c%p2%{1}%+%c, + + use=Gibmg+basic, + +# +# Graphics capabilities (low resolution, 9-pin, 5:6 aspect ratio): +# +Gibmc+low+5x6, + + spinv#84, + spinh#70, + +# defbi= +# Set 5:6 aspect ratio. +# Set the line spacing to 7/72 inch (10.29 lines per inch) +# to get approximately 84 dots per inch vertically +# (10.29 lines/inch * 8 pins/line equals 82.28 dots per inch). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 70 dots per inch horizontally this means 7 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\En^B\E1^R\EB%p2%{8}%/%c$<>\ED%p1%{7}%/%c$<>\013\r\t%;, + defbi=%?%p5%{1}%=%t\En^B\E1^R\EB%p2%{8}%/%c$<>\ED%p1%{7}%/%c$<>\013\r\t%;, + +# binel= + u5=\n\r\t, + binel=\n\r\t, + +# bicr= + u3=\r\t, + bicr=\r\t, + + use=Gibmg+low, + +# +# Graphics capabilities (low resolution, 9-pin, 1:1 aspect ratio): +# +Gibmc+low+1x1, + + spinh#84, + +# defbi= +# Set 1:1 aspect ratio. +# Set the line spacing to 7/72 inch (10.29 lines per inch) +# to get approximately 84 dots per inch vertically +# (10.29 lines/inch * 8 pins/line equals 82.28 dots per inch). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 84 dots per inch horizontally this means 8.4 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\En^A\E1^R\EB%p2%{8}%/%c$<>\ED%p1%{10}%*%{84}%/%c$<>\013\r\t%;, + defbi=%?%p5%{1}%=%t\En^A\E1^R\EB%p2%{8}%/%c$<>\ED%p1%{10}%*%{84}%/%c$<>\013\r\t%;, + + use=Gibmc+low+5x6, + +# +# Color capability: +# +Gibmc+color, + + colors#3, + +# setcolor= + initc=%?%p1%{0}%=%t\Eb%;%?%p1%{1}%=%t\Ec%;%?%p1%{2}%=%t\Em%;%?%p1%{3}%=%t\Ey%;, + +# colornm= + u8=%?%p1%{0}%=%tblack%;%?%p1%{1}%=%tcyan%;%?%p1%{2}%=%tmagenta%;%?%p1%{3}%=%tyellow%;%?%p1%{4}%=%torange=yellow+magenta%;%?%p1%{5}%=%tgreen=yellow+cyan%;%?%p1%{6}%=%tviolet=magenta+cyan%;%?%p1%{7}%=%tbrown=magenta+black%;, + colornm=%?%p1%{0}%=%tblack%;%?%p1%{1}%=%tcyan%;%?%p1%{2}%=%tmagenta%;%?%p1%{3}%=%tyellow%;%?%p1%{4}%=%torange=yellow+magenta%;%?%p1%{5}%=%tgreen=yellow+cyan%;%?%p1%{6}%=%tviolet=magenta+cyan%;%?%p1%{7}%=%tbrown=magenta+black%;, + +################################### +# +# IBM Proprinter XL: +# +# This printer appears to be a superset of the IBM Graphics +# and IBM Color printers, with a 24-wire printhead. The entry +# below uses the full capabilities of the superset and printhead. +# The printer has an Alternate Graphics Mode (AGM) that changes +# the vertical resolution from 1/216" to 1/180", and the graphics +# aspect ratio from 5:6 to 1:1. HOWEVER, there does not appear to +# be a control sequence that switches into this mode--it must be +# done by hand! +# + +# +# Basic capabilities (printer not in AGM): +# +Gibmxl+basic, + + orc#12, + orhi#120, + orl#36, + orvi#216, + + cub1=\b, + + cpi=%?%p1%{10}%=%t^R%e%p1%{12}%=%t\E:%e%p1%{17}%=%t^O%;, + cvr=%?%p1%{0}%>%p1%{256}%<%&%t\E3%p1%c%;, + + is1=^Q^X, + is2=^R\EP0\EA\014\E2\EC\102\EO\ER\Eb\E50\EF\EH\EW0\ET\E-0\E_0\E7, + is3=\EX\001\120, + + smglp=\EX%p1%{1}%+%c%p2%{1}%+%c, + + use=Gibmg+basic, + +# +# Basic capabilities (printer in AGM): +# +Gibmxlagm+basic, + + orl#30, + orvi#180, + + is2=^R\EP0\EA\012\E2\EC\102\EO\ER\Eb\E50\EF\EH\EW0\ET\E-0\E_0\E7, + + use=Gibmxl+basic, + +# +# Graphics capabilities (low resolution, 8-pin, 5:6 aspect ratio): +# +Gibmxl+low+5x6, + + spinv#72, + spinh#60, + +# defbi= +# Set the line spacing to 8/72 inch (9 lines per inch) +# to get 72 dots per inch vertically (9 lines/" * 8 pins/line). +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 60 dots per inch horizontally this means 6 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\EA\010\E2^R\EB%p2%{8}%/%c$<>\ED%p1%{6}%/%c$<>\013\r\t%;, + defbi=%?%p5%{1}%=%t\EA\010\E2^R\EB%p2%{8}%/%c$<>\ED%p1%{6}%/%c$<>\013\r\t%;, + + use=Gibmc+low+5x6, + +# +# Graphics capabilities (low resolution, 8-pin, 1:1 aspect ratio): +# +Gibmxl+low+1x1, + + spinv#60, + +# In AGM the "defbi" cap from Gibmxl+low+5x6 will work. The +# line spacing will be 8/60 inch to get 60 dots per inch, using +# the same control sequence. + + use=Gibmxl+low+5x6, + +# +# Graphics capabilities (high resolution, 24-pin, 5:6 aspect ratio): +# +# This doesn't work as the pin spacing doesn't get set to +# 1/216 inch, but stays at 1/180 inch, even out of AGM. +# + +# +# Graphics capabilities (high resolution, 24-pin, 1:1 aspect ratio): +# +Gibmxl+high+1x1, + + npins#24, + spinv#180, + spinh#180, + + porder=1\,2\,3\,4\,5\,6\,7\,8\,9\,10\,11\,12\,13\,14\,15\,16\,17\,18\,19\,20\,21\,22\,23\,24;0, + + sbim=\E*\047%p1%{256}%m%c%p1%{256}%/%c, + +# defbi= +# Set the line spacing to 8/60 inch (7.5 lines per inch) +# to get 180 dots per inch vertically (7.5 lines/" * 24 pins/line). +# This requires the printer or emulation in Alternate Graphics Mode. +# Set the character spacing to pica (1/10 inch or 10 characters +# per inch); at 180 dots per inch horizontally this means 18 +# dots per character. +# Set vertical and horizontal tab stops at the upper left corner +# of the image, then tab to the upper left corner. +# Note: $<> is a true null (only works with special Curses routine). +# THIS ASSUMES WE START AT THE TOP OF THE PAGE! (although +# maybe not in the first column.) + u6=%?%p5%{1}%=%t\EA\010\E2^R\EB%p2%{24}%/%c$<>\ED%p1%{18}%/%c$<>\013\r\t%;, + defbi=%?%p5%{1}%=%t\EA\010\E2^R\EB%p2%{24}%/%c$<>\ED%p1%{18}%/%c$<>\013\r\t%;, + + use=Gibmc+low+5x6, + diff --git a/usr/src/cmd/ssh/libopenbsd-compat/i386/Makefile b/usr/src/cmd/lp/terminfo/unknown.ti index fde6250470..85f95a606e 100644 --- a/usr/src/cmd/ssh/libopenbsd-compat/i386/Makefile +++ b/usr/src/cmd/lp/terminfo/unknown.ti @@ -19,12 +19,12 @@ # # CDDL HEADER END # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# +# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved -include ../Makefile.com -install: all +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ +unknown, + am, gn, + cols#80, + bel=^G, cr=\r, cud1=\n, ind=\n, diff --git a/usr/src/cmd/ssh/scp/Makefile b/usr/src/cmd/machid/Makefile index 0d0bf4f6c9..6a3c7138dc 100644 --- a/usr/src/cmd/ssh/scp/Makefile +++ b/usr/src/cmd/machid/Makefile @@ -19,42 +19,62 @@ # # CDDL HEADER END # +# +# ident "%Z%%M% %I% %E% SMI" +# # Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" + +PROG= machid + +include ../Makefile.cmd + +# +# List of all links present on all architectures and machines. # -# cmd/ssh/scp/Makefile +# Note that this function is obsolesent and we don't generally +# add to this list (see psarc/1992/171). +# +FIRSTLINK = i286 +LINKS = i386 i486 i860 i86pc iAPX286 \ + m68k mc68000 mc68010 mc68020 mc68030 mc68040 \ + sparc sun sun2 sun3 sun3x sun4 sun4c sun4m sun4d sun4e \ + u370 u3b u3b15 u3b2 u3b5 vax pdp11 -PROG= scp +ROOTFIRSTLINK = $(ROOTBIN)/$(FIRSTLINK) +ROOTLINKS = $(LINKS:%=$(ROOTBIN)/%) -OBJS = \ - scp.o -SRCS = $(OBJS:.o=.c) +# +# Install the program as the first machine in the list. +# +INSTALLIT= $(INS.link) +$(ROOTFIRSTLINK):= INSTALLIT = $(INS.rename) +$(ROOTLINKS):= INSLINKTARGET = $(ROOTFIRSTLINK) -include ../../Makefile.cmd -include ../Makefile.ssh-common +$(ROOTLINKS): $(ROOTFIRSTLINK) -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket +# +# Link installation rules +# +$(ROOTBIN)/%: $(PROG) + $(INSTALLIT) -POFILE_DIR= .. +$(ROOTFIRSTLINK): $(ROOTBIN) -.KEEP_STATE: +$(ROOTBIN): + $(INS.dir) -.PARALLEL: $(OBJS) +CFLAGS += $(CCVERBOSE) -all: $(PROG) +.KEEP_STATE: -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) - $(POST_PROCESS) +all: $(PROG) -install: all $(ROOTPROG) +install: all $(ROOTLINKS) clean: - $(RM) -f $(OBJS) $(PROG) -lint: lint_SRCS +lint: lint_PROG -include ../Makefile.msg.targ -include ../../Makefile.targ +include ../Makefile.targ diff --git a/usr/src/cmd/machid/machid.c b/usr/src/cmd/machid/machid.c new file mode 100644 index 0000000000..c3d57b91f9 --- /dev/null +++ b/usr/src/cmd/machid/machid.c @@ -0,0 +1,137 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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) 1993-1994, by Sun Microsystems, Inc. + */ + +/* + * This program replicates the function of the links from a machine name + * (such as sun4c) through /usr/kvm to true or false as appropriate. It + * knows the correct special cases. + * + * IMPORTANT NOTE: + * + * Do not modify this program to know about additional special cases or + * reflect new platforms or instruction set architectures. This is a + * deprecated interface and strictly for backwards compatibility. This + * is psarc/1992/171. Note the following excerpt from the opinion: + * + * It is most important to note that the manual page states in + * the NOTES section: "The machid family of commands is + * obsolete. Use uname -p and uname -m instead." + * + * The intent of Kernel Architecture Project team is to provide + * only enough functionality to mimic the existing definitions + * on the SPARC and Intel x86 versions of Solaris 2.x. No new + * identifiers will ever be added to the documented and + * undocumented identifiers listed above. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <limits.h> +#include <sys/systeminfo.h> + +static char static_buf[SYS_NMLN]; +static char *progname; + +static void get_info_item(int command, char **buf, long *count); + +/* ARGSUSED */ +int +main(int argc, char *argv[], char *envp[]) +{ + char *buf = &static_buf[0]; + long buflen = SYS_NMLN; + + if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + progname++; + + /* + * First possible match is on the processor type. + * + * Special case for architectures: i386 matches i486 and visa versa. + */ + get_info_item(SI_ARCHITECTURE, &buf, &buflen); + if (strcmp(buf, progname) == 0) + return (0); + if ((strcmp(buf, "i386") == 0 && strcmp(progname, "i486") == 0) || + (strcmp(buf, "i486") == 0 && strcmp(progname, "i386") == 0)) + return (0); + + /* + * Next possible match is the machine, or more exactly, the value + * which would be returned by uname(2) in the machine field or uname(1) + * with the -m option. For historical reasons this is really is + * often a class of platforms which are identical to userland processes + * such as sun4c, sun4m, etc. + */ + get_info_item(SI_MACHINE, &buf, &buflen); + if (strcmp(buf, progname) == 0) + return (0); + + /* + * Finally, match the vendor. We hardwire in one historical match. + */ + get_info_item(SI_HW_PROVIDER, &buf, &buflen); + if (strcmp(buf, progname) == 0) + return (0); + if (strcasecmp(buf, "Sun_Microsystems") == 0 && + strcmp("sun", progname) == 0) + return (0); + + return (255); +} + +/* + * get_info_item is a wrapper around the sysinfo system call. It makes sure + * the buffer is large enough, returning a larger buffer if needed. On + * unrecoverable error, it exits. An error message doesn't help and makes + * this tiny program link stdio and maybe deal with internationalization, + * so the best thing is to die silently. Note that the larger buffer is + * retained for later use. Reality is that the buffer will always be big + * enough, but this is coded to the spec rather than implementation. + */ +static void +get_info_item(int command, char **buf, long *count) +{ + long error; + + error = sysinfo(command, *buf, *count); + if (error > *count) { + *count = error; + if (*buf != static_buf) { + free(*buf); + } + *buf = (char *) malloc(*count); + error = sysinfo(command, *buf, *count); + } + + if (error == -1) + exit(-1); +} diff --git a/usr/src/cmd/man/Makefile b/usr/src/cmd/man/Makefile index 911bae6340..7c7afebb10 100644 --- a/usr/src/cmd/man/Makefile +++ b/usr/src/cmd/man/Makefile @@ -14,12 +14,7 @@ # Copyright 2014 Garrett D'Amore <garrett@damore.org> # -PROG= man -LINKS= apropos whatis catman -LIBLINKS = makewhatis -OBJS= makewhatis.o man.o stringlist.o -SRCS= $(OBJS:%.o=%.c) - +include Makefile.com include $(SRC)/cmd/Makefile.cmd CFLAGS += $(CCVERBOSE) diff --git a/usr/src/cmd/man/Makefile.com b/usr/src/cmd/man/Makefile.com new file mode 100644 index 0000000000..8f1b3adf7d --- /dev/null +++ b/usr/src/cmd/man/Makefile.com @@ -0,0 +1,23 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2012 Nexenta Systems, Inc. All rights reserved. +# Copyright 2014 Garrett D'Amore <garrett@damore.org> +# + +PROG= man +LINKS= apropos whatis catman +LIBLINKS = makewhatis +OBJS= makewhatis.o man.o stringlist.o +SRCS= $(OBJS:%.o=%.c) + + diff --git a/usr/src/cmd/mdb/Makefile.common b/usr/src/cmd/mdb/Makefile.common index aca0144fdf..6644e8bc25 100644 --- a/usr/src/cmd/mdb/Makefile.common +++ b/usr/src/cmd/mdb/Makefile.common @@ -40,7 +40,8 @@ COMMON_MODULES_PROC = \ libuutil \ libzpool \ mdb_ds \ - mdb_test + mdb_test \ + v8 # # MDB modules used for debugging user processes which are only 32-bit diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c b/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c index 81ac1eacfc..f39fb83c9b 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c @@ -742,10 +742,10 @@ kmdb_prom_debugger_exit(void) mdb.m_pio = NULL; } -#ifdef DEBUG /* - * The prom_* files use ASSERT, which is #defined as assfail(). - * We need to redirect that to our assert function. + * The prom_* files use ASSERT, which is #defined as assfail(). We need to + * redirect that to our assert function. This is also used by the various STAND + * libraries. */ int kmdb_prom_assfail(const char *assertion, const char *file, int line) @@ -754,7 +754,6 @@ kmdb_prom_assfail(const char *assertion, const char *file, int line) /*NOTREACHED*/ return (0); } -#endif /* * Begin the initialization of the debugger/PROM interface. Initialization is diff --git a/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c b/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c index 0a211fcd22..e8c703e754 100644 --- a/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c +++ b/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <mdb/mdb_debug.h> #include <mdb/mdb.h> @@ -67,6 +65,13 @@ ctf_fdopen(int fd, int *errp) /*ARGSUSED*/ ctf_file_t * +ctf_fdcreate_int(int fd, int *errp, ctf_sect_t *ctfp) +{ + return (ctf_set_open_errno(errp, ENOTSUP)); +} + +/*ARGSUSED*/ +ctf_file_t * ctf_open(const char *filename, int *errp) { return (ctf_set_open_errno(errp, ENOTSUP)); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c index 66a8b009a3..4d4cb226c6 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c @@ -24,7 +24,7 @@ */ /* * Copyright (c) 2013 by Delphix. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #include <mdb/mdb_ctf.h> @@ -37,6 +37,7 @@ #include <libctf.h> #include <string.h> +#include <limits.h> typedef struct tnarg { mdb_tgt_t *tn_tgt; /* target to use for lookup */ @@ -781,8 +782,9 @@ mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data) /* * callback proxy for mdb_ctf_type_iter */ +/* ARGSUSED */ static int -type_iter_cb(ctf_id_t type, void *data) +type_iter_cb(ctf_id_t type, boolean_t root, void *data) { type_iter_t *tip = data; mdb_ctf_id_t id; @@ -812,7 +814,7 @@ mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) ti.ti_arg = data; ti.ti_fp = fp; - if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR) + if ((ret = ctf_type_iter(fp, B_FALSE, type_iter_cb, &ti)) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); return (ret); @@ -1780,7 +1782,6 @@ mdb_ctf_synthetics_create_base(int kind) return (0); discard: - err = set_errno(ctf_to_errno(ctf_errno(cp))); (void) ctf_discard(cp); return (err); } @@ -1939,7 +1940,7 @@ mdb_ctf_add_member(const mdb_ctf_id_t *p, const char *name, return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); } - id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid); + id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid, ULONG_MAX); if (id == CTF_ERR) { mdb_dprintf(MDB_DBG_CTF, "failed to add member %s: %s\n", name, ctf_errmsg(ctf_errno(mdb.m_synth))); @@ -2040,7 +2041,7 @@ mdb_ctf_add_pointer(const mdb_ctf_id_t *p, mdb_ctf_id_t *rid) } - id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, id); + id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, NULL, id); if (id == CTF_ERR) { mdb_dprintf(MDB_DBG_CTF, "failed to add pointer: %s\n", ctf_errmsg(ctf_errno(mdb.m_synth))); @@ -2088,6 +2089,7 @@ mdb_ctf_type_delete(const mdb_ctf_id_t *id) return (0); } +/* ARGSUSED */ static int mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id, void *arg) { @@ -2125,7 +2127,7 @@ mdb_ctf_synthetics_from_file(const char *file) ti.ti_fp = fp; ti.ti_arg = syn; ti.ti_cb = mdb_ctf_synthetics_file_cb; - if (ctf_type_iter(fp, type_iter_cb, &ti) == CTF_ERR) { + if (ctf_type_iter(fp, B_FALSE, type_iter_cb, &ti) == CTF_ERR) { ret = set_errno(ctf_to_errno(ctf_errno(fp))); mdb_warn("failed to add types"); goto cleanup; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_debug.c b/usr/src/cmd/mdb/common/mdb/mdb_debug.c index d373d3726e..a158864a28 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_debug.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_debug.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <mdb/mdb_debug.h> #include <mdb/mdb_err.h> #include <mdb/mdb_io.h> @@ -157,7 +155,6 @@ mdb_dmode(uint_t bits) mdb.m_debug = bits; } -#ifdef DEBUG int mdb_dassert(const char *expr, const char *file, int line) { @@ -165,7 +162,6 @@ mdb_dassert(const char *expr, const char *file, int line) /*NOTREACHED*/ return (0); } -#endif /* * Function to convert mdb longjmp codes (see <mdb/mdb.h>) into a string for diff --git a/usr/src/cmd/mdb/common/mdb/mdb_debug.h b/usr/src/cmd/mdb/common/mdb/mdb_debug.h index cf3b97b499..f889238e4f 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_debug.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_debug.h @@ -27,8 +27,6 @@ #ifndef _MDB_DEBUG_H #define _MDB_DEBUG_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -66,8 +64,8 @@ extern void mdb_dmode(uint_t); extern const char *mdb_err2str(int); -#ifdef DEBUG extern int mdb_dassert(const char *, const char *, int); +#ifdef DEBUG #define ASSERT(x) ((void)((x) || mdb_dassert(#x, __FILE__, __LINE__))) #else #define ASSERT(x) diff --git a/usr/src/cmd/mdb/common/mdb/mdb_demangle.c b/usr/src/cmd/mdb/common/mdb/mdb_demangle.c index 7ab7d19716..27c8a1d21d 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_demangle.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_demangle.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ #include <mdb/mdb_modapi.h> #include <mdb/mdb_demangle.h> @@ -263,7 +265,8 @@ int cmd_demangle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { mdb_demangler_t *dmp = mdb.m_demangler; - const char *path = LIB_DEMANGLE; + const char *path; + char buf[MAXPATHLEN]; if (argc > 1 || (argc > 0 && argv->a_type != MDB_TYPE_STRING)) return (DCMD_USAGE); @@ -272,6 +275,10 @@ cmd_demangle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (dmp != NULL) mdb_dem_unload(mdb.m_demangler); path = argv->a_un.a_str; + } else { + (void) snprintf(buf, MAXPATHLEN, + "%s/%s", mdb.m_root, LIB_DEMANGLE); + path = buf; } if (dmp != NULL && argc == 0 && !(mdb.m_flags & MDB_FL_DEMANGLE)) { diff --git a/usr/src/cmd/mdb/common/mdb/mdb_main.c b/usr/src/cmd/mdb/common/mdb/mdb_main.c index 90e048bb82..a30ee45b7e 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_main.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_main.c @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -51,6 +51,7 @@ #include <libctf.h> #include <errno.h> #include <kvm.h> +#include <zone.h> #include <mdb/mdb_lex.h> #include <mdb/mdb_debug.h> @@ -797,9 +798,15 @@ main(int argc, char *argv[], char *envp[]) if (strchr(pidarg, '/') != NULL) (void) mdb_iob_snprintf(object, MAXPATHLEN, "%s/object/a.out", pidarg); - else + else { + const char *root; + (void) mdb_iob_snprintf(object, MAXPATHLEN, - "/proc/%s/object/a.out", pidarg); + "%s/proc/%s/object/a.out", + (root = zone_get_nroot()) != NULL ? root : "", + pidarg); + } + tgt_argv[tgt_argc++] = object; tgt_argv[tgt_argc++] = pidarg; } diff --git a/usr/src/cmd/mdb/common/mdb/mdb_modapi.h b/usr/src/cmd/mdb/common/mdb/mdb_modapi.h index 9d08a18c69..c6b4956b3b 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_modapi.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_modapi.h @@ -22,7 +22,7 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. - * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Copyright (c) 2013 Joyent, Inc. All rights reserved. */ #ifndef _MDB_MODAPI_H @@ -71,7 +71,13 @@ extern "C" { #define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif +#ifdef MDB_API_VERSION +#if (MDB_API_VERSION != 3 && MDB_API_VERSION != 4) +#error "Only modapi versions three and four are supported." +#endif +#else /* !MDB_API_VERISON */ #define MDB_API_VERSION 4 /* Current API version number */ +#endif /* MDB_API_VERISON */ /* * Debugger command function flags: @@ -85,11 +91,6 @@ extern "C" { #define DCMD_HDRSPEC(fl) (((fl) & DCMD_LOOPFIRST) || !((fl) & DCMD_LOOP)) /* - * Debugger tab command function flags - */ -#define DCMD_TAB_SPACE 0x01 /* Tab cb invoked with trailing space */ - -/* * Debugger command function return values: */ #define DCMD_OK 0 /* Dcmd completed successfully */ @@ -118,10 +119,18 @@ typedef struct mdb_arg { } a_un; } mdb_arg_t; +#if (MDB_API_VERSION >= 4) +/* + * Debugger tab command function flags + */ +#define DCMD_TAB_SPACE 0x01 /* Tab cb invoked with trailing space */ + typedef struct mdb_tab_cookie mdb_tab_cookie_t; -typedef int mdb_dcmd_f(uintptr_t, uint_t, int, const mdb_arg_t *); typedef int mdb_dcmd_tab_f(mdb_tab_cookie_t *, uint_t, int, const mdb_arg_t *); +#endif /* MDB_API_VERSION >= 4 */ + +typedef int mdb_dcmd_f(uintptr_t, uint_t, int, const mdb_arg_t *); typedef struct mdb_dcmd { const char *dc_name; /* Command name */ @@ -129,7 +138,9 @@ typedef struct mdb_dcmd { const char *dc_descr; /* Description */ mdb_dcmd_f *dc_funcp; /* Command function */ void (*dc_help)(void); /* Command help function (or NULL) */ +#if (MDB_API_VERSION >= 4) mdb_dcmd_tab_f *dc_tabp; /* Tab completion function */ +#endif } mdb_dcmd_t; #define WALK_ERR -1 /* Walk fatal error (terminate walk) */ @@ -346,6 +357,7 @@ typedef void (*mdb_callback_f)(void *); extern void *mdb_callback_add(int, mdb_callback_f, void *); extern void mdb_callback_remove(void *); +#if (MDB_API_VERSION >= 4) #define MDB_TABC_ALL_TYPES 0x1 /* Include array types in type output */ #define MDB_TABC_MEMBERS 0x2 /* Tab comp. types with members */ #define MDB_TABC_NOPOINT 0x4 /* Tab comp. everything but pointers */ @@ -370,6 +382,7 @@ extern int mdb_tab_typename(int *, const mdb_arg_t **, char *buf, size_t len); */ extern int mdb_tab_complete_mt(mdb_tab_cookie_t *, uint_t, int, const mdb_arg_t *); +#endif /* MDB_API_VERSION >= 4 */ extern size_t strlcat(char *, const char *, size_t); extern char *strcat(char *, const char *); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.c b/usr/src/cmd/mdb/common/mdb/mdb_print.c index 3a083d4ac0..fe74265b68 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_print.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_print.c @@ -2106,10 +2106,10 @@ cmd_print_tab_common(mdb_tab_cookie_t *mcp, uint_t flags, int argc, /* * This is the reason that tab completion was created. We're going to go - * along and walk the delimiters until we find something a member that - * we don't recognize, at which point we'll try and tab complete it. - * Note that ::print takes multiple args, so this is going to operate on - * whatever the last arg that we have is. + * along and walk the delimiters until we find something in a member + * that we don't recognize, at which point we'll try and tab complete + * it. Note that ::print takes multiple args, so this is going to + * operate on whatever the last arg that we have is. */ if (mdb_ctf_lookup_by_name(tn, &id) != 0) return (1); @@ -2119,11 +2119,11 @@ cmd_print_tab_common(mdb_tab_cookie_t *mcp, uint_t flags, int argc, delim = parse_delimiter(&start); /* - * If we hit the case where we actually have no delimiters, than we need + * If we hit the case where we actually have no delimiters, then we need * to make sure that we properly set up the fields the loops would. */ if (delim == MEMBER_DELIM_DONE) - (void) mdb_snprintf(member, sizeof (member), "%s", start); + (void) mdb_snprintf(member, sizeof (member), start); while (delim != MEMBER_DELIM_DONE) { switch (delim) { @@ -2180,7 +2180,7 @@ cmd_print_tab_common(mdb_tab_cookie_t *mcp, uint_t flags, int argc, /* * We are going to try to resolve this name as a member. There - * are a few two different questions that we need to answer. The + * are a two different questions that we need to answer. The * first is do we recognize this member. The second is are we at * the end of the string. If we encounter a member that we don't * recognize before the end, then we have to error out and can't @@ -2210,6 +2210,7 @@ cmd_print_tab_common(mdb_tab_cookie_t *mcp, uint_t flags, int argc, * already have in rid. */ return (mdb_tab_complete_member_by_id(mcp, rid, member)); + } int @@ -2539,8 +2540,7 @@ print_help(void) } static int -printf_signed(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt, - boolean_t sign) +printf_signed(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt, int sign) { ssize_t size; mdb_ctf_id_t base; @@ -2558,7 +2558,7 @@ printf_signed(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt, } u; if (mdb_ctf_type_resolve(id, &base) == -1) { - mdb_warn("could not resolve type"); + mdb_warn("could not resolve type\n"); return (DCMD_ABORT); } @@ -2796,7 +2796,6 @@ printf_string(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt) if (size != 1) { mdb_warn("string format specifier requires " "an array of characters\n"); - return (DCMD_ABORT); } bzero(buf, sizeof (buf)); @@ -2930,7 +2929,7 @@ cmd_printf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (argc == 0 || argv[0].a_type != MDB_TYPE_STRING) { mdb_warn("expected a format string\n"); - return (DCMD_USAGE); + return (DCMD_ABORT); } /* @@ -2939,12 +2938,6 @@ cmd_printf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * subset of mdb_printf() format strings that we allow. */ fmt = argv[0].a_un.a_str; - /* - * 'dest' must be large enough to hold a copy of the format string, - * plus a NUL and up to 2 additional characters for each conversion - * in the format string. This gives us a bloat factor of 5/2 ~= 3. - * e.g. "%d" (strlen of 2) --> "%lld\0" (need 5 bytes) - */ dest = mdb_zalloc(strlen(fmt) * 3, UM_SLEEP | UM_GC); fmts = mdb_zalloc(strlen(fmt) * sizeof (char *), UM_SLEEP | UM_GC); funcs = mdb_zalloc(strlen(fmt) * sizeof (void *), UM_SLEEP | UM_GC); @@ -3128,22 +3121,22 @@ static char _mdb_printf_help[] = "\n" " %% Prints the '%' symbol.\n" " %a Prints the member in symbolic form.\n" -" %d Prints the member as a decimal integer. If the member is a signed\n" +" %d Prints the member as a decimal integer. If the member is a signed\n" " integer type, the output will be signed.\n" " %H Prints the member as a human-readable size.\n" " %I Prints the member as an IPv4 address (must be 32-bit integer type).\n" " %N Prints the member as an IPv6 address (must be of type in6_addr_t).\n" " %o Prints the member as an unsigned octal integer.\n" " %p Prints the member as a pointer, in hexadecimal.\n" -" %q Prints the member in signed octal. Honk if you ever use this!\n" -" %r Prints the member as an unsigned value in the current output radix.\n" -" %R Prints the member as a signed value in the current output radix.\n" +" %q Prints the member in signed octal. Honk if you ever use this!\n" +" %r Prints the member as an unsigned value in the current output radix. \n" +" %R Prints the member as a signed value in the current output radix. \n" " %s Prints the member as a string (requires a pointer or an array of\n" " characters).\n" " %u Prints the member as an unsigned decimal integer.\n" " %x Prints the member in hexadecimal.\n" " %X Prints the member in hexadecimal, using the characters A-F as the\n" -" digits for the values 10-15.\n" +" digits for the values 10-15. \n" " %Y Prints the member as a time_t as the string " "'year month day HH:MM:SS'.\n" "\n" @@ -3156,13 +3149,13 @@ static char _mdb_printf_help[] = "\n" "The following flag specifers are recognized by ::printf:\n" "\n" -" %- Left-justify the output within the specified field width. If the\n" +" %- Left-justify the output within the specified field width. If the\n" " width of the output is less than the specified field width, the\n" -" output will be padded with blanks on the right-hand side. Without\n" +" output will be padded with blanks on the right-hand side. Without\n" " %-, values are right-justified by default.\n" "\n" " %0 Zero-fill the output field if the output is right-justified and the\n" -" width of the output is less than the specified field width. Without\n" +" width of the output is less than the specified field width. Without\n" " %0, right-justified values are prepended with blanks in order to\n" " fill the field.\n" "\n" diff --git a/usr/src/cmd/mdb/common/mdb/mdb_tab.c b/usr/src/cmd/mdb/common/mdb/mdb_tab.c index af32623470..66bd18586e 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_tab.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_tab.c @@ -388,11 +388,6 @@ mdb_tab_size(mdb_tab_cookie_t *mcp) return (mdb_nv_size(&mcp->mtc_nv)); } -/* - * Determine whether the specified name is a valid tab completion for - * the given command. If the name is a valid tab completion then - * it will be saved in the mdb_tab_cookie_t. - */ void mdb_tab_insert(mdb_tab_cookie_t *mcp, const char *name) { @@ -508,31 +503,18 @@ tab_complete_type(mdb_ctf_id_t id, void *arg) mdb_tab_cookie_t *mcp = arg; uint_t flags = (uint_t)(uintptr_t)mcp->mtc_cba; - /* - * CTF data includes types that mdb commands don't understand. Before - * we resolve the actual type prune any entry that is a type we - * don't care about. - */ - switch (mdb_ctf_type_kind(id)) { - case CTF_K_CONST: - case CTF_K_RESTRICT: - case CTF_K_VOLATILE: - return (0); - } - if (mdb_ctf_type_resolve(id, &rid) != 0) return (1); rkind = mdb_ctf_type_kind(rid); - - if ((flags & MDB_TABC_MEMBERS) && rkind != CTF_K_STRUCT && + if (flags & MDB_TABC_MEMBERS && rkind != CTF_K_STRUCT && rkind != CTF_K_UNION) return (0); - if ((flags & MDB_TABC_NOPOINT) && rkind == CTF_K_POINTER) + if (flags & MDB_TABC_NOPOINT && rkind == CTF_K_POINTER) return (0); - if ((flags & MDB_TABC_NOARRAY) && rkind == CTF_K_ARRAY) + if (flags & MDB_TABC_NOARRAY && rkind == CTF_K_ARRAY) return (0); (void) mdb_ctf_type_name(id, buf, sizeof (buf)); diff --git a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c index 7858866a01..50ad2c3497 100644 --- a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c +++ b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -433,6 +433,7 @@ dtracemdb_bufsnap(dtrace_buffer_t *which, dtrace_bufdesc_t *desc) desc->dtbd_size = bufsize; desc->dtbd_drops = buf.dtb_drops; desc->dtbd_errors = buf.dtb_errors; + desc->dtbd_timestamp = gethrtime(); return (0); } diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c index 4b24ee5a31..152e52b790 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c +++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c @@ -21,7 +21,7 @@ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013 Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. */ @@ -113,10 +113,6 @@ */ #define NINTR 16 -#define KILOS 10 -#define MEGS 20 -#define GIGS 30 - #ifndef STACK_BIAS #define STACK_BIAS 0 #endif @@ -169,6 +165,88 @@ ps_threadprint(uintptr_t addr, const void *data, void *private) return (WALK_NEXT); } +static int +pflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + proc_t pr; + struct pid pid; + + static const mdb_bitmask_t p_flag_bits[] = { + { "SSYS", SSYS, SSYS }, + { "SEXITING", SEXITING, SEXITING }, + { "SITBUSY", SITBUSY, SITBUSY }, + { "SFORKING", SFORKING, SFORKING }, + { "SWATCHOK", SWATCHOK, SWATCHOK }, + { "SKILLED", SKILLED, SKILLED }, + { "SSCONT", SSCONT, SSCONT }, + { "SZONETOP", SZONETOP, SZONETOP }, + { "SEXTKILLED", SEXTKILLED, SEXTKILLED }, + { "SUGID", SUGID, SUGID }, + { "SEXECED", SEXECED, SEXECED }, + { "SJCTL", SJCTL, SJCTL }, + { "SNOWAIT", SNOWAIT, SNOWAIT }, + { "SVFORK", SVFORK, SVFORK }, + { "SVFWAIT", SVFWAIT, SVFWAIT }, + { "SEXITLWPS", SEXITLWPS, SEXITLWPS }, + { "SHOLDFORK", SHOLDFORK, SHOLDFORK }, + { "SHOLDFORK1", SHOLDFORK1, SHOLDFORK1 }, + { "SCOREDUMP", SCOREDUMP, SCOREDUMP }, + { "SMSACCT", SMSACCT, SMSACCT }, + { "SLWPWRAP", SLWPWRAP, SLWPWRAP }, + { "SAUTOLPG", SAUTOLPG, SAUTOLPG }, + { "SNOCD", SNOCD, SNOCD }, + { "SHOLDWATCH", SHOLDWATCH, SHOLDWATCH }, + { "SMSFORK", SMSFORK, SMSFORK }, + { "SDOCORE", SDOCORE, SDOCORE }, + { NULL, 0, 0 } + }; + + static const mdb_bitmask_t p_pidflag_bits[] = { + { "CLDPEND", CLDPEND, CLDPEND }, + { "CLDCONT", CLDCONT, CLDCONT }, + { "CLDNOSIGCHLD", CLDNOSIGCHLD, CLDNOSIGCHLD }, + { "CLDWAITPID", CLDWAITPID, CLDWAITPID }, + { NULL, 0, 0 } + }; + + static const mdb_bitmask_t p_proc_flag_bits[] = { + { "P_PR_TRACE", P_PR_TRACE, P_PR_TRACE }, + { "P_PR_PTRACE", P_PR_PTRACE, P_PR_PTRACE }, + { "P_PR_FORK", P_PR_FORK, P_PR_FORK }, + { "P_PR_LOCK", P_PR_LOCK, P_PR_LOCK }, + { "P_PR_ASYNC", P_PR_ASYNC, P_PR_ASYNC }, + { "P_PR_EXEC", P_PR_EXEC, P_PR_EXEC }, + { "P_PR_BPTADJ", P_PR_BPTADJ, P_PR_BPTADJ }, + { "P_PR_RUNLCL", P_PR_RUNLCL, P_PR_RUNLCL }, + { "P_PR_KILLCL", P_PR_KILLCL, P_PR_KILLCL }, + { NULL, 0, 0 } + }; + + if (!(flags & DCMD_ADDRSPEC)) { + if (mdb_walk_dcmd("proc", "pflags", argc, argv) == -1) { + mdb_warn("can't walk 'proc'"); + return (DCMD_ERR); + } + return (DCMD_OK); + } + + if (mdb_vread(&pr, sizeof (pr), addr) == -1 || + mdb_vread(&pid, sizeof (pid), (uintptr_t)pr.p_pidp) == -1) { + mdb_warn("cannot read proc_t or pid"); + return (DCMD_ERR); + } + + mdb_printf("%p [pid %d]:\n", addr, pid.pid_id); + mdb_printf("\tp_flag: %08x <%b>\n", pr.p_flag, pr.p_flag, + p_flag_bits); + mdb_printf("\tp_pidflag: %08x <%b>\n", pr.p_pidflag, pr.p_pidflag, + p_pidflag_bits); + mdb_printf("\tp_proc_flag: %08x <%b>\n", pr.p_proc_flag, pr.p_proc_flag, + p_proc_flag_bits); + + return (DCMD_OK); +} + int ps(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { @@ -1904,24 +1982,24 @@ typedef struct datafmt { } datafmt_t; static datafmt_t kmemfmt[] = { - { "cache ", "name ", - "-------------------------", "%-25s " }, - { " buf", " size", "------", "%6u " }, - { " buf", "in use", "------", "%6u " }, - { " buf", " total", "------", "%6u " }, - { " memory", " in use", "----------", "%10lu%c " }, - { " alloc", " succeed", "---------", "%9u " }, - { "alloc", " fail", "-----", "%5u " }, + { "cache ", "name ", + "------------------------------", "%-30s " }, + { " buf", " size", "-----", "%5H " }, + { " buf", " in use", "---------", "%9u " }, + { " buf", " total", "---------", "%9u " }, + { "memory", "in use", "------", "%6lH " }, + { " alloc", " succeed", "----------", "%10u " }, + { "alloc", " fail", "-----", "%5u" }, { NULL, NULL, NULL, NULL } }; static datafmt_t vmemfmt[] = { - { "vmem ", "name ", - "-------------------------", "%-*s " }, - { " memory", " in use", "----------", "%9llu%c " }, - { " memory", " total", "-----------", "%10llu%c " }, - { " memory", " import", "----------", "%9llu%c " }, - { " alloc", " succeed", "---------", "%9llu " }, + { "vmem ", "name ", + "------------------------------", "%-*s " }, + { " memory", " in use", "---------", "%9llH " }, + { " memory", " total", "----------", "%10llH " }, + { " memory", " import", "---------", "%9llH " }, + { " alloc", " succeed", "----------", "%10llu " }, { "alloc", " fail", "-----", "%5llu " }, { NULL, NULL, NULL, NULL } }; @@ -1973,15 +2051,9 @@ typedef struct kmastat_vmem { int kv_fail; } kmastat_vmem_t; -typedef struct kmastat_args { - kmastat_vmem_t **ka_kvpp; - uint_t ka_shift; -} kmastat_args_t; - static int -kmastat_cache(uintptr_t addr, const kmem_cache_t *cp, kmastat_args_t *kap) +kmastat_cache(uintptr_t addr, const kmem_cache_t *cp, kmastat_vmem_t **kvpp) { - kmastat_vmem_t **kvpp = kap->ka_kvpp; kmastat_vmem_t *kv; datafmt_t *dfp = kmemfmt; int magsize; @@ -2022,9 +2094,7 @@ out: mdb_printf((dfp++)->fmt, cp->cache_bufsize); mdb_printf((dfp++)->fmt, total - avail); mdb_printf((dfp++)->fmt, total); - mdb_printf((dfp++)->fmt, meminuse >> kap->ka_shift, - kap->ka_shift == GIGS ? 'G' : kap->ka_shift == MEGS ? 'M' : - kap->ka_shift == KILOS ? 'K' : 'B'); + mdb_printf((dfp++)->fmt, meminuse); mdb_printf((dfp++)->fmt, alloc); mdb_printf((dfp++)->fmt, cp->cache_alloc_fail); mdb_printf("\n"); @@ -2033,9 +2103,8 @@ out: } static int -kmastat_vmem_totals(uintptr_t addr, const vmem_t *v, kmastat_args_t *kap) +kmastat_vmem_totals(uintptr_t addr, const vmem_t *v, kmastat_vmem_t *kv) { - kmastat_vmem_t *kv = *kap->ka_kvpp; size_t len; while (kv != NULL && kv->kv_addr != addr) @@ -2044,20 +2113,18 @@ kmastat_vmem_totals(uintptr_t addr, const vmem_t *v, kmastat_args_t *kap) if (kv == NULL || kv->kv_alloc == 0) return (WALK_NEXT); - len = MIN(17, strlen(v->vm_name)); + len = MIN(22, strlen(v->vm_name)); - mdb_printf("Total [%s]%*s %6s %6s %6s %10lu%c %9u %5u\n", v->vm_name, - 17 - len, "", "", "", "", - kv->kv_meminuse >> kap->ka_shift, - kap->ka_shift == GIGS ? 'G' : kap->ka_shift == MEGS ? 'M' : - kap->ka_shift == KILOS ? 'K' : 'B', kv->kv_alloc, kv->kv_fail); + mdb_printf("Total [%s]%*s %5s %9s %9s %6lH %10u %5u\n", v->vm_name, + 22 - len, "", "", "", "", + kv->kv_meminuse, kv->kv_alloc, kv->kv_fail); return (WALK_NEXT); } /*ARGSUSED*/ static int -kmastat_vmem(uintptr_t addr, const vmem_t *v, const uint_t *shiftp) +kmastat_vmem(uintptr_t addr, const vmem_t *v, const void *ignored) { datafmt_t *dfp = vmemfmt; const vmem_kstat_t *vkp = &v->vm_kstat; @@ -2075,16 +2142,10 @@ kmastat_vmem(uintptr_t addr, const vmem_t *v, const uint_t *shiftp) } mdb_printf("%*s", ident, ""); - mdb_printf((dfp++)->fmt, 25 - ident, v->vm_name); - mdb_printf((dfp++)->fmt, vkp->vk_mem_inuse.value.ui64 >> *shiftp, - *shiftp == GIGS ? 'G' : *shiftp == MEGS ? 'M' : - *shiftp == KILOS ? 'K' : 'B'); - mdb_printf((dfp++)->fmt, vkp->vk_mem_total.value.ui64 >> *shiftp, - *shiftp == GIGS ? 'G' : *shiftp == MEGS ? 'M' : - *shiftp == KILOS ? 'K' : 'B'); - mdb_printf((dfp++)->fmt, vkp->vk_mem_import.value.ui64 >> *shiftp, - *shiftp == GIGS ? 'G' : *shiftp == MEGS ? 'M' : - *shiftp == KILOS ? 'K' : 'B'); + mdb_printf((dfp++)->fmt, 30 - ident, v->vm_name); + mdb_printf((dfp++)->fmt, vkp->vk_mem_inuse.value.ui64); + mdb_printf((dfp++)->fmt, vkp->vk_mem_total.value.ui64); + mdb_printf((dfp++)->fmt, vkp->vk_mem_import.value.ui64); mdb_printf((dfp++)->fmt, vkp->vk_alloc.value.ui64); mdb_printf((dfp++)->fmt, vkp->vk_fail.value.ui64); @@ -2099,44 +2160,35 @@ kmastat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { kmastat_vmem_t *kv = NULL; datafmt_t *dfp; - kmastat_args_t ka; - - ka.ka_shift = 0; - if (mdb_getopts(argc, argv, - 'k', MDB_OPT_SETBITS, KILOS, &ka.ka_shift, - 'm', MDB_OPT_SETBITS, MEGS, &ka.ka_shift, - 'g', MDB_OPT_SETBITS, GIGS, &ka.ka_shift, NULL) != argc) - return (DCMD_USAGE); for (dfp = kmemfmt; dfp->hdr1 != NULL; dfp++) - mdb_printf("%s ", dfp->hdr1); + mdb_printf("%s%s", dfp == kmemfmt ? "" : " ", dfp->hdr1); mdb_printf("\n"); for (dfp = kmemfmt; dfp->hdr1 != NULL; dfp++) - mdb_printf("%s ", dfp->hdr2); + mdb_printf("%s%s", dfp == kmemfmt ? "" : " ", dfp->hdr2); mdb_printf("\n"); for (dfp = kmemfmt; dfp->hdr1 != NULL; dfp++) - mdb_printf("%s ", dfp->dashes); + mdb_printf("%s%s", dfp == kmemfmt ? "" : " ", dfp->dashes); mdb_printf("\n"); - ka.ka_kvpp = &kv; - if (mdb_walk("kmem_cache", (mdb_walk_cb_t)kmastat_cache, &ka) == -1) { + if (mdb_walk("kmem_cache", (mdb_walk_cb_t)kmastat_cache, &kv) == -1) { mdb_warn("can't walk 'kmem_cache'"); return (DCMD_ERR); } for (dfp = kmemfmt; dfp->hdr1 != NULL; dfp++) - mdb_printf("%s ", dfp->dashes); + mdb_printf("%s%s", dfp == kmemfmt ? "" : " ", dfp->dashes); mdb_printf("\n"); - if (mdb_walk("vmem", (mdb_walk_cb_t)kmastat_vmem_totals, &ka) == -1) { + if (mdb_walk("vmem", (mdb_walk_cb_t)kmastat_vmem_totals, kv) == -1) { mdb_warn("can't walk 'vmem'"); return (DCMD_ERR); } for (dfp = kmemfmt; dfp->hdr1 != NULL; dfp++) - mdb_printf("%s ", dfp->dashes); + mdb_printf("%s%s", dfp == kmemfmt ? "" : " ", dfp->dashes); mdb_printf("\n"); mdb_printf("\n"); @@ -2153,7 +2205,7 @@ kmastat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("%s ", dfp->dashes); mdb_printf("\n"); - if (mdb_walk("vmem", (mdb_walk_cb_t)kmastat_vmem, &ka.ka_shift) == -1) { + if (mdb_walk("vmem", (mdb_walk_cb_t)kmastat_vmem, NULL) == -1) { mdb_warn("can't walk 'vmem'"); return (DCMD_ERR); } @@ -3867,6 +3919,7 @@ static const mdb_dcmd_t dcmds[] = { { "pid2proc", "?", "convert PID to proc_t address", pid2proc }, { "project", NULL, "display kernel project(s)", project }, { "ps", "[-fltzTP]", "list processes (and associated thr,lwp)", ps }, + { "pflags", NULL, "display various proc_t flags", pflags }, { "pgrep", "[-x] [-n | -o] pattern", "pattern match against all processes", pgrep }, { "ptree", NULL, "print process tree", ptree }, @@ -3993,8 +4046,7 @@ static const mdb_dcmd_t dcmds[] = { { "freedby", ":", "given a thread, print its freed buffers", freedby }, { "kmalog", "?[ fail | slab ]", "display kmem transaction log and stack traces", kmalog }, - { "kmastat", "[-kmg]", "kernel memory allocator stats", - kmastat }, + { "kmastat", NULL, "kernel memory allocator stats", kmastat }, { "kmausers", "?[-ef] [cache ...]", "current medium and large users " "of the kmem allocator", kmausers, kmausers_help }, { "kmem_cache", "?[-n name]", @@ -4191,6 +4243,8 @@ static const mdb_dcmd_t dcmds[] = { /* from zone.c */ { "zid2zone", ":", "find the zone_t with the given zone id", zid2zone }, + { "zdid2zone", ":", "find the zone_t with the given zone debug id", + zdid2zone }, { "zone", "?[-r [-v]]", "display kernel zone(s)", zoneprt }, { "zsd", ":[-v] [zsd_key]", "display zone-specific-data entries for " "selected zones", zsd }, diff --git a/usr/src/cmd/mdb/common/modules/genunix/kmem.c b/usr/src/cmd/mdb/common/modules/genunix/kmem.c index f1693d7bf6..0df368d70c 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/kmem.c +++ b/usr/src/cmd/mdb/common/modules/genunix/kmem.c @@ -24,7 +24,7 @@ */ /* - * Copyright 2011 Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -3896,6 +3896,8 @@ kmalog(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) logname = "kmem_failure_log"; else if (strcmp(argv->a_un.a_str, "slab") == 0) logname = "kmem_slab_log"; + else if (strcmp(argv->a_un.a_str, "zerosized") == 0) + logname = "kmem_zerosized_log"; else return (DCMD_USAGE); } diff --git a/usr/src/cmd/mdb/common/modules/genunix/zone.c b/usr/src/cmd/mdb/common/modules/genunix/zone.c index a332cdfc01..77ed2cbc48 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/zone.c +++ b/usr/src/cmd/mdb/common/modules/genunix/zone.c @@ -34,9 +34,9 @@ #define ZONE_NAMELEN 20 #ifdef _LP64 -#define ZONE_PATHLEN 32 +#define ZONE_PATHLEN 25 #else -#define ZONE_PATHLEN 40 +#define ZONE_PATHLEN 33 #endif /* @@ -80,6 +80,31 @@ zid2zone(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } +static int +zdid_lookup_cb(uintptr_t addr, const zone_t *zone, void *arg) +{ + zoneid_t zdid = *(uintptr_t *)arg; + if (zone->zone_did == zdid) + mdb_printf("%p\n", addr); + + return (WALK_NEXT); +} + +/*ARGSUSED*/ +int +zdid2zone(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + if (!(flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + if (mdb_walk("zone", (mdb_walk_cb_t)zdid_lookup_cb, &addr) == -1) { + mdb_warn("failed to walk zone"); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + int zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { @@ -122,10 +147,10 @@ zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) */ if (DCMD_HDRSPEC(flags)) { if (ropt_given == FALSE) - mdb_printf("%<u>%?s %6s %-13s %-20s %-s%</u>\n", + mdb_printf("%<u>%?s %4s %-13s %-19s %-s%</u>\n", "ADDR", "ID", "STATUS", "NAME", "PATH"); else - mdb_printf("%<u>%?s %6s %10s %10s %-20s%</u>\n", + mdb_printf("%<u>%?s %6s %10s %10s %-19s%</u>\n", "ADDR", "ID", "REFS", "CREFS", "NAME"); } @@ -164,7 +189,7 @@ zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) statusp = zone_status_names[zn.zone_status]; else statusp = "???"; - mdb_printf("%0?p %6d %-13s %-20s %s\n", addr, zn.zone_id, + mdb_printf("%0?p %4d %-13s %-19s %s\n", addr, zn.zone_id, statusp, name, path); } else { /* @@ -172,7 +197,7 @@ zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * Display the zone's subsystem-specific reference counts if * the user specified the '-v' option. */ - mdb_printf("%0?p %6d %10u %10u %-20s\n", addr, zn.zone_id, + mdb_printf("%0?p %6d %10u %10u %-19s\n", addr, zn.zone_id, zn.zone_ref, zn.zone_cred_ref, name); if (vopt_given == TRUE) { GElf_Sym subsys_names_sym; @@ -410,7 +435,7 @@ zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * Prepare to output the specified zone's ZSD information. */ if (DCMD_HDRSPEC(flags)) - mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY", + mdb_printf("%<u>%-19s %?s %?s %8s%</u>\n", "ZONE", "KEY", "VALUE", "FLAGS"); len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name); if (len > 0) { @@ -419,7 +444,7 @@ zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } else { (void) strcpy(name, "??"); } - mdb_printf("%-20s ", name); + mdb_printf("%-19s ", name); /* * Display the requested ZSD entries. diff --git a/usr/src/cmd/mdb/common/modules/genunix/zone.h b/usr/src/cmd/mdb/common/modules/genunix/zone.h index 0881f9bbae..94a383e41c 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/zone.h +++ b/usr/src/cmd/mdb/common/modules/genunix/zone.h @@ -34,6 +34,7 @@ extern "C" { #endif extern int zid2zone(uintptr_t, uint_t, int argc, const mdb_arg_t *); +extern int zdid2zone(uintptr_t, uint_t, int argc, const mdb_arg_t *); extern int zoneprt(uintptr_t, uint_t, int argc, const mdb_arg_t *); extern int zone_walk_init(mdb_walk_state_t *); diff --git a/usr/src/cmd/mdb/common/modules/libc/libc.c b/usr/src/cmd/mdb/common/modules/libc/libc.c index 967198e40b..c4b713f096 100644 --- a/usr/src/cmd/mdb/common/modules/libc/libc.c +++ b/usr/src/cmd/mdb/common/modules/libc/libc.c @@ -137,6 +137,8 @@ d_ucontext(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) uc.uc_stack.ss_sp, uc.uc_stack.ss_size, stack_flags(&uc.uc_stack)); mdb_printf(" mcontext = 0x%p\n", addr + OFFSETOF(ucontext_t, uc_mcontext)); + mdb_printf(" brand = 0x%p 0x%p 0x%p\n", + uc.uc_brand_data[0], uc.uc_brand_data[1], uc.uc_brand_data[2]); return (DCMD_OK); } @@ -841,14 +843,19 @@ d_uberdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) prt_addr(uberdata.all_lwps, 1), prt_addr(uberdata.all_zombies, 0)); - HD("nthreads nzombies ndaemons pid sigacthandler"); - mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %s\n", + HD("nthreads nzombies ndaemons pid"); + mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d\n", OFFSET(nthreads), uberdata.nthreads, uberdata.nzombies, uberdata.ndaemons, - (int)uberdata.pid, - prt_addr((void *)uberdata.sigacthandler, 0)); + (int)uberdata.pid); + + HD("sigacthandler setctxt"); + mdb_printf(OFFSTR "%s %s\n", + OFFSET(sigacthandler), + prt_addr((void *)uberdata.sigacthandler, 1), + prt_addr((void *)uberdata.setctxt, 1)); HD("lwp_stacks lwp_laststack nfreestack stk_cache"); mdb_printf(OFFSTR "%s %s %-10d %d\n", @@ -871,12 +878,17 @@ d_uberdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) prt_addr(uberdata.ulwp_replace_last, 1), prt_addr(uberdata.atforklist, 0)); - HD("robustlocks robustlist progname"); - mdb_printf(OFFSTR "%s %s %s\n", + HD("robustlocks robustlist"); + mdb_printf(OFFSTR "%s %s\n", OFFSET(robustlocks), prt_addr(uberdata.robustlocks, 1), - prt_addr(uberdata.robustlist, 1), - prt_addr(uberdata.progname, 0)); + prt_addr(uberdata.robustlist, 1)); + + HD("progname ub_broot"); + mdb_printf(OFFSTR "%s %s\n", + OFFSET(progname), + prt_addr(uberdata.progname, 1), + prt_addr(uberdata.ub_broot, 1)); HD("tdb_bootstrap tdb_sync_addr_hash tdb_'count tdb_'fail"); mdb_printf(OFFSTR "%s %s %-10d %d\n", diff --git a/usr/src/cmd/mdb/common/modules/mac/mac.c b/usr/src/cmd/mdb/common/modules/mac/mac.c index 29fe51870d..9c1bcf458f 100644 --- a/usr/src/cmd/mdb/common/modules/mac/mac.c +++ b/usr/src/cmd/mdb/common/modules/mac/mac.c @@ -42,6 +42,7 @@ #define LAYERED_WALKER_FOR_FLOW "flow_entry_cache" #define LAYERED_WALKER_FOR_SRS "mac_srs_cache" #define LAYERED_WALKER_FOR_RING "mac_ring_cache" +#define LAYERED_WALKER_FOR_GROUP "mac_impl_cache" /* arguments passed to mac_flow dee-command */ #define MAC_FLOW_NONE 0x01 @@ -70,6 +71,12 @@ #define MAC_SRS_RXINTR (MAC_SRS_RX|MAC_SRS_INTR) #define MAC_SRS_TXINTR (MAC_SRS_TX|MAC_SRS_INTR) +/* arguments passed to mac_group dcmd */ +#define MAC_GROUP_NONE 0x00 +#define MAC_GROUP_RX 0x01 +#define MAC_GROUP_TX 0x02 +#define MAC_GROUP_UNINIT 0x04 + static char * mac_flow_proto2str(uint8_t protocol) { @@ -369,7 +376,8 @@ mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args, 't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args, 's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args, - 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args) != argc)) { + 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args, + NULL) != argc)) { return (DCMD_USAGE); } if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER))) @@ -551,7 +559,8 @@ mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args, 'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args, 'i', MDB_OPT_SETBITS, MAC_SRS_INTR, &args, - 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args) != argc) { + 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args, + NULL) != argc) { return (DCMD_USAGE); } @@ -1002,10 +1011,214 @@ mac_ring_help(void) "hardware rings in the system are printed.\n"); } +/* + * To walk groups we have to have our own somewhat-complicated state machine. We + * basically start by walking the mac_impl_t walker as all groups are stored off + * of the various mac_impl_t in the system. The tx and rx rings are kept + * separately. So we'll need to walk through all the rx rings and then all of + * the tx rings. + */ +static int +mac_group_walk_init(mdb_walk_state_t *wsp) +{ + int ret; + + if (wsp->walk_addr != NULL) { + mdb_warn("non-global walks are not supported\n"); + return (WALK_ERR); + } + + if ((ret = mdb_layered_walk(LAYERED_WALKER_FOR_GROUP, wsp)) == -1) { + mdb_warn("couldn't walk '%s'", LAYERED_WALKER_FOR_GROUP); + return (ret); + } + + return (WALK_NEXT); +} + +static int +mac_group_walk_step(mdb_walk_state_t *wsp) +{ + int ret; + mac_impl_t mi; + mac_group_t mg; + uintptr_t mgp; + + /* + * Nothing to do if we can't find the layer above us. But the kmem + * walkers are a bit unsporting, they don't actually read in the data + * for us. + */ + if (wsp->walk_addr == NULL) + return (WALK_DONE); + + if (mdb_vread(&mi, sizeof (mac_impl_t), wsp->walk_addr) == -1) { + mdb_warn("failed to read mac_impl_t at %p", wsp->walk_addr); + return (DCMD_ERR); + } + + /* + * First go for rx groups, then tx groups. + */ + mgp = (uintptr_t)mi.mi_rx_groups; + while (mgp != NULL) { + if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) { + mdb_warn("failed to read mac_group_t at %p", mgp); + return (WALK_ERR); + } + + ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata); + if (ret != WALK_NEXT) + return (ret); + mgp = (uintptr_t)mg.mrg_next; + } + + mgp = (uintptr_t)mi.mi_tx_groups; + while (mgp != NULL) { + if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) { + mdb_warn("failed to read mac_group_t at %p", mgp); + return (WALK_ERR); + } + + ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata); + if (ret != WALK_NEXT) + return (ret); + mgp = (uintptr_t)mg.mrg_next; + } + + return (WALK_NEXT); +} + +static int +mac_group_count_clients(mac_group_t *mgp) +{ + int clients = 0; + uintptr_t mcp = (uintptr_t)mgp->mrg_clients; + + while (mcp != NULL) { + mac_grp_client_t c; + + if (mdb_vread(&c, sizeof (c), mcp) == -1) { + mdb_warn("failed to read mac_grp_client_t at %p", mcp); + return (-1); + } + clients++; + mcp = (uintptr_t)c.mgc_next; + } + + return (clients); +} + +static const char * +mac_group_type(mac_group_t *mgp) +{ + const char *ret; + + switch (mgp->mrg_type) { + case MAC_RING_TYPE_RX: + ret = "RECEIVE"; + break; + case MAC_RING_TYPE_TX: + ret = "TRANSMIT"; + break; + default: + ret = "UNKNOWN"; + break; + } + + return (ret); +} + +static const char * +mac_group_state(mac_group_t *mgp) +{ + const char *ret; + + switch (mgp->mrg_state) { + case MAC_GROUP_STATE_UNINIT: + ret = "UNINT"; + break; + case MAC_GROUP_STATE_REGISTERED: + ret = "REGISTERED"; + break; + case MAC_GROUP_STATE_RESERVED: + ret = "RESERVED"; + break; + case MAC_GROUP_STATE_SHARED: + ret = "SHARED"; + break; + default: + ret = "UNKNOWN"; + break; + } + + return (ret); +} + +static int +mac_group_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uint_t args = MAC_SRS_NONE; + mac_group_t mg; + int clients; + + if (!(flags & DCMD_ADDRSPEC)) { + if (mdb_walk_dcmd("mac_group", "mac_group", argc, argv) == -1) { + mdb_warn("failed to walk 'mac_group'"); + return (DCMD_ERR); + } + + return (DCMD_OK); + } + + if (mdb_getopts(argc, argv, + 'r', MDB_OPT_SETBITS, MAC_GROUP_RX, &args, + 't', MDB_OPT_SETBITS, MAC_GROUP_TX, &args, + 'u', MDB_OPT_SETBITS, MAC_GROUP_UNINIT, &args, + NULL) != argc) + return (DCMD_USAGE); + + if (mdb_vread(&mg, sizeof (mac_group_t), addr) == -1) { + mdb_warn("failed to read mac_group_t at %p", addr); + return (DCMD_ERR); + } + + if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) { + mdb_printf("%<u>%-?s %-8s %-10s %6s %8s %-?s%</u>\n", + "ADDR", "TYPE", "STATE", "NRINGS", "NCLIENTS", "RINGS"); + } + + if ((args & MAC_GROUP_RX) != 0 && mg.mrg_type != MAC_RING_TYPE_RX) + return (DCMD_OK); + if ((args & MAC_GROUP_TX) != 0 && mg.mrg_type != MAC_RING_TYPE_TX) + return (DCMD_OK); + + /* + * By default, don't show uninitialized groups. They're not very + * interesting. They have no rings and no clients. + */ + if (mg.mrg_state == MAC_GROUP_STATE_UNINIT && + (args & MAC_GROUP_UNINIT) == 0) + return (DCMD_OK); + + if (flags & DCMD_PIPE_OUT) { + mdb_printf("%lr\n", addr); + return (DCMD_OK); + } + + clients = mac_group_count_clients(&mg); + mdb_printf("%?p %-8s %-10s %6d %8d %?p\n", addr, mac_group_type(&mg), + mac_group_state(&mg), mg.mrg_cur_count, clients, mg.mrg_rings); + + return (DCMD_OK); +} + /* Supported dee-commands */ static const mdb_dcmd_t dcmds[] = { {"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures", mac_flow_dcmd, mac_flow_help}, + {"mac_group", "?[-rtu]", "display MAC Ring Groups", mac_group_dcmd, + NULL }, {"mac_srs", "?[ -r[i|s|c[v]] | -t[i|s|c[v]] ]", "display MAC Soft Ring Set" " structures", mac_srs_dcmd, mac_srs_help}, @@ -1018,6 +1231,8 @@ static const mdb_dcmd_t dcmds[] = { static const mdb_walker_t walkers[] = { {"mac_flow", "walk list of flow entry structures", mac_flow_walk_init, mac_common_walk_step, NULL, NULL}, + {"mac_group", "walk list of ring group structures", mac_group_walk_init, + mac_group_walk_step, NULL, NULL}, {"mac_srs", "walk list of mac soft ring set structures", mac_srs_walk_init, mac_common_walk_step, NULL, NULL}, {"mac_ring", "walk list of mac ring structures", mac_ring_walk_init, diff --git a/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c b/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c index c39583b1f5..6556fc9cd5 100644 --- a/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c +++ b/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c @@ -24,7 +24,7 @@ */ /* - * Copyright 2014 Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. All rights reserved. * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. */ @@ -34,6 +34,7 @@ #include <sys/sunmdi.h> #include <sys/list.h> #include <sys/scsi/scsi.h> +#include <sys/refhash.h> #pragma pack(1) #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> @@ -47,7 +48,6 @@ #pragma pack() #include <sys/scsi/adapters/mpt_sas/mptsas_var.h> -#include <sys/scsi/adapters/mpt_sas/mptsas_hash.h> struct { int value; diff --git a/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c b/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c new file mode 100644 index 0000000000..6609097742 --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c @@ -0,0 +1,5709 @@ +/* + * 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) 2015, Joyent, Inc. All rights reserved. + */ + +/* + * mdb(1M) module for debugging the V8 JavaScript engine. This implementation + * makes heavy use of metadata defined in the V8 binary for inspecting in-memory + * structures. Canned configurations can be manually loaded for V8 binaries + * that predate this metadata. See mdb_v8_cfg.c for details. + * + * NOTE: This dmod implementation (including this file and related headers and C + * files) exist in both the Node and illumos source trees. THESE SHOULD BE KEPT + * IN SYNC. The version in the Node tree is built directly into modern Node + * binaries as part of the build process, and the version in the illumos source + * tree is delivered with the OS for debugging Node binaries that predate + * support for including the dmod directly in the binary. Note too that these + * files have different licenses to match their corresponding repositories. + */ + +/* + * We hard-code our MDB_API_VERSION to be 3 to allow this module to be + * compiled on systems with higher version numbers, but still allow the + * resulting binary object to be used on older systems. (We do not make use + * of functionality present in versions later than 3.) This is particularly + * important for mdb_v8 because (1) it's used in particular to debug + * application-level software and (2) it has a history of rapid evolution. + */ +#define MDB_API_VERSION 3 + +#include <sys/mdb_modapi.h> +#include <assert.h> +#include <ctype.h> +#include <inttypes.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <libproc.h> +#include <sys/avl.h> +#include <alloca.h> + +#include "v8dbg.h" +#include "v8cfg.h" + +#define offsetof(s, m) ((size_t)(&(((s *)0)->m))) + +/* + * The "v8_class" and "v8_field" structures describe the C++ classes used to + * represent V8 heap objects. + */ +typedef struct v8_class { + struct v8_class *v8c_next; /* list linkage */ + struct v8_class *v8c_parent; /* parent class (inheritance) */ + struct v8_field *v8c_fields; /* array of class fields */ + size_t v8c_start; /* offset of first class field */ + size_t v8c_end; /* offset of first subclass field */ + char v8c_name[64]; /* heap object class name */ +} v8_class_t; + +typedef struct v8_field { + struct v8_field *v8f_next; /* list linkage */ + ssize_t v8f_offset; /* field offset */ + char v8f_name[64]; /* field name */ + boolean_t v8f_isbyte; /* 1-byte int field */ + boolean_t v8f_isstr; /* NUL-terminated string */ +} v8_field_t; + +/* + * Similarly, the "v8_enum" structure describes an enum from V8. + */ +typedef struct { + char v8e_name[64]; + uint_t v8e_value; +} v8_enum_t; + +/* + * During configuration, the dmod updates these globals with the actual set of + * classes, types, and frame types based on the debug metadata. + */ +static v8_class_t *v8_classes; + +static v8_enum_t v8_types[128]; +static int v8_next_type; + +static v8_enum_t v8_frametypes[16]; +static int v8_next_frametype; + +static int v8_warnings; +static int v8_silent; + +/* + * The following constants describe offsets from the frame pointer that are used + * to inspect each stack frame. They're initialized from the debug metadata. + */ +static ssize_t V8_OFF_FP_CONTEXT; +static ssize_t V8_OFF_FP_MARKER; +static ssize_t V8_OFF_FP_FUNCTION; +static ssize_t V8_OFF_FP_ARGS; + +/* + * The following constants are used by macros defined in heap-dbg-common.h to + * examine the types of various V8 heap objects. In general, the macros should + * be preferred to using the constants directly. The values of these constants + * are initialized from the debug metadata. + */ +static intptr_t V8_FirstNonstringType; +static intptr_t V8_IsNotStringMask; +static intptr_t V8_StringTag; +static intptr_t V8_NotStringTag; +static intptr_t V8_StringEncodingMask; +static intptr_t V8_TwoByteStringTag; +static intptr_t V8_AsciiStringTag; +static intptr_t V8_StringRepresentationMask; +static intptr_t V8_SeqStringTag; +static intptr_t V8_ConsStringTag; +static intptr_t V8_SlicedStringTag; +static intptr_t V8_ExternalStringTag; +static intptr_t V8_FailureTag; +static intptr_t V8_FailureTagMask; +static intptr_t V8_HeapObjectTag; +static intptr_t V8_HeapObjectTagMask; +static intptr_t V8_SmiTag; +static intptr_t V8_SmiTagMask; +static intptr_t V8_SmiValueShift; +static intptr_t V8_SmiShiftSize; +static intptr_t V8_PointerSizeLog2; + +static intptr_t V8_ISSHARED_SHIFT; +static intptr_t V8_DICT_SHIFT; +static intptr_t V8_DICT_PREFIX_SIZE; +static intptr_t V8_DICT_ENTRY_SIZE; +static intptr_t V8_DICT_START_INDEX; +static intptr_t V8_FIELDINDEX_MASK; +static intptr_t V8_FIELDINDEX_SHIFT; +static intptr_t V8_PROP_IDX_CONTENT; +static intptr_t V8_PROP_IDX_FIRST; +static intptr_t V8_PROP_TYPE_FIELD; +static intptr_t V8_PROP_TYPE_MASK; +static intptr_t V8_PROP_DESC_KEY; +static intptr_t V8_PROP_DESC_DETAILS; +static intptr_t V8_PROP_DESC_VALUE; +static intptr_t V8_PROP_DESC_SIZE; +static intptr_t V8_TRANSITIONS_IDX_DESC; + +static intptr_t V8_TYPE_JSOBJECT = -1; +static intptr_t V8_TYPE_JSARRAY = -1; +static intptr_t V8_TYPE_JSFUNCTION = -1; +static intptr_t V8_TYPE_FIXEDARRAY = -1; + +static intptr_t V8_ELEMENTS_KIND_SHIFT; +static intptr_t V8_ELEMENTS_KIND_BITCOUNT; +static intptr_t V8_ELEMENTS_FAST_ELEMENTS; +static intptr_t V8_ELEMENTS_FAST_HOLEY_ELEMENTS; +static intptr_t V8_ELEMENTS_DICTIONARY_ELEMENTS; + +/* + * Although we have this information in v8_classes, the following offsets are + * defined explicitly because they're used directly in code below. + */ +static ssize_t V8_OFF_CODE_INSTRUCTION_SIZE; +static ssize_t V8_OFF_CODE_INSTRUCTION_START; +static ssize_t V8_OFF_CONSSTRING_FIRST; +static ssize_t V8_OFF_CONSSTRING_SECOND; +static ssize_t V8_OFF_EXTERNALSTRING_RESOURCE; +static ssize_t V8_OFF_FIXEDARRAY_DATA; +static ssize_t V8_OFF_FIXEDARRAY_LENGTH; +static ssize_t V8_OFF_HEAPNUMBER_VALUE; +static ssize_t V8_OFF_HEAPOBJECT_MAP; +static ssize_t V8_OFF_JSARRAY_LENGTH; +static ssize_t V8_OFF_JSDATE_VALUE; +static ssize_t V8_OFF_JSFUNCTION_SHARED; +static ssize_t V8_OFF_JSOBJECT_ELEMENTS; +static ssize_t V8_OFF_JSOBJECT_PROPERTIES; +static ssize_t V8_OFF_MAP_CONSTRUCTOR; +static ssize_t V8_OFF_MAP_INOBJECT_PROPERTIES; +static ssize_t V8_OFF_MAP_INSTANCE_ATTRIBUTES; +static ssize_t V8_OFF_MAP_INSTANCE_DESCRIPTORS; +static ssize_t V8_OFF_MAP_INSTANCE_SIZE; +static ssize_t V8_OFF_MAP_BIT_FIELD; +static ssize_t V8_OFF_MAP_BIT_FIELD2; +static ssize_t V8_OFF_MAP_BIT_FIELD3; +static ssize_t V8_OFF_MAP_TRANSITIONS; +static ssize_t V8_OFF_ODDBALL_TO_STRING; +static ssize_t V8_OFF_SCRIPT_LINE_ENDS; +static ssize_t V8_OFF_SCRIPT_NAME; +static ssize_t V8_OFF_SCRIPT_SOURCE; +static ssize_t V8_OFF_SEQASCIISTR_CHARS; +static ssize_t V8_OFF_SEQONEBYTESTR_CHARS; +static ssize_t V8_OFF_SEQTWOBYTESTR_CHARS; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_CODE; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_END_POSITION; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_INFERRED_NAME; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_LENGTH; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_SCRIPT; +static ssize_t V8_OFF_SHAREDFUNCTIONINFO_NAME; +static ssize_t V8_OFF_SLICEDSTRING_PARENT; +static ssize_t V8_OFF_SLICEDSTRING_OFFSET; +static ssize_t V8_OFF_STRING_LENGTH; + +/* see node_string.h */ +#define NODE_OFF_EXTSTR_DATA sizeof (uintptr_t) + +#define V8_CONSTANT_OPTIONAL 1 +#define V8_CONSTANT_HASFALLBACK 2 +#define V8_CONSTANT_REMOVED 4 + +#define V8_CONSTANT_MAJORSHIFT 3 +#define V8_CONSTANT_MAJORMASK ((1 << 4) - 1) +#define V8_CONSTANT_MAJOR(flags) \ + (((flags) >> V8_CONSTANT_MAJORSHIFT) & V8_CONSTANT_MAJORMASK) + +#define V8_CONSTANT_MINORSHIFT 7 +#define V8_CONSTANT_MINORMASK ((1 << 9) - 1) +#define V8_CONSTANT_MINOR(flags) \ + (((flags) >> V8_CONSTANT_MINORSHIFT) & V8_CONSTANT_MINORMASK) + +#define V8_CONSTANT_FALLBACK(maj, min) \ + (V8_CONSTANT_OPTIONAL | V8_CONSTANT_HASFALLBACK | \ + ((maj) << V8_CONSTANT_MAJORSHIFT) | ((min) << V8_CONSTANT_MINORSHIFT)) + +#define V8_CONSTANT_REMOVED_SINCE(maj, min) \ + (V8_CONSTANT_REMOVED | \ + ((maj) << V8_CONSTANT_MAJORSHIFT) | ((min) << V8_CONSTANT_MINORSHIFT)) + +/* + * Table of constants used directly by this file. + */ +typedef struct v8_constant { + intptr_t *v8c_valp; + const char *v8c_symbol; + uint32_t v8c_flags; + intptr_t v8c_fallback; +} v8_constant_t; + +static v8_constant_t v8_constants[] = { + { &V8_OFF_FP_CONTEXT, "v8dbg_off_fp_context" }, + { &V8_OFF_FP_FUNCTION, "v8dbg_off_fp_function" }, + { &V8_OFF_FP_MARKER, "v8dbg_off_fp_marker" }, + { &V8_OFF_FP_ARGS, "v8dbg_off_fp_args" }, + + { &V8_FirstNonstringType, "v8dbg_FirstNonstringType" }, + { &V8_IsNotStringMask, "v8dbg_IsNotStringMask" }, + { &V8_StringTag, "v8dbg_StringTag" }, + { &V8_NotStringTag, "v8dbg_NotStringTag" }, + { &V8_StringEncodingMask, "v8dbg_StringEncodingMask" }, + { &V8_TwoByteStringTag, "v8dbg_TwoByteStringTag" }, + { &V8_AsciiStringTag, "v8dbg_AsciiStringTag" }, + { &V8_StringRepresentationMask, "v8dbg_StringRepresentationMask" }, + { &V8_SeqStringTag, "v8dbg_SeqStringTag" }, + { &V8_ConsStringTag, "v8dbg_ConsStringTag" }, + { &V8_SlicedStringTag, "v8dbg_SlicedStringTag", + V8_CONSTANT_FALLBACK(0, 0), 0x3 }, + { &V8_ExternalStringTag, "v8dbg_ExternalStringTag" }, + { &V8_FailureTag, "v8dbg_FailureTag", + V8_CONSTANT_REMOVED_SINCE(3, 28) }, + { &V8_FailureTagMask, "v8dbg_FailureTagMask", + V8_CONSTANT_REMOVED_SINCE(3, 28) }, + { &V8_HeapObjectTag, "v8dbg_HeapObjectTag" }, + { &V8_HeapObjectTagMask, "v8dbg_HeapObjectTagMask" }, + { &V8_SmiTag, "v8dbg_SmiTag" }, + { &V8_SmiTagMask, "v8dbg_SmiTagMask" }, + { &V8_SmiValueShift, "v8dbg_SmiValueShift" }, + { &V8_SmiShiftSize, "v8dbg_SmiShiftSize", +#ifdef _LP64 + V8_CONSTANT_FALLBACK(0, 0), 31 }, +#else + V8_CONSTANT_FALLBACK(0, 0), 0 }, +#endif + { &V8_PointerSizeLog2, "v8dbg_PointerSizeLog2" }, + + { &V8_DICT_SHIFT, "v8dbg_bit_field3_dictionary_map_shift", + V8_CONSTANT_FALLBACK(3, 13), 24 }, + { &V8_DICT_PREFIX_SIZE, "v8dbg_dict_prefix_size", + V8_CONSTANT_FALLBACK(3, 11), 2 }, + { &V8_DICT_ENTRY_SIZE, "v8dbg_dict_entry_size", + V8_CONSTANT_FALLBACK(3, 11), 3 }, + { &V8_DICT_START_INDEX, "v8dbg_dict_start_index", + V8_CONSTANT_FALLBACK(3, 11), 3 }, + { &V8_FIELDINDEX_MASK, "v8dbg_fieldindex_mask", + V8_CONSTANT_FALLBACK(3, 26), 0x3ff00000 }, + { &V8_FIELDINDEX_SHIFT, "v8dbg_fieldindex_shift", + V8_CONSTANT_FALLBACK(3, 26), 20 }, + { &V8_ISSHARED_SHIFT, "v8dbg_isshared_shift", + V8_CONSTANT_FALLBACK(3, 11), 0 }, + { &V8_PROP_IDX_FIRST, "v8dbg_prop_idx_first" }, + { &V8_PROP_TYPE_FIELD, "v8dbg_prop_type_field" }, + { &V8_PROP_TYPE_MASK, "v8dbg_prop_type_mask" }, + { &V8_PROP_IDX_CONTENT, "v8dbg_prop_idx_content", + V8_CONSTANT_OPTIONAL }, + { &V8_PROP_DESC_KEY, "v8dbg_prop_desc_key", + V8_CONSTANT_FALLBACK(0, 0), 0 }, + { &V8_PROP_DESC_DETAILS, "v8dbg_prop_desc_details", + V8_CONSTANT_FALLBACK(0, 0), 1 }, + { &V8_PROP_DESC_VALUE, "v8dbg_prop_desc_value", + V8_CONSTANT_FALLBACK(0, 0), 2 }, + { &V8_PROP_DESC_SIZE, "v8dbg_prop_desc_size", + V8_CONSTANT_FALLBACK(0, 0), 3 }, + { &V8_TRANSITIONS_IDX_DESC, "v8dbg_transitions_idx_descriptors", + V8_CONSTANT_OPTIONAL }, + + { &V8_ELEMENTS_KIND_SHIFT, "v8dbg_elements_kind_shift", + V8_CONSTANT_FALLBACK(0, 0), 3 }, + { &V8_ELEMENTS_KIND_BITCOUNT, "v8dbg_elements_kind_bitcount", + V8_CONSTANT_FALLBACK(0, 0), 5 }, + { &V8_ELEMENTS_FAST_ELEMENTS, + "v8dbg_elements_fast_elements", + V8_CONSTANT_FALLBACK(0, 0), 2 }, + { &V8_ELEMENTS_FAST_HOLEY_ELEMENTS, + "v8dbg_elements_fast_holey_elements", + V8_CONSTANT_FALLBACK(0, 0), 3 }, + { &V8_ELEMENTS_DICTIONARY_ELEMENTS, + "v8dbg_elements_dictionary_elements", + V8_CONSTANT_FALLBACK(0, 0), 6 }, +}; + +static int v8_nconstants = sizeof (v8_constants) / sizeof (v8_constants[0]); + +typedef struct v8_offset { + ssize_t *v8o_valp; + const char *v8o_class; + const char *v8o_member; + boolean_t v8o_optional; +} v8_offset_t; + +static v8_offset_t v8_offsets[] = { + { &V8_OFF_CODE_INSTRUCTION_SIZE, + "Code", "instruction_size" }, + { &V8_OFF_CODE_INSTRUCTION_START, + "Code", "instruction_start" }, + { &V8_OFF_CONSSTRING_FIRST, + "ConsString", "first" }, + { &V8_OFF_CONSSTRING_SECOND, + "ConsString", "second" }, + { &V8_OFF_EXTERNALSTRING_RESOURCE, + "ExternalString", "resource" }, + { &V8_OFF_FIXEDARRAY_DATA, + "FixedArray", "data" }, + { &V8_OFF_FIXEDARRAY_LENGTH, + "FixedArray", "length" }, + { &V8_OFF_HEAPNUMBER_VALUE, + "HeapNumber", "value" }, + { &V8_OFF_HEAPOBJECT_MAP, + "HeapObject", "map" }, + { &V8_OFF_JSARRAY_LENGTH, + "JSArray", "length" }, + { &V8_OFF_JSDATE_VALUE, + "JSDate", "value", B_TRUE }, + { &V8_OFF_JSFUNCTION_SHARED, + "JSFunction", "shared" }, + { &V8_OFF_JSOBJECT_ELEMENTS, + "JSObject", "elements" }, + { &V8_OFF_JSOBJECT_PROPERTIES, + "JSObject", "properties" }, + { &V8_OFF_MAP_CONSTRUCTOR, + "Map", "constructor" }, + { &V8_OFF_MAP_INOBJECT_PROPERTIES, + "Map", "inobject_properties" }, + { &V8_OFF_MAP_INSTANCE_ATTRIBUTES, + "Map", "instance_attributes" }, + { &V8_OFF_MAP_INSTANCE_DESCRIPTORS, + "Map", "instance_descriptors", B_TRUE }, + { &V8_OFF_MAP_TRANSITIONS, + "Map", "transitions", B_TRUE }, + { &V8_OFF_MAP_INSTANCE_SIZE, + "Map", "instance_size" }, + { &V8_OFF_MAP_BIT_FIELD2, + "Map", "bit_field2", B_TRUE }, + { &V8_OFF_MAP_BIT_FIELD3, + "Map", "bit_field3", B_TRUE }, + { &V8_OFF_ODDBALL_TO_STRING, + "Oddball", "to_string" }, + { &V8_OFF_SCRIPT_LINE_ENDS, + "Script", "line_ends" }, + { &V8_OFF_SCRIPT_NAME, + "Script", "name" }, + { &V8_OFF_SCRIPT_SOURCE, + "Script", "source" }, + { &V8_OFF_SEQASCIISTR_CHARS, + "SeqAsciiString", "chars", B_TRUE }, + { &V8_OFF_SEQONEBYTESTR_CHARS, + "SeqOneByteString", "chars", B_TRUE }, + { &V8_OFF_SEQTWOBYTESTR_CHARS, + "SeqTwoByteString", "chars", B_TRUE }, + { &V8_OFF_SHAREDFUNCTIONINFO_CODE, + "SharedFunctionInfo", "code" }, + { &V8_OFF_SHAREDFUNCTIONINFO_END_POSITION, + "SharedFunctionInfo", "end_position" }, + { &V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION, + "SharedFunctionInfo", "function_token_position" }, + { &V8_OFF_SHAREDFUNCTIONINFO_INFERRED_NAME, + "SharedFunctionInfo", "inferred_name" }, + { &V8_OFF_SHAREDFUNCTIONINFO_LENGTH, + "SharedFunctionInfo", "length" }, + { &V8_OFF_SHAREDFUNCTIONINFO_NAME, + "SharedFunctionInfo", "name" }, + { &V8_OFF_SHAREDFUNCTIONINFO_SCRIPT, + "SharedFunctionInfo", "script" }, + { &V8_OFF_SLICEDSTRING_OFFSET, + "SlicedString", "offset" }, + { &V8_OFF_SLICEDSTRING_PARENT, + "SlicedString", "parent", B_TRUE }, + { &V8_OFF_STRING_LENGTH, + "String", "length" }, +}; + +static int v8_noffsets = sizeof (v8_offsets) / sizeof (v8_offsets[0]); + +static uintptr_t v8_major; +static uintptr_t v8_minor; +static uintptr_t v8_build; +static uintptr_t v8_patch; + +static int autoconf_iter_symbol(mdb_symbol_t *, void *); +static v8_class_t *conf_class_findcreate(const char *); +static v8_field_t *conf_field_create(v8_class_t *, const char *, size_t); +static char *conf_next_part(char *, char *); +static int conf_update_parent(const char *); +static int conf_update_field(v8_cfg_t *, const char *); +static int conf_update_enum(v8_cfg_t *, const char *, const char *, + v8_enum_t *); +static int conf_update_type(v8_cfg_t *, const char *); +static int conf_update_frametype(v8_cfg_t *, const char *); +static void conf_class_compute_offsets(v8_class_t *); + +static int read_typebyte(uint8_t *, uintptr_t); +static int heap_offset(const char *, const char *, ssize_t *); +static int jsfunc_name(uintptr_t, char **, size_t *); + +/* + * When iterating properties, it's useful to keep track of what kinds of + * properties were found. This is useful for developers to identify objects of + * different kinds in order to debug them. + */ +typedef enum { + JPI_NONE = 0, + + /* + * Indicates how properties are stored in this object. There can be + * both numeric properties and some of the other kinds. + */ + JPI_NUMERIC = 0x01, /* numeric-named properties in "elements" */ + JPI_DICT = 0x02, /* dictionary properties */ + JPI_INOBJECT = 0x04, /* properties stored inside object */ + JPI_PROPS = 0x08, /* "properties" array */ + + /* error-like cases */ + JPI_SKIPPED = 0x10, /* some properties were skipped */ + JPI_BADLAYOUT = 0x20, /* we didn't recognize the layout at all */ + + /* fallback cases */ + JPI_HASTRANSITIONS = 0x100, /* found a transitions array */ + JPI_HASCONTENT = 0x200, /* found a separate content array */ +} jspropinfo_t; + +typedef struct jsobj_print { + char **jsop_bufp; + size_t *jsop_lenp; + int jsop_indent; + uint64_t jsop_depth; + boolean_t jsop_printaddr; + uintptr_t jsop_baseaddr; + int jsop_nprops; + const char *jsop_member; + boolean_t jsop_found; + boolean_t jsop_descended; + jspropinfo_t jsop_propinfo; +} jsobj_print_t; + +static int jsobj_print_number(uintptr_t, jsobj_print_t *); +static int jsobj_print_oddball(uintptr_t, jsobj_print_t *); +static int jsobj_print_jsobject(uintptr_t, jsobj_print_t *); +static int jsobj_print_jsarray(uintptr_t, jsobj_print_t *); +static int jsobj_print_jsfunction(uintptr_t, jsobj_print_t *); +static int jsobj_print_jsdate(uintptr_t, jsobj_print_t *); + +/* + * Returns 1 if the V8 version v8_major.v8.minor is strictly older than + * the V8 version represented by "flags". + * Returns 0 otherwise. + */ +static int +v8_version_older(uintptr_t v8_major, uintptr_t v8_minor, uint32_t flags) { + return (v8_major < V8_CONSTANT_MAJOR(flags) || + (v8_major == V8_CONSTANT_MAJOR(flags) && + v8_minor < V8_CONSTANT_MINOR(flags))); +} + +/* + * Invoked when this dmod is initially loaded to load the set of classes, enums, + * and other constants from the metadata in the target binary. + */ +static int +autoconfigure(v8_cfg_t *cfgp) +{ + v8_class_t *clp; + v8_enum_t *ep; + struct v8_constant *cnp; + int ii; + int failed = 0; + + assert(v8_classes == NULL); + + /* + * Iterate all global symbols looking for metadata. + */ + if (cfgp->v8cfg_iter(cfgp, autoconf_iter_symbol, cfgp) != 0) { + mdb_warn("failed to autoconfigure V8 support\n"); + return (-1); + } + + /* + * By now we've configured all of the classes so we can update the + * "start" and "end" fields in each class with information from its + * parent class. + */ + for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { + if (clp->v8c_end != (size_t)-1) + continue; + + conf_class_compute_offsets(clp); + }; + + /* + * Load various constants used directly in the module. + */ + for (ii = 0; ii < v8_nconstants; ii++) { + cnp = &v8_constants[ii]; + + if (cfgp->v8cfg_readsym(cfgp, + cnp->v8c_symbol, cnp->v8c_valp) != -1) { + continue; + } + + if (!(cnp->v8c_flags & V8_CONSTANT_OPTIONAL) && + (!(cnp->v8c_flags & V8_CONSTANT_REMOVED) || + v8_version_older(v8_major, v8_minor, cnp->v8c_flags))) { + mdb_warn("failed to read \"%s\"", cnp->v8c_symbol); + failed++; + continue; + } + + if (!(cnp->v8c_flags & V8_CONSTANT_HASFALLBACK) || + v8_major < V8_CONSTANT_MAJOR(cnp->v8c_flags) || + (v8_major == V8_CONSTANT_MAJOR(cnp->v8c_flags) && + v8_minor < V8_CONSTANT_MINOR(cnp->v8c_flags))) { + *cnp->v8c_valp = -1; + continue; + } + + /* + * We have a fallback -- and we know that the version satisfies + * the fallback's version constraints; use the fallback value. + */ + *cnp->v8c_valp = cnp->v8c_fallback; + } + + /* + * Load type values for well-known classes that we use a lot. + */ + for (ep = v8_types; ep->v8e_name[0] != '\0'; ep++) { + if (strcmp(ep->v8e_name, "JSObject") == 0) + V8_TYPE_JSOBJECT = ep->v8e_value; + + if (strcmp(ep->v8e_name, "JSArray") == 0) + V8_TYPE_JSARRAY = ep->v8e_value; + + if (strcmp(ep->v8e_name, "JSFunction") == 0) + V8_TYPE_JSFUNCTION = ep->v8e_value; + + if (strcmp(ep->v8e_name, "FixedArray") == 0) + V8_TYPE_FIXEDARRAY = ep->v8e_value; + } + + if (V8_TYPE_JSOBJECT == -1) { + mdb_warn("couldn't find JSObject type\n"); + failed++; + } + + if (V8_TYPE_JSARRAY == -1) { + mdb_warn("couldn't find JSArray type\n"); + failed++; + } + + if (V8_TYPE_JSFUNCTION == -1) { + mdb_warn("couldn't find JSFunction type\n"); + failed++; + } + + if (V8_TYPE_FIXEDARRAY == -1) { + mdb_warn("couldn't find FixedArray type\n"); + failed++; + } + + /* + * Finally, load various class offsets. + */ + for (ii = 0; ii < v8_noffsets; ii++) { + struct v8_offset *offp = &v8_offsets[ii]; + const char *klass = offp->v8o_class; + +again: + if (heap_offset(klass, offp->v8o_member, offp->v8o_valp) == 0) + continue; + + if (strcmp(klass, "FixedArray") == 0) { + /* + * The V8 included in node v0.6 uses a FixedArrayBase + * class to contain the "length" field, while the one + * in v0.4 has no such base class and stores the field + * directly in FixedArray; if we failed to derive + * the offset from FixedArray, try FixedArrayBase. + */ + klass = "FixedArrayBase"; + goto again; + } + + if (offp->v8o_optional) { + *offp->v8o_valp = -1; + continue; + } + + mdb_warn("couldn't find class \"%s\", field \"%s\"\n", + offp->v8o_class, offp->v8o_member); + failed++; + } + + if (!((V8_OFF_SEQASCIISTR_CHARS != -1) ^ + (V8_OFF_SEQONEBYTESTR_CHARS != -1))) { + mdb_warn("expected exactly one of SeqAsciiString and " + "SeqOneByteString to be defined\n"); + failed++; + } + + if (V8_OFF_SEQONEBYTESTR_CHARS != -1) + V8_OFF_SEQASCIISTR_CHARS = V8_OFF_SEQONEBYTESTR_CHARS; + + if (V8_OFF_SEQTWOBYTESTR_CHARS == -1) + V8_OFF_SEQTWOBYTESTR_CHARS = V8_OFF_SEQASCIISTR_CHARS; + + if (V8_OFF_SLICEDSTRING_PARENT == -1) + V8_OFF_SLICEDSTRING_PARENT = V8_OFF_SLICEDSTRING_OFFSET - + sizeof (uintptr_t); + + /* + * If we don't have bit_field/bit_field2 for Map, we know that they're + * the second and third byte of instance_attributes. + */ + if (V8_OFF_MAP_BIT_FIELD == -1) + V8_OFF_MAP_BIT_FIELD = V8_OFF_MAP_INSTANCE_ATTRIBUTES + 2; + + if (V8_OFF_MAP_BIT_FIELD2 == -1) + V8_OFF_MAP_BIT_FIELD2 = V8_OFF_MAP_INSTANCE_ATTRIBUTES + 3; + + return (failed ? -1 : 0); +} + +/* ARGSUSED */ +static int +autoconf_iter_symbol(mdb_symbol_t *symp, void *arg) +{ + v8_cfg_t *cfgp = arg; + + if (strncmp(symp->sym_name, "v8dbg_parent_", + sizeof ("v8dbg_parent_") - 1) == 0) + return (conf_update_parent(symp->sym_name)); + + if (strncmp(symp->sym_name, "v8dbg_class_", + sizeof ("v8dbg_class_") - 1) == 0) + return (conf_update_field(cfgp, symp->sym_name)); + + if (strncmp(symp->sym_name, "v8dbg_type_", + sizeof ("v8dbg_type_") - 1) == 0) + return (conf_update_type(cfgp, symp->sym_name)); + + if (strncmp(symp->sym_name, "v8dbg_frametype_", + sizeof ("v8dbg_frametype_") - 1) == 0) + return (conf_update_frametype(cfgp, symp->sym_name)); + + return (0); +} + +/* + * Extracts the next field of a string whose fields are separated by "__" (as + * the V8 metadata symbols are). + */ +static char * +conf_next_part(char *buf, char *start) +{ + char *pp; + + if ((pp = strstr(start, "__")) == NULL) { + mdb_warn("malformed symbol name: %s\n", buf); + return (NULL); + } + + *pp = '\0'; + return (pp + sizeof ("__") - 1); +} + +static v8_class_t * +conf_class_findcreate(const char *name) +{ + v8_class_t *clp, *iclp, *prev = NULL; + int cmp; + + for (iclp = v8_classes; iclp != NULL; iclp = iclp->v8c_next) { + if ((cmp = strcmp(iclp->v8c_name, name)) == 0) + return (iclp); + + if (cmp > 0) + break; + + prev = iclp; + } + + if ((clp = mdb_zalloc(sizeof (*clp), UM_NOSLEEP)) == NULL) + return (NULL); + + (void) strlcpy(clp->v8c_name, name, sizeof (clp->v8c_name)); + clp->v8c_end = (size_t)-1; + clp->v8c_next = iclp; + + if (prev != NULL) { + prev->v8c_next = clp; + } else { + v8_classes = clp; + } + + return (clp); +} + +static v8_field_t * +conf_field_create(v8_class_t *clp, const char *name, size_t offset) +{ + v8_field_t *flp, *iflp; + + if ((flp = mdb_zalloc(sizeof (*flp), UM_NOSLEEP)) == NULL) + return (NULL); + + (void) strlcpy(flp->v8f_name, name, sizeof (flp->v8f_name)); + flp->v8f_offset = offset; + + if (clp->v8c_fields == NULL || clp->v8c_fields->v8f_offset > offset) { + flp->v8f_next = clp->v8c_fields; + clp->v8c_fields = flp; + return (flp); + } + + for (iflp = clp->v8c_fields; iflp->v8f_next != NULL; + iflp = iflp->v8f_next) { + if (iflp->v8f_next->v8f_offset > offset) + break; + } + + flp->v8f_next = iflp->v8f_next; + iflp->v8f_next = flp; + return (flp); +} + +/* + * Given a "v8dbg_parent_X__Y", symbol, update the parent of class X to class Y. + * Note that neither class necessarily exists already. + */ +static int +conf_update_parent(const char *symbol) +{ + char *pp, *qq; + char buf[128]; + v8_class_t *clp, *pclp; + + (void) strlcpy(buf, symbol, sizeof (buf)); + pp = buf + sizeof ("v8dbg_parent_") - 1; + qq = conf_next_part(buf, pp); + + if (qq == NULL) + return (-1); + + clp = conf_class_findcreate(pp); + pclp = conf_class_findcreate(qq); + + if (clp == NULL || pclp == NULL) { + mdb_warn("mdb_v8: out of memory\n"); + return (-1); + } + + clp->v8c_parent = pclp; + return (0); +} + +/* + * Given a "v8dbg_class_CLASS__FIELD__TYPE", symbol, save field "FIELD" into + * class CLASS with the offset described by the symbol. Note that CLASS does + * not necessarily exist already. + */ +static int +conf_update_field(v8_cfg_t *cfgp, const char *symbol) +{ + v8_class_t *clp; + v8_field_t *flp; + intptr_t offset; + char *pp, *qq, *tt; + char buf[128]; + + (void) strlcpy(buf, symbol, sizeof (buf)); + + pp = buf + sizeof ("v8dbg_class_") - 1; + qq = conf_next_part(buf, pp); + + if (qq == NULL || (tt = conf_next_part(buf, qq)) == NULL) + return (-1); + + if (cfgp->v8cfg_readsym(cfgp, symbol, &offset) == -1) { + mdb_warn("failed to read symbol \"%s\"", symbol); + return (-1); + } + + if ((clp = conf_class_findcreate(pp)) == NULL || + (flp = conf_field_create(clp, qq, (size_t)offset)) == NULL) + return (-1); + + if (strcmp(tt, "int") == 0) + flp->v8f_isbyte = B_TRUE; + + if (strcmp(tt, "char") == 0) + flp->v8f_isstr = B_TRUE; + + return (0); +} + +static int +conf_update_enum(v8_cfg_t *cfgp, const char *symbol, const char *name, + v8_enum_t *enp) +{ + intptr_t value; + + if (cfgp->v8cfg_readsym(cfgp, symbol, &value) == -1) { + mdb_warn("failed to read symbol \"%s\"", symbol); + return (-1); + } + + enp->v8e_value = (int)value; + (void) strlcpy(enp->v8e_name, name, sizeof (enp->v8e_name)); + return (0); +} + +/* + * Given a "v8dbg_type_TYPENAME" constant, save the type name in v8_types. Note + * that this enum has multiple integer values with the same string label. + */ +static int +conf_update_type(v8_cfg_t *cfgp, const char *symbol) +{ + char *klass; + v8_enum_t *enp; + char buf[128]; + + if (v8_next_type > sizeof (v8_types) / sizeof (v8_types[0])) { + mdb_warn("too many V8 types\n"); + return (-1); + } + + (void) strlcpy(buf, symbol, sizeof (buf)); + + klass = buf + sizeof ("v8dbg_type_") - 1; + if (conf_next_part(buf, klass) == NULL) + return (-1); + + enp = &v8_types[v8_next_type++]; + return (conf_update_enum(cfgp, symbol, klass, enp)); +} + +/* + * Given a "v8dbg_frametype_TYPENAME" constant, save the frame type in + * v8_frametypes. + */ +static int +conf_update_frametype(v8_cfg_t *cfgp, const char *symbol) +{ + const char *frametype; + v8_enum_t *enp; + + if (v8_next_frametype > + sizeof (v8_frametypes) / sizeof (v8_frametypes[0])) { + mdb_warn("too many V8 frame types\n"); + return (-1); + } + + enp = &v8_frametypes[v8_next_frametype++]; + frametype = symbol + sizeof ("v8dbg_frametype_") - 1; + return (conf_update_enum(cfgp, symbol, frametype, enp)); +} + +/* + * Now that all classes have been loaded, update the "start" and "end" fields of + * each class based on the values of its parent class. + */ +static void +conf_class_compute_offsets(v8_class_t *clp) +{ + v8_field_t *flp; + + assert(clp->v8c_start == 0); + assert(clp->v8c_end == (size_t)-1); + + if (clp->v8c_parent != NULL) { + if (clp->v8c_parent->v8c_end == (size_t)-1) + conf_class_compute_offsets(clp->v8c_parent); + + clp->v8c_start = clp->v8c_parent->v8c_end; + } + + if (clp->v8c_fields == NULL) { + clp->v8c_end = clp->v8c_start; + return; + } + + for (flp = clp->v8c_fields; flp->v8f_next != NULL; flp = flp->v8f_next) + ; + + if (flp == NULL) + clp->v8c_end = clp->v8c_start; + else + clp->v8c_end = flp->v8f_offset + sizeof (uintptr_t); +} + +/* + * Utility functions + */ +#define JSSTR_NONE 0 +#define JSSTR_NUDE JSSTR_NONE + +#define JSSTR_FLAGSHIFT 16 +#define JSSTR_VERBOSE (0x1 << JSSTR_FLAGSHIFT) +#define JSSTR_QUOTED (0x2 << JSSTR_FLAGSHIFT) +#define JSSTR_ISASCII (0x4 << JSSTR_FLAGSHIFT) + +#define JSSTR_MAXDEPTH 512 +#define JSSTR_DEPTH(f) ((f) & ((1 << JSSTR_FLAGSHIFT) - 1)) +#define JSSTR_BUMPDEPTH(f) ((f) + 1) + +static int jsstr_print(uintptr_t, uint_t, char **, size_t *); +static boolean_t jsobj_is_undefined(uintptr_t addr); +static boolean_t jsobj_is_hole(uintptr_t addr); + +static const char * +enum_lookup_str(v8_enum_t *enums, int val, const char *dflt) +{ + v8_enum_t *ep; + + for (ep = enums; ep->v8e_name[0] != '\0'; ep++) { + if (ep->v8e_value == val) + return (ep->v8e_name); + } + + return (dflt); +} + +static void +enum_print(v8_enum_t *enums) +{ + v8_enum_t *itp; + + for (itp = enums; itp->v8e_name[0] != '\0'; itp++) + mdb_printf("%-30s = 0x%02x\n", itp->v8e_name, itp->v8e_value); +} + +/* + * b[v]snprintf behave like [v]snprintf(3c), except that they update the buffer + * and length arguments based on how much buffer space is used by the operation. + * This makes it much easier to combine multiple calls in sequence without + * worrying about buffer overflow. + */ +static size_t +bvsnprintf(char **bufp, size_t *buflenp, const char *format, va_list alist) +{ + size_t rv, len; + + if (*buflenp == 0) + return (vsnprintf(NULL, 0, format, alist)); + + rv = vsnprintf(*bufp, *buflenp, format, alist); + + len = MIN(rv, *buflenp); + *buflenp -= len; + *bufp += len; + + return (len); +} + +static size_t +bsnprintf(char **bufp, size_t *buflenp, const char *format, ...) +{ + va_list alist; + size_t rv; + + va_start(alist, format); + rv = bvsnprintf(bufp, buflenp, format, alist); + va_end(alist); + + return (rv); +} + +static void +v8_warn(const char *format, ...) +{ + char buf[512]; + va_list alist; + int len; + + if (!v8_warnings || v8_silent) + return; + + va_start(alist, format); + (void) vsnprintf(buf, sizeof (buf), format, alist); + va_end(alist); + + /* + * This is made slightly annoying because we need to effectively + * preserve the original format string to allow for mdb to use the + * new-line at the end to indicate that strerror should be elided. + */ + if ((len = strlen(format)) > 0 && format[len - 1] == '\n') { + buf[strlen(buf) - 1] = '\0'; + mdb_warn("%s\n", buf); + } else { + mdb_warn("%s", buf); + } +} + +static v8_field_t * +conf_field_lookup(const char *klass, const char *field) +{ + v8_class_t *clp; + v8_field_t *flp; + + for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { + if (strcmp(klass, clp->v8c_name) == 0) + break; + } + + if (clp == NULL) + return (NULL); + + for (flp = clp->v8c_fields; flp != NULL; flp = flp->v8f_next) { + if (strcmp(field, flp->v8f_name) == 0) + break; + } + + return (flp); +} + +/* + * Returns in "offp" the offset of field "field" in C++ class "klass". + */ +static int +heap_offset(const char *klass, const char *field, ssize_t *offp) +{ + v8_field_t *flp; + + flp = conf_field_lookup(klass, field); + + if (flp == NULL) + return (-1); + + *offp = V8_OFF_HEAP(flp->v8f_offset); + return (0); +} + +/* + * Assuming "addr" is an instance of the C++ heap class "klass", read into *valp + * the pointer-sized value of field "field". + */ +static int +read_heap_ptr(uintptr_t *valp, uintptr_t addr, ssize_t off) +{ + if (mdb_vread(valp, sizeof (*valp), addr + off) == -1) { + v8_warn("failed to read offset %d from %p", off, addr); + return (-1); + } + + return (0); +} + +/* + * Like read_heap_ptr, but assume the field is an SMI and store the actual value + * into *valp rather than the encoded representation. + */ +static int +read_heap_smi(uintptr_t *valp, uintptr_t addr, ssize_t off) +{ + if (read_heap_ptr(valp, addr, off) != 0) + return (-1); + + if (!V8_IS_SMI(*valp)) { + v8_warn("expected SMI, got %p\n", *valp); + return (-1); + } + + *valp = V8_SMI_VALUE(*valp); + + return (0); +} + +static int +read_heap_double(double *valp, uintptr_t addr, ssize_t off) +{ + if (mdb_vread(valp, sizeof (*valp), addr + off) == -1) { + v8_warn("failed to read heap value at %p", addr + off); + return (-1); + } + + return (0); +} + +/* + * Assuming "addr" refers to a FixedArray, return a newly-allocated array + * representing its contents. + */ +static int +read_heap_array(uintptr_t addr, uintptr_t **retp, size_t *lenp, int flags) +{ + uint8_t type; + uintptr_t len; + + if (!V8_IS_HEAPOBJECT(addr)) + return (-1); + + if (read_typebyte(&type, addr) != 0) + return (-1); + + if (type != V8_TYPE_FIXEDARRAY) + return (-1); + + if (read_heap_smi(&len, addr, V8_OFF_FIXEDARRAY_LENGTH) != 0) + return (-1); + + *lenp = len; + + if (len == 0) { + *retp = NULL; + return (0); + } + + if ((*retp = mdb_zalloc(len * sizeof (uintptr_t), flags)) == NULL) + return (-1); + + if (mdb_vread(*retp, len * sizeof (uintptr_t), + addr + V8_OFF_FIXEDARRAY_DATA) == -1) { + if (!(flags & UM_GC)) + mdb_free(*retp, len * sizeof (uintptr_t)); + + *retp = NULL; + return (-1); + } + + return (0); +} + +static int +read_heap_byte(uint8_t *valp, uintptr_t addr, ssize_t off) +{ + if (mdb_vread(valp, sizeof (*valp), addr + off) == -1) { + v8_warn("failed to read heap value at %p", addr + off); + return (-1); + } + + return (0); +} + +/* + * This is truly horrific. Inside the V8 Script class are a number of + * small-integer fields like the function_token_position (an offset into the + * script's text where the "function" token appears). For 32-bit processes, V8 + * stores these as a sequence of SMI fields, which we know how to interpret well + * enough. For 64-bit processes, "to avoid wasting space", they use a different + * trick: each 8-byte word contains two integer fields. The low word is + * represented like an SMI: shifted left by one. They don't bother shifting the + * high word, since its low bit will never be looked at (since it's not + * word-aligned). + * + * This function is used for cases where we would use read_heap_smi(), except + * that this is one of those fields that might be encoded or might not be, + * depending on whether the address is word-aligned. + */ +static int +read_heap_maybesmi(uintptr_t *valp, uintptr_t addr, ssize_t off) +{ +#ifdef _LP64 + uint32_t readval; + + if (mdb_vread(&readval, sizeof (readval), addr + off) == -1) { + *valp = -1; + v8_warn("failed to read offset %d from %p", off, addr); + return (-1); + } + + /* + * If this was the low half-word, it needs to be shifted right. + */ + if ((addr + off) % sizeof (uintptr_t) == 0) + readval >>= 1; + + *valp = (uintptr_t)readval; + return (0); +#else + return (read_heap_smi(valp, addr, off)); +#endif +} + +/* + * Given a heap object, returns in *valp the byte describing the type of the + * object. This is shorthand for first retrieving the Map at the start of the + * heap object and then retrieving the type byte from the Map object. + */ +static int +read_typebyte(uint8_t *valp, uintptr_t addr) +{ + uintptr_t mapaddr; + ssize_t off = V8_OFF_HEAPOBJECT_MAP; + + if (mdb_vread(&mapaddr, sizeof (mapaddr), addr + off) == -1) { + v8_warn("failed to read type of %p", addr); + return (-1); + } + + if (!V8_IS_HEAPOBJECT(mapaddr)) { + v8_warn("object map is not a heap object\n"); + return (-1); + } + + if (read_heap_byte(valp, mapaddr, V8_OFF_MAP_INSTANCE_ATTRIBUTES) == -1) + return (-1); + + return (0); +} + +/* + * Given a heap object, returns in *valp the size of the object. For + * variable-size objects, returns an undefined value. + */ +static int +read_size(size_t *valp, uintptr_t addr) +{ + uintptr_t mapaddr; + uint8_t size; + + if (read_heap_ptr(&mapaddr, addr, V8_OFF_HEAPOBJECT_MAP) != 0) + return (-1); + + if (!V8_IS_HEAPOBJECT(mapaddr)) { + v8_warn("heap object map is not itself a heap object\n"); + return (-1); + } + + if (read_heap_byte(&size, mapaddr, V8_OFF_MAP_INSTANCE_SIZE) != 0) + return (-1); + + *valp = size << V8_PointerSizeLog2; + return (0); +} + +/* + * Assuming "addr" refers to a FixedArray that is implementing a + * StringDictionary, iterate over its contents calling the specified function + * with key and value. + */ +static int +read_heap_dict(uintptr_t addr, + int (*func)(const char *, uintptr_t, void *), void *arg) +{ + uint8_t type; + uintptr_t len; + char buf[512]; + char *bufp; + int rval = -1; + uintptr_t *dict, ndict, i; + + if (read_heap_array(addr, &dict, &ndict, UM_SLEEP) != 0) + return (-1); + + if (V8_DICT_ENTRY_SIZE < 2) { + v8_warn("dictionary entry size (%d) is too small for a " + "key and value\n", V8_DICT_ENTRY_SIZE); + goto out; + } + + for (i = V8_DICT_START_INDEX + V8_DICT_PREFIX_SIZE; i < ndict; + i += V8_DICT_ENTRY_SIZE) { + /* + * The layout here is key, value, details. (This is hardcoded + * in Dictionary<Shape, Key>::SetEntry().) + */ + if (jsobj_is_undefined(dict[i])) + continue; + + if (V8_IS_SMI(dict[i])) { + intptr_t val = V8_SMI_VALUE(dict[i]); + (void) snprintf(buf, sizeof (buf), "%" PRIdPTR, val); + } else { + if (jsobj_is_hole(dict[i])) { + /* + * In some cases, the key can (apparently) be a + * hole, in which case we skip over it. + */ + continue; + } + + if (read_typebyte(&type, dict[i]) != 0) + goto out; + + if (!V8_TYPE_STRING(type)) + goto out; + + bufp = buf; + len = sizeof (buf); + + if (jsstr_print(dict[i], JSSTR_NUDE, &bufp, &len) != 0) + goto out; + } + + if (func(buf, dict[i + 1], arg) == -1) + goto out; + } + + rval = 0; +out: + mdb_free(dict, ndict * sizeof (uintptr_t)); + + return (rval); +} + +/* + * Given an object, returns in "buf" the name of the constructor function. With + * "verbose", prints the pointer to the JSFunction object. Given anything else, + * returns an error (and warns the user why). + */ +static int +obj_jsconstructor(uintptr_t addr, char **bufp, size_t *lenp, boolean_t verbose) +{ + uint8_t type; + uintptr_t map, consfunc, funcinfop; + const char *constype; + + if (!V8_IS_HEAPOBJECT(addr) || + read_typebyte(&type, addr) != 0 || + (type != V8_TYPE_JSOBJECT && type != V8_TYPE_JSARRAY)) { + mdb_warn("%p is not a JSObject\n", addr); + return (-1); + } + + if (mdb_vread(&map, sizeof (map), addr + V8_OFF_HEAPOBJECT_MAP) == -1 || + mdb_vread(&consfunc, sizeof (consfunc), + map + V8_OFF_MAP_CONSTRUCTOR) == -1) { + mdb_warn("unable to read object map\n"); + return (-1); + } + + if (read_typebyte(&type, consfunc) != 0) + return (-1); + + constype = enum_lookup_str(v8_types, type, ""); + if (strcmp(constype, "Oddball") == 0) { + jsobj_print_t jsop; + bzero(&jsop, sizeof (jsop)); + jsop.jsop_bufp = bufp; + jsop.jsop_lenp = lenp; + return (jsobj_print_oddball(consfunc, &jsop)); + } + + if (strcmp(constype, "JSFunction") != 0) { + mdb_warn("constructor: expected JSFunction, found %s\n", + constype); + return (-1); + } + + if (read_heap_ptr(&funcinfop, consfunc, V8_OFF_JSFUNCTION_SHARED) != 0) + return (-1); + + if (jsfunc_name(funcinfop, bufp, lenp) != 0) + return (-1); + + if (verbose) + bsnprintf(bufp, lenp, " (JSFunction: %p)", consfunc); + + return (0); +} + +/* + * Returns in "buf" a description of the type of "addr" suitable for printing. + */ +static int +obj_jstype(uintptr_t addr, char **bufp, size_t *lenp, uint8_t *typep) +{ + uint8_t typebyte; + uintptr_t strptr, map, consfunc, funcinfop; + const char *typename; + + if (V8_IS_FAILURE(addr)) { + if (typep) + *typep = 0; + (void) bsnprintf(bufp, lenp, "'Failure' object"); + return (0); + } + + if (V8_IS_SMI(addr)) { + if (typep) + *typep = 0; + (void) bsnprintf(bufp, lenp, "SMI: value = %d", + V8_SMI_VALUE(addr)); + return (0); + } + + if (read_typebyte(&typebyte, addr) != 0) + return (-1); + + if (typep) + *typep = typebyte; + + typename = enum_lookup_str(v8_types, typebyte, "<unknown>"); + (void) bsnprintf(bufp, lenp, typename); + + if (strcmp(typename, "Oddball") == 0) { + if (read_heap_ptr(&strptr, addr, + V8_OFF_ODDBALL_TO_STRING) != -1) { + (void) bsnprintf(bufp, lenp, ": \""); + (void) jsstr_print(strptr, JSSTR_NUDE, bufp, lenp); + (void) bsnprintf(bufp, lenp, "\""); + } + } + + if (strcmp(typename, "JSObject") == 0 && + mdb_vread(&map, sizeof (map), addr + V8_OFF_HEAPOBJECT_MAP) != -1 && + mdb_vread(&consfunc, sizeof (consfunc), + map + V8_OFF_MAP_CONSTRUCTOR) != -1 && + read_typebyte(&typebyte, consfunc) == 0 && + strcmp(enum_lookup_str(v8_types, typebyte, ""), + "JSFunction") == 0 && + mdb_vread(&funcinfop, sizeof (funcinfop), + consfunc + V8_OFF_JSFUNCTION_SHARED) != -1) { + (void) bsnprintf(bufp, lenp, ": "); + (void) jsfunc_name(funcinfop, bufp, lenp); + } + + return (0); +} + +/* + * V8 allows implementers (like Node) to store pointer-sized values into + * internal fields within V8 heap objects. Implementors access these values by + * 0-based index (e.g., SetInternalField(0, value)). These values are stored as + * an array directly after the last actual C++ field in the C++ object. + * + * Node uses internal fields to refer to handles. For example, a socket's C++ + * HandleWrap object is typically stored as internal field 0 in the JavaScript + * Socket object. Similarly, the native-heap-allocated chunk of memory + * associated with a Node Buffer is referenced by field 0 in the External array + * pointed-to by the Node Buffer JSObject. + */ +static int +obj_v8internal(uintptr_t addr, uint_t idx, uintptr_t *valp) +{ + char *bufp; + size_t len; + ssize_t off; + uint8_t type; + + v8_class_t *clp; + char buf[256]; + + bufp = buf; + len = sizeof (buf); + if (obj_jstype(addr, &bufp, &len, &type) != 0) + return (DCMD_ERR); + + if (type == 0) { + mdb_warn("%p: unsupported type\n", addr); + return (DCMD_ERR); + } + + for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { + if (strcmp(buf, clp->v8c_name) == 0) + break; + } + + if (clp == NULL) { + mdb_warn("%p: didn't find expected class\n", addr); + return (DCMD_ERR); + } + + off = clp->v8c_end + (idx * sizeof (uintptr_t)) - 1; + if (read_heap_ptr(valp, addr, off) != 0) { + mdb_warn("%p: failed to read from %p\n", addr, addr + off); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +/* + * Print out the fields of the given object that come from the given class. + */ +static int +obj_print_fields(uintptr_t baddr, v8_class_t *clp) +{ + v8_field_t *flp; + uintptr_t addr, value; + int rv; + char *bufp; + size_t len; + uint8_t type; + char buf[256]; + + for (flp = clp->v8c_fields; flp != NULL; flp = flp->v8f_next) { + bufp = buf; + len = sizeof (buf); + + addr = baddr + V8_OFF_HEAP(flp->v8f_offset); + + if (flp->v8f_isstr) { + if (mdb_readstr(buf, sizeof (buf), addr) == -1) { + mdb_printf("%p %s (unreadable)\n", + addr, flp->v8f_name); + continue; + } + + mdb_printf("%p %s = \"%s\"\n", + addr, flp->v8f_name, buf); + continue; + } + + if (flp->v8f_isbyte) { + uint8_t sv; + if (mdb_vread(&sv, sizeof (sv), addr) == -1) { + mdb_printf("%p %s (unreadable)\n", + addr, flp->v8f_name); + continue; + } + + mdb_printf("%p %s = 0x%x\n", addr, flp->v8f_name, sv); + continue; + } + + rv = mdb_vread((void *)&value, sizeof (value), addr); + + if (rv != sizeof (value) || + obj_jstype(value, &bufp, &len, &type) != 0) { + mdb_printf("%p %s (unreadable)\n", addr, flp->v8f_name); + continue; + } + + if (type != 0 && V8_TYPE_STRING(type)) { + (void) bsnprintf(&bufp, &len, ": "); + (void) jsstr_print(value, JSSTR_QUOTED, &bufp, &len); + } + + mdb_printf("%p %s = %p (%s)\n", addr, flp->v8f_name, value, + buf); + } + + return (DCMD_OK); +} + +/* + * Print out all fields of the given object, starting with the root of the class + * hierarchy and working down the most specific type. + */ +static int +obj_print_class(uintptr_t addr, v8_class_t *clp) +{ + int rv = 0; + + /* + * If we have no fields, we just print a simple inheritance hierarchy. + * If we have fields but our parent doesn't, our header includes the + * inheritance hierarchy. + */ + if (clp->v8c_end == 0) { + mdb_printf("%s ", clp->v8c_name); + + if (clp->v8c_parent != NULL) { + mdb_printf("< "); + (void) obj_print_class(addr, clp->v8c_parent); + } + + return (0); + } + + mdb_printf("%p %s", addr, clp->v8c_name); + + if (clp->v8c_start == 0 && clp->v8c_parent != NULL) { + mdb_printf(" < "); + (void) obj_print_class(addr, clp->v8c_parent); + } + + mdb_printf(" {\n"); + (void) mdb_inc_indent(4); + + if (clp->v8c_start > 0 && clp->v8c_parent != NULL) + rv = obj_print_class(addr, clp->v8c_parent); + + rv |= obj_print_fields(addr, clp); + (void) mdb_dec_indent(4); + mdb_printf("}\n"); + + return (rv); +} + +/* + * Print the ASCII string for the given JS string, expanding ConsStrings and + * ExternalStrings as needed. + */ +static int jsstr_print_seq(uintptr_t, uint_t, char **, size_t *, size_t, + ssize_t); +static int jsstr_print_cons(uintptr_t, uint_t, char **, size_t *); +static int jsstr_print_sliced(uintptr_t, uint_t, char **, size_t *); +static int jsstr_print_external(uintptr_t, uint_t, char **, size_t *); + +static int +jsstr_print(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) +{ + uint8_t typebyte; + int err = 0; + char *lbufp; + size_t llen; + char buf[64]; + boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; + + if (read_typebyte(&typebyte, addr) != 0) { + (void) bsnprintf(bufp, lenp, "<could not read type>"); + return (-1); + } + + if (!V8_TYPE_STRING(typebyte)) { + (void) bsnprintf(bufp, lenp, "<not a string>"); + return (-1); + } + + if (verbose) { + lbufp = buf; + llen = sizeof (buf); + (void) obj_jstype(addr, &lbufp, &llen, NULL); + mdb_printf("%s\n", buf); + (void) mdb_inc_indent(4); + } + + if (JSSTR_DEPTH(flags) > JSSTR_MAXDEPTH) { + (void) bsnprintf(bufp, lenp, "<maximum depth exceeded>"); + return (-1); + } + + if (V8_STRENC_ASCII(typebyte)) + flags |= JSSTR_ISASCII; + else + flags &= ~JSSTR_ISASCII; + + flags = JSSTR_BUMPDEPTH(flags); + + if (V8_STRREP_SEQ(typebyte)) + err = jsstr_print_seq(addr, flags, bufp, lenp, 0, -1); + else if (V8_STRREP_CONS(typebyte)) + err = jsstr_print_cons(addr, flags, bufp, lenp); + else if (V8_STRREP_EXT(typebyte)) + err = jsstr_print_external(addr, flags, bufp, lenp); + else if (V8_STRREP_SLICED(typebyte)) + err = jsstr_print_sliced(addr, flags, bufp, lenp); + else { + (void) bsnprintf(bufp, lenp, "<unknown string type>"); + err = -1; + } + + if (verbose) + (void) mdb_dec_indent(4); + + return (err); +} + +static int +jsstr_print_seq(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp, + size_t sliceoffset, ssize_t slicelen) +{ + /* + * To allow the caller to allocate a very large buffer for strings, + * we'll allocate a buffer sized based on our input, making it at + * least enough space for our ellipsis and at most 256K. + */ + uintptr_t i, nreadoffset, blen, nstrbytes, nstrchrs; + ssize_t nreadbytes; + boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; + boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; + char *buf; + uint16_t chrval; + + if (read_heap_smi(&nstrchrs, addr, V8_OFF_STRING_LENGTH) != 0) { + (void) bsnprintf(bufp, lenp, + "<string (failed to read length)>"); + return (-1); + } + + if (slicelen != -1) + nstrchrs = slicelen; + + blen = ((flags & JSSTR_ISASCII) != 0) ? *lenp : 2 * (*lenp); + if ((blen = MIN(blen, 256 * 1024)) == 0) + return (0); + + if ((flags & JSSTR_ISASCII) != 0) { + nstrbytes = nstrchrs; + nreadoffset = sliceoffset; + nreadbytes = nstrbytes + sizeof ("\"\"") <= *lenp ? + nstrbytes : *lenp - sizeof ("\"\"[...]"); + } else { + nstrbytes = 2 * nstrchrs; + nreadoffset = 2 * sliceoffset; + nreadbytes = nstrchrs + sizeof ("\"\"") <= *lenp ? + nstrbytes : 2 * (*lenp - sizeof ("\"\"[...]")); + } + + if (nreadbytes < 0) { + /* + * We don't even have the room to store the ellipsis; zero + * the buffer out and set the length to zero. + */ + *bufp = '\0'; + *lenp = 0; + return (0); + } + + if (verbose) { + mdb_printf("length: %d chars (%d bytes), " + "will read %d bytes from offset %d\n", + nstrchrs, nstrbytes, nreadbytes, nreadoffset); + mdb_printf("given buffer size: %d, internal buffer: %d\n", + *lenp, blen); + } + + if (nstrbytes == 0) { + (void) bsnprintf(bufp, lenp, "%s%s", + quoted ? "\"" : "", quoted ? "\"" : ""); + return (0); + } + + buf = alloca(blen); + buf[0] = '\0'; + + if ((flags & JSSTR_ISASCII) != 0) { + if (mdb_readstr(buf, nreadbytes + 1, + addr + V8_OFF_SEQASCIISTR_CHARS + nreadoffset) == -1) { + v8_warn("failed to read SeqString data"); + return (-1); + } + + if (nreadbytes != nstrbytes) + (void) strlcat(buf, "[...]", blen); + + (void) bsnprintf(bufp, lenp, "%s%s%s", + quoted ? "\"" : "", buf, quoted ? "\"" : ""); + } else { + if (mdb_readstr(buf, nreadbytes, + addr + V8_OFF_SEQTWOBYTESTR_CHARS + nreadoffset) == -1) { + v8_warn("failed to read SeqTwoByteString data"); + return (-1); + } + + (void) bsnprintf(bufp, lenp, "%s", quoted ? "\"" : ""); + for (i = 0; i < nreadbytes; i += 2) { + /*LINTED*/ + chrval = *((uint16_t *)(buf + i)); + (void) bsnprintf(bufp, lenp, "%c", + (isascii(chrval) || chrval == 0) ? + (char)chrval : '?'); + } + if (nreadbytes != nstrbytes) + (void) bsnprintf(bufp, lenp, "[...]"); + (void) bsnprintf(bufp, lenp, "%s", quoted ? "\"" : ""); + } + + return (0); +} + +static int +jsstr_print_cons(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) +{ + boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; + boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; + uintptr_t ptr1, ptr2; + + if (read_heap_ptr(&ptr1, addr, V8_OFF_CONSSTRING_FIRST) != 0) { + (void) bsnprintf(bufp, lenp, + "<cons string (failed to read first)>"); + return (-1); + } + + if (read_heap_ptr(&ptr2, addr, V8_OFF_CONSSTRING_SECOND) != 0) { + (void) bsnprintf(bufp, lenp, + "<cons string (failed to read second)>"); + return (-1); + } + + if (verbose) { + mdb_printf("ptr1: %p\n", ptr1); + mdb_printf("ptr2: %p\n", ptr2); + } + + if (quoted) + (void) bsnprintf(bufp, lenp, "\""); + + flags = JSSTR_BUMPDEPTH(flags) & ~JSSTR_QUOTED; + + if (jsstr_print(ptr1, flags, bufp, lenp) != 0) + return (-1); + + if (jsstr_print(ptr2, flags, bufp, lenp) != 0) + return (-1); + + if (quoted) + (void) bsnprintf(bufp, lenp, "\""); + + return (0); +} + +static int +jsstr_print_sliced(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) +{ + uintptr_t parent, offset, length; + uint8_t typebyte; + boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; + boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; + + if (read_heap_ptr(&parent, addr, V8_OFF_SLICEDSTRING_PARENT) != 0) { + (void) bsnprintf(bufp, lenp, + "<sliced string (failed to read parent)>"); + return (-1); + } + + if (read_heap_smi(&offset, addr, V8_OFF_SLICEDSTRING_OFFSET) != 0) { + (void) bsnprintf(bufp, lenp, + "<sliced string (failed to read offset)>"); + return (-1); + } + + if (read_heap_smi(&length, addr, V8_OFF_STRING_LENGTH) != 0) { + (void) bsnprintf(bufp, lenp, + "<sliced string (failed to read length)>"); + return (-1); + } + + if (verbose) + mdb_printf("parent: %p, offset = %d, length = %d\n", + parent, offset, length); + + if (read_typebyte(&typebyte, parent) != 0) { + (void) bsnprintf(bufp, lenp, + "<sliced string (failed to read parent type)>"); + return (0); + } + + if (!V8_STRREP_SEQ(typebyte)) { + (void) bsnprintf(bufp, lenp, + "<sliced string (parent is not a sequential string)>"); + return (0); + } + + if (quoted) + (void) bsnprintf(bufp, lenp, "\""); + + flags = JSSTR_BUMPDEPTH(flags) & ~JSSTR_QUOTED; + + if (V8_STRENC_ASCII(typebyte)) + flags |= JSSTR_ISASCII; + + if (jsstr_print_seq(parent, flags, bufp, lenp, offset, length) != 0) + return (-1); + + if (quoted) + (void) bsnprintf(bufp, lenp, "\""); + + return (0); +} + +static int +jsstr_print_external(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) +{ + uintptr_t ptr1, ptr2; + size_t blen = *lenp + 1; + char *buf; + boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; + int rval = -1; + + if ((flags & JSSTR_ISASCII) == 0) { + (void) bsnprintf(bufp, lenp, "<external two-byte string>"); + return (0); + } + + if (flags & JSSTR_VERBOSE) + mdb_printf("assuming Node.js string\n"); + + if (read_heap_ptr(&ptr1, addr, V8_OFF_EXTERNALSTRING_RESOURCE) != 0) { + (void) bsnprintf(bufp, lenp, + "<external string (failed to read resource)>"); + return (-1); + } + + if (mdb_vread(&ptr2, sizeof (ptr2), + ptr1 + NODE_OFF_EXTSTR_DATA) == -1) { + (void) bsnprintf(bufp, lenp, "<external string (failed to " + "read node external pointer %p)>", + ptr1 + NODE_OFF_EXTSTR_DATA); + return (-1); + } + + buf = mdb_alloc(blen, UM_SLEEP); + + if (mdb_readstr(buf, blen, ptr2) == -1) { + (void) bsnprintf(bufp, lenp, "<external string " + "(failed to read ExternalString data)>"); + goto out; + } + + if (buf[0] != '\0' && !isascii(buf[0])) { + (void) bsnprintf(bufp, lenp, "<external string " + "(failed to read ExternalString ascii data)>"); + goto out; + } + + (void) bsnprintf(bufp, lenp, "%s%s%s", + quoted ? "\"" : "", buf, quoted ? "\"" : ""); + + rval = 0; +out: + mdb_free(buf, blen); + + return (rval); +} + +/* + * Returns true if the given address refers to the named oddball object (e.g. + * "undefined"). Returns false on failure (since we shouldn't fail on the + * actual "undefined" value). + */ +static boolean_t +jsobj_is_oddball(uintptr_t addr, char *oddball) +{ + uint8_t type; + uintptr_t strptr; + const char *typename; + char buf[16]; + char *bufp = buf; + size_t len = sizeof (buf); + + v8_silent++; + + if (read_typebyte(&type, addr) != 0) { + v8_silent--; + return (B_FALSE); + } + + v8_silent--; + typename = enum_lookup_str(v8_types, type, "<unknown>"); + if (strcmp(typename, "Oddball") != 0) + return (B_FALSE); + + if (read_heap_ptr(&strptr, addr, V8_OFF_ODDBALL_TO_STRING) == -1) + return (B_FALSE); + + if (jsstr_print(strptr, JSSTR_NUDE, &bufp, &len) != 0) + return (B_FALSE); + + return (strcmp(buf, oddball) == 0); +} + +static boolean_t +jsobj_is_undefined(uintptr_t addr) +{ + return (jsobj_is_oddball(addr, "undefined")); +} + +static boolean_t +jsobj_is_hole(uintptr_t addr) +{ + return (jsobj_is_oddball(addr, "hole")); +} + +/* + * Iterate the properties of a JavaScript object "addr". + * + * Every heap object refers to a Map that describes how that heap object is laid + * out. The Map includes information like the constructor function used to + * create the object, how many bytes each object uses, and how many properties + * are stored inside the object. (A single Map object can be shared by many + * objects of the same general type, which is why this information is encoded by + * reference rather than contained in each object.) + * + * V8 knows about lots of different kinds of properties: + * + * o properties with numeric names (e.g., array elements) + * o dictionary properties + * o "fast" properties stored inside each object, much like a C struct + * o properties stored in the separate "properties" array + * o getters, setters, and other magic (not supported by this module) + * + * While property lookup in JavaScript involves traversing an object's prototype + * chain, this module only iterates the properties local to the object itself. + * + * + * Numeric properties + * + * Properties having numeric indexes are stored in the "elements" array attached + * to each object. Objects with numeric properties can also have other + * properties. + * + * + * Dictionary properties + * + * An object with dictionary properties is identified by one of the bits in + * "bitfield3" in the object's Map. For details on slow properties, see + * read_heap_dict(). + * + * + * Other properties + * + * The Map object refers to an array of "instance descriptors". This array has + * a few metadata entries at the front, followed by groups of three entries for + * each property. In Node v0.10 and later, it looks roughly like this: + * + * +--------------+ +----------------------+ + * | JSObject | +--> | Map | + * +--------------| | +----------------------+ + * | map | ---+ | ... | + * | ... | | instance_descriptors | --+ + * in-object | [prop 0 val] | | ... | | + * properties | [prop 1 val] | +----------------------+ | + * (not for all | ... | | + * objects) | [prop N val] | | + * +--------------+ | + * +------------------------------------------------+ + * | + * +----> +------------------------------+ + * | FixedArray | + * +------------------------------+ + * | ... | + * | prop 0 "key" descriptor | + * | prop 0 "details" descriptor | + * | prop 0 "value" descriptor | + * | prop 1 "key" descriptor | + * | prop 1 "details" descriptor | + * | prop 1 "value" descriptor | + * | ... | + * | prop N "key" descriptor | + * | prop N "details" descriptor | + * | prop N "value" descriptor | + * +------------------------------+ + * + * In versions of Node prior to 0.10, there's an extra level of indirection. + * The Map refers to a "transitions" array, which has an entry that points to + * the instance descriptors. In both cases, the descriptors look roughly the + * same. + * + * Each property is described by three pointer-sized entries: + * + * o key: a string denoting the name of the property + * o details: a bitfield describing attributes of this property + * o value: an integer describing where this property's value is stored + * + * "key" is straightforward: it's just the name of the property as the + * JavaScript programmer knows it. + * + * In versions prior to Node 0.12, "value" is an integer. If "value" is less + * than the number of properties stored inside the object (which is also + * recorded in the Map), then it denotes which of the in-object property value + * slots (shown above inside the JSObject object) stores the value for this + * property. If "value" is greater than the number of properties stored inside + * the object, then it denotes which index into the separate "properties" array + * (a separate field in the JSObject, not shown above) contains the value for + * this property. + * + * In Node 0.12, for properties that are stored inside the object, the offset is + * obtained not using "value", but using a bitfield from the "details" part of + * the descriptor. + * + * Terminology notes: it's important to keep straight the different senses of + * "object" and "property" here. We use "JavaScript objects" to refer to the + * things that JavaScript programmers would call objects, including instances of + * Object and Array and subclasses of those. These are a subset of V8 heap + * objects, since V8 uses its heap to manage lots of other objects that + * JavaScript programmers don't think about. This function iterates JavaScript + * properties of these JavaScript objects, not internal properties of heap + * objects in general. + * + * Relatedly, while JavaScript programmers frequently interchange the notions of + * property names, property values, and property configurations (e.g., getters + * and setters, read-only or not, hidden or not), these are all distinct in the + * implementation of the VM, and "property" typically refers to the whole + * configuration, which may include a way to get the property name and value. + * + * The canonical source of the information used here is the implementation of + * property lookup in the V8 source code, currently in Object::GetProperty. + */ + +static int +jsobj_properties(uintptr_t addr, + int (*func)(const char *, uintptr_t, void *), void *arg, + jspropinfo_t *propinfop) +{ + uintptr_t ptr, map, elements; + uintptr_t *props = NULL, *descs = NULL, *content = NULL, *trans, *elts; + size_t size, nprops, ndescs, ncontent, ntrans, len; + ssize_t ii, rndescs; + uint8_t type, ninprops; + int rval = -1; + size_t ps = sizeof (uintptr_t); + ssize_t off; + jspropinfo_t propinfo = JPI_NONE; + + /* + * First, check if the JSObject's "properties" field is a FixedArray. + * If not, then this is something we don't know how to deal with, and + * we'll just pass the caller a NULL value. + */ + if (mdb_vread(&ptr, ps, addr + V8_OFF_JSOBJECT_PROPERTIES) == -1) + return (-1); + + if (read_typebyte(&type, ptr) != 0) + return (-1); + + if (type != V8_TYPE_FIXEDARRAY) { + char buf[256]; + (void) mdb_snprintf(buf, sizeof (buf), "<%s>", + enum_lookup_str(v8_types, type, "unknown")); + if (propinfop != NULL) + *propinfop = JPI_BADLAYOUT; + return (func(buf, NULL, arg)); + } + + /* + * As described above, we need the Map to figure out how to iterate the + * properties for this object. + */ + if (mdb_vread(&map, ps, addr + V8_OFF_HEAPOBJECT_MAP) == -1) + goto err; + + /* + * Check to see if our elements member is an array and non-zero; if + * so, it contains numerically-named properties. Whether or not there + * are any numerically-named properties, there may be other kinds of + * properties. + */ + if (V8_ELEMENTS_KIND_SHIFT != -1 && + read_heap_ptr(&elements, addr, V8_OFF_JSOBJECT_ELEMENTS) == 0 && + read_heap_array(elements, &elts, &len, UM_SLEEP) == 0 && len != 0) { + uint8_t bit_field2, kind; + size_t sz = len * sizeof (uintptr_t); + + if (mdb_vread(&bit_field2, sizeof (bit_field2), + map + V8_OFF_MAP_BIT_FIELD2) == -1) { + mdb_free(elts, sz); + goto err; + } + + kind = bit_field2 >> V8_ELEMENTS_KIND_SHIFT; + kind &= (1 << V8_ELEMENTS_KIND_BITCOUNT) - 1; + propinfo |= JPI_NUMERIC; + + if (kind == V8_ELEMENTS_FAST_ELEMENTS || + kind == V8_ELEMENTS_FAST_HOLEY_ELEMENTS) { + for (ii = 0; ii < len; ii++) { + char name[10]; + + if (kind == V8_ELEMENTS_FAST_HOLEY_ELEMENTS && + jsobj_is_hole(elts[ii])) + continue; + + snprintf(name, sizeof (name), "%" PRIdPTR, ii); + + if (func(name, elts[ii], arg) != 0) { + mdb_free(elts, sz); + goto err; + } + } + } else if (kind == V8_ELEMENTS_DICTIONARY_ELEMENTS) { + propinfo |= JPI_DICT; + if (read_heap_dict(elements, func, arg) != 0) { + mdb_free(elts, sz); + goto err; + } + } + + mdb_free(elts, sz); + } + + if (V8_DICT_SHIFT != -1) { + v8_field_t *flp; + uintptr_t bit_field3; + + /* + * If dictionary properties are supported (the V8_DICT_SHIFT + * offset is not -1), then bitfield 3 tells us if the properties + * for this object are stored in "properties" field of the + * object using a Dictionary representation. + * + * Versions of V8 prior to Node 0.12 treated bit_field3 as an + * SMI, so it was pointer-sized, and it has to be converted from + * an SMI before using it. In 0.12, it's treated as a raw + * uint32_t, meaning it's always int-sized and it should not be + * converted. We can tell which case we're in because the debug + * constant (v8dbg_class_map__bit_field3__TYPE) tells us whether + * the TYPE is "SMI" or "int". + */ + + flp = conf_field_lookup("Map", "bit_field3"); + if (flp == NULL || flp->v8f_isbyte) { + /* + * v8f_isbyte indicates the type is "int", so we're in + * the int-sized not-a-SMI world. + */ + unsigned int bf3_value; + if (mdb_vread(&bf3_value, sizeof (bf3_value), + map + V8_OFF_MAP_BIT_FIELD3) == -1) + goto err; + bit_field3 = (uintptr_t)bf3_value; + } else { + /* The metadata indicates this is an SMI. */ + if (mdb_vread(&bit_field3, sizeof (bit_field3), + map + V8_OFF_MAP_BIT_FIELD3) == -1) + goto err; + bit_field3 = V8_SMI_VALUE(bit_field3); + } + + if (bit_field3 & (1 << V8_DICT_SHIFT)) { + propinfo |= JPI_DICT; + if (propinfop != NULL) + *propinfop = propinfo; + return (read_heap_dict(ptr, func, arg)); + } + } else if (V8_OFF_MAP_INSTANCE_DESCRIPTORS != -1) { + uintptr_t bit_field3; + + if (mdb_vread(&bit_field3, sizeof (bit_field3), + map + V8_OFF_MAP_INSTANCE_DESCRIPTORS) == -1) + goto err; + + if (V8_SMI_VALUE(bit_field3) == (1 << V8_ISSHARED_SHIFT)) { + /* + * On versions of V8 prior to that used in 0.10, + * the instance descriptors were overloaded to also + * be bit_field3 -- and there was no way from that + * field to infer a dictionary type. Because we + * can't determine if the map is actually the + * hash_table_map, we assume that if it's an object + * that has kIsShared set, that it is in fact a + * dictionary -- an assumption that is assuredly in + * error in some cases. + */ + propinfo |= JPI_DICT; + if (propinfop != NULL) + *propinfop = propinfo; + return (read_heap_dict(ptr, func, arg)); + } + } + + if (read_heap_array(ptr, &props, &nprops, UM_SLEEP) != 0) + goto err; + + /* + * Check if we're looking at an older version of V8, where the instance + * descriptors are stored not directly in the Map, but in the + * "transitions" array that's stored in the Map. + */ + if (V8_OFF_MAP_INSTANCE_DESCRIPTORS == -1) { + if (V8_OFF_MAP_TRANSITIONS == -1 || + V8_TRANSITIONS_IDX_DESC == -1 || + V8_PROP_IDX_CONTENT != -1) { + mdb_warn("missing instance_descriptors, but did " + "not find expected transitions array metadata; " + "cannot read properties\n"); + goto err; + } + + propinfo |= JPI_HASTRANSITIONS; + off = V8_OFF_MAP_TRANSITIONS; + if (mdb_vread(&ptr, ps, map + off) == -1) + goto err; + + if (read_heap_array(ptr, &trans, &ntrans, UM_SLEEP) != 0) + goto err; + + ptr = trans[V8_TRANSITIONS_IDX_DESC]; + mdb_free(trans, ntrans * sizeof (uintptr_t)); + } else { + off = V8_OFF_MAP_INSTANCE_DESCRIPTORS; + if (mdb_vread(&ptr, ps, map + off) == -1) + goto err; + } + + /* + * Either way, at this point "ptr" should refer to the descriptors + * array. + */ + if (read_heap_array(ptr, &descs, &ndescs, UM_SLEEP) != 0) + goto err; + + /* + * For cases where property values are stored directly inside the object + * ("fast properties"), we need to know the whole size of the object and + * the number of properties in the object in order to calculate the + * correct offset for each property. + */ + if (read_size(&size, addr) != 0) + size = 0; + if (mdb_vread(&ninprops, ps, + map + V8_OFF_MAP_INOBJECT_PROPERTIES) == -1) + goto err; + + if (V8_PROP_IDX_CONTENT == -1) { + /* + * On node v0.8 and later, the content is not stored in a + * separate FixedArray, but rather with the descriptors. The + * number of actual properties is the length of the array minus + * the first (non-property) elements divided by the number of + * elements per property. + */ + content = descs; + ncontent = ndescs; + rndescs = ndescs > V8_PROP_IDX_FIRST ? + (ndescs - V8_PROP_IDX_FIRST) / V8_PROP_DESC_SIZE : 0; + } else { + /* + * On older versions, the content is stored in a separate array, + * and there's one entry per property (rather than three). + */ + if (V8_PROP_IDX_CONTENT < ndescs && + read_heap_array(descs[V8_PROP_IDX_CONTENT], &content, + &ncontent, UM_SLEEP) != 0) + goto err; + + rndescs = ndescs - V8_PROP_IDX_FIRST; + propinfo |= JPI_HASCONTENT; + } + + /* + * At this point, we've read all the pieces we need to process the list + * of instance descriptors. + */ + for (ii = 0; ii < rndescs; ii++) { + uintptr_t keyidx, validx, detidx, baseidx; + char buf[1024]; + intptr_t val; + size_t len = sizeof (buf); + char *c = buf; + + if (V8_PROP_IDX_CONTENT != -1) { + /* + * In node versions prior to v0.8, this was hardcoded + * in the V8 implementation, so we hardcode it here + * as well. + */ + keyidx = ii + V8_PROP_IDX_FIRST; + validx = ii << 1; + detidx = (ii << 1) + 1; + } else { + baseidx = V8_PROP_IDX_FIRST + (ii * V8_PROP_DESC_SIZE); + keyidx = baseidx + V8_PROP_DESC_KEY; + validx = baseidx + V8_PROP_DESC_VALUE; + detidx = baseidx + V8_PROP_DESC_DETAILS; + } + + /* + * Ignore cases where our understanding doesn't appear to match + * what's here. + */ + if (detidx >= ncontent) { + propinfo |= JPI_SKIPPED; + v8_warn("property descriptor %d: detidx (%d) " + "out of bounds for content array (length %d)\n", + ii, detidx, ncontent); + continue; + } + + /* + * We only process fields. There are other entries here + * (notably: transitions) that we don't care about (and these + * are not errors). + */ + if (!V8_DESC_ISFIELD(content[detidx])) + continue; + + if (keyidx >= ndescs) { + propinfo |= JPI_SKIPPED; + v8_warn("property descriptor %d: keyidx (%d) " + "out of bounds for descriptor array (length %d)\n", + ii, keyidx, ndescs); + continue; + } + + if (jsstr_print(descs[keyidx], JSSTR_NUDE, &c, &len) != 0) { + propinfo |= JPI_SKIPPED; + continue; + } + + val = (intptr_t)content[validx]; + if (!V8_IS_SMI(val)) { + propinfo |= JPI_SKIPPED; + v8_warn("object %p: property descriptor %d: value " + "index is not an SMI: %p\n", addr, ii, val); + continue; + } + + /* + * The "value" part of each property descriptor tells us whether + * the property value is stored directly in the object or in the + * related "props" array. See JSObject::RawFastPropertyAt() in + * the V8 source. + */ + val = V8_SMI_VALUE(val) - ninprops; + if (val < 0) { + uintptr_t propaddr; + + /* + * The property is stored directly inside the object. + * In Node 0.10, "val - ninprops" is the (negative) + * index of the property counted from the end of the + * object. In that context, -1 refers to the last + * word in the object; -2 refers to the second-last + * word, and so on. + * + * In Node 0.12, we get the 0-based index from the + * first property inside the object by reading certain + * bits from the property descriptor details word. + * These constants are literal here because they're + * literal in the V8 source itself. + */ + if (v8_major > 3 || (v8_major == 3 && v8_minor >= 26)) { + val = V8_PROP_FIELDINDEX(content[detidx]); + propaddr = addr + V8_OFF_HEAP( + size - (ninprops - val) * ps); + } else { + propaddr = addr + V8_OFF_HEAP(size + val * ps); + } + + if (mdb_vread(&ptr, sizeof (ptr), propaddr) == -1) { + propinfo |= JPI_SKIPPED; + v8_warn("object %p: failed to read in-object " + "property at %p", addr, propaddr); + continue; + } + + propinfo |= JPI_INOBJECT; + } else { + /* + * The property is in the separate "props" array. + */ + if (val >= nprops) { + /* + * This can happen when properties are deleted. + * If this value isn't obviously corrupt, we'll + * just silently ignore it. + */ + if (val < rndescs) + continue; + + propinfo |= JPI_SKIPPED; + v8_warn("object %p: property descriptor %d: " + "value index value (%d) out of bounds " + "(%d)\n", addr, ii, val, nprops); + goto err; + } + + propinfo |= JPI_PROPS; + ptr = props[val]; + } + + if (func(buf, ptr, arg) != 0) + goto err; + } + + rval = 0; + if (propinfop != NULL) + *propinfop = propinfo; + +err: + if (props != NULL) + mdb_free(props, nprops * sizeof (uintptr_t)); + + if (descs != NULL) + mdb_free(descs, ndescs * sizeof (uintptr_t)); + + if (content != NULL && V8_PROP_IDX_CONTENT != -1) + mdb_free(content, ncontent * sizeof (uintptr_t)); + + return (rval); +} + +/* + * Given the line endings table in "lendsp", computes the line number for the + * given token position and print the result into "buf". If "lendsp" is + * undefined, prints the token position instead. + */ +static int +jsfunc_lineno(uintptr_t lendsp, uintptr_t tokpos, + char *buf, size_t buflen, int *lineno) +{ + uintptr_t size, bufsz, lower, upper, ii = 0; + uintptr_t *data; + + if (lineno != NULL) + *lineno = -1; + + if (jsobj_is_undefined(lendsp)) { + /* + * The token position is an SMI, but it comes in as its raw + * value so we can more easily compare it to values in the line + * endings table. If we're just printing the position directly, + * we must convert it here, unless we're checking against the + * "-1" sentinel. + */ + if (tokpos == V8_VALUE_SMI(-1)) + mdb_snprintf(buf, buflen, "unknown position"); + else + mdb_snprintf(buf, buflen, "position %d", + V8_SMI_VALUE(tokpos)); + + if (lineno != NULL) + *lineno = 0; + + return (0); + } + + if (read_heap_smi(&size, lendsp, V8_OFF_FIXEDARRAY_LENGTH) != 0) + return (-1); + + bufsz = size * sizeof (data[0]); + + if ((data = mdb_alloc(bufsz, UM_NOSLEEP)) == NULL) { + v8_warn("failed to alloc %d bytes for FixedArray data", bufsz); + return (-1); + } + + if (mdb_vread(data, bufsz, lendsp + V8_OFF_FIXEDARRAY_DATA) != bufsz) { + v8_warn("failed to read FixedArray data"); + mdb_free(data, bufsz); + return (-1); + } + + lower = 0; + upper = size - 1; + + if (tokpos > data[upper]) { + (void) strlcpy(buf, "position out of range", buflen); + mdb_free(data, bufsz); + + if (lineno != NULL) + *lineno = 0; + + return (0); + } + + if (tokpos <= data[0]) { + (void) strlcpy(buf, "line 1", buflen); + mdb_free(data, bufsz); + + if (lineno != NULL) + *lineno = 1; + + return (0); + } + + while (upper >= 1) { + ii = (lower + upper) >> 1; + if (tokpos > data[ii]) + lower = ii + 1; + else if (tokpos <= data[ii - 1]) + upper = ii - 1; + else + break; + } + + if (lineno != NULL) + *lineno = ii + 1; + + (void) mdb_snprintf(buf, buflen, "line %d", ii + 1); + mdb_free(data, bufsz); + return (0); +} + +/* + * Given a Script object, prints nlines on either side of lineno, with each + * line prefixed by prefix (if non-NULL). + */ +static void +jsfunc_lines(uintptr_t scriptp, + uintptr_t start, uintptr_t end, int nlines, char *prefix) +{ + uintptr_t src; + char *buf, *bufp; + size_t bufsz = 1024, len; + int i, line, slop = 10; + boolean_t newline = B_TRUE; + int startline = -1, endline = -1; + + if (read_heap_ptr(&src, scriptp, V8_OFF_SCRIPT_SOURCE) != 0) + return; + + for (;;) { + if ((buf = mdb_zalloc(bufsz, UM_NOSLEEP)) == NULL) { + mdb_warn("failed to allocate source code " + "buffer of size %d", bufsz); + return; + } + + bufp = buf; + len = bufsz; + + if (jsstr_print(src, JSSTR_NUDE, &bufp, &len) != 0) { + mdb_free(buf, bufsz); + return; + } + + if (len > slop) + break; + + mdb_free(buf, bufsz); + bufsz <<= 1; + } + + if (end >= bufsz) + return; + + /* + * First, take a pass to determine where our lines actually start. + */ + for (i = 0, line = 1; buf[i] != '\0'; i++) { + if (buf[i] == '\n') + line++; + + if (i == start) + startline = line; + + if (i == end) { + endline = line; + break; + } + } + + if (startline == -1 || endline == -1) { + mdb_warn("for script %p, could not determine startline/endline" + " (start %ld, end %ld, nlines %d)\n", + scriptp, start, end, nlines); + mdb_free(buf, bufsz); + return; + } + + for (i = 0, line = 1; buf[i] != '\0'; i++) { + if (buf[i] == '\n') { + line++; + newline = B_TRUE; + } + + if (line < startline - nlines) + continue; + + if (line > endline + nlines) + break; + + mdb_printf("%c", buf[i]); + + if (newline) { + if (line >= startline && line <= endline) + mdb_printf("%<b>"); + + if (prefix != NULL) + mdb_printf(prefix, line); + + if (line >= startline && line <= endline) + mdb_printf("%</b>"); + + newline = B_FALSE; + } + } + + mdb_printf("\n"); + + if (line == endline) + mdb_printf("%</b>"); + + mdb_free(buf, bufsz); +} + +/* + * Given a SharedFunctionInfo object, prints into bufp a name of the function + * suitable for printing. This function attempts to infer a name for anonymous + * functions. + */ +static int +jsfunc_name(uintptr_t funcinfop, char **bufp, size_t *lenp) +{ + uintptr_t ptrp; + char *bufs = *bufp; + + if (read_heap_ptr(&ptrp, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_NAME) != 0) { + (void) bsnprintf(bufp, lenp, + "<function (failed to read SharedFunctionInfo)>"); + return (-1); + } + + if (jsstr_print(ptrp, JSSTR_NUDE, bufp, lenp) != 0) + return (-1); + + if (*bufp != bufs) + return (0); + + if (read_heap_ptr(&ptrp, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_INFERRED_NAME) != 0) { + (void) bsnprintf(bufp, lenp, "<anonymous>"); + return (0); + } + + (void) bsnprintf(bufp, lenp, "<anonymous> (as "); + bufs = *bufp; + + if (jsstr_print(ptrp, JSSTR_NUDE, bufp, lenp) != 0) + return (-1); + + if (*bufp == bufs) + (void) bsnprintf(bufp, lenp, "<anon>"); + + (void) bsnprintf(bufp, lenp, ")"); + + return (0); +} + +/* + * JavaScript-level object printing + */ + +static int +jsobj_print(uintptr_t addr, jsobj_print_t *jsop) +{ + uint8_t type; + const char *klass; + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + + const struct { + char *name; + int (*func)(uintptr_t, jsobj_print_t *); + } table[] = { + { "HeapNumber", jsobj_print_number }, + { "Oddball", jsobj_print_oddball }, + { "JSObject", jsobj_print_jsobject }, + { "JSArray", jsobj_print_jsarray }, + { "JSFunction", jsobj_print_jsfunction }, + { "JSDate", jsobj_print_jsdate }, + { NULL } + }, *ent; + + if (jsop->jsop_baseaddr != NULL && jsop->jsop_member == NULL) + (void) bsnprintf(bufp, lenp, "%p: ", jsop->jsop_baseaddr); + + if (jsop->jsop_printaddr && jsop->jsop_member == NULL) + (void) bsnprintf(bufp, lenp, "%p: ", addr); + + if (V8_IS_SMI(addr)) { + (void) bsnprintf(bufp, lenp, "%d", V8_SMI_VALUE(addr)); + return (0); + } + + if (!V8_IS_HEAPOBJECT(addr)) { + (void) bsnprintf(bufp, lenp, "<not a heap object>"); + return (-1); + } + + if (read_typebyte(&type, addr) != 0) { + (void) bsnprintf(bufp, lenp, "<couldn't read type>"); + return (-1); + } + + if (V8_TYPE_STRING(type)) { + if (jsstr_print(addr, JSSTR_QUOTED, bufp, lenp) == -1) + return (-1); + + return (0); + } + + klass = enum_lookup_str(v8_types, type, "<unknown>"); + + for (ent = &table[0]; ent->name != NULL; ent++) { + if (strcmp(klass, ent->name) == 0) { + jsop->jsop_descended = B_TRUE; + return (ent->func(addr, jsop)); + } + } + + (void) bsnprintf(bufp, lenp, + "<unknown JavaScript object type \"%s\">", klass); + return (-1); +} + +static int +jsobj_print_number(uintptr_t addr, jsobj_print_t *jsop) +{ + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + double numval; + + if (read_heap_double(&numval, addr, V8_OFF_HEAPNUMBER_VALUE) == -1) + return (-1); + + if (numval == (long long)numval) + (void) bsnprintf(bufp, lenp, "%lld", (long long)numval); + else + (void) bsnprintf(bufp, lenp, "%e", numval); + + return (0); +} + +static int +jsobj_print_oddball(uintptr_t addr, jsobj_print_t *jsop) +{ + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + uintptr_t strptr; + + if (read_heap_ptr(&strptr, addr, V8_OFF_ODDBALL_TO_STRING) != 0) + return (-1); + + return (jsstr_print(strptr, JSSTR_NUDE, bufp, lenp)); +} + +static int +jsobj_print_prop(const char *desc, uintptr_t val, void *arg) +{ + jsobj_print_t *jsop = arg, descend; + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + + (void) bsnprintf(bufp, lenp, "%s\n%*s\"%s\": ", jsop->jsop_nprops == 0 ? + "{" : "", jsop->jsop_indent + 4, "", desc); + + descend = *jsop; + descend.jsop_depth--; + descend.jsop_indent += 4; + + (void) jsobj_print(val, &descend); + (void) bsnprintf(bufp, lenp, ","); + + jsop->jsop_nprops++; + + return (0); +} + +static int +jsobj_print_prop_member(const char *desc, uintptr_t val, void *arg) +{ + jsobj_print_t *jsop = arg, descend; + const char *member = jsop->jsop_member, *next = member; + int rv; + + for (; *next != '\0' && *next != '.' && *next != '['; next++) + continue; + + if (*member == '[') { + mdb_warn("cannot use array indexing on an object\n"); + return (-1); + } + + if (strncmp(member, desc, next - member) != 0) + return (0); + + if (desc[next - member] != '\0') + return (0); + + /* + * This property matches the desired member; descend. + */ + descend = *jsop; + + if (*next == '\0') { + descend.jsop_member = NULL; + descend.jsop_found = B_TRUE; + } else { + descend.jsop_member = *next == '.' ? next + 1 : next; + } + + rv = jsobj_print(val, &descend); + jsop->jsop_found = descend.jsop_found; + + return (rv); +} + +static int +jsobj_print_jsobject(uintptr_t addr, jsobj_print_t *jsop) +{ + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + + if (jsop->jsop_member != NULL) + return (jsobj_properties(addr, jsobj_print_prop_member, + jsop, &jsop->jsop_propinfo)); + + if (jsop->jsop_depth == 0) { + (void) bsnprintf(bufp, lenp, "[...]"); + return (0); + } + + jsop->jsop_nprops = 0; + + if (jsobj_properties(addr, jsobj_print_prop, jsop, + &jsop->jsop_propinfo) != 0) + return (-1); + + if (jsop->jsop_nprops > 0) { + (void) bsnprintf(bufp, lenp, "\n%*s", jsop->jsop_indent, ""); + } else if (jsop->jsop_nprops == 0) { + (void) bsnprintf(bufp, lenp, "{"); + } else { + (void) bsnprintf(bufp, lenp, "{ /* unknown property */ "); + } + + (void) bsnprintf(bufp, lenp, "}"); + + return (0); +} + +static int +jsobj_print_jsarray_member(uintptr_t addr, jsobj_print_t *jsop) +{ + uintptr_t *elts; + jsobj_print_t descend; + uintptr_t ptr; + const char *member = jsop->jsop_member, *end, *p; + size_t elt = 0, place = 1, len, rv; + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + + if (read_heap_ptr(&ptr, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0) { + (void) bsnprintf(bufp, lenp, + "<array member (failed to read elements)>"); + return (-1); + } + + if (read_heap_array(ptr, &elts, &len, UM_SLEEP | UM_GC) != 0) { + (void) bsnprintf(bufp, lenp, + "<array member (failed to read array)>"); + return (-1); + } + + if (*member != '[') { + mdb_warn("expected bracketed array index; " + "found '%s'\n", member); + return (-1); + } + + if ((end = strchr(member, ']')) == NULL) { + mdb_warn("missing array index terminator\n"); + return (-1); + } + + /* + * We know where our array index ends; convert it to an integer + * by stepping through it from least significant digit to most. + */ + for (p = end - 1; p > member; p--) { + if (*p < '0' || *p > '9') { + mdb_warn("illegal array index at '%c'\n", *p); + return (-1); + } + + elt += (*p - '0') * place; + place *= 10; + } + + if (place == 1) { + mdb_warn("missing array index\n"); + return (-1); + } + + if (elt >= len) { + mdb_warn("array index %d exceeds size of %d\n", elt, len); + return (-1); + } + + descend = *jsop; + + switch (*(++end)) { + case '\0': + descend.jsop_member = NULL; + descend.jsop_found = B_TRUE; + break; + + case '.': + descend.jsop_member = end + 1; + break; + + case '[': + descend.jsop_member = end; + break; + + default: + mdb_warn("illegal character '%c' following " + "array index terminator\n", *end); + return (-1); + } + + rv = jsobj_print(elts[elt], &descend); + jsop->jsop_found = descend.jsop_found; + + return (rv); +} + +static int +jsobj_print_jsarray(uintptr_t addr, jsobj_print_t *jsop) +{ + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + int indent = jsop->jsop_indent; + jsobj_print_t descend; + uintptr_t ptr; + uintptr_t *elts; + size_t ii, len; + + if (jsop->jsop_member != NULL) + return (jsobj_print_jsarray_member(addr, jsop)); + + if (jsop->jsop_depth == 0) { + (void) bsnprintf(bufp, lenp, "[...]"); + return (0); + } + + if (read_heap_ptr(&ptr, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0) { + (void) bsnprintf(bufp, lenp, + "<array (failed to read elements)>"); + return (-1); + } + + if (read_heap_array(ptr, &elts, &len, UM_SLEEP | UM_GC) != 0) { + (void) bsnprintf(bufp, lenp, "<array (failed to read array)>"); + return (-1); + } + + if (len == 0) { + (void) bsnprintf(bufp, lenp, "[]"); + return (0); + } + + descend = *jsop; + descend.jsop_depth--; + descend.jsop_indent += 4; + + if (len == 1) { + (void) bsnprintf(bufp, lenp, "[ "); + (void) jsobj_print(elts[0], &descend); + (void) bsnprintf(bufp, lenp, " ]"); + return (0); + } + + (void) bsnprintf(bufp, lenp, "[\n"); + + for (ii = 0; ii < len && *lenp > 0; ii++) { + (void) bsnprintf(bufp, lenp, "%*s", indent + 4, ""); + (void) jsobj_print(elts[ii], &descend); + (void) bsnprintf(bufp, lenp, ",\n"); + } + + (void) bsnprintf(bufp, lenp, "%*s", indent, ""); + (void) bsnprintf(bufp, lenp, "]"); + + return (0); +} + +static int +jsobj_print_jsfunction(uintptr_t addr, jsobj_print_t *jsop) +{ + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + uintptr_t shared; + + if (read_heap_ptr(&shared, addr, V8_OFF_JSFUNCTION_SHARED) != 0) + return (-1); + + (void) bsnprintf(bufp, lenp, "function "); + return (jsfunc_name(shared, bufp, lenp) != 0); +} + +static int +jsobj_print_jsdate(uintptr_t addr, jsobj_print_t *jsop) +{ + char **bufp = jsop->jsop_bufp; + size_t *lenp = jsop->jsop_lenp; + char buf[128]; + uintptr_t value; + uint8_t type; + double numval; + + if (V8_OFF_JSDATE_VALUE == -1) { + (void) bsnprintf(bufp, lenp, "<JSDate>", buf); + return (0); + } + + if (read_heap_ptr(&value, addr, V8_OFF_JSDATE_VALUE) != 0) { + (void) bsnprintf(bufp, lenp, "<JSDate (failed to read value)>"); + return (-1); + } + + if (read_typebyte(&type, value) != 0) { + (void) bsnprintf(bufp, lenp, "<JSDate (failed to read type)>"); + return (-1); + } + + if (strcmp(enum_lookup_str(v8_types, type, ""), "HeapNumber") != 0) + return (-1); + + if (read_heap_double(&numval, value, V8_OFF_HEAPNUMBER_VALUE) == -1) { + (void) bsnprintf(bufp, lenp, "<JSDate (failed to read num)>"); + return (-1); + } + + mdb_snprintf(buf, sizeof (buf), "%Y", + (time_t)((long long)numval / MILLISEC)); + (void) bsnprintf(bufp, lenp, "%lld (%s)", (long long)numval, buf); + + return (0); +} + +/* + * dcmd implementations + */ + +/* ARGSUSED */ +static int +dcmd_v8classes(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + v8_class_t *clp; + + for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) + mdb_printf("%s\n", clp->v8c_name); + + return (DCMD_OK); +} + +static int +do_v8code(uintptr_t addr, boolean_t opt_d) +{ + uintptr_t instrlen; + ssize_t instroff = V8_OFF_CODE_INSTRUCTION_START; + + if (read_heap_ptr(&instrlen, addr, V8_OFF_CODE_INSTRUCTION_SIZE) != 0) + return (DCMD_ERR); + + mdb_printf("code: %p\n", addr); + mdb_printf("instructions: [%p, %p)\n", addr + instroff, + addr + instroff + instrlen); + + if (!opt_d) + return (DCMD_OK); + + mdb_set_dot(addr + instroff); + + do { + (void) mdb_inc_indent(8); /* gets reset by mdb_eval() */ + + /* + * This is absolutely awful. We want to disassemble the above + * range of instructions. Because we don't know how many there + * are, we can't use "::dis". We resort to evaluating "./i", + * but then we need to advance "." by the size of the + * instruction just printed. The only way to do that is by + * printing out "+", but we don't want that to show up, so we + * redirect it to /dev/null. + */ + if (mdb_eval("/i") != 0 || + mdb_eval("+=p ! cat > /dev/null") != 0) { + (void) mdb_dec_indent(8); + v8_warn("failed to disassemble at %p", mdb_get_dot()); + return (DCMD_ERR); + } + } while (mdb_get_dot() < addr + instroff + instrlen); + + (void) mdb_dec_indent(8); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_v8code(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + boolean_t opt_d = B_FALSE; + + if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, B_TRUE, &opt_d, + NULL) != argc) + return (DCMD_USAGE); + + return (do_v8code(addr, opt_d)); +} + +/* ARGSUSED */ +static int +dcmd_v8function(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uint8_t type; + uintptr_t funcinfop, scriptp, lendsp, tokpos, namep, codep; + char *bufp; + size_t len; + boolean_t opt_d = B_FALSE; + char buf[512]; + + if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, B_TRUE, &opt_d, + NULL) != argc) + return (DCMD_USAGE); + + v8_warnings++; + + if (read_typebyte(&type, addr) != 0) + goto err; + + if (strcmp(enum_lookup_str(v8_types, type, ""), "JSFunction") != 0) { + v8_warn("%p is not an instance of JSFunction\n", addr); + goto err; + } + + if (read_heap_ptr(&funcinfop, addr, V8_OFF_JSFUNCTION_SHARED) != 0 || + read_heap_maybesmi(&tokpos, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION) != 0 || + read_heap_ptr(&scriptp, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0 || + read_heap_ptr(&namep, scriptp, V8_OFF_SCRIPT_NAME) != 0 || + read_heap_ptr(&lendsp, scriptp, V8_OFF_SCRIPT_LINE_ENDS) != 0) + goto err; + + /* + * The token position is normally a SMI, so read_heap_maybesmi() will + * interpret the value for us. However, this code uses its SMI-encoded + * value, so convert it back here. + */ + tokpos = V8_VALUE_SMI(tokpos); + + bufp = buf; + len = sizeof (buf); + if (jsfunc_name(funcinfop, &bufp, &len) != 0) + goto err; + + mdb_printf("%p: JSFunction: %s\n", addr, buf); + + bufp = buf; + len = sizeof (buf); + mdb_printf("defined at "); + + if (jsstr_print(namep, JSSTR_NUDE, &bufp, &len) == 0) + mdb_printf("%s ", buf); + + if (jsfunc_lineno(lendsp, tokpos, buf, sizeof (buf), NULL) == 0) + mdb_printf("%s", buf); + + mdb_printf("\n"); + + if (read_heap_ptr(&codep, + funcinfop, V8_OFF_SHAREDFUNCTIONINFO_CODE) != 0) + goto err; + + v8_warnings--; + + return (do_v8code(codep, opt_d)); + +err: + v8_warnings--; + return (DCMD_ERR); +} + +/* + * Access an internal field of a V8 object. + */ +/* ARGSUSED */ +static int +dcmd_v8internal(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uintptr_t idx; + uintptr_t fieldaddr; + + if (mdb_getopts(argc, argv, NULL) != argc - 1 || + argv[argc - 1].a_type != MDB_TYPE_STRING) + return (DCMD_USAGE); + + idx = mdb_strtoull(argv[argc - 1].a_un.a_str); + if (obj_v8internal(addr, idx, &fieldaddr) != 0) + return (DCMD_ERR); + + mdb_printf("%p\n", fieldaddr); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_v8frametypes(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + enum_print(v8_frametypes); + return (DCMD_OK); +} + +static void +dcmd_v8print_help(void) +{ + mdb_printf( + "Prints out \".\" (a V8 heap object) as an instance of its C++\n" + "class. With no arguments, the appropriate class is detected\n" + "automatically. The 'class' argument overrides this to print an\n" + "object as an instance of the given class. The list of known\n" + "classes can be viewed with ::jsclasses."); +} + +/* ARGSUSED */ +static int +dcmd_v8print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + const char *rqclass; + v8_class_t *clp; + char *bufp; + size_t len; + uint8_t type; + char buf[256]; + + if (argc < 1) { + /* + * If no type was specified, determine it automatically. + */ + bufp = buf; + len = sizeof (buf); + if (obj_jstype(addr, &bufp, &len, &type) != 0) + return (DCMD_ERR); + + if (type == 0) { + /* For SMI or Failure, just print out the type. */ + mdb_printf("%s\n", buf); + return (DCMD_OK); + } + + if ((rqclass = enum_lookup_str(v8_types, type, NULL)) == NULL) { + v8_warn("object has unknown type\n"); + return (DCMD_ERR); + } + } else { + if (argv[0].a_type != MDB_TYPE_STRING) + return (DCMD_USAGE); + + rqclass = argv[0].a_un.a_str; + } + + for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { + if (strcmp(rqclass, clp->v8c_name) == 0) + break; + } + + if (clp == NULL) { + v8_warn("unknown class '%s'\n", rqclass); + return (DCMD_USAGE); + } + + return (obj_print_class(addr, clp)); +} + +/* ARGSUSED */ +static int +dcmd_v8type(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + char buf[64]; + char *bufp = buf; + size_t len = sizeof (buf); + + if (obj_jstype(addr, &bufp, &len, NULL) != 0) + return (DCMD_ERR); + + mdb_printf("0x%p: %s\n", addr, buf); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_v8types(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + enum_print(v8_types); + return (DCMD_OK); +} + +static int +load_current_context(uintptr_t *fpp, uintptr_t *raddrp) +{ + mdb_reg_t regfp, regip; + +#ifdef __amd64 + if (mdb_getareg(1, "rbp", ®fp) != 0 || + mdb_getareg(1, "rip", ®ip) != 0) { +#else +#ifdef __i386 + if (mdb_getareg(1, "ebp", ®fp) != 0 || + mdb_getareg(1, "eip", ®ip) != 0) { +#else +#error Unrecognized microprocessor +#endif +#endif + v8_warn("failed to load current context"); + return (-1); + } + + if (fpp != NULL) + *fpp = (uintptr_t)regfp; + + if (raddrp != NULL) + *raddrp = (uintptr_t)regip; + + return (0); +} + +typedef struct jsframe { + boolean_t jsf_showall; /* show hidden frames and pointers */ + boolean_t jsf_verbose; /* show arguments and JS code */ + char *jsf_func; /* filter frames for named function */ + char *jsf_prop; /* filter arguments */ + uintptr_t jsf_nlines; /* lines of context (for verbose) */ + uint_t jsf_nskipped; /* skipped frames */ +} jsframe_t; + +static void +jsframe_skip(jsframe_t *jsf) +{ + jsf->jsf_nskipped++; +} + +static void +jsframe_print_skipped(jsframe_t *jsf) +{ + if (jsf->jsf_nskipped == 1) + mdb_printf(" (1 internal frame elided)\n"); + else if (jsf->jsf_nskipped > 1) + mdb_printf(" (%d internal frames elided)\n", + jsf->jsf_nskipped); + jsf->jsf_nskipped = 0; +} + +static int +do_jsframe_special(uintptr_t fptr, uintptr_t raddr, jsframe_t *jsf) +{ + uint_t count; + uintptr_t ftype; + const char *ftypename; + char *prop = jsf->jsf_prop; + + /* + * First see if this looks like a native frame rather than a JavaScript + * frame. We check this by asking MDB to print the return address + * symbolically. If that works, we assume this was NOT a V8 frame, + * since those are never in the symbol table. + */ + count = mdb_snprintf(NULL, 0, "%A", raddr); + if (count > 1) { + if (prop != NULL) + return (0); + + jsframe_print_skipped(jsf); + if (jsf->jsf_showall) { + mdb_printf("%p %a\n", fptr, raddr); + } else if (count <= 65) { + mdb_printf("native: %a\n", raddr); + } else { + char buf[65]; + mdb_snprintf(buf, sizeof (buf), "%a", raddr); + mdb_printf("native: %s...\n", buf); + } + return (0); + } + + /* + * Figure out what kind of frame this is using the same algorithm as + * V8's ComputeType function. First, look for an ArgumentsAdaptorFrame. + */ + if (mdb_vread(&ftype, sizeof (ftype), fptr + V8_OFF_FP_CONTEXT) != -1 && + V8_IS_SMI(ftype) && + (ftypename = enum_lookup_str(v8_frametypes, V8_SMI_VALUE(ftype), + NULL)) != NULL && strstr(ftypename, "ArgumentsAdaptor") != NULL) { + if (prop != NULL) + return (0); + + if (jsf->jsf_showall) { + jsframe_print_skipped(jsf); + mdb_printf("%p %a <%s>\n", fptr, raddr, ftypename); + } else { + jsframe_skip(jsf); + } + return (0); + } + + /* + * Other special frame types are indicated by a marker. + */ + if (mdb_vread(&ftype, sizeof (ftype), fptr + V8_OFF_FP_MARKER) != -1 && + V8_IS_SMI(ftype)) { + if (prop != NULL) + return (0); + + ftypename = enum_lookup_str(v8_frametypes, V8_SMI_VALUE(ftype), + NULL); + + if (jsf->jsf_showall && ftypename != NULL) { + jsframe_print_skipped(jsf); + mdb_printf("%p %a <%s>\n", fptr, raddr, ftypename); + } else { + jsframe_skip(jsf); + } + + return (0); + } + + return (-1); +} + +static int +do_jsframe(uintptr_t fptr, uintptr_t raddr, jsframe_t *jsf) +{ + boolean_t showall = jsf->jsf_showall; + boolean_t verbose = jsf->jsf_verbose; + const char *func = jsf->jsf_func; + const char *prop = jsf->jsf_prop; + uintptr_t nlines = jsf->jsf_nlines; + + uintptr_t funcp, funcinfop, tokpos, endpos, scriptp, lendsp, ptrp; + uintptr_t ii, nargs; + const char *typename; + char *bufp; + size_t len; + uint8_t type; + char buf[256]; + int lineno; + + /* + * Check for non-JavaScript frames first. + */ + if (func == NULL && do_jsframe_special(fptr, raddr, jsf) == 0) + return (DCMD_OK); + + /* + * At this point we assume we're looking at a JavaScript frame. As with + * native frames, fish the address out of the parent frame. + */ + if (mdb_vread(&funcp, sizeof (funcp), + fptr + V8_OFF_FP_FUNCTION) == -1) { + v8_warn("failed to read stack at %p", + fptr + V8_OFF_FP_FUNCTION); + return (DCMD_ERR); + } + + /* + * Check if this thing is really a JSFunction at all. For some frames, + * it's a Code object, presumably indicating some internal frame. + */ + if (read_typebyte(&type, funcp) != 0 || + (typename = enum_lookup_str(v8_types, type, NULL)) == NULL) { + if (func != NULL || prop != NULL) + return (DCMD_OK); + + if (showall) { + jsframe_print_skipped(jsf); + mdb_printf("%p %a\n", fptr, raddr); + } else { + jsframe_skip(jsf); + } + return (DCMD_OK); + } + + if (strcmp("Code", typename) == 0) { + if (func != NULL || prop != NULL) + return (DCMD_OK); + + if (showall) { + jsframe_print_skipped(jsf); + mdb_printf("%p %a internal (Code: %p)\n", + fptr, raddr, funcp); + } else { + jsframe_skip(jsf); + } + return (DCMD_OK); + } + + if (strcmp("JSFunction", typename) != 0) { + if (func != NULL || prop != NULL) + return (DCMD_OK); + + if (showall) { + jsframe_print_skipped(jsf); + mdb_printf("%p %a unknown (%s: %p)", + fptr, raddr, typename, funcp); + } else { + jsframe_skip(jsf); + } + return (DCMD_OK); + } + + if (read_heap_ptr(&funcinfop, funcp, V8_OFF_JSFUNCTION_SHARED) != 0) + return (DCMD_ERR); + + bufp = buf; + len = sizeof (buf); + if (jsfunc_name(funcinfop, &bufp, &len) != 0) + return (DCMD_ERR); + + if (func != NULL && strcmp(buf, func) != 0) + return (DCMD_OK); + + if (prop == NULL) { + jsframe_print_skipped(jsf); + if (showall) + mdb_printf("%p %a ", fptr, raddr); + else + mdb_printf("js: "); + mdb_printf("%s", buf); + if (showall) + mdb_printf(" (JSFunction: %p)\n", funcp); + else + mdb_printf("\n"); + } + + if (!verbose && prop == NULL) + return (DCMD_OK); + + if (verbose) + jsframe_print_skipped(jsf); + + /* + * Although the token position is technically an SMI, we're going to + * byte-compare it to other SMI values so we don't want decode it here. + */ + if (read_heap_maybesmi(&tokpos, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION) != 0) + return (DCMD_ERR); + tokpos = V8_VALUE_SMI(tokpos); + + if (read_heap_ptr(&scriptp, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0) + return (DCMD_ERR); + + if (read_heap_ptr(&ptrp, scriptp, V8_OFF_SCRIPT_NAME) != 0) + return (DCMD_ERR); + + bufp = buf; + len = sizeof (buf); + (void) jsstr_print(ptrp, JSSTR_NUDE, &bufp, &len); + + if (prop != NULL && strcmp(prop, "file") == 0) { + mdb_printf("%s\n", buf); + return (DCMD_OK); + } + + if (prop == NULL) { + (void) mdb_inc_indent(10); + mdb_printf("file: %s\n", buf); + } + + if (read_heap_ptr(&lendsp, scriptp, V8_OFF_SCRIPT_LINE_ENDS) != 0) + return (DCMD_ERR); + + (void) jsfunc_lineno(lendsp, tokpos, buf, sizeof (buf), &lineno); + + if (prop != NULL && strcmp(prop, "posn") == 0) { + mdb_printf("%s\n", buf); + return (DCMD_OK); + } + + if (prop == NULL) + mdb_printf("posn: %s\n", buf); + + if (read_heap_maybesmi(&nargs, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_LENGTH) == 0) { + uintptr_t argptr; + char arg[10]; + + if (mdb_vread(&argptr, sizeof (argptr), + fptr + V8_OFF_FP_ARGS + nargs * sizeof (uintptr_t)) != -1 && + argptr != NULL) { + (void) snprintf(arg, sizeof (arg), "this"); + if (prop != NULL && strcmp(arg, prop) == 0) { + mdb_printf("%p\n", argptr); + return (DCMD_OK); + } + + if (prop == NULL) { + bufp = buf; + len = sizeof (buf); + (void) obj_jstype(argptr, &bufp, &len, NULL); + + mdb_printf("this: %p (%s)\n", argptr, buf); + } + } + + for (ii = 0; ii < nargs; ii++) { + if (mdb_vread(&argptr, sizeof (argptr), + fptr + V8_OFF_FP_ARGS + (nargs - ii - 1) * + sizeof (uintptr_t)) == -1) + continue; + + (void) snprintf(arg, sizeof (arg), "arg%" PRIuPTR, + ii + 1); + + if (prop != NULL) { + if (strcmp(arg, prop) != 0) + continue; + + mdb_printf("%p\n", argptr); + return (DCMD_OK); + } + + bufp = buf; + len = sizeof (buf); + (void) obj_jstype(argptr, &bufp, &len, NULL); + + mdb_printf("arg%d: %p (%s)\n", (ii + 1), argptr, buf); + } + } + + + if (prop != NULL) { + mdb_warn("unknown frame property '%s'\n", prop); + return (DCMD_ERR); + } + + if (nlines != 0 && read_heap_maybesmi(&endpos, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_END_POSITION) == 0) { + jsfunc_lines(scriptp, + V8_SMI_VALUE(tokpos), endpos, nlines, "%5d "); + mdb_printf("\n"); + } + + (void) mdb_dec_indent(10); + + return (DCMD_OK); +} + +typedef struct findjsobjects_prop { + struct findjsobjects_prop *fjsp_next; + char fjsp_desc[1]; +} findjsobjects_prop_t; + +typedef struct findjsobjects_instance { + uintptr_t fjsi_addr; + struct findjsobjects_instance *fjsi_next; +} findjsobjects_instance_t; + +typedef struct findjsobjects_obj { + findjsobjects_prop_t *fjso_props; + findjsobjects_prop_t *fjso_last; + jspropinfo_t fjso_propinfo; + size_t fjso_nprops; + findjsobjects_instance_t fjso_instances; + int fjso_ninstances; + avl_node_t fjso_node; + struct findjsobjects_obj *fjso_next; + boolean_t fjso_malformed; + char fjso_constructor[80]; +} findjsobjects_obj_t; + +typedef struct findjsobjects_func { + findjsobjects_instance_t fjsf_instances; + int fjsf_ninstances; + avl_node_t fjsf_node; + struct findjsobjects_func *fjsf_next; + uintptr_t fjsf_shared; + char fjsf_funcname[40]; + char fjsf_scriptname[80]; + char fjsf_location[20]; +} findjsobjects_func_t; + +typedef struct findjsobjects_stats { + int fjss_heapobjs; + int fjss_cached; + int fjss_typereads; + int fjss_jsobjs; + int fjss_objects; + int fjss_arrays; + int fjss_uniques; + int fjss_funcs; + int fjss_funcs_skipped; + int fjss_funcs_unique; +} findjsobjects_stats_t; + +typedef struct findjsobjects_reference { + uintptr_t fjsrf_addr; + char *fjsrf_desc; + size_t fjsrf_index; + struct findjsobjects_reference *fjsrf_next; +} findjsobjects_reference_t; + +typedef struct findjsobjects_referent { + avl_node_t fjsr_node; + uintptr_t fjsr_addr; + findjsobjects_reference_t *fjsr_head; + findjsobjects_reference_t *fjsr_tail; + struct findjsobjects_referent *fjsr_next; +} findjsobjects_referent_t; + +typedef struct findjsobjects_state { + uintptr_t fjs_addr; + uintptr_t fjs_size; + boolean_t fjs_verbose; + boolean_t fjs_brk; + boolean_t fjs_allobjs; + boolean_t fjs_initialized; + boolean_t fjs_marking; + boolean_t fjs_referred; + avl_tree_t fjs_tree; + avl_tree_t fjs_referents; + avl_tree_t fjs_funcinfo; + findjsobjects_referent_t *fjs_head; + findjsobjects_referent_t *fjs_tail; + findjsobjects_obj_t *fjs_current; + findjsobjects_obj_t *fjs_objects; + findjsobjects_func_t *fjs_funcs; + findjsobjects_stats_t fjs_stats; +} findjsobjects_state_t; + +findjsobjects_obj_t * +findjsobjects_alloc(uintptr_t addr) +{ + findjsobjects_obj_t *obj; + + obj = mdb_zalloc(sizeof (findjsobjects_obj_t), UM_SLEEP); + obj->fjso_instances.fjsi_addr = addr; + obj->fjso_ninstances = 1; + + return (obj); +} + +void +findjsobjects_free(findjsobjects_obj_t *obj) +{ + findjsobjects_prop_t *prop, *next; + + for (prop = obj->fjso_props; prop != NULL; prop = next) { + next = prop->fjsp_next; + mdb_free(prop, sizeof (findjsobjects_prop_t) + + strlen(prop->fjsp_desc)); + } + + mdb_free(obj, sizeof (findjsobjects_obj_t)); +} + +int +findjsobjects_cmp(findjsobjects_obj_t *lhs, findjsobjects_obj_t *rhs) +{ + findjsobjects_prop_t *lprop, *rprop; + int rv; + + lprop = lhs->fjso_props; + rprop = rhs->fjso_props; + + while (lprop != NULL && rprop != NULL) { + if ((rv = strcmp(lprop->fjsp_desc, rprop->fjsp_desc)) != 0) + return (rv > 0 ? 1 : -1); + + lprop = lprop->fjsp_next; + rprop = rprop->fjsp_next; + } + + if (lprop != NULL) + return (1); + + if (rprop != NULL) + return (-1); + + if (lhs->fjso_nprops > rhs->fjso_nprops) + return (1); + + if (lhs->fjso_nprops < rhs->fjso_nprops) + return (-1); + + rv = strcmp(lhs->fjso_constructor, rhs->fjso_constructor); + + return (rv < 0 ? -1 : rv > 0 ? 1 : 0); +} + +int +findjsobjects_cmp_funcinfo(findjsobjects_func_t *lhs, + findjsobjects_func_t *rhs) +{ + int diff = lhs->fjsf_shared - rhs->fjsf_shared; + return (diff < 0 ? -1 : diff > 0 ? 1 : 0); +} + +int +findjsobjects_cmp_referents(findjsobjects_referent_t *lhs, + findjsobjects_referent_t *rhs) +{ + if (lhs->fjsr_addr < rhs->fjsr_addr) + return (-1); + + if (lhs->fjsr_addr > rhs->fjsr_addr) + return (1); + + return (0); +} + +int +findjsobjects_cmp_ninstances(const void *l, const void *r) +{ + findjsobjects_obj_t *lhs = *((findjsobjects_obj_t **)l); + findjsobjects_obj_t *rhs = *((findjsobjects_obj_t **)r); + size_t lprod = lhs->fjso_ninstances * lhs->fjso_nprops; + size_t rprod = rhs->fjso_ninstances * rhs->fjso_nprops; + + if (lprod < rprod) + return (-1); + + if (lprod > rprod) + return (1); + + if (lhs->fjso_ninstances < rhs->fjso_ninstances) + return (-1); + + if (lhs->fjso_ninstances > rhs->fjso_ninstances) + return (1); + + if (lhs->fjso_nprops < rhs->fjso_nprops) + return (-1); + + if (lhs->fjso_nprops > rhs->fjso_nprops) + return (1); + + return (0); +} + +/*ARGSUSED*/ +int +findjsobjects_prop(const char *desc, uintptr_t val, void *arg) +{ + findjsobjects_state_t *fjs = arg; + findjsobjects_obj_t *current = fjs->fjs_current; + findjsobjects_prop_t *prop; + + if (desc == NULL) + desc = "<unknown>"; + + prop = mdb_zalloc(sizeof (findjsobjects_prop_t) + + strlen(desc), UM_SLEEP); + + strcpy(prop->fjsp_desc, desc); + + if (current->fjso_last != NULL) { + current->fjso_last->fjsp_next = prop; + } else { + current->fjso_props = prop; + } + + current->fjso_last = prop; + current->fjso_nprops++; + current->fjso_malformed = + val == NULL && current->fjso_nprops == 1 && desc[0] == '<'; + + return (0); +} + +static void +findjsobjects_constructor(findjsobjects_obj_t *obj) +{ + char *bufp = obj->fjso_constructor; + size_t len = sizeof (obj->fjso_constructor); + uintptr_t map, funcinfop; + uintptr_t addr = obj->fjso_instances.fjsi_addr; + uint8_t type; + + v8_silent++; + + if (read_heap_ptr(&map, addr, V8_OFF_HEAPOBJECT_MAP) != 0 || + read_heap_ptr(&addr, map, V8_OFF_MAP_CONSTRUCTOR) != 0) + goto out; + + if (read_typebyte(&type, addr) != 0) + goto out; + + if (strcmp(enum_lookup_str(v8_types, type, ""), "JSFunction") != 0) + goto out; + + if (read_heap_ptr(&funcinfop, addr, V8_OFF_JSFUNCTION_SHARED) != 0) + goto out; + + if (jsfunc_name(funcinfop, &bufp, &len) != 0) + goto out; +out: + v8_silent--; +} + +static void +findjsobjects_jsfunc(findjsobjects_state_t *fjs, uintptr_t addr) +{ + findjsobjects_func_t *func, *ofunc; + findjsobjects_instance_t *inst; + uintptr_t funcinfo, script, name; + avl_index_t where; + int err; + char *bufp; + size_t len; + + /* + * This may be somewhat expensive to do for all JSFunctions, but in most + * core files, there aren't that many. We could defer some of this work + * until the user tries to print the function ::jsfunctions, but this + * step is useful to do early to filter out garbage data. + */ + + v8_silent++; + if (read_heap_ptr(&funcinfo, addr, V8_OFF_JSFUNCTION_SHARED) != 0 || + read_heap_ptr(&script, funcinfo, + V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0 || + read_heap_ptr(&name, script, V8_OFF_SCRIPT_NAME) != 0) { + fjs->fjs_stats.fjss_funcs_skipped++; + v8_silent--; + return; + } + + func = mdb_zalloc(sizeof (findjsobjects_func_t), UM_SLEEP); + func->fjsf_ninstances = 1; + func->fjsf_instances.fjsi_addr = addr; + func->fjsf_shared = funcinfo; + + bufp = func->fjsf_funcname; + len = sizeof (func->fjsf_funcname); + err = jsfunc_name(funcinfo, &bufp, &len); + + bufp = func->fjsf_scriptname; + len = sizeof (func->fjsf_scriptname); + err |= jsstr_print(name, JSSTR_NUDE, &bufp, &len); + + v8_silent--; + if (err != 0) { + fjs->fjs_stats.fjss_funcs_skipped++; + mdb_free(func, sizeof (findjsobjects_func_t)); + return; + } + + fjs->fjs_stats.fjss_funcs++; + ofunc = avl_find(&fjs->fjs_funcinfo, func, &where); + if (ofunc == NULL) { + avl_add(&fjs->fjs_funcinfo, func); + func->fjsf_next = fjs->fjs_funcs; + fjs->fjs_funcs = func; + fjs->fjs_stats.fjss_funcs_unique++; + } else { + inst = mdb_alloc(sizeof (findjsobjects_instance_t), UM_SLEEP); + inst->fjsi_addr = addr; + inst->fjsi_next = ofunc->fjsf_instances.fjsi_next; + ofunc->fjsf_instances.fjsi_next = inst; + ofunc->fjsf_ninstances++; + mdb_free(func, sizeof (findjsobjects_func_t)); + } +} + +int +findjsobjects_range(findjsobjects_state_t *fjs, uintptr_t addr, uintptr_t size) +{ + uintptr_t limit; + findjsobjects_stats_t *stats = &fjs->fjs_stats; + uint8_t type; + int jsobject = V8_TYPE_JSOBJECT, jsarray = V8_TYPE_JSARRAY; + int jsfunction = V8_TYPE_JSFUNCTION; + caddr_t range = mdb_alloc(size, UM_SLEEP); + uintptr_t base = addr, mapaddr; + + if (mdb_vread(range, size, addr) == -1) + return (0); + + for (limit = addr + size; addr < limit; addr++) { + findjsobjects_instance_t *inst; + findjsobjects_obj_t *obj; + avl_index_t where; + + if (V8_IS_SMI(addr)) + continue; + + if (!V8_IS_HEAPOBJECT(addr)) + continue; + + stats->fjss_heapobjs++; + + mapaddr = *((uintptr_t *)((uintptr_t)range + + (addr - base) + V8_OFF_HEAPOBJECT_MAP)); + + if (!V8_IS_HEAPOBJECT(mapaddr)) + continue; + + mapaddr += V8_OFF_MAP_INSTANCE_ATTRIBUTES; + stats->fjss_typereads++; + + if (mapaddr >= base && mapaddr < base + size) { + stats->fjss_cached++; + + type = *((uint8_t *)((uintptr_t)range + + (mapaddr - base))); + } else { + if (mdb_vread(&type, sizeof (uint8_t), mapaddr) == -1) + continue; + } + + if (type == jsfunction) { + findjsobjects_jsfunc(fjs, addr); + continue; + } + + if (type != jsobject && type != jsarray) + continue; + + stats->fjss_jsobjs++; + + fjs->fjs_current = findjsobjects_alloc(addr); + + if (type == jsobject) { + if (jsobj_properties(addr, + findjsobjects_prop, fjs, + &fjs->fjs_current->fjso_propinfo) != 0) { + findjsobjects_free(fjs->fjs_current); + fjs->fjs_current = NULL; + continue; + } + + findjsobjects_constructor(fjs->fjs_current); + stats->fjss_objects++; + } else { + uintptr_t ptr; + size_t *nprops = &fjs->fjs_current->fjso_nprops; + ssize_t len = V8_OFF_JSARRAY_LENGTH; + ssize_t elems = V8_OFF_JSOBJECT_ELEMENTS; + ssize_t flen = V8_OFF_FIXEDARRAY_LENGTH; + uintptr_t nelems; + uint8_t t; + + if (read_heap_smi(nprops, addr, len) != 0 || + read_heap_ptr(&ptr, addr, elems) != 0 || + !V8_IS_HEAPOBJECT(ptr) || + read_typebyte(&t, ptr) != 0 || + t != V8_TYPE_FIXEDARRAY || + read_heap_smi(&nelems, ptr, flen) != 0 || + nelems < *nprops) { + findjsobjects_free(fjs->fjs_current); + fjs->fjs_current = NULL; + continue; + } + + strcpy(fjs->fjs_current->fjso_constructor, "Array"); + stats->fjss_arrays++; + } + + /* + * Now determine if we already have an object matching our + * properties. If we don't, we'll add our new object; if we + * do we'll merely enqueue our instance. + */ + obj = avl_find(&fjs->fjs_tree, fjs->fjs_current, &where); + + if (obj == NULL) { + avl_add(&fjs->fjs_tree, fjs->fjs_current); + fjs->fjs_current->fjso_next = fjs->fjs_objects; + fjs->fjs_objects = fjs->fjs_current; + fjs->fjs_current = NULL; + stats->fjss_uniques++; + continue; + } + + findjsobjects_free(fjs->fjs_current); + fjs->fjs_current = NULL; + + inst = mdb_alloc(sizeof (findjsobjects_instance_t), UM_SLEEP); + inst->fjsi_addr = addr; + inst->fjsi_next = obj->fjso_instances.fjsi_next; + obj->fjso_instances.fjsi_next = inst; + obj->fjso_ninstances++; + } + + mdb_free(range, size); + + return (0); +} + +static int +findjsobjects_mapping(findjsobjects_state_t *fjs, const prmap_t *pmp, + const char *name) +{ + if (name != NULL && !(fjs->fjs_brk && (pmp->pr_mflags & MA_BREAK))) + return (0); + + if (fjs->fjs_addr != NULL && (fjs->fjs_addr < pmp->pr_vaddr || + fjs->fjs_addr >= pmp->pr_vaddr + pmp->pr_size)) + return (0); + + return (findjsobjects_range(fjs, pmp->pr_vaddr, pmp->pr_size)); +} + +static void +findjsobjects_references_add(findjsobjects_state_t *fjs, uintptr_t val, + const char *desc, size_t index) +{ + findjsobjects_referent_t search, *referent; + findjsobjects_reference_t *reference; + + search.fjsr_addr = val; + + if ((referent = avl_find(&fjs->fjs_referents, &search, NULL)) == NULL) + return; + + reference = mdb_zalloc(sizeof (*reference), UM_SLEEP | UM_GC); + reference->fjsrf_addr = fjs->fjs_addr; + + if (desc != NULL) { + reference->fjsrf_desc = + mdb_alloc(strlen(desc) + 1, UM_SLEEP | UM_GC); + (void) strcpy(reference->fjsrf_desc, desc); + } else { + reference->fjsrf_index = index; + } + + if (referent->fjsr_head == NULL) { + referent->fjsr_head = reference; + } else { + referent->fjsr_tail->fjsrf_next = reference; + } + + referent->fjsr_tail = reference; +} + +static int +findjsobjects_references_prop(const char *desc, uintptr_t val, void *arg) +{ + findjsobjects_references_add(arg, val, desc, -1); + + return (0); +} + +static void +findjsobjects_references_array(findjsobjects_state_t *fjs, + findjsobjects_obj_t *obj) +{ + findjsobjects_instance_t *inst = &obj->fjso_instances; + uintptr_t *elts; + size_t i, len; + + for (; inst != NULL; inst = inst->fjsi_next) { + uintptr_t addr = inst->fjsi_addr, ptr; + + if (read_heap_ptr(&ptr, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0 || + read_heap_array(ptr, &elts, &len, UM_SLEEP) != 0) + continue; + + fjs->fjs_addr = addr; + + for (i = 0; i < len; i++) + findjsobjects_references_add(fjs, elts[i], NULL, i); + + mdb_free(elts, len * sizeof (uintptr_t)); + } +} + +static void +findjsobjects_referent(findjsobjects_state_t *fjs, uintptr_t addr) +{ + findjsobjects_referent_t search, *referent; + + search.fjsr_addr = addr; + + if (avl_find(&fjs->fjs_referents, &search, NULL) != NULL) { + assert(fjs->fjs_marking); + mdb_warn("%p is already marked; ignoring\n", addr); + return; + } + + referent = mdb_zalloc(sizeof (findjsobjects_referent_t), UM_SLEEP); + referent->fjsr_addr = addr; + + avl_add(&fjs->fjs_referents, referent); + + if (fjs->fjs_tail != NULL) { + fjs->fjs_tail->fjsr_next = referent; + } else { + fjs->fjs_head = referent; + } + + fjs->fjs_tail = referent; + + if (fjs->fjs_marking) + mdb_printf("findjsobjects: marked %p\n", addr); +} + +static void +findjsobjects_references(findjsobjects_state_t *fjs) +{ + findjsobjects_reference_t *reference; + findjsobjects_referent_t *referent; + avl_tree_t *referents = &fjs->fjs_referents; + findjsobjects_obj_t *obj; + void *cookie = NULL; + uintptr_t addr; + + fjs->fjs_referred = B_FALSE; + + v8_silent++; + + /* + * First traverse over all objects and arrays, looking for references + * to our designated referent(s). + */ + for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { + findjsobjects_instance_t *head = &obj->fjso_instances, *inst; + + if (obj->fjso_nprops != 0 && obj->fjso_props == NULL) { + findjsobjects_references_array(fjs, obj); + continue; + } + + for (inst = head; inst != NULL; inst = inst->fjsi_next) { + fjs->fjs_addr = inst->fjsi_addr; + + (void) jsobj_properties(inst->fjsi_addr, + findjsobjects_references_prop, fjs, NULL); + } + } + + v8_silent--; + fjs->fjs_addr = NULL; + + /* + * Now go over our referent(s), reporting any references that we have + * accumulated. + */ + for (referent = fjs->fjs_head; referent != NULL; + referent = referent->fjsr_next) { + addr = referent->fjsr_addr; + + if ((reference = referent->fjsr_head) == NULL) { + mdb_printf("%p is not referred to by a " + "known object.\n", addr); + continue; + } + + for (; reference != NULL; reference = reference->fjsrf_next) { + mdb_printf("%p referred to by %p", + addr, reference->fjsrf_addr); + + if (reference->fjsrf_desc == NULL) { + mdb_printf("[%d]\n", reference->fjsrf_index); + } else { + mdb_printf(".%s\n", reference->fjsrf_desc); + } + } + } + + /* + * Finally, destroy our referent nodes. + */ + while ((referent = avl_destroy_nodes(referents, &cookie)) != NULL) + mdb_free(referent, sizeof (findjsobjects_referent_t)); + + fjs->fjs_head = NULL; + fjs->fjs_tail = NULL; +} + +static findjsobjects_instance_t * +findjsobjects_instance(findjsobjects_state_t *fjs, uintptr_t addr, + findjsobjects_instance_t **headp) +{ + findjsobjects_obj_t *obj; + + for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { + findjsobjects_instance_t *head = &obj->fjso_instances, *inst; + + for (inst = head; inst != NULL; inst = inst->fjsi_next) { + if (inst->fjsi_addr == addr) { + *headp = head; + return (inst); + } + } + } + + return (NULL); +} + +/*ARGSUSED*/ +static void +findjsobjects_match_all(findjsobjects_obj_t *obj, const char *ignored) +{ + mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); +} + +static void +findjsobjects_match_propname(findjsobjects_obj_t *obj, const char *propname) +{ + findjsobjects_prop_t *prop; + + for (prop = obj->fjso_props; prop != NULL; prop = prop->fjsp_next) { + if (strcmp(prop->fjsp_desc, propname) == 0) { + mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); + return; + } + } +} + +static void +findjsobjects_match_constructor(findjsobjects_obj_t *obj, + const char *constructor) +{ + if (strcmp(constructor, obj->fjso_constructor) == 0) + mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); +} + +static void +findjsobjects_match_kind(findjsobjects_obj_t *obj, const char *propkind) +{ + jspropinfo_t p = obj->fjso_propinfo; + + if (((p & JPI_NUMERIC) != 0 && strstr(propkind, "numeric") != NULL) || + ((p & JPI_DICT) != 0 && strstr(propkind, "dict") != NULL) || + ((p & JPI_INOBJECT) != 0 && strstr(propkind, "inobject") != NULL) || + ((p & JPI_PROPS) != 0 && strstr(propkind, "props") != NULL) || + ((p & JPI_HASTRANSITIONS) != 0 && + strstr(propkind, "transitions") != NULL) || + ((p & JPI_HASCONTENT) != 0 && + strstr(propkind, "content") != NULL) || + ((p & JPI_SKIPPED) != 0 && strstr(propkind, "skipped") != NULL) || + ((p & JPI_BADLAYOUT) != 0 && + strstr(propkind, "badlayout") != NULL)) { + mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); + } +} + +static int +findjsobjects_match(findjsobjects_state_t *fjs, uintptr_t addr, + uint_t flags, void (*func)(findjsobjects_obj_t *, const char *), + const char *match) +{ + findjsobjects_obj_t *obj; + + if (!(flags & DCMD_ADDRSPEC)) { + for (obj = fjs->fjs_objects; obj != NULL; + obj = obj->fjso_next) { + if (obj->fjso_malformed && !fjs->fjs_allobjs) + continue; + + func(obj, match); + } + + return (DCMD_OK); + } + + /* + * First, look for the specified address among the representative + * objects. + */ + for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { + if (obj->fjso_instances.fjsi_addr == addr) { + func(obj, match); + return (DCMD_OK); + } + } + + /* + * We didn't find it among the representative objects; iterate over + * all objects. + */ + for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { + findjsobjects_instance_t *head = &obj->fjso_instances, *inst; + + for (inst = head; inst != NULL; inst = inst->fjsi_next) { + if (inst->fjsi_addr == addr) { + func(obj, match); + return (DCMD_OK); + } + } + } + + mdb_warn("%p does not correspond to a known object\n", addr); + return (DCMD_ERR); +} + +static void +findjsobjects_print(findjsobjects_obj_t *obj) +{ + int col = 19 + (sizeof (uintptr_t) * 2) + strlen("..."), len; + uintptr_t addr = obj->fjso_instances.fjsi_addr; + findjsobjects_prop_t *prop; + + mdb_printf("%?p %8d %8d ", + addr, obj->fjso_ninstances, obj->fjso_nprops); + + if (obj->fjso_constructor[0] != '\0') { + mdb_printf("%s%s", obj->fjso_constructor, + obj->fjso_props != NULL ? ": " : ""); + col += strlen(obj->fjso_constructor) + 2; + } + + for (prop = obj->fjso_props; prop != NULL; prop = prop->fjsp_next) { + if (col + (len = strlen(prop->fjsp_desc) + 2) < 80) { + mdb_printf("%s%s", prop->fjsp_desc, + prop->fjsp_next != NULL ? ", " : ""); + col += len; + } else { + mdb_printf("..."); + break; + } + } + + mdb_printf("\n", col); +} + +static void +dcmd_findjsobjects_help(void) +{ + mdb_printf("%s\n\n", +"Finds all JavaScript objects in the V8 heap via brute force iteration over\n" +"all mapped anonymous memory. (This can take up to several minutes on large\n" +"dumps.) The output consists of representative objects, the number of\n" +"instances of that object and the number of properties on the object --\n" +"followed by the constructor and first few properties of the objects. Once\n" +"run, subsequent calls to ::findjsobjects use cached data. If provided an\n" +"address (and in the absence of -r, described below), ::findjsobjects treats\n" +"the address as that of a representative object, and lists all instances of\n" +"that object (that is, all objects that have a matching property signature)."); + + mdb_dec_indent(2); + mdb_printf("%<b>OPTIONS%</b>\n"); + mdb_inc_indent(2); + + mdb_printf("%s\n", +" -b Include the heap denoted by the brk(2) (normally excluded)\n" +" -c cons Display representative objects with the specified constructor\n" +" -p prop Display representative objects that have the specified property\n" +" -l List all objects that match the representative object\n" +" -m Mark specified object for later reference determination via -r\n" +" -r Find references to the specified and/or marked object(s)\n" +" -v Provide verbose statistics\n"); +} + +static findjsobjects_state_t findjsobjects_state; + +static int +findjsobjects_run(findjsobjects_state_t *fjs) +{ + struct ps_prochandle *Pr; + findjsobjects_obj_t *obj; + findjsobjects_stats_t *stats = &fjs->fjs_stats; + + if (!fjs->fjs_initialized) { + avl_create(&fjs->fjs_tree, + (int(*)(const void *, const void *))findjsobjects_cmp, + sizeof (findjsobjects_obj_t), + offsetof(findjsobjects_obj_t, fjso_node)); + + avl_create(&fjs->fjs_referents, + (int(*)(const void *, const void *)) + findjsobjects_cmp_referents, + sizeof (findjsobjects_referent_t), + offsetof(findjsobjects_referent_t, fjsr_node)); + + avl_create(&fjs->fjs_funcinfo, + (int(*)(const void *, const void*)) + findjsobjects_cmp_funcinfo, + sizeof (findjsobjects_func_t), + offsetof(findjsobjects_func_t, fjsf_node)); + + fjs->fjs_initialized = B_TRUE; + } + + if (avl_is_empty(&fjs->fjs_tree)) { + findjsobjects_obj_t **sorted; + int nobjs, i; + hrtime_t start = gethrtime(); + + if (mdb_get_xdata("pshandle", &Pr, sizeof (Pr)) == -1) { + mdb_warn("couldn't read pshandle xdata"); + return (-1); + } + + v8_silent++; + + if (Pmapping_iter(Pr, + (proc_map_f *)findjsobjects_mapping, fjs) != 0) { + v8_silent--; + return (-1); + } + + if ((nobjs = avl_numnodes(&fjs->fjs_tree)) != 0) { + /* + * We have the objects -- now sort them. + */ + sorted = mdb_alloc(nobjs * sizeof (void *), + UM_SLEEP | UM_GC); + + for (obj = fjs->fjs_objects, i = 0; obj != NULL; + obj = obj->fjso_next, i++) { + sorted[i] = obj; + } + + qsort(sorted, avl_numnodes(&fjs->fjs_tree), + sizeof (void *), findjsobjects_cmp_ninstances); + + for (i = 1, fjs->fjs_objects = sorted[0]; + i < nobjs; i++) + sorted[i - 1]->fjso_next = sorted[i]; + + sorted[nobjs - 1]->fjso_next = NULL; + } + + v8_silent--; + + if (fjs->fjs_verbose) { + const char *f = "findjsobjects: %30s => %d\n"; + int elapsed = (int)((gethrtime() - start) / NANOSEC); + + mdb_printf(f, "elapsed time (seconds)", elapsed); + mdb_printf(f, "heap objects", stats->fjss_heapobjs); + mdb_printf(f, "type reads", stats->fjss_typereads); + mdb_printf(f, "cached reads", stats->fjss_cached); + mdb_printf(f, "JavaScript objects", stats->fjss_jsobjs); + mdb_printf(f, "processed objects", stats->fjss_objects); + mdb_printf(f, "processed arrays", stats->fjss_arrays); + mdb_printf(f, "unique objects", stats->fjss_uniques); + mdb_printf(f, "functions found", stats->fjss_funcs); + mdb_printf(f, "unique functions", + stats->fjss_funcs_unique); + mdb_printf(f, "functions skipped", + stats->fjss_funcs_skipped); + } + } + + return (0); +} + +static int +dcmd_findjsobjects(uintptr_t addr, + uint_t flags, int argc, const mdb_arg_t *argv) +{ + findjsobjects_state_t *fjs = &findjsobjects_state; + findjsobjects_obj_t *obj; + boolean_t references = B_FALSE, listlike = B_FALSE; + const char *propname = NULL; + const char *constructor = NULL; + const char *propkind = NULL; + + fjs->fjs_verbose = B_FALSE; + fjs->fjs_brk = B_FALSE; + fjs->fjs_marking = B_FALSE; + fjs->fjs_allobjs = B_FALSE; + + if (mdb_getopts(argc, argv, + 'a', MDB_OPT_SETBITS, B_TRUE, &fjs->fjs_allobjs, + 'b', MDB_OPT_SETBITS, B_TRUE, &fjs->fjs_brk, + 'c', MDB_OPT_STR, &constructor, + 'k', MDB_OPT_STR, &propkind, + 'l', MDB_OPT_SETBITS, B_TRUE, &listlike, + 'm', MDB_OPT_SETBITS, B_TRUE, &fjs->fjs_marking, + 'p', MDB_OPT_STR, &propname, + 'r', MDB_OPT_SETBITS, B_TRUE, &references, + 'v', MDB_OPT_SETBITS, B_TRUE, &fjs->fjs_verbose, + NULL) != argc) + return (DCMD_USAGE); + + if (findjsobjects_run(fjs) != 0) + return (DCMD_ERR); + + if (listlike && !(flags & DCMD_ADDRSPEC)) { + if (propname != NULL || constructor != NULL || + propkind != NULL) { + char opt = propname != NULL ? 'p' : + propkind != NULL ? 'k' :'c'; + + mdb_warn("cannot specify -l with -%c; instead, pipe " + "output of ::findjsobjects -%c to " + "::findjsobjects -l\n", opt, opt); + return (DCMD_ERR); + } + + return (findjsobjects_match(fjs, addr, flags, + findjsobjects_match_all, NULL)); + } + + if (propname != NULL) { + if (constructor != NULL || propkind != NULL) { + mdb_warn("cannot specify both a property name " + "and a %s\n", constructor != NULL ? + "constructor" : "property kind"); + return (DCMD_ERR); + } + + return (findjsobjects_match(fjs, addr, flags, + findjsobjects_match_propname, propname)); + } + + if (constructor != NULL) { + if (propkind != NULL) { + mdb_warn("cannot specify both a constructor name " + "and a property kind\n"); + return (DCMD_ERR); + } + + return (findjsobjects_match(fjs, addr, flags, + findjsobjects_match_constructor, constructor)); + } + + if (propkind != NULL) { + return (findjsobjects_match(fjs, addr, flags, + findjsobjects_match_kind, propkind)); + } + + if (references && !(flags & DCMD_ADDRSPEC) && + avl_is_empty(&fjs->fjs_referents)) { + mdb_warn("must specify or mark an object to find references\n"); + return (DCMD_ERR); + } + + if (fjs->fjs_marking && !(flags & DCMD_ADDRSPEC)) { + mdb_warn("must specify an object to mark\n"); + return (DCMD_ERR); + } + + if (references && fjs->fjs_marking) { + mdb_warn("can't both mark an object and find its references\n"); + return (DCMD_ERR); + } + + if (flags & DCMD_ADDRSPEC) { + findjsobjects_instance_t *inst, *head; + + /* + * If we've been passed an address, it's to either list like + * objects (-l), mark an object (-m) or find references to the + * specified/marked objects (-r). (Note that the absence of + * any of these options implies -l.) + */ + inst = findjsobjects_instance(fjs, addr, &head); + + if (inst == NULL) { + mdb_warn("%p is not a valid object\n", addr); + return (DCMD_ERR); + } + + if (!references && !fjs->fjs_marking) { + for (inst = head; inst != NULL; inst = inst->fjsi_next) + mdb_printf("%p\n", inst->fjsi_addr); + + return (DCMD_OK); + } + + if (!listlike) { + findjsobjects_referent(fjs, inst->fjsi_addr); + } else { + for (inst = head; inst != NULL; inst = inst->fjsi_next) + findjsobjects_referent(fjs, inst->fjsi_addr); + } + } + + if (references) + findjsobjects_references(fjs); + + if (references || fjs->fjs_marking) + return (DCMD_OK); + + mdb_printf("%?s %8s %8s %s\n", "OBJECT", + "#OBJECTS", "#PROPS", "CONSTRUCTOR: PROPS"); + + for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { + if (obj->fjso_malformed && !fjs->fjs_allobjs) + continue; + + findjsobjects_print(obj); + } + + return (DCMD_OK); +} + +/* + * Given a Node Buffer object, print out details about it. With "-a", just + * print the address. + */ +/* ARGSUSED */ +static int +dcmd_nodebuffer(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + boolean_t opt_f = B_FALSE; + char buf[80]; + char *bufp = buf; + size_t len = sizeof (buf); + uintptr_t elts, rawbuf; + + /* + * The undocumented "-f" option allows users to override constructor + * checks. + */ + if (mdb_getopts(argc, argv, + 'f', MDB_OPT_SETBITS, B_TRUE, &opt_f, NULL) != argc) + return (DCMD_USAGE); + + if (!opt_f) { + if (obj_jsconstructor(addr, &bufp, &len, B_FALSE) != 0) + return (DCMD_ERR); + + if (strcmp(buf, "Buffer") != 0) { + mdb_warn("%p does not appear to be a buffer\n", addr); + return (DCMD_ERR); + } + } + + if (read_heap_ptr(&elts, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0) + return (DCMD_ERR); + + if (obj_v8internal(elts, 0, &rawbuf) != 0) + return (DCMD_ERR); + + mdb_printf("%p\n", rawbuf); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_jsconstructor(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + boolean_t opt_v = B_FALSE; + char buf[80]; + char *bufp; + size_t len = sizeof (buf); + + if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, B_TRUE, &opt_v, + NULL) != argc) + return (DCMD_USAGE); + + bufp = buf; + if (obj_jsconstructor(addr, &bufp, &len, opt_v)) + return (DCMD_ERR); + + mdb_printf("%s\n", buf); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_jsframe(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uintptr_t fptr, raddr; + boolean_t opt_i = B_FALSE; + jsframe_t jsf; + int rv; + + bzero(&jsf, sizeof (jsf)); + jsf.jsf_nlines = 5; + + if (mdb_getopts(argc, argv, + 'a', MDB_OPT_SETBITS, B_TRUE, &jsf.jsf_showall, + 'v', MDB_OPT_SETBITS, B_TRUE, &jsf.jsf_verbose, + 'i', MDB_OPT_SETBITS, B_TRUE, &opt_i, + 'f', MDB_OPT_STR, &jsf.jsf_func, + 'n', MDB_OPT_UINTPTR, &jsf.jsf_nlines, + 'p', MDB_OPT_STR, &jsf.jsf_prop, NULL) != argc) + return (DCMD_USAGE); + + /* + * As with $C, we assume we are given a *pointer* to the frame pointer + * for a frame, rather than the actual frame pointer for the frame of + * interest. This is needed to show the instruction pointer, which is + * actually stored with the next frame. For debugging, this can be + * overridden with the "-i" option (for "immediate"). + */ + if (opt_i) { + rv = do_jsframe(addr, 0, &jsf); + if (rv == 0) + jsframe_print_skipped(&jsf); + return (rv); + } + + if (mdb_vread(&raddr, sizeof (raddr), + addr + sizeof (uintptr_t)) == -1) { + mdb_warn("failed to read return address from %p", + addr + sizeof (uintptr_t)); + return (DCMD_ERR); + } + + if (mdb_vread(&fptr, sizeof (fptr), addr) == -1) { + mdb_warn("failed to read frame pointer from %p", addr); + return (DCMD_ERR); + } + + if (fptr == NULL) + return (DCMD_OK); + + rv = do_jsframe(fptr, raddr, &jsf); + if (rv == 0) + jsframe_print_skipped(&jsf); + return (rv); +} + +static void +jsobj_print_propinfo(jspropinfo_t propinfo) +{ + if (propinfo == JPI_NONE) + return; + + mdb_printf("property kind: "); + if ((propinfo & JPI_NUMERIC) != 0) + mdb_printf("numeric-named "); + if ((propinfo & JPI_DICT) != 0) + mdb_printf("dictionary "); + if ((propinfo & JPI_INOBJECT) != 0) + mdb_printf("in-object "); + if ((propinfo & JPI_PROPS) != 0) + mdb_printf("\"properties\" array "); + mdb_printf("\n"); + + if ((propinfo & (JPI_HASTRANSITIONS | JPI_HASCONTENT)) != 0) { + mdb_printf("fallbacks: "); + if ((propinfo & JPI_HASTRANSITIONS) != 0) + mdb_printf("transitions "); + if ((propinfo & JPI_HASCONTENT) != 0) + mdb_printf("content "); + mdb_printf("\n"); + } + + if ((propinfo & JPI_SKIPPED) != 0) + mdb_printf( + "some properties skipped due to unexpected layout\n"); + if ((propinfo & JPI_BADLAYOUT) != 0) + mdb_printf("object has unexpected layout\n"); +} + +/* ARGSUSED */ +static int +dcmd_jsprint(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + char *buf, *bufp; + size_t bufsz = 262144, len = bufsz; + jsobj_print_t jsop; + boolean_t opt_b = B_FALSE; + boolean_t opt_v = B_FALSE; + int rv, i; + + bzero(&jsop, sizeof (jsop)); + jsop.jsop_depth = 2; + jsop.jsop_printaddr = B_FALSE; + + i = mdb_getopts(argc, argv, + 'a', MDB_OPT_SETBITS, B_TRUE, &jsop.jsop_printaddr, + 'b', MDB_OPT_SETBITS, B_TRUE, &opt_b, + 'd', MDB_OPT_UINT64, &jsop.jsop_depth, + 'v', MDB_OPT_SETBITS, B_TRUE, &opt_v, NULL); + + if (opt_b) + jsop.jsop_baseaddr = addr; + + do { + if (i != argc) { + const mdb_arg_t *member = &argv[i++]; + + if (member->a_type != MDB_TYPE_STRING) + return (DCMD_USAGE); + + jsop.jsop_member = member->a_un.a_str; + } + + for (;;) { + if ((buf = bufp = + mdb_zalloc(bufsz, UM_NOSLEEP)) == NULL) + return (DCMD_ERR); + + jsop.jsop_bufp = &bufp; + jsop.jsop_lenp = &len; + + rv = jsobj_print(addr, &jsop); + + if (len > 0) + break; + + mdb_free(buf, bufsz); + bufsz <<= 1; + len = bufsz; + } + + if (jsop.jsop_member == NULL && rv != 0) { + if (!jsop.jsop_descended) + mdb_warn("%s\n", buf); + + return (DCMD_ERR); + } + + if (jsop.jsop_member && !jsop.jsop_found) { + if (jsop.jsop_baseaddr) + (void) mdb_printf("%p: ", jsop.jsop_baseaddr); + + (void) mdb_printf("undefined%s", + i < argc ? " " : ""); + } else { + (void) mdb_printf("%s%s", buf, i < argc && + !isspace(buf[strlen(buf) - 1]) ? " " : ""); + } + + mdb_free(buf, bufsz); + jsop.jsop_found = B_FALSE; + jsop.jsop_baseaddr = NULL; + } while (i < argc); + + mdb_printf("\n"); + + if (opt_v) + jsobj_print_propinfo(jsop.jsop_propinfo); + + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_jssource(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + const char *typename; + uintptr_t nlines = 5; + uintptr_t funcinfop, scriptp, funcnamep; + uintptr_t tokpos, endpos; + uint8_t type; + char buf[256]; + char *bufp = buf; + size_t len = sizeof (buf); + + if (mdb_getopts(argc, argv, 'n', MDB_OPT_UINTPTR, &nlines, + NULL) != argc) + return (DCMD_USAGE); + + if (!V8_IS_HEAPOBJECT(addr) || read_typebyte(&type, addr) != 0) { + mdb_warn("%p is not a heap object\n", addr); + return (DCMD_ERR); + } + + typename = enum_lookup_str(v8_types, type, ""); + if (strcmp(typename, "JSFunction") != 0) { + mdb_warn("%p is not a JSFunction\n", addr); + return (DCMD_ERR); + } + + if (read_heap_ptr(&funcinfop, addr, V8_OFF_JSFUNCTION_SHARED) != 0 || + read_heap_ptr(&scriptp, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0 || + read_heap_ptr(&funcnamep, scriptp, V8_OFF_SCRIPT_NAME) != 0) { + mdb_warn("%p: failed to find script for function\n", addr); + return (DCMD_ERR); + } + + if (read_heap_maybesmi(&tokpos, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION) != 0 || + read_heap_maybesmi(&endpos, funcinfop, + V8_OFF_SHAREDFUNCTIONINFO_END_POSITION) != 0) { + mdb_warn("%p: failed to find function's boundaries\n", addr); + } + + if (jsstr_print(funcnamep, JSSTR_NUDE, &bufp, &len) == 0) + mdb_printf("file: %s\n", buf); + + if (tokpos != endpos) + jsfunc_lines(scriptp, tokpos, endpos, nlines, "%5d "); + mdb_printf("\n"); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_jsfunctions(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + findjsobjects_state_t *fjs = &findjsobjects_state; + findjsobjects_func_t *func; + uintptr_t funcinfo; + boolean_t showrange = B_FALSE; + const char *name = NULL, *filename = NULL; + uintptr_t instr = 0; + + if (mdb_getopts(argc, argv, + 'x', MDB_OPT_UINTPTR, &instr, + 'X', MDB_OPT_SETBITS, B_TRUE, &showrange, + 'n', MDB_OPT_STR, &name, + 's', MDB_OPT_STR, &filename, + NULL) != argc) + return (DCMD_USAGE); + + if (findjsobjects_run(fjs) != 0) + return (DCMD_ERR); + + if (!showrange) + mdb_printf("%?s %8s %-40s %s\n", "FUNC", "#FUNCS", "NAME", + "FROM"); + else + mdb_printf("%?s %8s %?s %?s %-40s %s\n", "FUNC", "#FUNCS", + "START", "END", "NAME", "FROM"); + + for (func = fjs->fjs_funcs; func != NULL; func = func->fjsf_next) { + uintptr_t code, ilen; + + funcinfo = func->fjsf_shared; + + if (func->fjsf_location[0] == '\0') { + uintptr_t tokpos, script, lends; + ptrdiff_t tokposoff = + V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION; + + /* + * We don't want to actually decode the token position + * as an SMI here, so we re-encode it when we pass it to + * jsfunc_lineno() below. + */ + if (read_heap_maybesmi(&tokpos, funcinfo, + tokposoff) != 0 || + read_heap_ptr(&script, funcinfo, + V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0 || + read_heap_ptr(&lends, script, + V8_OFF_SCRIPT_LINE_ENDS) != 0 || + jsfunc_lineno(lends, V8_VALUE_SMI(tokpos), + func->fjsf_location, + sizeof (func->fjsf_location), NULL) != 0) { + func->fjsf_location[0] = '\0'; + } + } + + if (name != NULL && strstr(func->fjsf_funcname, name) == NULL) + continue; + + if (filename != NULL && + strstr(func->fjsf_scriptname, filename) == NULL) + continue; + + code = 0; + ilen = 0; + if ((showrange || instr != 0) && + (read_heap_ptr(&code, funcinfo, + V8_OFF_SHAREDFUNCTIONINFO_CODE) != 0 || + read_heap_ptr(&ilen, code, + V8_OFF_CODE_INSTRUCTION_SIZE) != 0)) { + code = 0; + ilen = 0; + } + + if ((instr != 0 && ilen != 0) && + (instr < code + V8_OFF_CODE_INSTRUCTION_START || + instr >= code + V8_OFF_CODE_INSTRUCTION_START + ilen)) + continue; + + if (!showrange) { + mdb_printf("%?p %8d %-40s %s %s\n", + func->fjsf_instances.fjsi_addr, + func->fjsf_ninstances, func->fjsf_funcname, + func->fjsf_scriptname, func->fjsf_location); + } else { + uintptr_t code, ilen; + + if (read_heap_ptr(&code, funcinfo, + V8_OFF_SHAREDFUNCTIONINFO_CODE) != 0 || + read_heap_ptr(&ilen, code, + V8_OFF_CODE_INSTRUCTION_SIZE) != 0) { + mdb_printf("%?p %8d %?s %?s %-40s %s %s\n", + func->fjsf_instances.fjsi_addr, + func->fjsf_ninstances, "?", "?", + func->fjsf_funcname, func->fjsf_scriptname, + func->fjsf_location); + } else { + mdb_printf("%?p %8d %?p %?p %-40s %s %s\n", + func->fjsf_instances.fjsi_addr, + func->fjsf_ninstances, + code + V8_OFF_CODE_INSTRUCTION_START, + code + V8_OFF_CODE_INSTRUCTION_START + ilen, + func->fjsf_funcname, func->fjsf_scriptname, + func->fjsf_location); + } + } + } + + return (DCMD_OK); +} + +static void +dcmd_jsfunctions_help(void) +{ + mdb_printf("%s\n\n", +"Lists JavaScript functions, optionally filtered by a substring of the\n" +"function name or script filename or by the instruction address. This uses\n" +"the cache created by ::findjsobjects. If ::findjsobjects has not already\n" +"been run, this command runs it automatically without printing the output.\n" +"This can take anywhere from a second to several minutes, depending on the\n" +"size of the core dump.\n" +"\n" +"It's important to keep in mind that each time you create a function in\n" +"JavaScript (even from a function definition that has already been used),\n" +"the VM must create a new object to represent it. For example, if your\n" +"program has a function A that returns a closure B, the VM will create new\n" +"instances of the closure function (B) each time the surrounding function (A)\n" +"is called. To show this, the output of this command consists of one line \n" +"per function definition that appears in the JavaScript source, and the\n" +"\"#FUNCS\" column shows how many different functions were created by VM from\n" +"this definition."); + + mdb_dec_indent(2); + mdb_printf("%<b>OPTIONS%</b>\n"); + mdb_inc_indent(2); + + mdb_printf("%s\n", +" -f file List functions that were defined in a file whose name contains\n" +" this substring.\n" +" -n func List functions whose name contains this substring\n" +" -x instr List functions whose compiled instructions include this address\n" +" -X Show where the function's instructions are stored in memory\n"); +} + +/* ARGSUSED */ +static int +dcmd_v8field(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + v8_class_t *clp; + v8_field_t *flp; + const char *klass, *field; + uintptr_t offset = 0; + + /* + * We may be invoked with either two arguments (class and field name) or + * three (an offset to save). + */ + if (argc != 2 && argc != 3) + return (DCMD_USAGE); + + if (argv[0].a_type != MDB_TYPE_STRING || + argv[1].a_type != MDB_TYPE_STRING) + return (DCMD_USAGE); + + klass = argv[0].a_un.a_str; + field = argv[1].a_un.a_str; + + if (argc == 3) { + if (argv[2].a_type != MDB_TYPE_STRING) + return (DCMD_USAGE); + + offset = mdb_strtoull(argv[2].a_un.a_str); + } + + for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) + if (strcmp(clp->v8c_name, klass) == 0) + break; + + if (clp == NULL) { + (void) mdb_printf("error: no such class: \"%s\"", klass); + return (DCMD_ERR); + } + + for (flp = clp->v8c_fields; flp != NULL; flp = flp->v8f_next) + if (strcmp(field, flp->v8f_name) == 0) + break; + + if (flp == NULL) { + if (argc == 2) { + mdb_printf("error: no such field in class \"%s\": " + "\"%s\"", klass, field); + return (DCMD_ERR); + } + + flp = conf_field_create(clp, field, offset); + if (flp == NULL) { + mdb_warn("failed to create field"); + return (DCMD_ERR); + } + } else if (argc == 3) { + flp->v8f_offset = offset; + } + + mdb_printf("%s::%s at offset 0x%x\n", klass, field, flp->v8f_offset); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_v8array(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uint8_t type; + uintptr_t *array; + size_t ii, len; + + if (read_typebyte(&type, addr) != 0) + return (DCMD_ERR); + + if (type != V8_TYPE_FIXEDARRAY) { + mdb_warn("%p is not an instance of FixedArray\n", addr); + return (DCMD_ERR); + } + + if (read_heap_array(addr, &array, &len, UM_SLEEP | UM_GC) != 0) + return (DCMD_ERR); + + for (ii = 0; ii < len; ii++) + mdb_printf("%p\n", array[ii]); + + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_jsstack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uintptr_t raddr; + jsframe_t jsf; + + bzero(&jsf, sizeof (jsf)); + jsf.jsf_nlines = 5; + + if (mdb_getopts(argc, argv, + 'a', MDB_OPT_SETBITS, B_TRUE, &jsf.jsf_showall, + 'v', MDB_OPT_SETBITS, B_TRUE, &jsf.jsf_verbose, + 'f', MDB_OPT_STR, &jsf.jsf_func, + 'n', MDB_OPT_UINTPTR, &jsf.jsf_nlines, + 'p', MDB_OPT_STR, &jsf.jsf_prop, + NULL) != argc) + return (DCMD_USAGE); + + /* + * The "::jsframe" walker iterates the valid frame pointers, but the + * "::jsframe" dcmd looks at the frame after the one it was given, so we + * have to explicitly examine the top frame here. + */ + if (!(flags & DCMD_ADDRSPEC)) { + if (load_current_context(&addr, &raddr) != 0 || + do_jsframe(addr, raddr, &jsf) != 0) + return (DCMD_ERR); + } + + if (mdb_pwalk_dcmd("jsframe", "jsframe", argc, argv, addr) == -1) + return (DCMD_ERR); + + jsframe_print_skipped(&jsf); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_v8str(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + boolean_t opt_v = B_FALSE; + char buf[512 * 1024]; + char *bufp; + size_t len; + + if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, B_TRUE, &opt_v, + NULL) != argc) + return (DCMD_USAGE); + + bufp = buf; + len = sizeof (buf); + if (jsstr_print(addr, (opt_v ? JSSTR_VERBOSE : JSSTR_NONE) | + JSSTR_QUOTED, &bufp, &len) != 0) + return (DCMD_ERR); + + mdb_printf("%s\n", buf); + return (DCMD_OK); +} + +static void +dcmd_v8load_help(void) +{ + v8_cfg_t *cfp, **cfgpp; + + mdb_printf( + "To traverse in-memory V8 structures, the V8 dmod requires\n" + "configuration that describes the layout of various V8 structures\n" + "in memory. Normally, this information is pulled from metadata\n" + "in the target binary. However, it's possible to use the module\n" + "with a binary not built with metadata by loading one of the\n" + "canned configurations.\n\n"); + + mdb_printf("Available configurations:\n"); + + (void) mdb_inc_indent(4); + + for (cfgpp = v8_cfgs; *cfgpp != NULL; cfgpp++) { + cfp = *cfgpp; + mdb_printf("%-10s %s\n", cfp->v8cfg_name, cfp->v8cfg_label); + } + + (void) mdb_dec_indent(4); +} + +/* ARGSUSED */ +static int +dcmd_v8load(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + v8_cfg_t *cfgp = NULL, **cfgpp; + + if (v8_classes != NULL) { + mdb_warn("v8 module already configured\n"); + return (DCMD_ERR); + } + + if (argc < 1 || argv->a_type != MDB_TYPE_STRING) + return (DCMD_USAGE); + + for (cfgpp = v8_cfgs; *cfgpp != NULL; cfgpp++) { + cfgp = *cfgpp; + if (strcmp(argv->a_un.a_str, cfgp->v8cfg_name) == 0) + break; + } + + if (cfgp == NULL || cfgp->v8cfg_name == NULL) { + mdb_warn("unknown configuration: \"%s\"\n", argv->a_un.a_str); + return (DCMD_ERR); + } + + if (autoconfigure(cfgp) == -1) { + mdb_warn("autoconfigure failed\n"); + return (DCMD_ERR); + } + + mdb_printf("V8 dmod configured based on %s\n", cfgp->v8cfg_name); + return (DCMD_OK); +} + +/* ARGSUSED */ +static int +dcmd_v8warnings(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + v8_warnings ^= 1; + mdb_printf("v8 warnings are now %s\n", v8_warnings ? "on" : "off"); + + return (DCMD_OK); +} + +static int +walk_jsframes_init(mdb_walk_state_t *wsp) +{ + if (wsp->walk_addr != NULL) + return (WALK_NEXT); + + if (load_current_context(&wsp->walk_addr, NULL) != 0) + return (WALK_ERR); + + return (WALK_NEXT); +} + +static int +walk_jsframes_step(mdb_walk_state_t *wsp) +{ + uintptr_t addr, next; + int rv; + + addr = wsp->walk_addr; + rv = wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata); + + if (rv != WALK_NEXT) + return (rv); + + if (mdb_vread(&next, sizeof (next), addr) == -1) + return (WALK_ERR); + + if (next == NULL) + return (WALK_DONE); + + wsp->walk_addr = next; + return (WALK_NEXT); +} + +typedef struct jsprop_walk_data { + int jspw_nprops; + int jspw_current; + uintptr_t *jspw_props; +} jsprop_walk_data_t; + +/*ARGSUSED*/ +static int +walk_jsprop_nprops(const char *desc, uintptr_t val, void *arg) +{ + jsprop_walk_data_t *jspw = arg; + jspw->jspw_nprops++; + + return (0); +} + +/*ARGSUSED*/ +static int +walk_jsprop_props(const char *desc, uintptr_t val, void *arg) +{ + jsprop_walk_data_t *jspw = arg; + jspw->jspw_props[jspw->jspw_current++] = val; + + return (0); +} + +static int +walk_jsprop_init(mdb_walk_state_t *wsp) +{ + jsprop_walk_data_t *jspw; + uintptr_t addr; + uint8_t type; + + if ((addr = wsp->walk_addr) == NULL) { + mdb_warn("'jsprop' does not support global walks\n"); + return (WALK_ERR); + } + + if (!V8_IS_HEAPOBJECT(addr) || read_typebyte(&type, addr) != 0 || + type != V8_TYPE_JSOBJECT) { + mdb_warn("%p is not a JSObject\n", addr); + return (WALK_ERR); + } + + jspw = mdb_zalloc(sizeof (jsprop_walk_data_t), UM_SLEEP | UM_GC); + + if (jsobj_properties(addr, walk_jsprop_nprops, jspw, NULL) == -1) { + mdb_warn("couldn't iterate over properties for %p\n", addr); + return (WALK_ERR); + } + + jspw->jspw_props = mdb_zalloc(jspw->jspw_nprops * + sizeof (uintptr_t), UM_SLEEP | UM_GC); + + if (jsobj_properties(addr, walk_jsprop_props, jspw, NULL) == -1) { + mdb_warn("couldn't iterate over properties for %p\n", addr); + return (WALK_ERR); + } + + jspw->jspw_current = 0; + wsp->walk_data = jspw; + + return (WALK_NEXT); +} + +static int +walk_jsprop_step(mdb_walk_state_t *wsp) +{ + jsprop_walk_data_t *jspw = wsp->walk_data; + int rv; + + if (jspw->jspw_current >= jspw->jspw_nprops) + return (WALK_DONE); + + if ((rv = wsp->walk_callback(jspw->jspw_props[jspw->jspw_current++], + NULL, wsp->walk_cbdata)) != WALK_NEXT) + return (rv); + + return (WALK_NEXT); +} + +/* + * MDB linkage + */ + +static const mdb_dcmd_t v8_mdb_dcmds[] = { + /* + * Commands to inspect Node-level state + */ + { "nodebuffer", ":[-a]", + "print details about the given Node Buffer", dcmd_nodebuffer }, + + /* + * Commands to inspect JavaScript-level state + */ + { "jsconstructor", ":[-v]", + "print the constructor for a JavaScript object", + dcmd_jsconstructor }, + { "jsframe", ":[-aiv] [-f function] [-p property] [-n numlines]", + "summarize a JavaScript stack frame", dcmd_jsframe }, + { "jsprint", ":[-ab] [-d depth] [member]", "print a JavaScript object", + dcmd_jsprint }, + { "jssource", ":[-n numlines]", + "print the source code for a JavaScript function", + dcmd_jssource }, + { "jsstack", "[-av] [-f function] [-p property] [-n numlines]", + "print a JavaScript stacktrace", dcmd_jsstack }, + { "findjsobjects", "?[-vb] [-r | -c cons | -p prop]", "find JavaScript " + "objects", dcmd_findjsobjects, dcmd_findjsobjects_help }, + { "jsfunctions", "[-X] [-s file_filter] [-n name_filter] " + "[-x instr_filter]", "list JavaScript functions", + dcmd_jsfunctions, dcmd_jsfunctions_help }, + + /* + * Commands to inspect V8-level state + */ + { "v8array", ":", "print elements of a V8 FixedArray", + dcmd_v8array }, + { "v8classes", NULL, "list known V8 heap object C++ classes", + dcmd_v8classes }, + { "v8code", ":[-d]", "print information about a V8 Code object", + dcmd_v8code }, + { "v8field", "classname fieldname offset", + "manually add a field to a given class", dcmd_v8field }, + { "v8function", ":[-d]", "print JSFunction object details", + dcmd_v8function }, + { "v8internal", ":[fieldidx]", "print v8 object internal fields", + dcmd_v8internal }, + { "v8load", "version", "load canned config for a specific V8 version", + dcmd_v8load, dcmd_v8load_help }, + { "v8frametypes", NULL, "list known V8 frame types", + dcmd_v8frametypes }, + { "v8print", ":[class]", "print a V8 heap object", + dcmd_v8print, dcmd_v8print_help }, + { "v8str", ":[-v]", "print the contents of a V8 string", + dcmd_v8str }, + { "v8type", ":", "print the type of a V8 heap object", + dcmd_v8type }, + { "v8types", NULL, "list known V8 heap object types", + dcmd_v8types }, + { "v8warnings", NULL, "toggle V8 warnings", + dcmd_v8warnings }, + + { NULL } +}; + +static const mdb_walker_t v8_mdb_walkers[] = { + { "jsframe", "walk V8 JavaScript stack frames", + walk_jsframes_init, walk_jsframes_step }, + { "jsprop", "walk property values for an object", + walk_jsprop_init, walk_jsprop_step }, + { NULL } +}; + +static mdb_modinfo_t v8_mdb = { MDB_API_VERSION, v8_mdb_dcmds, v8_mdb_walkers }; + +static void +configure(void) +{ + char *success; + v8_cfg_t *cfgp = NULL; + GElf_Sym sym; + int major, minor, build, patch; + + if (mdb_readsym(&major, sizeof (major), + "_ZN2v88internal7Version6major_E") == -1 || + mdb_readsym(&minor, sizeof (minor), + "_ZN2v88internal7Version6minor_E") == -1 || + mdb_readsym(&build, sizeof (build), + "_ZN2v88internal7Version6build_E") == -1 || + mdb_readsym(&patch, sizeof (patch), + "_ZN2v88internal7Version6patch_E") == -1) { + mdb_warn("failed to determine V8 version"); + return; + } + + v8_major = major; + v8_minor = minor; + v8_build = build; + v8_patch = patch; + mdb_printf("V8 version: %d.%d.%d.%d\n", + v8_major, v8_minor, v8_build, v8_patch); + + /* + * First look for debug metadata embedded within the binary, which may + * be present in recent V8 versions built with postmortem metadata. + */ + if (mdb_lookup_by_name("v8dbg_SmiTag", &sym) == 0) { + cfgp = &v8_cfg_target; + success = "Autoconfigured V8 support from target"; + } else if (v8_major == 3 && v8_minor == 1 && v8_build == 8) { + cfgp = &v8_cfg_04; + success = "Configured V8 support based on node v0.4"; + } else if (v8_major == 3 && v8_minor == 6 && v8_build == 6) { + cfgp = &v8_cfg_06; + success = "Configured V8 support based on node v0.6"; + } else { + mdb_printf("mdb_v8: target has no debug metadata and " + "no existing config found\n"); + return; + } + + if (autoconfigure(cfgp) != 0) { + mdb_warn("failed to autoconfigure from target; " + "commands may have incorrect results!\n"); + return; + } + + mdb_printf("%s\n", success); +} + +static void +enable_demangling(void) +{ + const char *symname = "_ZN2v88internal7Version6major_E"; + GElf_Sym sym; + char buf[64]; + + /* + * Try to determine whether C++ symbol demangling has been enabled. If + * not, enable it. + */ + if (mdb_lookup_by_name("_ZN2v88internal7Version6major_E", &sym) != 0) + return; + + (void) mdb_snprintf(buf, sizeof (buf), "%a", sym.st_value); + if (strstr(buf, symname) != NULL) + (void) mdb_eval("$G"); +} + +const mdb_modinfo_t * +_mdb_init(void) +{ + configure(); + enable_demangling(); + return (&v8_mdb); +} diff --git a/usr/src/cmd/mdb/common/modules/v8/mdb_v8_cfg.c b/usr/src/cmd/mdb/common/modules/v8/mdb_v8_cfg.c new file mode 100644 index 0000000000..d907242435 --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/v8/mdb_v8_cfg.c @@ -0,0 +1,728 @@ +/* + * 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) 2013, Joyent, Inc. All rights reserved. + */ + +/* + * mdb_v8_cfg.c: canned configurations for previous V8 versions. + * + * The functions and data defined here enable this dmod to support debugging + * Node.js binaries that predated V8's built-in postmortem debugging support. + */ + +#include "v8cfg.h" + +/*ARGSUSED*/ +static int +v8cfg_target_iter(v8_cfg_t *cfgp, int (*func)(mdb_symbol_t *, void *), + void *arg) +{ + return (mdb_symbol_iter(MDB_OBJ_EVERY, MDB_DYNSYM, + MDB_BIND_GLOBAL | MDB_TYPE_OBJECT | MDB_TYPE_FUNC, + func, arg)); +} + +/*ARGSUSED*/ +static int +v8cfg_target_readsym(v8_cfg_t *cfgp, const char *name, intptr_t *valp) +{ + int val, rval; + + if ((rval = mdb_readsym(&val, sizeof (val), name)) != -1) + *valp = (intptr_t)val; + + return (rval); +} + +/* + * Analog of mdb_symbol_iter() for a canned configuration. + */ +static int +v8cfg_canned_iter(v8_cfg_t *cfgp, int (*func)(mdb_symbol_t *, void *), + void *arg) +{ + v8_cfg_symbol_t *v8sym; + mdb_symbol_t mdbsym; + int rv; + + for (v8sym = cfgp->v8cfg_symbols; v8sym->v8cs_name != NULL; v8sym++) { + mdbsym.sym_name = v8sym->v8cs_name; + mdbsym.sym_object = NULL; + mdbsym.sym_sym = NULL; + mdbsym.sym_table = 0; + mdbsym.sym_id = 0; + + if ((rv = func(&mdbsym, arg)) != 0) + return (rv); + } + + return (0); +} + +/* + * Analog of mdb_readsym() for a canned configuration. + */ +static int +v8cfg_canned_readsym(v8_cfg_t *cfgp, const char *name, intptr_t *valp) +{ + v8_cfg_symbol_t *v8sym; + + for (v8sym = cfgp->v8cfg_symbols; v8sym->v8cs_name != NULL; v8sym++) { + if (strcmp(name, v8sym->v8cs_name) == 0) + break; + } + + if (v8sym->v8cs_name == NULL) + return (-1); + + *valp = v8sym->v8cs_value; + return (0); +} + +/* + * Canned configuration for the V8 bundled with Node.js v0.4.8 and later. + */ +static v8_cfg_symbol_t v8_symbols_node_04[] = { + { "v8dbg_type_AccessCheckInfo__ACCESS_CHECK_INFO_TYPE", 0x91 }, + { "v8dbg_type_AccessorInfo__ACCESSOR_INFO_TYPE", 0x90 }, + { "v8dbg_type_BreakPointInfo__BREAK_POINT_INFO_TYPE", 0x9b }, + { "v8dbg_type_ByteArray__BYTE_ARRAY_TYPE", 0x86 }, + { "v8dbg_type_CallHandlerInfo__CALL_HANDLER_INFO_TYPE", 0x93 }, + { "v8dbg_type_Code__CODE_TYPE", 0x81 }, + { "v8dbg_type_CodeCache__CODE_CACHE_TYPE", 0x99 }, + { "v8dbg_type_ConsString__CONS_ASCII_STRING_TYPE", 0x5 }, + { "v8dbg_type_ConsString__CONS_ASCII_SYMBOL_TYPE", 0x45 }, + { "v8dbg_type_ConsString__CONS_STRING_TYPE", 0x1 }, + { "v8dbg_type_ConsString__CONS_SYMBOL_TYPE", 0x41 }, + { "v8dbg_type_DebugInfo__DEBUG_INFO_TYPE", 0x9a }, + { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_STRING_TYPE", 0x6 }, + { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_SYMBOL_TYPE", 0x46 }, + { "v8dbg_type_ExternalByteArray__EXTERNAL_BYTE_ARRAY_TYPE", 0x88 }, + { "v8dbg_type_ExternalFloatArray__EXTERNAL_FLOAT_ARRAY_TYPE", 0x8e }, + { "v8dbg_type_ExternalIntArray__EXTERNAL_INT_ARRAY_TYPE", 0x8c }, + { "v8dbg_type_ExternalShortArray__EXTERNAL_SHORT_ARRAY_TYPE", 0x8a }, + { "v8dbg_type_ExternalString__EXTERNAL_STRING_TYPE", 0x2 }, + { "v8dbg_type_ExternalString__EXTERNAL_SYMBOL_TYPE", 0x42 }, + { "v8dbg_type_ExternalUnsignedByteArray__" + "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE", 0x89 }, + { "v8dbg_type_ExternalUnsignedIntArray__" + "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE", 0x8d }, + { "v8dbg_type_ExternalUnsignedShortArray__" + "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE", 0x8b }, + { "v8dbg_type_FixedArray__FIXED_ARRAY_TYPE", 0x9c }, + { "v8dbg_type_FunctionTemplateInfo__" + "FUNCTION_TEMPLATE_INFO_TYPE", 0x94 }, + { "v8dbg_type_HeapNumber__HEAP_NUMBER_TYPE", 0x84 }, + { "v8dbg_type_InterceptorInfo__INTERCEPTOR_INFO_TYPE", 0x92 }, + { "v8dbg_type_JSArray__JS_ARRAY_TYPE", 0xa5 }, + { "v8dbg_type_JSBuiltinsObject__JS_BUILTINS_OBJECT_TYPE", 0xa3 }, + { "v8dbg_type_JSFunction__JS_FUNCTION_TYPE", 0xa7 }, + { "v8dbg_type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE", 0xa2 }, + { "v8dbg_type_JSGlobalPropertyCell__" + "JS_GLOBAL_PROPERTY_CELL_TYPE", 0x83 }, + { "v8dbg_type_JSGlobalProxy__JS_GLOBAL_PROXY_TYPE", 0xa4 }, + { "v8dbg_type_JSMessageObject__JS_MESSAGE_OBJECT_TYPE", 0x9e }, + { "v8dbg_type_JSObject__JS_OBJECT_TYPE", 0xa0 }, + { "v8dbg_type_JSRegExp__JS_REGEXP_TYPE", 0xa6 }, + { "v8dbg_type_JSValue__JS_VALUE_TYPE", 0x9f }, + { "v8dbg_type_Map__MAP_TYPE", 0x80 }, + { "v8dbg_type_ObjectTemplateInfo__OBJECT_TEMPLATE_INFO_TYPE", 0x95 }, + { "v8dbg_type_Oddball__ODDBALL_TYPE", 0x82 }, + { "v8dbg_type_Script__SCRIPT_TYPE", 0x98 }, + { "v8dbg_type_SeqAsciiString__ASCII_STRING_TYPE", 0x4 }, + { "v8dbg_type_SeqAsciiString__ASCII_SYMBOL_TYPE", 0x44 }, + { "v8dbg_type_SharedFunctionInfo__SHARED_FUNCTION_INFO_TYPE", 0x9d }, + { "v8dbg_type_SignatureInfo__SIGNATURE_INFO_TYPE", 0x96 }, + { "v8dbg_type_String__STRING_TYPE", 0x0 }, + { "v8dbg_type_String__SYMBOL_TYPE", 0x40 }, + { "v8dbg_type_TypeSwitchInfo__TYPE_SWITCH_INFO_TYPE", 0x97 }, + + { "v8dbg_class_AccessCheckInfo__data__Object", 0xc }, + { "v8dbg_class_AccessCheckInfo__indexed_callback__Object", 0x8 }, + { "v8dbg_class_AccessCheckInfo__named_callback__Object", 0x4 }, + { "v8dbg_class_AccessorInfo__data__Object", 0xc }, + { "v8dbg_class_AccessorInfo__flag__Smi", 0x14 }, + { "v8dbg_class_AccessorInfo__getter__Object", 0x4 }, + { "v8dbg_class_AccessorInfo__name__Object", 0x10 }, + { "v8dbg_class_AccessorInfo__setter__Object", 0x8 }, + { "v8dbg_class_BreakPointInfo__break_point_objects__Object", 0x10 }, + { "v8dbg_class_BreakPointInfo__code_position__Smi", 0x4 }, + { "v8dbg_class_BreakPointInfo__source_position__Smi", 0x8 }, + { "v8dbg_class_BreakPointInfo__statement_position__Smi", 0xc }, + { "v8dbg_class_ByteArray__length__SMI", 0x4 }, + { "v8dbg_class_CallHandlerInfo__callback__Object", 0x4 }, + { "v8dbg_class_CallHandlerInfo__data__Object", 0x8 }, + { "v8dbg_class_Code__deoptimization_data__FixedArray", 0xc }, + { "v8dbg_class_Code__instruction_size__int", 0x4 }, + { "v8dbg_class_Code__instruction_start__int", 0x20 }, + { "v8dbg_class_Code__relocation_info__ByteArray", 0x8 }, + { "v8dbg_class_CodeCache__default_cache__FixedArray", 0x4 }, + { "v8dbg_class_CodeCache__normal_type_cache__Object", 0x8 }, + { "v8dbg_class_ConsString__first__String", 0xc }, + { "v8dbg_class_ConsString__second__String", 0x10 }, + { "v8dbg_class_DebugInfo__break_points__FixedArray", 0x14 }, + { "v8dbg_class_DebugInfo__code__Code", 0xc }, + { "v8dbg_class_DebugInfo__original_code__Code", 0x8 }, + { "v8dbg_class_DebugInfo__shared__SharedFunctionInfo", 0x4 }, + { "v8dbg_class_ExternalString__resource__Object", 0xc }, + { "v8dbg_class_FixedArray__data__uintptr_t", 0x8 }, + { "v8dbg_class_FixedArray__length__SMI", 0x4 }, + { "v8dbg_class_FunctionTemplateInfo__access_check_info__Object", 0x38 }, + { "v8dbg_class_FunctionTemplateInfo__call_code__Object", 0x10 }, + { "v8dbg_class_FunctionTemplateInfo__class_name__Object", 0x2c }, + { "v8dbg_class_FunctionTemplateInfo__flag__Smi", 0x3c }, + { "v8dbg_class_FunctionTemplateInfo__" + "indexed_property_handler__Object", 0x24 }, + { "v8dbg_class_FunctionTemplateInfo__" + "instance_call_handler__Object", 0x34 }, + { "v8dbg_class_FunctionTemplateInfo__instance_template__Object", 0x28 }, + { "v8dbg_class_FunctionTemplateInfo__" + "named_property_handler__Object", 0x20 }, + { "v8dbg_class_FunctionTemplateInfo__parent_template__Object", 0x1c }, + { "v8dbg_class_FunctionTemplateInfo__" + "property_accessors__Object", 0x14 }, + { "v8dbg_class_FunctionTemplateInfo__" + "prototype_template__Object", 0x18 }, + { "v8dbg_class_FunctionTemplateInfo__serial_number__Object", 0xc }, + { "v8dbg_class_FunctionTemplateInfo__signature__Object", 0x30 }, + { "v8dbg_class_GlobalObject__builtins__JSBuiltinsObject", 0xc }, + { "v8dbg_class_GlobalObject__global_context__Context", 0x10 }, + { "v8dbg_class_GlobalObject__global_receiver__JSObject", 0x14 }, + { "v8dbg_class_HeapNumber__value__SMI", 0x4 }, + { "v8dbg_class_HeapObject__map__Map", 0x0 }, + { "v8dbg_class_InterceptorInfo__data__Object", 0x18 }, + { "v8dbg_class_InterceptorInfo__deleter__Object", 0x10 }, + { "v8dbg_class_InterceptorInfo__enumerator__Object", 0x14 }, + { "v8dbg_class_InterceptorInfo__getter__Object", 0x4 }, + { "v8dbg_class_InterceptorInfo__query__Object", 0xc }, + { "v8dbg_class_InterceptorInfo__setter__Object", 0x8 }, + { "v8dbg_class_JSArray__length__Object", 0xc }, + { "v8dbg_class_JSFunction__literals__FixedArray", 0x1c }, + { "v8dbg_class_JSFunction__next_function_link__Object", 0x20 }, + { "v8dbg_class_JSFunction__prototype_or_initial_map__Object", 0x10 }, + { "v8dbg_class_JSFunction__shared__SharedFunctionInfo", 0x14 }, + { "v8dbg_class_JSGlobalProxy__context__Object", 0xc }, + { "v8dbg_class_JSMessageObject__arguments__JSArray", 0x10 }, + { "v8dbg_class_JSMessageObject__end_position__SMI", 0x24 }, + { "v8dbg_class_JSMessageObject__script__Object", 0x14 }, + { "v8dbg_class_JSMessageObject__stack_frames__Object", 0x1c }, + { "v8dbg_class_JSMessageObject__stack_trace__Object", 0x18 }, + { "v8dbg_class_JSMessageObject__start_position__SMI", 0x20 }, + { "v8dbg_class_JSMessageObject__type__String", 0xc }, + { "v8dbg_class_JSObject__elements__Object", 0x8 }, + { "v8dbg_class_JSObject__properties__FixedArray", 0x4 }, + { "v8dbg_class_JSRegExp__data__Object", 0xc }, + { "v8dbg_class_JSValue__value__Object", 0xc }, + { "v8dbg_class_Map__code_cache__Object", 0x18 }, + { "v8dbg_class_Map__constructor__Object", 0x10 }, + { "v8dbg_class_Map__inobject_properties__int", 0x5 }, + { "v8dbg_class_Map__instance_size__int", 0x4 }, + { "v8dbg_class_Map__instance_attributes__int", 0x8 }, + { "v8dbg_class_Map__instance_descriptors__DescriptorArray", 0x14 }, + { "v8dbg_class_ObjectTemplateInfo__constructor__Object", 0xc }, + { "v8dbg_class_ObjectTemplateInfo__" + "internal_field_count__Object", 0x10 }, + { "v8dbg_class_Oddball__to_number__Object", 0x8 }, + { "v8dbg_class_Oddball__to_string__String", 0x4 }, + { "v8dbg_class_Script__column_offset__Smi", 0x10 }, + { "v8dbg_class_Script__compilation_type__Smi", 0x24 }, + { "v8dbg_class_Script__context_data__Object", 0x18 }, + { "v8dbg_class_Script__data__Object", 0x14 }, + { "v8dbg_class_Script__eval_from_instructions_offset__Smi", 0x34 }, + { "v8dbg_class_Script__eval_from_shared__Object", 0x30 }, + { "v8dbg_class_Script__id__Object", 0x2c }, + { "v8dbg_class_Script__line_ends__Object", 0x28 }, + { "v8dbg_class_Script__line_offset__Smi", 0xc }, + { "v8dbg_class_Script__name__Object", 0x8 }, + { "v8dbg_class_Script__source__Object", 0x4 }, + { "v8dbg_class_Script__type__Smi", 0x20 }, + { "v8dbg_class_Script__wrapper__Proxy", 0x1c }, + { "v8dbg_class_SeqAsciiString__chars__char", 0xc }, + { "v8dbg_class_SharedFunctionInfo__code__Code", 0x8 }, + { "v8dbg_class_SharedFunctionInfo__compiler_hints__SMI", 0x50 }, + { "v8dbg_class_SharedFunctionInfo__construct_stub__Code", 0x10 }, + { "v8dbg_class_SharedFunctionInfo__debug_info__Object", 0x20 }, + { "v8dbg_class_SharedFunctionInfo__end_position__SMI", 0x48 }, + { "v8dbg_class_SharedFunctionInfo__" + "expected_nof_properties__SMI", 0x3c }, + { "v8dbg_class_SharedFunctionInfo__formal_parameter_count__SMI", 0x38 }, + { "v8dbg_class_SharedFunctionInfo__function_data__Object", 0x18 }, + { "v8dbg_class_SharedFunctionInfo__" + "function_token_position__SMI", 0x4c }, + { "v8dbg_class_SharedFunctionInfo__inferred_name__String", 0x24 }, + { "v8dbg_class_SharedFunctionInfo__initial_map__Object", 0x28 }, + { "v8dbg_class_SharedFunctionInfo__instance_class_name__Object", 0x14 }, + { "v8dbg_class_SharedFunctionInfo__length__SMI", 0x34 }, + { "v8dbg_class_SharedFunctionInfo__name__Object", 0x4 }, + { "v8dbg_class_SharedFunctionInfo__num_literals__SMI", 0x40 }, + { "v8dbg_class_SharedFunctionInfo__opt_count__SMI", 0x58 }, + { "v8dbg_class_SharedFunctionInfo__script__Object", 0x1c }, + { "v8dbg_class_SharedFunctionInfo__" + "start_position_and_type__SMI", 0x44 }, + { "v8dbg_class_SharedFunctionInfo__" + "this_property_assignments__Object", 0x2c }, + { "v8dbg_class_SharedFunctionInfo__" + "this_property_assignments_count__SMI", 0x54 }, + { "v8dbg_class_SignatureInfo__args__Object", 0x8 }, + { "v8dbg_class_SignatureInfo__receiver__Object", 0x4 }, + { "v8dbg_class_String__length__SMI", 0x4 }, + { "v8dbg_class_TemplateInfo__property_list__Object", 0x8 }, + { "v8dbg_class_TemplateInfo__tag__Object", 0x4 }, + { "v8dbg_class_TypeSwitchInfo__types__Object", 0x4 }, + + { "v8dbg_parent_AccessCheckInfo__Struct", 0x0 }, + { "v8dbg_parent_AccessorInfo__Struct", 0x0 }, + { "v8dbg_parent_BreakPointInfo__Struct", 0x0 }, + { "v8dbg_parent_ByteArray__HeapObject", 0x0 }, + { "v8dbg_parent_CallHandlerInfo__Struct", 0x0 }, + { "v8dbg_parent_Code__HeapObject", 0x0 }, + { "v8dbg_parent_CodeCache__Struct", 0x0 }, + { "v8dbg_parent_ConsString__String", 0x0 }, + { "v8dbg_parent_DebugInfo__Struct", 0x0 }, + { "v8dbg_parent_DeoptimizationInputData__FixedArray", 0x0 }, + { "v8dbg_parent_DeoptimizationOutputData__FixedArray", 0x0 }, + { "v8dbg_parent_DescriptorArray__FixedArray", 0x0 }, + { "v8dbg_parent_ExternalArray__HeapObject", 0x0 }, + { "v8dbg_parent_ExternalAsciiString__ExternalString", 0x0 }, + { "v8dbg_parent_ExternalByteArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalFloatArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalIntArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalShortArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalString__String", 0x0 }, + { "v8dbg_parent_ExternalTwoByteString__ExternalString", 0x0 }, + { "v8dbg_parent_ExternalUnsignedByteArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalUnsignedIntArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalUnsignedShortArray__ExternalArray", 0x0 }, + { "v8dbg_parent_Failure__MaybeObject", 0x0 }, + { "v8dbg_parent_FixedArray__HeapObject", 0x0 }, + { "v8dbg_parent_FunctionTemplateInfo__TemplateInfo", 0x0 }, + { "v8dbg_parent_GlobalObject__JSObject", 0x0 }, + { "v8dbg_parent_HeapNumber__HeapObject", 0x0 }, + { "v8dbg_parent_HeapObject__Object", 0x0 }, + { "v8dbg_parent_InterceptorInfo__Struct", 0x0 }, + { "v8dbg_parent_JSArray__JSObject", 0x0 }, + { "v8dbg_parent_JSBuiltinsObject__GlobalObject", 0x0 }, + { "v8dbg_parent_JSFunction__JSObject", 0x0 }, + { "v8dbg_parent_JSFunctionResultCache__FixedArray", 0x0 }, + { "v8dbg_parent_JSGlobalObject__GlobalObject", 0x0 }, + { "v8dbg_parent_JSGlobalPropertyCell__HeapObject", 0x0 }, + { "v8dbg_parent_JSGlobalProxy__JSObject", 0x0 }, + { "v8dbg_parent_JSMessageObject__JSObject", 0x0 }, + { "v8dbg_parent_JSObject__HeapObject", 0x0 }, + { "v8dbg_parent_JSRegExp__JSObject", 0x0 }, + { "v8dbg_parent_JSRegExpResult__JSArray", 0x0 }, + { "v8dbg_parent_JSValue__JSObject", 0x0 }, + { "v8dbg_parent_Map__HeapObject", 0x0 }, + { "v8dbg_parent_NormalizedMapCache__FixedArray", 0x0 }, + { "v8dbg_parent_Object__MaybeObject", 0x0 }, + { "v8dbg_parent_ObjectTemplateInfo__TemplateInfo", 0x0 }, + { "v8dbg_parent_Oddball__HeapObject", 0x0 }, + { "v8dbg_parent_Script__Struct", 0x0 }, + { "v8dbg_parent_SeqAsciiString__SeqString", 0x0 }, + { "v8dbg_parent_SeqString__String", 0x0 }, + { "v8dbg_parent_SeqTwoByteString__SeqString", 0x0 }, + { "v8dbg_parent_SharedFunctionInfo__HeapObject", 0x0 }, + { "v8dbg_parent_SignatureInfo__Struct", 0x0 }, + { "v8dbg_parent_Smi__Object", 0x0 }, + { "v8dbg_parent_String__HeapObject", 0x0 }, + { "v8dbg_parent_Struct__HeapObject", 0x0 }, + { "v8dbg_parent_TemplateInfo__Struct", 0x0 }, + { "v8dbg_parent_TypeSwitchInfo__Struct", 0x0 }, + + { "v8dbg_frametype_ArgumentsAdaptorFrame", 0x8 }, + { "v8dbg_frametype_ConstructFrame", 0x7 }, + { "v8dbg_frametype_EntryConstructFrame", 0x2 }, + { "v8dbg_frametype_EntryFrame", 0x1 }, + { "v8dbg_frametype_ExitFrame", 0x3 }, + { "v8dbg_frametype_InternalFrame", 0x6 }, + { "v8dbg_frametype_JavaScriptFrame", 0x4 }, + { "v8dbg_frametype_OptimizedFrame", 0x5 }, + + { "v8dbg_off_fp_context", -0x4 }, + { "v8dbg_off_fp_function", -0x8 }, + { "v8dbg_off_fp_marker", -0x8 }, + { "v8dbg_off_fp_args", 0x8 }, + + { "v8dbg_prop_idx_content", 0x0 }, + { "v8dbg_prop_idx_first", 0x2 }, + { "v8dbg_prop_type_field", 0x1 }, + { "v8dbg_prop_type_first_phantom", 0x6 }, + { "v8dbg_prop_type_mask", 0xf }, + + { "v8dbg_AsciiStringTag", 0x4 }, + { "v8dbg_ConsStringTag", 0x1 }, + { "v8dbg_ExternalStringTag", 0x2 }, + { "v8dbg_FailureTag", 0x3 }, + { "v8dbg_FailureTagMask", 0x3 }, + { "v8dbg_FirstNonstringType", 0x80 }, + { "v8dbg_HeapObjectTag", 0x1 }, + { "v8dbg_HeapObjectTagMask", 0x3 }, + { "v8dbg_IsNotStringMask", 0x80 }, + { "v8dbg_NotStringTag", 0x80 }, + { "v8dbg_SeqStringTag", 0x0 }, + { "v8dbg_SmiTag", 0x0 }, + { "v8dbg_SmiTagMask", 0x1 }, + { "v8dbg_SmiValueShift", 0x1 }, + { "v8dbg_StringEncodingMask", 0x4 }, + { "v8dbg_StringRepresentationMask", 0x3 }, + { "v8dbg_StringTag", 0x0 }, + { "v8dbg_TwoByteStringTag", 0x0 }, + { "v8dbg_PointerSizeLog2", 0x2 }, + + { NULL } +}; + +/* + * Canned configuration for the V8 bundled with Node.js v0.6.5. + */ +static v8_cfg_symbol_t v8_symbols_node_06[] = { + { "v8dbg_type_AccessCheckInfo__ACCESS_CHECK_INFO_TYPE", 0x93 }, + { "v8dbg_type_AccessorInfo__ACCESSOR_INFO_TYPE", 0x92 }, + { "v8dbg_type_BreakPointInfo__BREAK_POINT_INFO_TYPE", 0x9e }, + { "v8dbg_type_ByteArray__BYTE_ARRAY_TYPE", 0x86 }, + { "v8dbg_type_CallHandlerInfo__CALL_HANDLER_INFO_TYPE", 0x95 }, + { "v8dbg_type_Code__CODE_TYPE", 0x81 }, + { "v8dbg_type_CodeCache__CODE_CACHE_TYPE", 0x9b }, + { "v8dbg_type_ConsString__CONS_ASCII_STRING_TYPE", 0x5 }, + { "v8dbg_type_ConsString__CONS_ASCII_SYMBOL_TYPE", 0x45 }, + { "v8dbg_type_ConsString__CONS_STRING_TYPE", 0x1 }, + { "v8dbg_type_ConsString__CONS_SYMBOL_TYPE", 0x41 }, + { "v8dbg_type_DebugInfo__DEBUG_INFO_TYPE", 0x9d }, + { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_STRING_TYPE", 0x6 }, + { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_SYMBOL_TYPE", 0x46 }, + { "v8dbg_type_ExternalByteArray__EXTERNAL_BYTE_ARRAY_TYPE", 0x87 }, + { "v8dbg_type_ExternalDoubleArray__EXTERNAL_DOUBLE_ARRAY_TYPE", 0x8e }, + { "v8dbg_type_ExternalFloatArray__EXTERNAL_FLOAT_ARRAY_TYPE", 0x8d }, + { "v8dbg_type_ExternalIntArray__EXTERNAL_INT_ARRAY_TYPE", 0x8b }, + { "v8dbg_type_ExternalPixelArray__EXTERNAL_PIXEL_ARRAY_TYPE", 0x8f }, + { "v8dbg_type_ExternalShortArray__EXTERNAL_SHORT_ARRAY_TYPE", 0x89 }, + { "v8dbg_type_ExternalTwoByteString__EXTERNAL_STRING_TYPE", 0x2 }, + { "v8dbg_type_ExternalTwoByteString__EXTERNAL_SYMBOL_TYPE", 0x42 }, + { "v8dbg_type_ExternalUnsignedByteArray__" + "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE", 0x88 }, + { "v8dbg_type_ExternalUnsignedIntArray__" + "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE", 0x8c }, + { "v8dbg_type_ExternalUnsignedShortArray__" + "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE", 0x8a }, + { "v8dbg_type_FixedArray__FIXED_ARRAY_TYPE", 0x9f }, + { "v8dbg_type_FixedDoubleArray__FIXED_DOUBLE_ARRAY_TYPE", 0x90 }, + { "v8dbg_type_Foreign__FOREIGN_TYPE", 0x85 }, + { "v8dbg_type_FunctionTemplateInfo__FUNCTION_TEMPLATE_INFO_TYPE", + 0x96 }, + { "v8dbg_type_HeapNumber__HEAP_NUMBER_TYPE", 0x84 }, + { "v8dbg_type_InterceptorInfo__INTERCEPTOR_INFO_TYPE", 0x94 }, + { "v8dbg_type_JSArray__JS_ARRAY_TYPE", 0xa8 }, + { "v8dbg_type_JSBuiltinsObject__JS_BUILTINS_OBJECT_TYPE", 0xa6 }, + { "v8dbg_type_JSFunction__JS_FUNCTION_TYPE", 0xac }, + { "v8dbg_type_JSFunctionProxy__JS_FUNCTION_PROXY_TYPE", 0xad }, + { "v8dbg_type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE", 0xa5 }, + { "v8dbg_type_JSGlobalPropertyCell__JS_GLOBAL_PROPERTY_CELL_TYPE", + 0x83 }, + { "v8dbg_type_JSMessageObject__JS_MESSAGE_OBJECT_TYPE", 0xa1 }, + { "v8dbg_type_JSObject__JS_OBJECT_TYPE", 0xa3 }, + { "v8dbg_type_JSProxy__JS_PROXY_TYPE", 0xa9 }, + { "v8dbg_type_JSRegExp__JS_REGEXP_TYPE", 0xab }, + { "v8dbg_type_JSValue__JS_VALUE_TYPE", 0xa2 }, + { "v8dbg_type_JSWeakMap__JS_WEAK_MAP_TYPE", 0xaa }, + { "v8dbg_type_Map__MAP_TYPE", 0x80 }, + { "v8dbg_type_ObjectTemplateInfo__OBJECT_TEMPLATE_INFO_TYPE", 0x97 }, + { "v8dbg_type_Oddball__ODDBALL_TYPE", 0x82 }, + { "v8dbg_type_PolymorphicCodeCache__POLYMORPHIC_CODE_CACHE_TYPE", + 0x9c }, + { "v8dbg_type_Script__SCRIPT_TYPE", 0x9a }, + { "v8dbg_type_SeqAsciiString__ASCII_STRING_TYPE", 0x4 }, + { "v8dbg_type_SeqAsciiString__ASCII_SYMBOL_TYPE", 0x44 }, + { "v8dbg_type_SeqTwoByteString__STRING_TYPE", 0x0 }, + { "v8dbg_type_SeqTwoByteString__SYMBOL_TYPE", 0x40 }, + { "v8dbg_type_SharedFunctionInfo__SHARED_FUNCTION_INFO_TYPE", 0xa0 }, + { "v8dbg_type_SignatureInfo__SIGNATURE_INFO_TYPE", 0x98 }, + { "v8dbg_type_SlicedString__SLICED_ASCII_STRING_TYPE", 0x7 }, + { "v8dbg_type_SlicedString__SLICED_STRING_TYPE", 0x3 }, + { "v8dbg_type_TypeSwitchInfo__TYPE_SWITCH_INFO_TYPE", 0x99 }, + + { "v8dbg_class_AccessCheckInfo__data__Object", 0xc }, + { "v8dbg_class_AccessCheckInfo__indexed_callback__Object", 0x8 }, + { "v8dbg_class_AccessCheckInfo__named_callback__Object", 0x4 }, + { "v8dbg_class_AccessorInfo__data__Object", 0xc }, + { "v8dbg_class_AccessorInfo__flag__Smi", 0x14 }, + { "v8dbg_class_AccessorInfo__getter__Object", 0x4 }, + { "v8dbg_class_AccessorInfo__name__Object", 0x10 }, + { "v8dbg_class_AccessorInfo__setter__Object", 0x8 }, + { "v8dbg_class_BreakPointInfo__break_point_objects__Object", 0x10 }, + { "v8dbg_class_BreakPointInfo__code_position__Smi", 0x4 }, + { "v8dbg_class_BreakPointInfo__source_position__Smi", 0x8 }, + { "v8dbg_class_BreakPointInfo__statement_position__Smi", 0xc }, + { "v8dbg_class_CallHandlerInfo__callback__Object", 0x4 }, + { "v8dbg_class_CallHandlerInfo__data__Object", 0x8 }, + { "v8dbg_class_Code__deoptimization_data__FixedArray", 0xc }, + { "v8dbg_class_Code__instruction_size__int", 0x4 }, + { "v8dbg_class_Code__instruction_start__int", 0x20 }, + { "v8dbg_class_Code__next_code_flushing_candidate__Object", 0x10 }, + { "v8dbg_class_Code__relocation_info__ByteArray", 0x8 }, + { "v8dbg_class_CodeCache__default_cache__FixedArray", 0x4 }, + { "v8dbg_class_CodeCache__normal_type_cache__Object", 0x8 }, + { "v8dbg_class_ConsString__first__String", 0xc }, + { "v8dbg_class_ConsString__second__String", 0x10 }, + { "v8dbg_class_DebugInfo__break_points__FixedArray", 0x14 }, + { "v8dbg_class_DebugInfo__code__Code", 0xc }, + { "v8dbg_class_DebugInfo__original_code__Code", 0x8 }, + { "v8dbg_class_DebugInfo__shared__SharedFunctionInfo", 0x4 }, + { "v8dbg_class_ExternalString__resource__Object", 0xc }, + { "v8dbg_class_FixedArray__data__uintptr_t", 0x8 }, + { "v8dbg_class_FixedArrayBase__length__SMI", 0x4 }, + { "v8dbg_class_FunctionTemplateInfo__access_check_info__Object", 0x38 }, + { "v8dbg_class_FunctionTemplateInfo__call_code__Object", 0x10 }, + { "v8dbg_class_FunctionTemplateInfo__class_name__Object", 0x2c }, + { "v8dbg_class_FunctionTemplateInfo__flag__Smi", 0x3c }, + { "v8dbg_class_FunctionTemplateInfo__indexed_property_handler__Object", + 0x24 }, + { "v8dbg_class_FunctionTemplateInfo__instance_call_handler__Object", + 0x34 }, + { "v8dbg_class_FunctionTemplateInfo__instance_template__Object", 0x28 }, + { "v8dbg_class_FunctionTemplateInfo__named_property_handler__Object", + 0x20 }, + { "v8dbg_class_FunctionTemplateInfo__parent_template__Object", 0x1c }, + { "v8dbg_class_FunctionTemplateInfo__property_accessors__Object", + 0x14 }, + { "v8dbg_class_FunctionTemplateInfo__prototype_template__Object", + 0x18 }, + { "v8dbg_class_FunctionTemplateInfo__serial_number__Object", 0xc }, + { "v8dbg_class_FunctionTemplateInfo__signature__Object", 0x30 }, + { "v8dbg_class_GlobalObject__builtins__JSBuiltinsObject", 0xc }, + { "v8dbg_class_GlobalObject__global_context__Context", 0x10 }, + { "v8dbg_class_GlobalObject__global_receiver__JSObject", 0x14 }, + { "v8dbg_class_HeapNumber__value__double", 0x4 }, + { "v8dbg_class_HeapObject__map__Map", 0x0 }, + { "v8dbg_class_InterceptorInfo__data__Object", 0x18 }, + { "v8dbg_class_InterceptorInfo__deleter__Object", 0x10 }, + { "v8dbg_class_InterceptorInfo__enumerator__Object", 0x14 }, + { "v8dbg_class_InterceptorInfo__getter__Object", 0x4 }, + { "v8dbg_class_InterceptorInfo__query__Object", 0xc }, + { "v8dbg_class_InterceptorInfo__setter__Object", 0x8 }, + { "v8dbg_class_JSArray__length__Object", 0xc }, + { "v8dbg_class_JSFunction__literals__FixedArray", 0x1c }, + { "v8dbg_class_JSFunction__next_function_link__Object", 0x20 }, + { "v8dbg_class_JSFunction__prototype_or_initial_map__Object", 0x10 }, + { "v8dbg_class_JSFunction__shared__SharedFunctionInfo", 0x14 }, + { "v8dbg_class_JSFunctionProxy__call_trap__Object", 0x8 }, + { "v8dbg_class_JSFunctionProxy__construct_trap__Object", 0xc }, + { "v8dbg_class_JSGlobalProxy__context__Object", 0xc }, + { "v8dbg_class_JSMessageObject__arguments__JSArray", 0x10 }, + { "v8dbg_class_JSMessageObject__end_position__SMI", 0x24 }, + { "v8dbg_class_JSMessageObject__script__Object", 0x14 }, + { "v8dbg_class_JSMessageObject__stack_frames__Object", 0x1c }, + { "v8dbg_class_JSMessageObject__stack_trace__Object", 0x18 }, + { "v8dbg_class_JSMessageObject__start_position__SMI", 0x20 }, + { "v8dbg_class_JSMessageObject__type__String", 0xc }, + { "v8dbg_class_JSObject__elements__Object", 0x8 }, + { "v8dbg_class_JSObject__properties__FixedArray", 0x4 }, + { "v8dbg_class_JSProxy__handler__Object", 0x4 }, + { "v8dbg_class_JSRegExp__data__Object", 0xc }, + { "v8dbg_class_JSValue__value__Object", 0xc }, + { "v8dbg_class_JSWeakMap__next__Object", 0x10 }, + { "v8dbg_class_JSWeakMap__table__ObjectHashTable", 0xc }, + { "v8dbg_class_Map__code_cache__Object", 0x18 }, + { "v8dbg_class_Map__constructor__Object", 0x10 }, + { "v8dbg_class_Map__inobject_properties__int", 0x5 }, + { "v8dbg_class_Map__instance_attributes__int", 0x8 }, + { "v8dbg_class_Map__instance_descriptors__FixedArray", 0x14 }, + { "v8dbg_class_Map__instance_size__int", 0x4 }, + { "v8dbg_class_Map__prototype_transitions__FixedArray", 0x1c }, + { "v8dbg_class_ObjectTemplateInfo__constructor__Object", 0xc }, + { "v8dbg_class_ObjectTemplateInfo__internal_field_count__Object", + 0x10 }, + { "v8dbg_class_Oddball__to_number__Object", 0x8 }, + { "v8dbg_class_Oddball__to_string__String", 0x4 }, + { "v8dbg_class_PolymorphicCodeCache__cache__Object", 0x4 }, + { "v8dbg_class_Script__column_offset__Smi", 0x10 }, + { "v8dbg_class_Script__compilation_type__Smi", 0x24 }, + { "v8dbg_class_Script__context_data__Object", 0x18 }, + { "v8dbg_class_Script__data__Object", 0x14 }, + { "v8dbg_class_Script__eval_from_instructions_offset__Smi", 0x34 }, + { "v8dbg_class_Script__eval_from_shared__Object", 0x30 }, + { "v8dbg_class_Script__id__Object", 0x2c }, + { "v8dbg_class_Script__line_ends__Object", 0x28 }, + { "v8dbg_class_Script__line_offset__Smi", 0xc }, + { "v8dbg_class_Script__name__Object", 0x8 }, + { "v8dbg_class_Script__source__Object", 0x4 }, + { "v8dbg_class_Script__type__Smi", 0x20 }, + { "v8dbg_class_Script__wrapper__Foreign", 0x1c }, + { "v8dbg_class_SeqAsciiString__chars__char", 0xc }, + { "v8dbg_class_SharedFunctionInfo__code__Code", 0x8 }, + { "v8dbg_class_SharedFunctionInfo__compiler_hints__SMI", 0x50 }, + { "v8dbg_class_SharedFunctionInfo__construct_stub__Code", 0x10 }, + { "v8dbg_class_SharedFunctionInfo__debug_info__Object", 0x20 }, + { "v8dbg_class_SharedFunctionInfo__end_position__SMI", 0x48 }, + { "v8dbg_class_SharedFunctionInfo__expected_nof_properties__SMI", + 0x3c }, + { "v8dbg_class_SharedFunctionInfo__formal_parameter_count__SMI", 0x38 }, + { "v8dbg_class_SharedFunctionInfo__function_data__Object", 0x18 }, + { "v8dbg_class_SharedFunctionInfo__function_token_position__SMI", + 0x4c }, + { "v8dbg_class_SharedFunctionInfo__inferred_name__String", 0x24 }, + { "v8dbg_class_SharedFunctionInfo__initial_map__Object", 0x28 }, + { "v8dbg_class_SharedFunctionInfo__instance_class_name__Object", 0x14 }, + { "v8dbg_class_SharedFunctionInfo__length__SMI", 0x34 }, + { "v8dbg_class_SharedFunctionInfo__name__Object", 0x4 }, + { "v8dbg_class_SharedFunctionInfo__num_literals__SMI", 0x40 }, + { "v8dbg_class_SharedFunctionInfo__opt_count__SMI", 0x58 }, + { "v8dbg_class_SharedFunctionInfo__script__Object", 0x1c }, + { "v8dbg_class_SharedFunctionInfo__" + "start_position_and_type__SMI", 0x44 }, + { "v8dbg_class_SharedFunctionInfo__" + "this_property_assignments__Object", 0x2c }, + { "v8dbg_class_SharedFunctionInfo__" + "this_property_assignments_count__SMI", 0x54 }, + { "v8dbg_class_SignatureInfo__args__Object", 0x8 }, + { "v8dbg_class_SignatureInfo__receiver__Object", 0x4 }, + { "v8dbg_class_SlicedString__offset__SMI", 0x10 }, + { "v8dbg_class_String__length__SMI", 0x4 }, + { "v8dbg_class_TemplateInfo__property_list__Object", 0x8 }, + { "v8dbg_class_TemplateInfo__tag__Object", 0x4 }, + { "v8dbg_class_TypeSwitchInfo__types__Object", 0x4 }, + + { "v8dbg_parent_AccessCheckInfo__Struct", 0x0 }, + { "v8dbg_parent_AccessorInfo__Struct", 0x0 }, + { "v8dbg_parent_BreakPointInfo__Struct", 0x0 }, + { "v8dbg_parent_ByteArray__FixedArrayBase", 0x0 }, + { "v8dbg_parent_CallHandlerInfo__Struct", 0x0 }, + { "v8dbg_parent_Code__HeapObject", 0x0 }, + { "v8dbg_parent_CodeCache__Struct", 0x0 }, + { "v8dbg_parent_ConsString__String", 0x0 }, + { "v8dbg_parent_DebugInfo__Struct", 0x0 }, + { "v8dbg_parent_DeoptimizationInputData__FixedArray", 0x0 }, + { "v8dbg_parent_DeoptimizationOutputData__FixedArray", 0x0 }, + { "v8dbg_parent_DescriptorArray__FixedArray", 0x0 }, + { "v8dbg_parent_ExternalArray__FixedArrayBase", 0x0 }, + { "v8dbg_parent_ExternalAsciiString__ExternalString", 0x0 }, + { "v8dbg_parent_ExternalByteArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalDoubleArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalFloatArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalIntArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalPixelArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalShortArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalString__String", 0x0 }, + { "v8dbg_parent_ExternalTwoByteString__ExternalString", 0x0 }, + { "v8dbg_parent_ExternalUnsignedByteArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalUnsignedIntArray__ExternalArray", 0x0 }, + { "v8dbg_parent_ExternalUnsignedShortArray__ExternalArray", 0x0 }, + { "v8dbg_parent_Failure__MaybeObject", 0x0 }, + { "v8dbg_parent_FixedArray__FixedArrayBase", 0x0 }, + { "v8dbg_parent_FixedArrayBase__HeapObject", 0x0 }, + { "v8dbg_parent_FixedDoubleArray__FixedArrayBase", 0x0 }, + { "v8dbg_parent_Foreign__HeapObject", 0x0 }, + { "v8dbg_parent_FunctionTemplateInfo__TemplateInfo", 0x0 }, + { "v8dbg_parent_GlobalObject__JSObject", 0x0 }, + { "v8dbg_parent_HashTable__FixedArray", 0x0 }, + { "v8dbg_parent_HeapNumber__HeapObject", 0x0 }, + { "v8dbg_parent_HeapObject__Object", 0x0 }, + { "v8dbg_parent_InterceptorInfo__Struct", 0x0 }, + { "v8dbg_parent_JSArray__JSObject", 0x0 }, + { "v8dbg_parent_JSBuiltinsObject__GlobalObject", 0x0 }, + { "v8dbg_parent_JSFunction__JSObject", 0x0 }, + { "v8dbg_parent_JSFunctionProxy__JSProxy", 0x0 }, + { "v8dbg_parent_JSFunctionResultCache__FixedArray", 0x0 }, + { "v8dbg_parent_JSGlobalObject__GlobalObject", 0x0 }, + { "v8dbg_parent_JSGlobalPropertyCell__HeapObject", 0x0 }, + { "v8dbg_parent_JSMessageObject__JSObject", 0x0 }, + { "v8dbg_parent_JSObject__JSReceiver", 0x0 }, + { "v8dbg_parent_JSProxy__JSReceiver", 0x0 }, + { "v8dbg_parent_JSReceiver__HeapObject", 0x0 }, + { "v8dbg_parent_JSRegExp__JSObject", 0x0 }, + { "v8dbg_parent_JSRegExpResult__JSArray", 0x0 }, + { "v8dbg_parent_JSValue__JSObject", 0x0 }, + { "v8dbg_parent_JSWeakMap__JSObject", 0x0 }, + { "v8dbg_parent_Map__HeapObject", 0x0 }, + { "v8dbg_parent_NormalizedMapCache__FixedArray", 0x0 }, + { "v8dbg_parent_ObjectTemplateInfo__TemplateInfo", 0x0 }, + { "v8dbg_parent_Oddball__HeapObject", 0x0 }, + { "v8dbg_parent_PolymorphicCodeCache__Struct", 0x0 }, + { "v8dbg_parent_Script__Struct", 0x0 }, + { "v8dbg_parent_SeqAsciiString__SeqString", 0x0 }, + { "v8dbg_parent_SeqString__String", 0x0 }, + { "v8dbg_parent_SeqTwoByteString__SeqString", 0x0 }, + { "v8dbg_parent_SharedFunctionInfo__HeapObject", 0x0 }, + { "v8dbg_parent_SignatureInfo__Struct", 0x0 }, + { "v8dbg_parent_SlicedString__String", 0x0 }, + { "v8dbg_parent_Smi__Object", 0x0 }, + { "v8dbg_parent_String__HeapObject", 0x0 }, + { "v8dbg_parent_Struct__HeapObject", 0x0 }, + { "v8dbg_parent_TemplateInfo__Struct", 0x0 }, + { "v8dbg_parent_TypeSwitchInfo__Struct", 0x0 }, + + { "v8dbg_frametype_ArgumentsAdaptorFrame", 0x8 }, + { "v8dbg_frametype_ConstructFrame", 0x7 }, + { "v8dbg_frametype_EntryConstructFrame", 0x2 }, + { "v8dbg_frametype_EntryFrame", 0x1 }, + { "v8dbg_frametype_ExitFrame", 0x3 }, + { "v8dbg_frametype_InternalFrame", 0x6 }, + { "v8dbg_frametype_JavaScriptFrame", 0x4 }, + { "v8dbg_frametype_OptimizedFrame", 0x5 }, + + { "v8dbg_off_fp_args", 0x8 }, + { "v8dbg_off_fp_context", -0x4 }, + { "v8dbg_off_fp_function", -0x8 }, + { "v8dbg_off_fp_marker", -0x8 }, + + { "v8dbg_prop_idx_content", 0x1 }, + { "v8dbg_prop_idx_first", 0x3 }, + { "v8dbg_prop_type_field", 0x1 }, + { "v8dbg_prop_type_first_phantom", 0x6 }, + { "v8dbg_prop_type_mask", 0xf }, + + { "v8dbg_AsciiStringTag", 0x4 }, + { "v8dbg_PointerSizeLog2", 0x2 }, + { "v8dbg_SeqStringTag", 0x0 }, + { "v8dbg_SmiTag", 0x0 }, + { "v8dbg_SmiTagMask", 0x1 }, + { "v8dbg_SmiValueShift", 0x1 }, + { "v8dbg_StringEncodingMask", 0x4 }, + { "v8dbg_StringRepresentationMask", 0x3 }, + { "v8dbg_StringTag", 0x0 }, + { "v8dbg_TwoByteStringTag", 0x0 }, + { "v8dbg_ConsStringTag", 0x1 }, + { "v8dbg_ExternalStringTag", 0x2 }, + { "v8dbg_FailureTag", 0x3 }, + { "v8dbg_FailureTagMask", 0x3 }, + { "v8dbg_FirstNonstringType", 0x80 }, + { "v8dbg_HeapObjectTag", 0x1 }, + { "v8dbg_HeapObjectTagMask", 0x3 }, + { "v8dbg_IsNotStringMask", 0x80 }, + { "v8dbg_NotStringTag", 0x80 }, + + { NULL }, +}; + +v8_cfg_t v8_cfg_04 = { "node-0.4", "node v0.4", v8_symbols_node_04, + v8cfg_canned_iter, v8cfg_canned_readsym }; + +v8_cfg_t v8_cfg_06 = { "node-0.6", "node v0.6", v8_symbols_node_06, + v8cfg_canned_iter, v8cfg_canned_readsym }; + +v8_cfg_t *v8_cfgs[] = { + &v8_cfg_04, + &v8_cfg_06, + NULL +}; + +v8_cfg_t v8_cfg_target = { NULL, NULL, NULL, v8cfg_target_iter, + v8cfg_target_readsym }; diff --git a/usr/src/cmd/ssh/include/engine.h b/usr/src/cmd/mdb/common/modules/v8/v8cfg.h index 74ee80db01..9e722b0e2b 100644 --- a/usr/src/cmd/ssh/include/engine.h +++ b/usr/src/cmd/mdb/common/modules/v8/v8cfg.h @@ -19,25 +19,37 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ -#ifndef _ENGINE_H -#define _ENGINE_H +/* + * v8cfg.h: canned configurations for previous V8 versions + */ + +#ifndef V8CFG_H +#define V8CFG_H + +#include <sys/types.h> +#include <sys/mdb_modapi.h> -#ifdef __cplusplus -extern "C" { -#endif +typedef struct { + const char *v8cs_name; /* symbol name */ + intptr_t v8cs_value; /* symbol value */ +} v8_cfg_symbol_t; -#include "includes.h" -#include <openssl/engine.h> +typedef struct v8_cfg { + const char *v8cfg_name; /* canned config name */ + const char *v8cfg_label; /* description */ + v8_cfg_symbol_t *v8cfg_symbols; /* actual symbol values */ -ENGINE *pkcs11_engine_load(int use_engine); -void pkcs11_engine_finish(void *engine); + int (*v8cfg_iter)(struct v8_cfg *, int (*)(mdb_symbol_t *, void *), + void *); + int (*v8cfg_readsym)(struct v8_cfg *, const char *, intptr_t *); +} v8_cfg_t; -#ifdef __cplusplus -} -#endif +extern v8_cfg_t v8_cfg_04; +extern v8_cfg_t v8_cfg_06; +extern v8_cfg_t v8_cfg_target; +extern v8_cfg_t *v8_cfgs[]; -#endif /* _ENGINE_H */ +#endif /* V8CFG_H */ diff --git a/usr/src/cmd/mdb/common/modules/v8/v8dbg.h b/usr/src/cmd/mdb/common/modules/v8/v8dbg.h new file mode 100644 index 0000000000..b17f241fac --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/v8/v8dbg.h @@ -0,0 +1,91 @@ +/* + * 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) 2015, Joyent, Inc. All rights reserved. + */ + +/* + * v8dbg.h: macros for use by V8 heap inspection tools. The consumer must + * define values for various tags and shifts. The MDB module gets these + * constants from information encoded in the binary itself. + */ + +#ifndef _V8DBG_H +#define _V8DBG_H + +/* + * Recall that while V8 heap objects are always 4-byte aligned, heap object + * pointers always have the last bit set. So when looking for a field nominally + * at offset X, one must be sure to clear the tag bit first. + */ +#define V8_OFF_HEAP(x) ((x) - V8_HeapObjectTag) + +/* + * Determine whether a given pointer refers to a SMI, Failure, or HeapObject. + */ +#define V8_IS_SMI(ptr) (((ptr) & V8_SmiTagMask) == V8_SmiTag) +#define V8_IS_FAILURE(ptr) (V8_FailureTagMask != -1 && \ + V8_FailureTagMask != -1 && \ + ((ptr) & V8_FailureTagMask) == V8_FailureTag) + +#define V8_IS_HEAPOBJECT(ptr) \ + (((ptr) & V8_HeapObjectTagMask) == V8_HeapObjectTag) + +/* + * Extract the value of a SMI "pointer". Recall that small integers are stored + * using the upper 31 bits. + */ +#define V8_SMI_VALUE(smi) ((smi) >> (V8_SmiValueShift + V8_SmiShiftSize)) +#define V8_VALUE_SMI(value) \ + ((value) << (V8_SmiValueShift + V8_SmiShiftSize)) + +/* + * Determine the encoding and representation of a V8 string. + */ +#define V8_TYPE_STRING(type) (((type) & V8_IsNotStringMask) == V8_StringTag) + +#define V8_STRENC_ASCII(type) \ + (((type) & V8_StringEncodingMask) == V8_AsciiStringTag) + +#define V8_STRREP_SEQ(type) \ + (((type) & V8_StringRepresentationMask) == V8_SeqStringTag) +#define V8_STRREP_CONS(type) \ + (((type) & V8_StringRepresentationMask) == V8_ConsStringTag) +#define V8_STRREP_SLICED(type) \ + (((type) & V8_StringRepresentationMask) == V8_SlicedStringTag) +#define V8_STRREP_EXT(type) \ + (((type) & V8_StringRepresentationMask) == V8_ExternalStringTag) + +/* + * Several of the following constants and transformations are hardcoded in V8 as + * well, so there's no way to extract them programmatically from the binary. + */ +#define V8_DESC_KEYIDX(x) ((x) + V8_PROP_IDX_FIRST) +#define V8_DESC_VALIDX(x) ((x) << 1) +#define V8_DESC_DETIDX(x) (((x) << 1) + 1) + +#define V8_DESC_ISFIELD(x) \ + ((V8_SMI_VALUE(x) & V8_PROP_TYPE_MASK) == V8_PROP_TYPE_FIELD) + +#define V8_PROP_FIELDINDEX(value) \ + ((V8_SMI_VALUE(value) & V8_FIELDINDEX_MASK) >> V8_FIELDINDEX_SHIFT) + +#endif /* _V8DBG_H */ diff --git a/usr/src/cmd/mdb/intel/amd64/libumem/Makefile b/usr/src/cmd/mdb/intel/amd64/libumem/Makefile index 704ff65873..ae22217a1b 100644 --- a/usr/src/cmd/mdb/intel/amd64/libumem/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/libumem/Makefile @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2012 Joyent, Inc. All rights reserved. MODULE = libumem.so MDBTGT = proc diff --git a/usr/src/cmd/mdb/intel/amd64/v8/Makefile b/usr/src/cmd/mdb/intel/amd64/v8/Makefile new file mode 100644 index 0000000000..cf74ba1d1c --- /dev/null +++ b/usr/src/cmd/mdb/intel/amd64/v8/Makefile @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 2011, Joyent, Inc. All rights reserved. +# + +MODULE = v8.so +MDBTGT = proc + +MODSRCS_DIR = ../../../common/modules/v8 + +MODSRCS = mdb_v8.c mdb_v8_cfg.c + +include ../../../../Makefile.cmd +include ../../../../Makefile.cmd.64 +include ../../Makefile.amd64 +include ../../../Makefile.module + +dmod/$(MODULE) := LDLIBS += -lproc -lavl + +%.o: $(MODSRCS_DIR)/%.c + $(COMPILE.c) $< + $(CTFCONVERT_O) + +%.ln: $(MODSRCS_DIR)/%.c + $(LINT.c) -c $< diff --git a/usr/src/cmd/mdb/intel/ia32/libumem/Makefile b/usr/src/cmd/mdb/intel/ia32/libumem/Makefile index a1ab338f40..bde1be90ac 100644 --- a/usr/src/cmd/mdb/intel/ia32/libumem/Makefile +++ b/usr/src/cmd/mdb/intel/ia32/libumem/Makefile @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2012 Joyent, Inc. All rights reserved. MODULE = libumem.so MDBTGT = proc diff --git a/usr/src/cmd/mdb/intel/ia32/v8/Makefile b/usr/src/cmd/mdb/intel/ia32/v8/Makefile new file mode 100644 index 0000000000..c84532289e --- /dev/null +++ b/usr/src/cmd/mdb/intel/ia32/v8/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 2011, Joyent, Inc. All rights reserved. +# + +MODULE = v8.so +MDBTGT = proc + +MODSRCS_DIR = ../../../common/modules/v8 + +MODSRCS = mdb_v8.c mdb_v8_cfg.c + +include ../../../../Makefile.cmd +include ../../Makefile.ia32 +include ../../../Makefile.module + +dmod/$(MODULE) := LDLIBS += -lproc -lavl + +%.o: $(MODSRCS_DIR)/%.c + $(COMPILE.c) $< + $(CTFCONVERT_O) + +%.ln: $(MODSRCS_DIR)/%.c + $(LINT.c) -c $< diff --git a/usr/src/cmd/mdb/sparc/v7/libumem/Makefile b/usr/src/cmd/mdb/sparc/v7/libumem/Makefile index 906d05d5ea..0488e6739a 100644 --- a/usr/src/cmd/mdb/sparc/v7/libumem/Makefile +++ b/usr/src/cmd/mdb/sparc/v7/libumem/Makefile @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2012 Joyent, Inc. All rights reserved. MODULE = libumem.so MDBTGT = proc diff --git a/usr/src/cmd/mdb/sparc/v9/libumem/Makefile b/usr/src/cmd/mdb/sparc/v9/libumem/Makefile index 09ea0473c6..87ce977423 100644 --- a/usr/src/cmd/mdb/sparc/v9/libumem/Makefile +++ b/usr/src/cmd/mdb/sparc/v9/libumem/Makefile @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2012 Joyent, Inc. All rights reserved. MODULE = libumem.so MDBTGT = proc diff --git a/usr/src/cmd/mdb/test/mtest.sh b/usr/src/cmd/mdb/test/mtest.sh index f21d0faa21..f21d0faa21 100644..100755 --- a/usr/src/cmd/mdb/test/mtest.sh +++ b/usr/src/cmd/mdb/test/mtest.sh diff --git a/usr/src/cmd/mdb/test/typedef/tst.dellist.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.dellist.mdb.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.dellist.mdb.out diff --git a/usr/src/cmd/mdb/test/typedef/tst.emptylist.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.emptylist.mdb.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.emptylist.mdb.out diff --git a/usr/src/cmd/nicstat/Makefile b/usr/src/cmd/nicstat/Makefile new file mode 100644 index 0000000000..935011119a --- /dev/null +++ b/usr/src/cmd/nicstat/Makefile @@ -0,0 +1,31 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2013 Joyent, Inc. All rights reserved. +# + +PROG = nicstat + +include ../Makefile.cmd + +all: $(PROG) + +install: all .WAIT $(ROOTPROG) + +clean: + +$(ROOTBINPROG): $(PROG) + $(INS.file) + +lint: + +include ../Makefile.targ diff --git a/usr/src/cmd/nicstat/nicstat.pl b/usr/src/cmd/nicstat/nicstat.pl new file mode 100644 index 0000000000..fae4c797df --- /dev/null +++ b/usr/src/cmd/nicstat/nicstat.pl @@ -0,0 +1,424 @@ +#!/usr/perl5/bin/perl -w +# +# nicstat - print network traffic, Kbyte/s read and written. +# Solaris 8+, Perl (Sun::Solaris::Kstat). +# +# "netstat -i" only gives a packet count, this program gives Kbytes. +# +# 04-Apr-2011, ver 1.00J +# +# USAGE: nicstat [-hsz] [-i int[,int...]] | [interval [count]] +# +# -h # help +# -s # print summary output +# -z # skip zero lines +# -i int[,int...] # print these instances only +# eg, +# nicstat # print summary since boot +# nicstat 1 # print continually, every 1 second +# nicstat 1 5 # print 5 times, every 1 second +# nicstat -i hme0 # only examine hme0 +# +# This prints out the KB/s transferred for all the network cards (NICs), +# including packet counts and average sizes. The first line is the summary +# data since boot. +# +# FIELDS: +# Int Interface +# rKB/s read Kbytes/s +# wKB/s write Kbytes/s +# rPk/s read Packets/s +# wPk/s write Packets/s +# rAvs read Average size, bytes +# wAvs write Average size, bytes +# %Util %Utilisation (r or w/ifspeed) +# Sat Saturation (defer, nocanput, norecvbuf, noxmtbuf) +# +# NOTES: +# +# - Some unusual network cards may not provide all the details to Kstat, +# (or provide different symbols). Check for newer versions of this program, +# and the @Network array in the code below. +# - Utilisation is based on bytes transferred divided by speed of the interface +# (if the speed is known). It should be impossible to reach 100% as there +# are overheads due to bus negotiation and timing. +# - Loopback interfaces may only provide packet counts (if anything), and so +# bytes and %util will always be zero. Newer versions of Solaris (newer than +# Solaris 10 6/06) may provide loopback byte stats. +# - Saturation is determined by counting read and write errors caused by the +# interface running at saturation. This approach is not ideal, and the value +# reported is often lower than it should be (eg, 0.0). Reading the rKB/s and +# wKB/s fields may be more useful. +# +# SEE ALSO: +# nicstat.c # the C version, also on my website +# kstat -n hme0 [interval [count]] # or qfe0, ... +# netstat -iI hme0 [interval [count]] +# se netstat.se [interval] # SE Toolkit +# se nx.se [interval] # SE Toolkit +# +# COPYRIGHT: Copyright (c) 2013 Brendan Gregg. +# +# 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 docs/cddl1.txt or +# http://opensource.org/licenses/CDDL-1.0. +# 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 docs/cddl1.txt. +# 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 2015 Joyent, Inc. All rights reserved. +# +# Author: Brendan Gregg [Sydney, Australia] +# +# 18-Jul-2004 Brendan Gregg Created this. +# 07-Jan-2005 " " added saturation value. +# 07-Jan-2005 " " added summary style (from Peter Tribble). +# 23-Jan-2006 " " Tweaked style. +# 11-Aug-2006 " " Improved output neatness. +# 30-Sep-2006 " " Added loopback, tweaked output. +# 04-Apr-2011 brendan@joyent.com Updated for smartmachines. + +use strict; +use Getopt::Std; +use Sun::Solaris::Kstat; +my $Kstat = Sun::Solaris::Kstat->new(); + + +# +# Process command line args +# +usage() if defined $ARGV[0] and $ARGV[0] eq "--help"; +getopts('hi:sz') or usage(); +usage() if defined $main::opt_h; +my $STYLE = defined $main::opt_s ? $main::opt_s : 0; +my $SKIPZERO = defined $main::opt_z ? $main::opt_z : 0; + +# process [interval [count]], +my ($interval, $loop_max); +if (defined $ARGV[0]) { + $interval = $ARGV[0]; + $loop_max = defined $ARGV[1] ? $ARGV[1] : 2**32; + usage() if $interval == 0; +} +else { + $interval = 1; + $loop_max = 1; +} + +# check for -i, +my %NetworkOnly; # network interfaces to print +my $NETWORKONLY = 0; # match on network interfaces +if (defined $main::opt_i) { + foreach my $net (split /,/, $main::opt_i) { + $NetworkOnly{$net} = 1; + } + $NETWORKONLY = 1; +} + +# globals, +my $loop = 0; # current loop number +my $PAGESIZE = 20; # max lines per header +my $line = $PAGESIZE; # counter for lines printed +my %NetworkNames; # Kstat network interfaces +my %NetworkData; # network interface data +my %NetworkDataOld; # network interface data +$main::opt_h = 0; +$| = 1; # autoflush + +# kstat "link" module includes: +my @Network = qw(dmfe bge be bnx ce eri eth external ge hme igb ige internal ixgbe le net ppp qfe rtls); +my %Network; +$Network{$_} = 1 foreach (@Network); +my $ZONENAME = `/usr/bin/zonename`; +chomp $ZONENAME; + +### Determine network interfaces +unless (find_nets()) { + if ($NETWORKONLY) { + print STDERR "ERROR1: $main::opt_i matched no network interfaces.\n"; + } + else { + print STDERR "ERROR1: No network interfaces found!\n"; + } + exit 1; +} + + +# +# Main +# +while (1) { + + ### Print Header + if ($line >= $PAGESIZE) { + if ($STYLE == 0) { + printf "%8s %12s %7s %7s %7s %7s %7s %7s %6s %5s\n", + "Time", "Int", "rKB/s", "wKB/s", "rPk/s", "wPk/s", "rAvs", + "wAvs", "%Util", "Sat"; + } + elsif ($STYLE == 1) { + printf "%8s %12s %14s %14s\n", "Time", "Int", "rKB/s", "wKB/s"; + } + + $line = 0; + } + + ### Get new data + my (@NetworkData) = fetch_net_data(); + + foreach my $network_data (@NetworkData) { + + ### Extract values + my ($int, $rbytes, $wbytes, $rpackets, $wpackets, $speed, $sat, $time) + = split /:/, $network_data; + + ### Retrieve old values + my ($old_rbytes, $old_wbytes, $old_rpackets, $old_wpackets, $old_sat, + $old_time); + if (defined $NetworkDataOld{$int}) { + ($old_rbytes, $old_wbytes, $old_rpackets, $old_wpackets, + $old_sat, $old_time) = split /:/, $NetworkDataOld{$int}; + } + else { + $old_rbytes = $old_wbytes = $old_rpackets = $old_wpackets + = $old_sat = $old_time = 0; + } + + # + # Calculate statistics + # + + # delta time + my $tdiff = $time - $old_time; + + # per second values + my $rbps = ($rbytes - $old_rbytes) / $tdiff; + my $wbps = ($wbytes - $old_wbytes) / $tdiff; + my $rkps = $rbps / 1024; + my $wkps = $wbps / 1024; + my $rpps = ($rpackets - $old_rpackets) / $tdiff; + my $wpps = ($wpackets - $old_wpackets) / $tdiff; + my $ravs = $rpps > 0 ? $rbps / $rpps : 0; + my $wavs = $wpps > 0 ? $wbps / $wpps : 0; + + # skip zero lines if asked + next if $SKIPZERO and ($rbps + $wbps) == 0; + + # % utilisation + my $util; + if ($speed > 0) { + # the following has a mysterious "800", it is 100 + # for the % conversion, and 8 for bytes2bits. + my $rutil = $rbps * 800 / $speed; + my $wutil = $wbps * 800 / $speed; + $util = $rutil > $wutil ? $rutil : $wutil; + $util = 100 if $util > 100; + } + else { + $util = 0; + } + + # saturation per sec + my $sats = ($sat - $old_sat) / $tdiff; + + # + # Print statistics + # + if ($rbps ne "") { + my @Time = localtime(); + + if ($STYLE == 0) { + printf "%02d:%02d:%02d %12s ", + $Time[2], $Time[1], $Time[0], $int; + print_neat($rkps); + print_neat($wkps); + print_neat($rpps); + print_neat($wpps); + print_neat($ravs); + print_neat($wavs); + printf "%6.2f %5.2f\n", $util, $sats; + } + elsif ($STYLE == 1) { + printf "%02d:%02d:%02d %12s %14.3f %14.3f\n", + $Time[2], $Time[1], $Time[0], $int, $rkps, $wkps; + } + + $line++; + + # for multiple interfaces, always print the header + $line += $PAGESIZE if @NetworkData > 1; + } + + ### Store old values + $NetworkDataOld{$int} + = "$rbytes:$wbytes:$rpackets:$wpackets:$sat:$time"; + } + + ### Check for end + last if ++$loop == $loop_max; + + ### Interval + sleep $interval; +} + + +# find_nets - walk Kstat to discover network interfaces. +# +# This walks %Kstat and populates a %NetworkNames with discovered +# network interfaces. +# +sub find_nets { + my $found = 0; + + ### Loop over all Kstat modules + foreach my $module (keys %$Kstat) { + my $Modules = $Kstat->{$module}; + + foreach my $instance (keys %$Modules) { + my $Instances = $Modules->{$instance}; + + foreach my $name (keys %$Instances) { + + ### Skip interface if asked + if ($NETWORKONLY) { + next unless $NetworkOnly{$name}; + } + + my $Names = $Instances->{$name}; + + # Check this is a network device. + # Matching on ifspeed has been more reliable than "class" + # we also match loopback and "link" interfaces. + if (defined $$Names{ifspeed} || $module eq "lo" + || $module eq "link") { + next if $name eq "mac"; + if ($module eq "link") { + my $nname = $name; + $nname =~ s/\d+$//; + next unless defined $Network{$nname} + or $ZONENAME eq $nname + or $ZONENAME eq "global"; + } + ### Save network interface + $NetworkNames{$name} = $Names; + $found++; + } + } + } + } + + return $found; +} + +# fetch - fetch Kstat data for the network interfaces. +# +# This uses the interfaces in %NetworkNames and returns useful Kstat data. +# The Kstat values used are rbytes64, obytes64, ipackets64, opackets64 +# (or the 32 bit versions if the 64 bit values are not there). +# +sub fetch_net_data { + my ($rbytes, $wbytes, $rpackets, $wpackets, $speed, $time); + my @NetworkData = (); + + $Kstat->update(); + + ### Loop over previously found network interfaces + foreach my $name (sort keys %NetworkNames) { + my $Names = $NetworkNames{$name}; + + if (defined $$Names{opackets}) { + + ### Fetch write bytes + if (defined $$Names{obytes64}) { + $rbytes = $$Names{rbytes64}; + $wbytes = $$Names{obytes64}; + } + elsif (defined $$Names{obytes}) { + $rbytes = $$Names{rbytes}; + $wbytes = $$Names{obytes}; + } else { + $rbytes = $wbytes = 0; + } + + ### Fetch read bytes + if (defined $$Names{opackets64}) { + $rpackets = $$Names{ipackets64}; + $wpackets = $$Names{opackets64}; + } + else { + $rpackets = $$Names{ipackets}; + $wpackets = $$Names{opackets}; + } + + ### Fetch interface speed + if (defined $$Names{ifspeed}) { + $speed = $$Names{ifspeed}; + } + else { + # if we can't fetch the speed, print the + # %Util as 0.0 . To do this we, + $speed = 2 ** 48; + } + + ### Determine saturation value + my $sat = 0; + if (defined $$Names{nocanput} or defined $$Names{norcvbuf}) { + $sat += defined $$Names{defer} ? $$Names{defer} : 0; + $sat += defined $$Names{nocanput} ? $$Names{nocanput} : 0; + $sat += defined $$Names{norcvbuf} ? $$Names{norcvbuf} : 0; + $sat += defined $$Names{noxmtbuf} ? $$Names{noxmtbuf} : 0; + } + + ### use the last snaptime value, + $time = $$Names{snaptime}; + + ### store data + push @NetworkData, "$name:$rbytes:$wbytes:" . + "$rpackets:$wpackets:$speed:$sat:$time"; + } + } + + return @NetworkData; +} + +# print_neat - print a float with decimal places if appropriate. +# +# This specifically keeps the width to 7 characters, if possible, plus +# a trailing space. +# +sub print_neat { + my $num = shift; + if ($num >= 100000) { + printf "%7d ", $num; + } elsif ($num >= 100) { + printf "%7.1f ", $num; + } else { + printf "%7.2f ", $num; + } +} + +# usage - print usage and exit. +# +sub usage { + print STDERR <<END; +USAGE: nicstat [-hsz] [-i int[,int...]] | [interval [count]] + eg, nicstat # print summary since boot + nicstat 1 # print continually every 1 second + nicstat 1 5 # print 5 times, every 1 second + nicstat -s # summary output + nicstat -i hme0 # print hme0 only +END + exit 1; +} diff --git a/usr/src/cmd/nscd/Makefile b/usr/src/cmd/nscd/Makefile index aa478fa3b0..1e51819bb2 100644 --- a/usr/src/cmd/nscd/Makefile +++ b/usr/src/cmd/nscd/Makefile @@ -29,6 +29,7 @@ MANIFEST= name-service-cache.xml SVCMETHOD= svc-nscd include ../Makefile.cmd +include ../Makefile.ctf ROOTMANIFESTDIR= $(ROOTSVCSYSTEM) diff --git a/usr/src/cmd/nscd/svc-nscd b/usr/src/cmd/nscd/svc-nscd index 0c6aa1bc4b..78b318bf87 100644 --- a/usr/src/cmd/nscd/svc-nscd +++ b/usr/src/cmd/nscd/svc-nscd @@ -23,8 +23,8 @@ # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2012 Joyent, Inc. All rights reserved. # -#ident "%Z%%M% %I% %E% SMI" . /lib/svc/share/smf_include.sh @@ -51,7 +51,7 @@ if (smf_is_system_labeled); then $SMF_FMRI` fi if [ "$duration" != "transient" ]; then - ( while true ; do sleep 3600 ; done ) & + exit $SMF_EXIT_NODAEMON fi # The real daemon is not started in non-global zones, diff --git a/usr/src/cmd/passwd/Makefile b/usr/src/cmd/passwd/Makefile index 561357a16c..079e8b6050 100644 --- a/usr/src/cmd/passwd/Makefile +++ b/usr/src/cmd/passwd/Makefile @@ -33,6 +33,8 @@ lint := LDLIBS += -lpasswdutil LDFLAGS += $(ZIGNORE) LDLIBS += -lbsm -lpam -lnsl +CPPFLAGS += -D__EXTENSIONS__ + FILEMODE = 06555 XGETFLAGS += -a -x $(PROG).xcl diff --git a/usr/src/cmd/pgrep/pgrep.c b/usr/src/cmd/pgrep/pgrep.c index 4531f11267..857f6ef818 100644 --- a/usr/src/cmd/pgrep/pgrep.c +++ b/usr/src/cmd/pgrep/pgrep.c @@ -597,6 +597,8 @@ main(int argc, char *argv[]) const char *optstr; optdesc_t *optd; int nmatches, c; + const char *zroot; + char buf[PATH_MAX]; DIR *dirp; @@ -626,6 +628,12 @@ main(int argc, char *argv[]) opterr = 0; + zroot = zone_get_nroot(); + if (zroot != NULL) { + (void) snprintf(buf, sizeof (buf), "%s/%s", zroot, g_procdir); + g_procdir = buf; + } + while (optind < argc) { while ((c = getopt(argc, argv, optstr)) != (int)EOF) { diff --git a/usr/src/cmd/prstat/prstat.c b/usr/src/cmd/prstat/prstat.c index fc16e435f6..982c860d0d 100644 --- a/usr/src/cmd/prstat/prstat.c +++ b/usr/src/cmd/prstat/prstat.c @@ -26,6 +26,7 @@ * Use is subject to license terms. * * Portions Copyright 2009 Chad Mynhier + * Copyright 2012 Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -181,6 +182,33 @@ static optdesc_t opts = { -1 /* sort in decreasing order */ }; + +static int +proc_snprintf(char *_RESTRICT_KYWD s, size_t n, + const char *_RESTRICT_KYWD fmt, ...) +{ + static boolean_t ptools_zroot_valid = B_FALSE; + static const char *ptools_zroot = NULL; + va_list args; + int ret, nret = 0; + + if (ptools_zroot_valid == B_FALSE) { + ptools_zroot_valid = B_TRUE; + ptools_zroot = zone_get_nroot(); + } + + if (ptools_zroot != NULL) { + nret = snprintf(s, n, "%s", ptools_zroot); + if (nret > n) + return (nret); + } + va_start(args, fmt); + ret = vsnprintf(s + nret, n - nret, fmt, args); + va_end(args); + + return (ret + nret); +} + /* * Print timestamp as decimal reprentation of time_t value (-d u was specified) * or the standard date format (-d d was specified). @@ -236,7 +264,12 @@ list_getsize(list_t *list) size_t i; uint_t flags = 0; int ret; - size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize; + size_t physmem; + + if (!(opts.o_outpmode & OPT_VMUSAGE)) + return; + + physmem = sysconf(_SC_PHYS_PAGES) * pagesize; /* * Determine what swap/rss results to calculate. getvmusage() will @@ -848,9 +881,9 @@ lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage) static int read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize) { - char procfile[MAX_PROCFS_PATH]; + char procfile[PATH_MAX]; - (void) snprintf(procfile, MAX_PROCFS_PATH, + (void) proc_snprintf(procfile, PATH_MAX, "/proc/%s/%s", pidstr, file); if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL) return (1); @@ -1376,6 +1409,7 @@ main(int argc, char **argv) int timeout; struct pollfd pollset; char key; + char procpath[PATH_MAX]; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); @@ -1386,7 +1420,7 @@ main(int argc, char **argv) pagesize = sysconf(_SC_PAGESIZE); while ((opt = getopt(argc, argv, - "vcd:HmarRLtu:U:n:p:C:P:h:s:S:j:k:TJWz:Z")) != (int)EOF) { + "vVcd:HmarRLtu:U:n:p:C:P:h:s:S:j:k:TJWz:Z")) != (int)EOF) { switch (opt) { case 'r': opts.o_outpmode |= OPT_NORESOLVE; @@ -1466,6 +1500,9 @@ main(int argc, char **argv) while (p = strtok(NULL, ", ")) add_uid(&ruid_tbl, p); break; + case 'V': + opts.o_outpmode |= OPT_VMUSAGE; + break; case 'p': fill_table(&pid_tbl, optarg, 'p'); break; @@ -1575,7 +1612,8 @@ main(int argc, char **argv) list_setkeyfunc(NULL, &opts, &lgroups, LT_LGRPS); if (opts.o_outpmode & OPT_TERMCAP) curses_on(); - if ((procdir = opendir("/proc")) == NULL) + (void) proc_snprintf(procpath, sizeof (procpath), "/proc"); + if ((procdir = opendir(procpath)) == NULL) Die(gettext("cannot open /proc directory\n")); if (opts.o_outpmode & OPT_TTY) { (void) printf(gettext("Please wait...\r")); diff --git a/usr/src/cmd/prstat/prstat.h b/usr/src/cmd/prstat/prstat.h index 293123c5b9..bf38b3e2bd 100644 --- a/usr/src/cmd/prstat/prstat.h +++ b/usr/src/cmd/prstat/prstat.h @@ -26,6 +26,7 @@ * Use is subject to license terms. * * Portions Copyright 2009 Chad Mynhier + * Copyright 2012 Joyent, Inc. All rights reserved. */ #ifndef _PRSTAT_H @@ -72,6 +73,7 @@ extern "C" { #define OPT_ZONES 0x2000 /* report about zones */ #define OPT_PSETS 0x4000 /* report for specified psets */ #define OPT_LGRP 0x8000 /* report home lgroups */ +#define OPT_VMUSAGE 0x10000 /* print accurate, but expensive RSS */ #define OPT_UDATE 0x20000 /* print unix timestamp */ #define OPT_DDATE 0x40000 /* print timestamp in date(1) format */ #define OPT_NORESOLVE 0x80000 /* no nsswitch lookups */ diff --git a/usr/src/cmd/prstat/prutil.c b/usr/src/cmd/prstat/prutil.c index 0f9cbd6c4d..7def1bd40b 100644 --- a/usr/src/cmd/prstat/prutil.c +++ b/usr/src/cmd/prstat/prutil.c @@ -25,6 +25,7 @@ * Use is subject to license terms. * * Portions Copyright 2009 Chad Mynhier + * Copyright 2012 Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -108,7 +109,7 @@ void Usage() { (void) fprintf(stderr, gettext( - "Usage:\tprstat [-acHJLmrRtTvWZ] [-u euidlist] [-U uidlist]\n" + "Usage:\tprstat [-acHJLmrRtTvVWZ] [-u euidlist] [-U uidlist]\n" "\t[-p pidlist] [-P cpulist] [-C psrsetlist] [-h lgrouplist]\n" "\t[-j projidlist] [-k taskidlist] [-z zoneidlist]\n" "\t[-s key | -S key] [-n nprocs[,nusers]] [-d d|u]\n" diff --git a/usr/src/cmd/prtconf/prtconf.c b/usr/src/cmd/prtconf/prtconf.c index 551144976e..0982f1d40b 100644 --- a/usr/src/cmd/prtconf/prtconf.c +++ b/usr/src/cmd/prtconf/prtconf.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -168,7 +169,7 @@ cleanup_path(const char *input_path, char *path) #ifdef DEBUG static const char *optstring = "abcdDvVxpPFf:M:dLuC"; #else -static const char *optstring = "abcdDvVxpPFf:uC"; +static const char *optstring = "abcdDvVxmpPFf:uC"; #endif /* DEBUG */ int @@ -201,6 +202,9 @@ main(int argc, char *argv[]) case 'v': ++opts.o_verbose; break; + case 'm': + ++opts.o_memory; + break; case 'p': ++opts.o_prominfo; break; @@ -338,34 +342,42 @@ main(int argc, char *argv[]) return (0); } - ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider)); - /* - * If 0 bytes are returned (the system returns '1', for the \0), - * we're probably on x86, default to Oracle. - */ - if (ret <= 1) { - (void) strncpy(hw_provider, "Oracle Corporation", + if (!opts.o_memory) { + ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider)); + /* + * If 0 bytes are returned (the system returns '1', for the \0), + * we're probably on x86, and there has been no si-hw-provider + * set in /etc/bootrc, default to Joyent. + */ + if (ret <= 1) { + (void) strncpy(hw_provider, "Joyent", + sizeof (hw_provider)); + } + (void) printf("System Configuration: %s %s\n", hw_provider, + opts.o_uts.machine); } - (void) printf("System Configuration: %s %s\n", hw_provider, - opts.o_uts.machine); pagesize = sysconf(_SC_PAGESIZE); npages = sysconf(_SC_PHYS_PAGES); - (void) printf("Memory size: "); - if (pagesize == -1 || npages == -1) - (void) printf("unable to determine\n"); - else { - const int64_t kbyte = 1024; + if (pagesize == -1 || npages == -1) { + if (opts.o_memory) { + (void) printf("0\n"); + return (1); + } else { + (void) printf("Memory size: unable to determine\n"); + } + } else { const int64_t mbyte = 1024 * 1024; int64_t ii = (int64_t)pagesize * npages; - if (ii >= mbyte) - (void) printf("%ld Megabytes\n", + if (opts.o_memory) { + (void) printf("%ld\n", (long)((ii+mbyte-1) / mbyte)); + return (0); + } else { + (void) printf("Memory size: %ld Megabytes\n", (long)((ii+mbyte-1) / mbyte)); - else - (void) printf("%ld Kilobytes\n", - (long)((ii+kbyte-1) / kbyte)); + } } if (opts.o_prominfo) { diff --git a/usr/src/cmd/prtconf/prtconf.h b/usr/src/cmd/prtconf/prtconf.h index 5f9abe968c..0284cc8af1 100644 --- a/usr/src/cmd/prtconf/prtconf.h +++ b/usr/src/cmd/prtconf/prtconf.h @@ -54,6 +54,7 @@ struct prt_opts { int o_drv_name; int o_pseudodevs; int o_fbname; + int o_memory; int o_noheader; int o_prominfo; int o_productinfo; diff --git a/usr/src/cmd/prtdiag/i386/Makefile b/usr/src/cmd/prtdiag/i386/Makefile index 10bbed0d40..5a8e0cb5fe 100644 --- a/usr/src/cmd/prtdiag/i386/Makefile +++ b/usr/src/cmd/prtdiag/i386/Makefile @@ -19,18 +19,19 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2015 Joyent, Inc. +# SRCDIR = .. include $(SRCDIR)/Makefile.com OBJS += smbios.o -LDLIBS += -lsmbios +LDLIBS += -lsmbios -lnvpair -lpcidb -L$(ROOT)/usr/lib/fm -ltopo +LDFLAGS += -R/usr/lib/fm .KEEP_STATE: diff --git a/usr/src/cmd/prtdiag/i386/smbios.c b/usr/src/cmd/prtdiag/i386/smbios.c index 0936bfba77..4bdbfe36be 100644 --- a/usr/src/cmd/prtdiag/i386/smbios.c +++ b/usr/src/cmd/prtdiag/i386/smbios.c @@ -23,8 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2015 Joyent, Inc. + */ /* * x86 System Management BIOS prtdiag @@ -65,6 +66,12 @@ #include <stdlib.h> #include <stdio.h> #include <ctype.h> +#include <pcidb.h> +#include <fm/libtopo.h> +#include <fm/topo_hc.h> +#include <sys/fm/protocol.h> + +static pcidb_hdl_t *prt_php; /*ARGSUSED*/ static int @@ -163,6 +170,103 @@ do_obdevs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg) /*ARGSUSED*/ static int +do_slot_mapping_cb(topo_hdl_t *thp, tnode_t *node, void *arg) +{ + int err, ret; + nvlist_t *rsrc = NULL; + const char *match = arg; + char *s, *fmri = NULL; + char *didstr = NULL, *driver = NULL, *vidstr = NULL; + boolean_t printed = B_FALSE; + + ret = TOPO_WALK_NEXT; + if (topo_node_resource(node, &rsrc, &err) < 0) + goto next; + if (topo_fmri_nvl2str(thp, rsrc, &fmri, &err) < 0) + goto next; + + if ((s = strstr(fmri, match)) == NULL) + goto next; + if (s[strlen(match)] != '\0') + goto next; + + /* At this point we think we've found a match */ + ret = TOPO_WALK_TERMINATE; + if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DRIVER, &driver, + &err) != 0) + driver = NULL; + + if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_VENDID, + &vidstr, &err) != 0) + goto next; + + if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_DEVID, + &didstr, &err) != 0) + goto next; + + if (prt_php != NULL) { + long vid, did; + + vid = strtol(vidstr, NULL, 16); + did = strtol(didstr, NULL, 16); + if (vid >= 0 && vid <= UINT16_MAX && + did >= 0 && did <= UINT16_MAX) { + pcidb_device_t *pdev; + + pdev = pcidb_lookup_device(prt_php, vid, did); + if (pdev != NULL) { + pcidb_vendor_t *pvend; + pvend = pcidb_device_vendor(pdev); + (void) printf(gettext(", %s %s (%s)"), + pcidb_vendor_name(pvend), + pcidb_device_name(pdev), + driver != NULL ? driver : "<unknown>"); + printed = B_TRUE; + } + } + } + + if (printed == B_FALSE) { + (void) printf(gettext(", pci%s,%s (%s)"), vidstr, didstr, + driver != NULL ? driver : "<unknown>"); + } +next: + topo_hdl_strfree(thp, didstr); + topo_hdl_strfree(thp, driver); + topo_hdl_strfree(thp, vidstr); + topo_hdl_strfree(thp, fmri); + nvlist_free(rsrc); + return (ret); +} + +static void +do_slot_mapping(smbios_slot_t *s, topo_hdl_t *thp) +{ + int err; + uint_t dev, func; + topo_walk_t *twp; + char pciex[256]; + + /* + * Bits 7:3 are the device number and bits 2:0 are the function. + */ + dev = s->smbl_df >> 3; + func = s->smbl_df & 0x7; + + (void) snprintf(pciex, sizeof (pciex), "%s=%u/%s=%u/%s=%d", + PCIEX_BUS, s->smbl_bus, PCIEX_DEVICE, dev, PCIEX_FUNCTION, func); + + twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, do_slot_mapping_cb, pciex, + &err); + if (twp == NULL) + return; + + (void) topo_walk_step(twp, TOPO_WALK_CHILD); + topo_walk_fini(twp); +} + +/*ARGSUSED*/ +static int do_slots(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg) { smbios_slot_t s; @@ -173,9 +277,21 @@ do_slots(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg) const char *t = smbios_slot_type_desc(s.smbl_type); const char *u = smbios_slot_usage_desc(s.smbl_usage); - (void) printf(gettext("%-3u %-9s %-16s %s\n"), + (void) printf(gettext("%-3u %-9s %-16s %s"), s.smbl_id, u ? u : gettext("Unknown"), t ? t : gettext("Unknown"), s.smbl_name); + + /* + * If the slot isn't of a type where this makes sense, then + * SMBIOS will populate any of these members with the value + * 0xff. Therefore if we find any of them set there, we just + * ignore it for now. + */ + if (s.smbl_sg != 0xff || s.smbl_bus != 0xff || + s.smbl_df != 0xff || arg != NULL) + do_slot_mapping(&s, arg); + + (void) printf(gettext("\n")); } return (0); @@ -190,6 +306,8 @@ do_prominfo(int opt_v, char *progname, int opt_l, int opt_p) smbios_bios_t bios; smbios_ipmi_t ipmi; smbios_info_t info; + topo_hdl_t *thp; + char *uuid; const char *s; id_t id; @@ -229,6 +347,19 @@ do_prominfo(int opt_v, char *progname, int opt_l, int opt_p) ipmi.smbip_vers.smbv_major, ipmi.smbip_vers.smbv_minor, s); } + /* + * Silently swallow all libtopo and libpcidb related errors. + */ + uuid = NULL; + if ((thp = topo_open(TOPO_VERSION, NULL, &err)) != NULL) { + if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) { + topo_close(thp); + thp = NULL; + } + } + + prt_php = pcidb_open(PCIDB_VERSION); + (void) printf(gettext( "\n==== Processor Sockets ====================================\n")); @@ -260,8 +391,16 @@ do_prominfo(int opt_v, char *progname, int opt_l, int opt_p) (void) printf(gettext( "\n--- --------- ---------------- ----------------------------\n")); - (void) smbios_iter(shp, do_slots, NULL); + (void) smbios_iter(shp, do_slots, thp); smbios_close(shp); + + topo_hdl_strfree(thp, uuid); + if (thp != NULL) { + topo_snap_release(thp); + topo_close(thp); + } + pcidb_close(prt_php); + return (0); } diff --git a/usr/src/cmd/ptools/Makefile.bld b/usr/src/cmd/ptools/Makefile.bld index f5b50f5ea1..e8bb27b043 100644 --- a/usr/src/cmd/ptools/Makefile.bld +++ b/usr/src/cmd/ptools/Makefile.bld @@ -26,6 +26,8 @@ PROG:sh = basename `cd ..; pwd` +include ../../../Makefile.ctf + OBJS = $(PROG).o SRCS = ../$(PROG).c @@ -69,6 +71,12 @@ CERRWARN_pargs += -_gcc=-Wno-type-limits CERRWARN += $(CERRWARN_$(PROG)) +# +# Common code definitions +# +COBJS = ptools_common.o +CINC = -I../../common + # pargs depends on ../../common/elfcap components # pmadvise depends on pmap components @@ -79,14 +87,32 @@ CPPFLAGS_pargs = -I$(ELFCAP) OBJS_pargs = elfcap.o SRCS_pargs = $(ELFCAP)/elfcap.c -CPPFLAGS_pmap = -I$(PMAP) -OBJS_pmap = pmap_common.o +CPPFLAGS_pmap = -I$(PMAP) $(CINC) +OBJS_pmap = pmap_common.o $(COBJS) SRCS_pmap = $(PMAP)/pmap_common.c -CPPFLAGS_pmadvise = -I$(PMAP) -OBJS_pmadvise = pmap_common.o +CPPFLAGS_pmadvise = -I$(PMAP) $(CINC) +OBJS_pmadvise = pmap_common.o $(COBJS) SRCS_pmadvise = $(PMAP)/pmap_common.c +CPPFLAGS_preap = $(CINC) +OBJS_preap = $(COBJS) + +CPPFLAGS_psig = $(CINC) +OBJS_psig = $(COBJS) + +CPPFLAGS_ptime = $(CINC) +OBJS_ptime = $(COBJS) + +CPPFLAGS_ptree = $(CINC) +OBJS_ptree = $(COBJS) + +CPPFLAGS_pwait = $(CINC) +OBJS_pwait = $(COBJS) + +CPPFLAGS_pwdx = $(CINC) +OBJS_pwdx = $(COBJS) + CPPFLAGS += $(CPPFLAGS_$(PROG)) OBJS += $(OBJS_$(PROG)) SRCS += $(SRCS_$(PROG)) @@ -99,12 +125,19 @@ INSTALL_LEGACY=$(RM) $(ROOTPROCBINSYMLINK) ; \ elfcap.o: $(ELFCAP)/elfcap.c $(COMPILE.c) -o $@ $(ELFCAP)/elfcap.c + $(POST_PROCESS_O) pmap_common.o: $(PMAP)/pmap_common.c $(COMPILE.c) -o $@ $(PMAP)/pmap_common.c + $(POST_PROCESS_O) %.o: ../%.c $(COMPILE.c) $< + $(POST_PROCESS_O) + +%.o: ../../common/%.c + $(COMPILE.c) $< + $(POST_PROCESS_O) all: $(PROG) diff --git a/usr/src/cmd/ptools/common/ptools_common.c b/usr/src/cmd/ptools/common/ptools_common.c new file mode 100644 index 0000000000..a747ab213e --- /dev/null +++ b/usr/src/cmd/ptools/common/ptools_common.c @@ -0,0 +1,50 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +#include <sys/feature_tests.h> +#include <stdio.h> +#include <stdarg.h> +#include <sys/types.h> +#include <zone.h> + +/* + * Common routines for ptools. + */ + +int +proc_snprintf(char *_RESTRICT_KYWD s, size_t n, + const char *_RESTRICT_KYWD fmt, ...) +{ + static boolean_t ptools_zroot_valid = B_FALSE; + static const char *ptools_zroot = NULL; + va_list args; + int ret, nret = 0; + + if (ptools_zroot_valid == B_FALSE) { + ptools_zroot_valid = B_TRUE; + ptools_zroot = zone_get_nroot(); + } + + if (ptools_zroot != NULL) { + nret = snprintf(s, n, "%s", ptools_zroot); + if (nret > n) + return (nret); + } + va_start(args, fmt); + ret = vsnprintf(s + nret, n - nret, fmt, args); + va_end(args); + + return (ret + nret); +} diff --git a/usr/src/cmd/ptools/common/ptools_common.h b/usr/src/cmd/ptools/common/ptools_common.h new file mode 100644 index 0000000000..52bcae9e51 --- /dev/null +++ b/usr/src/cmd/ptools/common/ptools_common.h @@ -0,0 +1,36 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +#ifndef _PTOOLS_COMMON_H +#define _PTOOLS_COMMON_H + +#include <sys/feature_tests.h> + +/* + * Common functions for the ptools. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int proc_snprintf(char *_RESTRICT_KYWD, size_t, + const char *_RESTRICT_KYWD, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* _PTOOLS_COMMON_H */ diff --git a/usr/src/cmd/ptools/pargs/pargs.c b/usr/src/cmd/ptools/pargs/pargs.c index a0a4febcd4..c65dff56f1 100644 --- a/usr/src/cmd/ptools/pargs/pargs.c +++ b/usr/src/cmd/ptools/pargs/pargs.c @@ -23,7 +23,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ /* @@ -791,6 +791,7 @@ static struct aux_id aux_arr[] = { { AT_BASE, "AT_BASE", at_null }, { AT_FLAGS, "AT_FLAGS", at_null }, { AT_ENTRY, "AT_ENTRY", at_null }, + { AT_RANDOM, "AT_RANDOM", at_null }, { AT_SUN_UID, "AT_SUN_UID", at_uid }, { AT_SUN_RUID, "AT_SUN_RUID", at_uid }, { AT_SUN_GID, "AT_SUN_GID", at_gid }, @@ -810,9 +811,11 @@ static struct aux_id aux_arr[] = { { AT_SUN_AUXFLAGS, "AT_SUN_AUXFLAGS", at_flags }, { AT_SUN_EMULATOR, "AT_SUN_EMULATOR", at_str }, { AT_SUN_BRANDNAME, "AT_SUN_BRANDNAME", at_str }, + { AT_SUN_BRAND_NROOT, "AT_SUN_BRAND_NROOT", at_str }, { AT_SUN_BRAND_AUX1, "AT_SUN_BRAND_AUX1", at_null }, { AT_SUN_BRAND_AUX2, "AT_SUN_BRAND_AUX2", at_null }, - { AT_SUN_BRAND_AUX3, "AT_SUN_BRAND_AUX3", at_null } + { AT_SUN_BRAND_AUX3, "AT_SUN_BRAND_AUX3", at_null }, + { AT_SUN_BRAND_AUX4, "AT_SUN_BRAND_AUX4", at_null } }; #define N_AT_ENTS (sizeof (aux_arr) / sizeof (struct aux_id)) diff --git a/usr/src/cmd/ptools/pfiles/pfiles.c b/usr/src/cmd/ptools/pfiles/pfiles.c index fbe54fc0dd..8e09ef534b 100644 --- a/usr/src/cmd/ptools/pfiles/pfiles.c +++ b/usr/src/cmd/ptools/pfiles/pfiles.c @@ -24,7 +24,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. */ /* - * Copyright (c) 2013 Joyent, Inc. All Rights reserved. + * Copyright (c) 2014 Joyent, Inc. All Rights reserved. */ #include <stdio.h> @@ -271,15 +271,14 @@ show_file(void *data, prfdinfo_t *info) (mode & S_IFMT) == S_IFDOOR); if (Pstate(Pr) != PS_DEAD) { - char *dev; + char *dev = NULL; if ((mode & S_IFMT) == S_IFSOCK) dosocket(Pr, info->pr_fd); else if ((mode & S_IFMT) == S_IFIFO) dofifo(Pr, info->pr_fd); - if ((mode & S_IFMT) == S_IFCHR && - (dev = strrchr(info->pr_path, ':')) != NULL) { + if ((mode & S_IFMT) == S_IFCHR) { /* * There's no elegant way to determine * if a character device supports TLI, @@ -291,11 +290,20 @@ show_file(void *data, prfdinfo_t *info) "tcp", "tcp6", "udp", "udp6", NULL }; - dev++; /* skip past the `:' */ - for (i = 0; tlidevs[i] != NULL; i++) { - if (strcmp(dev, tlidevs[i]) == 0) { - dotli(Pr, info->pr_fd); - break; + /* global zone: /devices paths */ + dev = strrchr(info->pr_path, ':'); + /* also check the /dev path for zones */ + if (dev == NULL) + dev = strrchr(info->pr_path, '/'); + if (dev != NULL) { + dev++; /* skip past the `:' */ + + for (i = 0; tlidevs[i] != NULL; i++) { + if (strcmp(dev, tlidevs[i]) == + 0) { + dotli(Pr, info->pr_fd); + break; + } } } } @@ -549,6 +557,7 @@ show_sockaddr(const char *str, struct sockaddr *sa, socklen_t len) case AF_IPX: p = "AF_IPX"; break; case AF_ROUTE: p = "AF_ROUTE"; break; case AF_LINK: p = "AF_LINK"; break; + case AF_LX_NETLINK: p = "AF_LX_NETLINK"; break; } (void) printf("\t%s: %s\n", str, p); @@ -796,9 +805,11 @@ dotli(struct ps_prochandle *Pr, int fd) strcmd.sc_cmd = TI_GETMYNAME; if (pr_ioctl(Pr, fd, _I_CMD, &strcmd, sizeof (strcmd)) == 0) - show_sockaddr("sockname", (void *)&strcmd.sc_buf, 0); + show_sockaddr("sockname", (void *)&strcmd.sc_buf, + (size_t)strcmd.sc_len); strcmd.sc_cmd = TI_GETPEERNAME; if (pr_ioctl(Pr, fd, _I_CMD, &strcmd, sizeof (strcmd)) == 0) - show_sockaddr("peername", (void *)&strcmd.sc_buf, 0); + show_sockaddr("peername", (void *)&strcmd.sc_buf, + (size_t)strcmd.sc_len); } diff --git a/usr/src/cmd/ptools/pflags/pflags.c b/usr/src/cmd/ptools/pflags/pflags.c index 8054a80d3c..f19a945d95 100644 --- a/usr/src/cmd/ptools/pflags/pflags.c +++ b/usr/src/cmd/ptools/pflags/pflags.c @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2015, Joyent, Inc. */ #include <stdio.h> @@ -469,6 +469,9 @@ prwhy(int why) case PR_SUSPENDED: str = "PR_SUSPENDED"; break; + case PR_BRAND: + str = "PR_BRAND"; + break; default: str = buf; (void) sprintf(str, "%d", why); diff --git a/usr/src/cmd/ptools/pmadvise/pmadvise.c b/usr/src/cmd/ptools/pmadvise/pmadvise.c index 8500a00dc6..6b9623508a 100644 --- a/usr/src/cmd/ptools/pmadvise/pmadvise.c +++ b/usr/src/cmd/ptools/pmadvise/pmadvise.c @@ -25,6 +25,10 @@ */ /* + * Copyright (c) 2015, Joyent, Inc. All rights reserved. + */ + +/* * pmadvise * * ptool wrapper for madvise(3C) to apply memory advice to running processes @@ -153,7 +157,7 @@ * Advice that can be passed to madvise fit into three groups that each * contain 3 mutually exclusive options. These groups are defined below: * Group 1: normal, random, sequential - * Group 2: willneed, dontneed, free + * Group 2: willneed, dontneed, free, purge * Group 3: default, accesslwp, accessmany * Thus, advice that includes (at most) one from each group is valid. * @@ -164,7 +168,7 @@ #define GRP1_ADV (1 << MADV_NORMAL | 1 << MADV_RANDOM | \ 1 << MADV_SEQUENTIAL) #define GRP2_ADV (1 << MADV_WILLNEED | 1 << MADV_DONTNEED | \ - 1 << MADV_FREE) + 1 << MADV_FREE | 1 << MADV_PURGE) #define GRP3_ADV (1 << MADV_ACCESS_DEFAULT | 1 << MADV_ACCESS_LWP | \ 1 << MADV_ACCESS_MANY) @@ -346,6 +350,8 @@ get_advice(char *optarg) return (1 << MADV_NORMAL); else if (strcmp(optarg, "free") == 0) return (1 << MADV_FREE); + else if (strcmp(optarg, "purge") == 0) + return (1 << MADV_PURGE); else { (void) fprintf(stderr, gettext("%s: invalid advice: %s\n"), progname, optarg); @@ -676,7 +682,7 @@ apply_advice(saddr_t **advicelist) * with the for loop. */ if (psaddr->adv != NO_ADVICE) { - for (i = MADV_NORMAL; i <= MADV_ACCESS_MANY; i++) { + for (i = MADV_NORMAL; i <= MADV_PURGE; i++) { if ((psaddr->adv & (1 << i)) && (pr_madvise(Pr, (caddr_t)psaddr->addr, psaddr->length, i) < 0)) { @@ -898,7 +904,7 @@ advtostr(int adv) *buf = '\0'; if (adv != NO_ADVICE) { - for (i = MADV_NORMAL; i <= MADV_ACCESS_MANY; i++) { + for (i = MADV_NORMAL; i <= MADV_PURGE; i++) { if (adv & (1 << i)) { /* * check if it's the first advice entry diff --git a/usr/src/cmd/ptools/pmap/pmap.c b/usr/src/cmd/ptools/pmap/pmap.c index 78bfa6b596..03f8bde791 100644 --- a/usr/src/cmd/ptools/pmap/pmap.c +++ b/usr/src/cmd/ptools/pmap/pmap.c @@ -22,6 +22,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <stdio.h> @@ -42,6 +43,7 @@ #include <sys/mman.h> #include <sys/lgrp_user.h> #include <libproc.h> +#include "ptools_common.h" #include "pmap_common.h" @@ -199,7 +201,7 @@ main(int argc, char **argv) const char *bar; struct rlimit rlim; struct stat64 statbuf; - char buf[128]; + char buf[PATH_MAX]; int mapfd; int prg_gflags = PGRAB_RDONLY; int prr_flags = 0; @@ -358,7 +360,7 @@ main(int argc, char **argv) proc_unctrl_psinfo(&psinfo); if (Pstate(Pr) != PS_DEAD) { - (void) snprintf(buf, sizeof (buf), + (void) proc_snprintf(buf, sizeof (buf), "/proc/%d/map", (int)psinfo.pr_pid); if ((mapfd = open(buf, O_RDONLY)) < 0) { (void) fprintf(stderr, "%s: cannot " @@ -590,7 +592,7 @@ rmapping_iter(struct ps_prochandle *Pr, proc_map_f *func, void *cd) prmap_t *prmapp, *pmp; ssize_t n; - (void) snprintf(mapname, sizeof (mapname), + (void) proc_snprintf(mapname, sizeof (mapname), "/proc/%d/rmap", (int)Pstatus(Pr)->pr_pid); if ((mapfd = open(mapname, O_RDONLY)) < 0 || fstat(mapfd, &st) != 0) { @@ -631,7 +633,7 @@ xmapping_iter(struct ps_prochandle *Pr, proc_xmap_f *func, void *cd, int doswap) prxmap_t *prmapp, *pmp; ssize_t n; - (void) snprintf(mapname, sizeof (mapname), + (void) proc_snprintf(mapname, sizeof (mapname), "/proc/%d/xmap", (int)Pstatus(Pr)->pr_pid); if ((mapfd = open(mapname, O_RDONLY)) < 0 || fstat(mapfd, &st) != 0) { diff --git a/usr/src/cmd/ptools/pmap/pmap_common.c b/usr/src/cmd/ptools/pmap/pmap_common.c index fff55ffdbc..81f42d67f7 100644 --- a/usr/src/cmd/ptools/pmap/pmap_common.c +++ b/usr/src/cmd/ptools/pmap/pmap_common.c @@ -37,6 +37,7 @@ #include <sys/types.h> #include "pmap_common.h" +#include "ptools_common.h" /* * We compare the high memory addresses since stacks are faulted in from @@ -88,7 +89,7 @@ make_name(struct ps_prochandle *Pr, int lflag, uintptr_t addr, return (NULL); /* first see if we can find a path via /proc */ - (void) snprintf(path, sizeof (path), "/proc/%d/path/%s", + (void) proc_snprintf(path, sizeof (path), "/proc/%d/path/%s", (int)Psp->pr_pid, mapname); len = readlink(path, buf, bufsz - 1); if (len >= 0) { @@ -97,7 +98,7 @@ make_name(struct ps_prochandle *Pr, int lflag, uintptr_t addr, } /* fall back to object information reported by /proc */ - (void) snprintf(path, sizeof (path), + (void) proc_snprintf(path, sizeof (path), "/proc/%d/object/%s", (int)Psp->pr_pid, mapname); if (stat(path, &statb) == 0) { dev_t dev = statb.st_dev; diff --git a/usr/src/cmd/ptools/preap/preap.c b/usr/src/cmd/ptools/preap/preap.c index 8d30b8027c..6d8eb75611 100644 --- a/usr/src/cmd/ptools/preap/preap.c +++ b/usr/src/cmd/ptools/preap/preap.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -37,6 +35,8 @@ #include <sys/types.h> #include <sys/wait.h> #include <libproc.h> +#include <limits.h> +#include "ptools_common.h" #define NOREAP_TIME 60 /* wait 60 seconds before allow a reap */ @@ -53,11 +53,11 @@ intr(int sig) static int open_usage(pid_t pid, int *perr) { - char path[64]; + char path[PATH_MAX]; struct stat64 st; int fd; - (void) snprintf(path, sizeof (path), "/proc/%d/usage", (int)pid); + (void) proc_snprintf(path, sizeof (path), "/proc/%d/usage", (int)pid); /* * Attempt to open the usage file, and return the fd if we can diff --git a/usr/src/cmd/ptools/psig/psig.c b/usr/src/cmd/ptools/psig/psig.c index 70af35cb5e..848fda834c 100644 --- a/usr/src/cmd/ptools/psig/psig.c +++ b/usr/src/cmd/ptools/psig/psig.c @@ -21,10 +21,9 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <stdio_ext.h> #include <stdlib.h> @@ -37,6 +36,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <libproc.h> +#include "ptools_common.h" /* evil knowledge of libc internals */ #include "../../../lib/libc/inc/thr_uberdata.h" @@ -172,7 +172,7 @@ lwp_iter(void *cd, const lwpstatus_t *lwpstatus) static int look(char *arg) { - char pathname[100]; + char pathname[PATH_MAX]; struct stat statb; int fd = -1; int sig, gcode; @@ -199,7 +199,8 @@ look(char *arg) (void) memcpy(&psinfo, psinfop, sizeof (psinfo_t)); proc_unctrl_psinfo(&psinfo); - (void) sprintf(pathname, "/proc/%d/sigact", (int)psinfo.pr_pid); + (void) proc_snprintf(pathname, sizeof (pathname), "/proc/%d/sigact", + (int)psinfo.pr_pid); if ((fd = open(pathname, O_RDONLY)) < 0) { perr("open sigact"); goto look_error; @@ -213,8 +214,8 @@ look(char *arg) action = malloc(maxsig * sizeof (struct sigaction)); if (action == NULL) { (void) fprintf(stderr, - "%s: cannot malloc() space for %d sigaction structures\n", - command, maxsig); + "%s: cannot malloc() space for %d sigaction structures\n", + command, maxsig); goto look_error; } if (read(fd, (char *)action, maxsig * sizeof (struct sigaction)) != @@ -239,7 +240,7 @@ look(char *arg) if (psinfo.pr_dmodel != PR_MODEL_NATIVE) { caddr32_t addr; aharraddr = uberaddr + - offsetof(uberdata32_t, siguaction); + offsetof(uberdata32_t, siguaction); aharrlen = sizeof (siguaction32_t) * NSIG; (void) Pread(Pr, &addr, sizeof (addr), uberaddr + offsetof(uberdata32_t, sigacthandler)); @@ -248,7 +249,7 @@ look(char *arg) #endif { aharraddr = uberaddr + - offsetof(uberdata_t, siguaction); + offsetof(uberdata_t, siguaction); aharrlen = sizeof (siguaction_t) * NSIG; (void) Pread(Pr, &intfnaddr, sizeof (intfnaddr), uberaddr + offsetof(uberdata_t, sigacthandler)); @@ -323,7 +324,7 @@ look(char *arg) (void) printf("\t%-8s", hname); else (void) printf("\t0x%-8lx", - (ulong_t)haddr); + (ulong_t)haddr); s = sigflags(sig, sp->sa_flags); (void) printf("%s", (*s != '\0')? s : "\t0"); @@ -334,7 +335,7 @@ look(char *arg) } } else if (sig == SIGCLD) { s = sigflags(sig, - sp->sa_flags & (SA_NOCLDWAIT|SA_NOCLDSTOP)); + sp->sa_flags & (SA_NOCLDWAIT|SA_NOCLDSTOP)); if (*s != '\0') (void) printf("\t\t%s", s); } @@ -371,7 +372,7 @@ sigflags(int sig, int flags) static char code_buf[100]; char *str = code_buf; int flagmask = - (SA_ONSTACK|SA_RESETHAND|SA_RESTART|SA_SIGINFO|SA_NODEFER); + (SA_ONSTACK|SA_RESETHAND|SA_RESTART|SA_SIGINFO|SA_NODEFER); if (sig == SIGCLD) flagmask |= (SA_NOCLDSTOP|SA_NOCLDWAIT); @@ -414,19 +415,19 @@ deinterpose(int sig, void *aharr, psinfo_t *psinfo, struct sigaction *sp) #ifdef _LP64 if (psinfo->pr_dmodel != PR_MODEL_NATIVE) { struct sigaction32 *sa32 = (struct sigaction32 *) - ((uintptr_t)aharr + sig * sizeof (siguaction32_t) + - offsetof(siguaction32_t, sig_uaction)); + ((uintptr_t)aharr + sig * sizeof (siguaction32_t) + + offsetof(siguaction32_t, sig_uaction)); sp->sa_flags = sa32->sa_flags; sp->sa_handler = (void (*)())(uintptr_t)sa32->sa_handler; (void) memcpy(&sp->sa_mask, &sa32->sa_mask, - sizeof (sp->sa_mask)); + sizeof (sp->sa_mask)); } else #endif { struct sigaction *sa = (struct sigaction *) - ((uintptr_t)aharr + sig * sizeof (siguaction_t) + - offsetof(siguaction_t, sig_uaction)); + ((uintptr_t)aharr + sig * sizeof (siguaction_t) + + offsetof(siguaction_t, sig_uaction)); sp->sa_flags = sa->sa_flags; sp->sa_handler = sa->sa_handler; diff --git a/usr/src/cmd/ptools/ptime/ptime.c b/usr/src/cmd/ptools/ptime/ptime.c index bc862cddb8..7c9be226e1 100644 --- a/usr/src/cmd/ptools/ptime/ptime.c +++ b/usr/src/cmd/ptools/ptime/ptime.c @@ -24,6 +24,9 @@ * * Portions Copyright 2008 Chad Mynhier */ +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ #include <stdio.h> #include <stdlib.h> @@ -38,6 +41,8 @@ #include <sys/time.h> #include <signal.h> #include <libproc.h> +#include <limits.h> +#include "ptools_common.h" static int look(pid_t); static void hr_min_sec(char *, long); @@ -55,16 +60,39 @@ static char procname[64]; static int Fflag; static int mflag; static int errflg; +static int pflag; + +static int +ptime_pid(const char *pidstr) +{ + struct ps_prochandle *Pr; + pid_t pid; + int gret; + + if ((Pr = proc_arg_grab(pidstr, PR_ARG_PIDS, + Fflag | PGRAB_RDONLY, &gret)) == NULL) { + (void) fprintf(stderr, "%s: cannot examine %s: %s\n", + command, pidstr, Pgrab_error(gret)); + return (1); + } + + pid = Pstatus(Pr)->pr_pid; + (void) sprintf(procname, "%d", (int)pid); /* for perr() */ + (void) look(pid); + Prelease(Pr, 0); + return (0); +} int main(int argc, char **argv) { - int opt; + int opt, exit; pid_t pid; struct siginfo info; int status; int gret; struct ps_prochandle *Pr; + char *pp, *np; if ((command = strrchr(argv[0], '/')) != NULL) command++; @@ -80,6 +108,7 @@ main(int argc, char **argv) mflag = 1; break; case 'p': + pflag = 1; pidarg = optarg; break; default: @@ -93,69 +122,76 @@ main(int argc, char **argv) if (((pidarg != NULL) ^ (argc < 1)) || errflg) { (void) fprintf(stderr, - "usage:\t%s [-mh] [-p pid | command [ args ... ]]\n", + "usage:\t%s [-mh] [-p pidlist | command [ args ... ]]\n", command); (void) fprintf(stderr, " (time a command using microstate accounting)\n"); return (1); } - if (pidarg != NULL) { - if ((Pr = proc_arg_grab(pidarg, PR_ARG_PIDS, - Fflag | PGRAB_RDONLY, &gret)) == NULL) { - (void) fprintf(stderr, "%s: cannot examine %s: %s\n", - command, pidarg, Pgrab_error(gret)); - return (1); - } - } else { - if ((Pr = Pcreate(argv[0], &argv[0], &gret, NULL, 0)) == NULL) { - (void) fprintf(stderr, "%s: failed to exec %s: %s\n", - command, argv[0], Pcreate_error(gret)); - return (1); - } - if (Psetrun(Pr, 0, 0) == -1) { - (void) fprintf(stderr, "%s: failed to set running %s: " - "%s\n", command, argv[0], strerror(errno)); - return (1); + if (pflag) { + exit = 0; + (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGQUIT, SIG_IGN); + pp = pidarg; + if ((np = strchr(pp, ' ')) != NULL || + (np = strchr(pp, ',')) != NULL) + pflag++; + while (np != NULL) { + *np = '\0'; + exit |= ptime_pid(pp); + pp = np + 1; + np = strchr(pp, ' '); + if (np == NULL) + np = strchr(pp, ','); } + exit |= ptime_pid(pp); + return (exit); + } + + + if ((Pr = Pcreate(argv[0], &argv[0], &gret, NULL, 0)) == NULL) { + (void) fprintf(stderr, "%s: failed to exec %s: %s\n", + command, argv[0], Pcreate_error(gret)); + return (1); + } + if (Psetrun(Pr, 0, 0) == -1) { + (void) fprintf(stderr, "%s: failed to set running %s: " + "%s\n", command, argv[0], strerror(errno)); + return (1); } pid = Pstatus(Pr)->pr_pid; + (void) sprintf(procname, "%d", (int)pid); /* for perr() */ (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); - if (pidarg == NULL) - (void) waitid(P_PID, pid, &info, WEXITED | WNOWAIT); + (void) waitid(P_PID, pid, &info, WEXITED | WNOWAIT); (void) look(pid); - if (pidarg != NULL) { - Prelease(Pr, 0); - return (0); - } else { - (void) waitpid(pid, &status, 0); + (void) waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return (WEXITSTATUS(status)); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - char name[SIG2STR_MAX]; + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + char name[SIG2STR_MAX]; - (void) fprintf(stderr, "%s: command terminated " - "abnormally by %s\n", command, - proc_signame(sig, name, sizeof (name))); - } - - return (status | WCOREFLG); /* see time(1) */ + (void) fprintf(stderr, "%s: command terminated " + "abnormally by %s\n", command, + proc_signame(sig, name, sizeof (name))); } + + return (status | WCOREFLG); /* see time(1) */ } static int look(pid_t pid) { - char pathname[100]; + char pathname[PATH_MAX]; int rval = 0; int fd; psinfo_t psinfo; @@ -167,7 +203,8 @@ look(pid_t pid) if (proc_get_psinfo(pid, &psinfo) < 0) return (perr("read psinfo")); - (void) sprintf(pathname, "/proc/%d/usage", (int)pid); + (void) proc_snprintf(pathname, sizeof (pathname), "/proc/%d/usage", + (int)pid); if ((fd = open(pathname, O_RDONLY)) < 0) return (perr("open usage")); @@ -187,6 +224,9 @@ look(pid_t pid) tsadd(&sys, &sys, &pup->pr_ttime); (void) fprintf(stderr, "\n"); + if (pflag > 1) + (void) fprintf(stderr, "%d:\t%.70s\n", + (int)psinfo.pr_pid, psinfo.pr_psargs); prtime("real", &real); prtime("user", &user); prtime("sys", &sys); diff --git a/usr/src/cmd/ptools/ptree/ptree.c b/usr/src/cmd/ptools/ptree/ptree.c index 27fef9b7f0..92a65e2f44 100644 --- a/usr/src/cmd/ptools/ptree/ptree.c +++ b/usr/src/cmd/ptools/ptree/ptree.c @@ -21,14 +21,13 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ /* * ptree -- print family tree of processes */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <assert.h> #include <stdio.h> #include <string.h> @@ -48,6 +47,7 @@ #include <sys/ctfs.h> #include <libcontract_priv.h> #include <sys/stat.h> +#include "ptools_common.h" #define FAKEDPID0(p) (p->pid == 0 && p->psargs[0] == '\0') @@ -103,10 +103,11 @@ main(int argc, char **argv) char *s; int n; int retc = 0; + char ppath[PATH_MAX]; DIR *dirp; struct dirent *dentp; - char pname[100]; + char pname[PATH_MAX]; int pdlen; ps_t *p; @@ -169,16 +170,18 @@ main(int argc, char **argv) psize = 0; ps = NULL; + (void) proc_snprintf(ppath, sizeof (ppath), "/proc"); + /* * Search the /proc directory for all processes. */ - if ((dirp = opendir("/proc")) == NULL) { - (void) fprintf(stderr, "%s: cannot open /proc directory\n", - command); + if ((dirp = opendir(ppath)) == NULL) { + (void) fprintf(stderr, "%s: cannot open %s directory\n", + command, ppath); return (1); } - (void) strcpy(pname, "/proc"); + (void) strcpy(pname, ppath); pdlen = strlen(pname); pname[pdlen++] = '/'; diff --git a/usr/src/cmd/ptools/pwait/pwait.c b/usr/src/cmd/ptools/pwait/pwait.c index 0733c355cf..ec11573477 100644 --- a/usr/src/cmd/ptools/pwait/pwait.c +++ b/usr/src/cmd/ptools/pwait/pwait.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <stdio_ext.h> #include <ctype.h> @@ -39,6 +37,8 @@ #include <poll.h> #include <procfs.h> #include <sys/resource.h> +#include <limits.h> +#include "ptools_common.h" static int count_my_files(); static char *command; @@ -49,6 +49,7 @@ static char *command; int main(int argc, char **argv) { + char buf[PATH_MAX]; unsigned long remain = 0; struct pollfd *pollfd; struct pollfd *pfd; @@ -75,10 +76,12 @@ main(int argc, char **argv) (void) fprintf(stderr, "usage:\t%s [-v] pid ...\n", command); (void) fprintf(stderr, " (wait for processes to terminate)\n"); (void) fprintf(stderr, - " -v: verbose; report terminations to standard out\n"); + " -v: verbose; report terminations to standard out\n"); return (2); } + (void) proc_snprintf(buf, sizeof (buf), "/proc/"); + /* make sure we have enough file descriptors */ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { int nfiles = count_my_files(); @@ -87,8 +90,8 @@ main(int argc, char **argv) rlim.rlim_cur = argc + nfiles + SLOP; if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { (void) fprintf(stderr, - "%s: insufficient file descriptors\n", - command); + "%s: insufficient file descriptors\n", + command); return (2); } } @@ -108,11 +111,11 @@ main(int argc, char **argv) if (strchr(arg, '/') != NULL) (void) strncpy(psinfofile, arg, sizeof (psinfofile)); else { - (void) strcpy(psinfofile, "/proc/"); + (void) strcpy(psinfofile, buf); (void) strncat(psinfofile, arg, sizeof (psinfofile)-6); } (void) strncat(psinfofile, "/psinfo", - sizeof (psinfofile)-strlen(psinfofile)); + sizeof (psinfofile)-strlen(psinfofile)); pfd = &pollfd[i]; if ((pfd->fd = open(psinfofile, O_RDONLY)) >= 0) { @@ -126,7 +129,7 @@ main(int argc, char **argv) pfd->revents = 0; } else if (errno == ENOENT) { (void) fprintf(stderr, "%s: no such process: %s\n", - command, arg); + command, arg); } else { perror(arg); } @@ -160,9 +163,9 @@ main(int argc, char **argv) if (pread(pfd->fd, &psinfo, sizeof (psinfo), (off_t)0) == sizeof (psinfo)) { - (void) printf( - "%s: terminated, wait status 0x%.4x\n", - arg, psinfo.pr_wstat); + (void) printf("%s: terminated, " + "wait status 0x%.4x\n", + arg, psinfo.pr_wstat); } else { (void) printf( "%s: terminated\n", arg); @@ -170,10 +173,10 @@ main(int argc, char **argv) } if (pfd->revents & POLLNVAL) (void) printf("%s: system process\n", - arg); + arg); if (pfd->revents & ~(POLLPRI|POLLHUP|POLLNVAL)) (void) printf("%s: unknown error\n", - arg); + arg); } (void) close(pfd->fd); diff --git a/usr/src/cmd/ptools/pwdx/pwdx.c b/usr/src/cmd/ptools/pwdx/pwdx.c index adf42c0877..4a2c6f0c3f 100644 --- a/usr/src/cmd/ptools/pwdx/pwdx.c +++ b/usr/src/cmd/ptools/pwdx/pwdx.c @@ -22,10 +22,9 @@ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <unistd.h> #include <string.h> @@ -33,6 +32,8 @@ #include <libproc.h> #include <sys/param.h> +#include "ptools_common.h" + static char *command; static int @@ -49,7 +50,7 @@ show_cwd(const char *arg) return (1); } - (void) snprintf(proc, sizeof (proc), "/proc/%d/path/cwd", + (void) proc_snprintf(proc, sizeof (proc), "/proc/%d/path/cwd", (int)p.pr_pid); if ((ret = readlink(proc, cwd, sizeof (cwd) - 1)) <= 0) { diff --git a/usr/src/cmd/rcap/common/utils.c b/usr/src/cmd/rcap/common/utils.c index 799fdcef23..dd511c7c50 100644 --- a/usr/src/cmd/rcap/common/utils.c +++ b/usr/src/cmd/rcap/common/utils.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #include <sys/param.h> @@ -257,77 +258,3 @@ xatoi(char *p) return (i); } } - -/* - * get_running_zones() calls zone_list(2) to find out how many zones are - * running. It then calls zone_list(2) again to fetch the list of running - * zones (stored in *zents). - */ -int -get_running_zones(uint_t *nzents, zone_entry_t **zents) -{ - zoneid_t *zids; - uint_t nzents_saved; - int i; - zone_entry_t *zentp; - zone_state_t zstate; - - *zents = NULL; - if (zone_list(NULL, nzents) != 0) { - warn(gettext("could not get zoneid list\n")); - return (E_ERROR); - } - -again: - if (*nzents == 0) - return (E_SUCCESS); - - if ((zids = (zoneid_t *)calloc(*nzents, sizeof (zoneid_t))) == NULL) { - warn(gettext("out of memory: zones will not be capped\n")); - return (E_ERROR); - } - - nzents_saved = *nzents; - - if (zone_list(zids, nzents) != 0) { - warn(gettext("could not get zone list\n")); - free(zids); - return (E_ERROR); - } - if (*nzents != nzents_saved) { - /* list changed, try again */ - free(zids); - goto again; - } - - *zents = calloc(*nzents, sizeof (zone_entry_t)); - if (*zents == NULL) { - warn(gettext("out of memory: zones will not be capped\n")); - free(zids); - return (E_ERROR); - } - - zentp = *zents; - for (i = 0; i < *nzents; i++) { - char name[ZONENAME_MAX]; - - if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { - warn(gettext("could not get name for " - "zoneid %d\n"), zids[i]); - continue; - } - - (void) strlcpy(zentp->zname, name, sizeof (zentp->zname)); - zentp->zid = zids[i]; - if (zone_get_state(name, &zstate) != Z_OK || - zstate != ZONE_STATE_RUNNING) - continue; - - - zentp++; - } - *nzents = zentp - *zents; - - free(zids); - return (E_SUCCESS); -} diff --git a/usr/src/cmd/rcap/common/utils.h b/usr/src/cmd/rcap/common/utils.h index 7196cfb4ce..cf2e17c080 100644 --- a/usr/src/cmd/rcap/common/utils.h +++ b/usr/src/cmd/rcap/common/utils.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #ifndef _UTILS_H @@ -98,7 +99,6 @@ extern void vdprintfe(int, const char *, va_list); extern void dprintfe(int, char *, ...); extern void hrt2ts(hrtime_t, timestruc_t *); extern int xatoi(char *); -extern int get_running_zones(uint_t *, zone_entry_t **); #ifdef __cplusplus } diff --git a/usr/src/cmd/rcap/rcapadm/rcapadm.c b/usr/src/cmd/rcap/rcapadm/rcapadm.c index 92888b2071..b92115469a 100644 --- a/usr/src/cmd/rcap/rcapadm/rcapadm.c +++ b/usr/src/cmd/rcap/rcapadm/rcapadm.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -145,20 +146,29 @@ out: scf_handle_destroy(h); } +static int +set_zone_cap(char *zonename, uint64_t mcap) +{ + char cmd[128 + ZONENAME_MAX]; + + (void) snprintf(cmd, sizeof (cmd), "/usr/bin/prctl -r " + "-n zone.max-physical-memory -v %llu -i zone %s", mcap, zonename); + return (system(cmd)); +} + /* * Update the in-kernel memory cap for the specified zone. */ static int update_zone_mcap(char *zonename, char *maxrss) { - zoneid_t zone_id; uint64_t num; if (getzoneid() != GLOBAL_ZONEID || zonecfg_in_alt_root()) return (E_SUCCESS); /* get the running zone from the kernel */ - if ((zone_id = getzoneidbyname(zonename)) == -1) { + if (getzoneidbyname(zonename) == -1) { (void) fprintf(stderr, gettext("zone '%s' must be running\n"), zonename); return (E_ERROR); @@ -169,7 +179,7 @@ update_zone_mcap(char *zonename, char *maxrss) return (E_ERROR); } - if (zone_setattr(zone_id, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) { + if (set_zone_cap(zonename, num) == -1) { (void) fprintf(stderr, gettext("could not set memory " "cap for zone '%s'\n"), zonename); return (E_ERROR); diff --git a/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c b/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c index db86aa6276..88403dda37 100644 --- a/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c +++ b/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c @@ -21,16 +21,17 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <procfs.h> #include <project.h> #include <stdlib.h> #include <strings.h> #include <zone.h> #include <libzonecfg.h> +#include <dirent.h> +#include <libproc.h> #include "rcapd.h" #include "utils.h" @@ -39,61 +40,117 @@ extern boolean_t gz_capped; /* round up to next y = 2^n */ #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) -static void -update_zone(zone_entry_t *zent, void *walk_data) +static struct ps_prochandle * +grab_zone_proc(zoneid_t zid) { - void(*update_notification_cb)(char *, char *, int, uint64_t, int) = - (void(*)(char *, char *, int, uint64_t, int))walk_data; - int changes; - int64_t max_rss; + DIR *dirp; + struct dirent *dentp; + int pid, pid_self, tmp; + psinfo_t psinfo; + struct ps_prochandle *pr = NULL; + + pid_self = getpid(); + + if ((dirp = opendir("/proc")) == NULL) + return (NULL); + + while (dentp = readdir(dirp)) { + pid = atoi(dentp->d_name); + + /* Skip self */ + if (pid == pid_self) + continue; + + if (proc_get_psinfo(pid, &psinfo) != 0) + continue; + + if (psinfo.pr_zoneid != zid) + continue; + + /* attempt to grab process */ + if ((pr = Pgrab(pid, 0, &tmp)) != NULL) { + if (Psetflags(pr, PR_RLC) != 0) { + Prelease(pr, 0); + } + if (Pcreate_agent(pr) == 0) { + if (pr_getzoneid(pr) != zid) { + Prelease(pr, 0); + continue; + } + + (void) closedir(dirp); + return (pr); + } else { + Prelease(pr, 0); + } + } + } + + (void) closedir(dirp); + return (NULL); +} + +static uint64_t +get_zone_cap(zoneid_t zid) +{ + rctlblk_t *rblk; uint64_t mcap; - lcollection_t *lcol; - rcid_t colid; + struct ps_prochandle *pr; - if (zone_getattr(zent->zid, ZONE_ATTR_PHYS_MCAP, &mcap, - sizeof (mcap)) != -1 && mcap != 0) - max_rss = ROUNDUP(mcap, 1024) / 1024; - else - max_rss = 0; - - if (zent->zid == GLOBAL_ZONEID) { - if (max_rss > 0) - gz_capped = B_TRUE; - else - gz_capped = B_FALSE; + if ((rblk = (rctlblk_t *)malloc(rctlblk_size())) == NULL) + return (UINT64_MAX); + + if ((pr = grab_zone_proc(zid)) == NULL) { + free(rblk); + return (UINT64_MAX); } + if (pr_getrctl(pr, "zone.max-physical-memory", NULL, rblk, + RCTL_FIRST)) { + Pdestroy_agent(pr); + Prelease(pr, 0); + free(rblk); + return (UINT64_MAX); + } - colid.rcid_type = RCIDT_ZONE; - colid.rcid_val = zent->zid; + Pdestroy_agent(pr); + Prelease(pr, 0); - lcol = lcollection_insert_update(&colid, max_rss, zent->zname, - &changes); - if (update_notification_cb != NULL) - update_notification_cb("zone", zent->zname, changes, max_rss, - (lcol != NULL) ? lcol->lcol_mark : 0); + mcap = rctlblk_get_value(rblk); + free(rblk); + return (mcap); } - +/* + * For zones, rcapd only caps the global zone, since each non-global zone + * caps itself. + */ /* ARGSUSED */ void lcollection_update_zone(lcollection_update_type_t ut, void(*update_notification_cb)(char *, char *, int, uint64_t, int)) { - int i; - uint_t nzents; - zone_entry_t *zents; - - /* - * Enumerate running zones. - */ - if (get_running_zones(&nzents, &zents) != 0) - return; - - for (i = 0; i < nzents; i++) { - update_zone(&zents[i], (void *)update_notification_cb); + int changes; + int64_t max_rss; + uint64_t mcap; + lcollection_t *lcol; + rcid_t colid; + mcap = get_zone_cap(GLOBAL_ZONEID); + if (mcap != 0 && mcap != UINT64_MAX) { + max_rss = ROUNDUP(mcap, 1024) / 1024; + gz_capped = B_TRUE; + } else { + max_rss = UINT64_MAX / 1024; + gz_capped = B_FALSE; } - free(zents); + colid.rcid_type = RCIDT_ZONE; + colid.rcid_val = GLOBAL_ZONEID; + + lcol = lcollection_insert_update(&colid, max_rss, GLOBAL_ZONENAME, + &changes); + if (update_notification_cb != NULL) + update_notification_cb("zone", GLOBAL_ZONENAME, changes, + max_rss, (lcol != NULL) ? lcol->lcol_mark : 0); } diff --git a/usr/src/cmd/rcap/rcapd/rcapd_scanner.c b/usr/src/cmd/rcap/rcapd/rcapd_scanner.c index b39811b552..254bb9e922 100644 --- a/usr/src/cmd/rcap/rcapd/rcapd_scanner.c +++ b/usr/src/cmd/rcap/rcapd/rcapd_scanner.c @@ -21,6 +21,7 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2012 Joyent, Inc. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -551,7 +552,7 @@ pageout(pid_t pid, struct ps_prochandle *Pr, caddr_t start, caddr_t end) errno = 0; res = pr_memcntl(Pr, start, (end - start), MC_SYNC, - (caddr_t)(MS_ASYNC | MS_INVALIDATE), 0, 0); + (caddr_t)(MS_ASYNC | MS_INVALCURPROC), 0, 0); debug_high("pr_memcntl [%p-%p): %d", (void *)start, (void *)end, res); /* diff --git a/usr/src/cmd/rcap/rcapstat/rcapstat.c b/usr/src/cmd/rcap/rcapstat/rcapstat.c index 0632250fed..2838c6e5d5 100644 --- a/usr/src/cmd/rcap/rcapstat/rcapstat.c +++ b/usr/src/cmd/rcap/rcapstat/rcapstat.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -72,6 +73,8 @@ typedef struct col { static col_t *col_head; static int ncol; +#define RCAPD_NA "rcapd is not active (try zonememstat)\n" + static col_t * col_find(rcid_t id) { @@ -152,7 +155,7 @@ read_stats(rcid_type_t stat_type) struct stat st; if ((fd = open(STAT_FILE_DEFAULT, O_RDONLY)) < 0) { - warn(gettext("rcapd is not active\n")); + warn(gettext(RCAPD_NA)); return (E_ERROR); } @@ -173,7 +176,7 @@ read_stats(rcid_type_t stat_type) pid = hdr.rs_pid; (void) snprintf(procfile, 20, "/proc/%lld/psinfo", pid); if ((proc_fd = open(procfile, O_RDONLY)) < 0) { - warn(gettext("rcapd is not active\n")); + warn(gettext(RCAPD_NA)); (void) close(fd); return (E_ERROR); } diff --git a/usr/src/cmd/rcm_daemon/Makefile.com b/usr/src/cmd/rcm_daemon/Makefile.com index 4b12d1cd27..59e6e49371 100644 --- a/usr/src/cmd/rcm_daemon/Makefile.com +++ b/usr/src/cmd/rcm_daemon/Makefile.com @@ -56,7 +56,6 @@ COMMON_MOD_SRC = \ $(COMMON)/pool_rcm.c \ $(COMMON)/mpxio_rcm.c \ $(COMMON)/ip_anon_rcm.c \ - $(COMMON)/svm_rcm.c \ $(COMMON)/bridge_rcm.c sparc_MOD_SRC = $(COMMON)/ttymux_rcm.c @@ -82,7 +81,6 @@ COMMON_MOD_OBJ = \ pool_rcm.o \ mpxio_rcm.o \ ip_anon_rcm.o \ - svm_rcm.o \ bridge_rcm.o sparc_MOD_OBJ = ttymux_rcm.o @@ -103,7 +101,6 @@ COMMON_RCM_MODS = \ SUNW_pool_rcm.so \ SUNW_mpxio_rcm.so \ SUNW_ip_anon_rcm.so \ - SUNW_svm_rcm.so \ SUNW_bridge_rcm.so sparc_RCM_MODS = SUNW_ttymux_rcm.so @@ -132,7 +129,6 @@ LINTFLAGS += -u -erroff=E_FUNC_ARG_UNUSED LDLIBS_MODULES = SUNW_pool_rcm.so := LDLIBS_MODULES += -L$(ROOT)/usr/lib -lpool -SUNW_svm_rcm.so := LDLIBS_MODULES += -L$(ROOT)/usr/lib -lmeta SUNW_network_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldladm SUNW_vlan_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldladm SUNW_vnic_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldladm diff --git a/usr/src/cmd/savecore/savecore.c b/usr/src/cmd/savecore/savecore.c index 746c528347..f57309ec9b 100644 --- a/usr/src/cmd/savecore/savecore.c +++ b/usr/src/cmd/savecore/savecore.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright 2015, Joyent, Inc. */ /* * Copyright 2012 Nexenta Systems, Inc. All rights reserved. @@ -1929,24 +1929,32 @@ main(int argc, char *argv[]) if (sec < 1) sec = 1; - (void) fprintf(mfile, "[[[[,,,"); - for (i = 0; i < argc; i++) - (void) fprintf(mfile, "%s ", argv[i]); - (void) fprintf(mfile, "\n"); - (void) fprintf(mfile, ",,,%s/%s\n", savedir, corefile); - (void) fprintf(mfile, ",,,%s %s %s %s %s\n", - dumphdr.dump_utsname.sysname, - dumphdr.dump_utsname.nodename, - dumphdr.dump_utsname.release, - dumphdr.dump_utsname.version, - dumphdr.dump_utsname.machine); - (void) fprintf(mfile, "Uncompress pages,%"PRIu64"\n", - saved); - (void) fprintf(mfile, "Uncompress time,%d\n", sec); - (void) fprintf(mfile, "Uncompress pages/sec,%" - PRIu64"\n", saved / sec); - (void) fprintf(mfile, "]]]]\n"); - (void) fclose(mfile); + if (mfile == NULL) { + logprint(SC_SL_WARN, + "Can't create %s: %s", + METRICSFILE, strerror(errno)); + } else { + (void) fprintf(mfile, "[[[[,,,"); + for (i = 0; i < argc; i++) + (void) fprintf(mfile, "%s ", argv[i]); + (void) fprintf(mfile, "\n"); + (void) fprintf(mfile, ",,,%s/%s\n", savedir, + corefile); + (void) fprintf(mfile, ",,,%s %s %s %s %s\n", + dumphdr.dump_utsname.sysname, + dumphdr.dump_utsname.nodename, + dumphdr.dump_utsname.release, + dumphdr.dump_utsname.version, + dumphdr.dump_utsname.machine); + (void) fprintf(mfile, + "Uncompress pages,%"PRIu64"\n", saved); + (void) fprintf(mfile, "Uncompress time,%d\n", + sec); + (void) fprintf(mfile, "Uncompress pages/sec,%" + PRIu64"\n", saved / sec); + (void) fprintf(mfile, "]]]]\n"); + (void) fclose(mfile); + } } } diff --git a/usr/src/cmd/sed/main.c b/usr/src/cmd/sed/main.c index 204583b877..dc3ef02619 100644 --- a/usr/src/cmd/sed/main.c +++ b/usr/src/cmd/sed/main.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2013 Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.com> * Copyright (c) 2011 Gary Mills - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1992 Diomidis Spinellis. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -42,9 +42,7 @@ #include <err.h> #include <errno.h> #include <fcntl.h> -#include <getopt.h> #include <libgen.h> -#include <libintl.h> #include <limits.h> #include <locale.h> #include <regex.h> @@ -53,6 +51,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <libintl.h> #include "defs.h" #include "extern.h" @@ -107,11 +106,6 @@ static char tmpfname[PATH_MAX]; /* Temporary file name (for in-place editing) */ static const char *inplace; /* Inplace edit file extension. */ ulong_t linenum; -static const struct option lopts[] = { - {"in-place", optional_argument, NULL, 'i'}, - {NULL, 0, NULL, 0} -}; - static void add_compunit(enum e_cut, char *); static void add_file(char *); static void usage(void); @@ -133,18 +127,14 @@ main(int argc, char *argv[]) fflag = 0; inplace = NULL; - while ((c = getopt_long(argc, argv, "EI::ae:f:i::lnr", lopts, NULL)) != - -1) + while ((c = getopt(argc, argv, "EI:ae:f:i:lnr")) != -1) switch (c) { case 'r': /* Gnu sed compat */ case 'E': rflags = REG_EXTENDED; break; case 'I': - if (optarg != NULL) - inplace = optarg; - else - inplace = ""; + inplace = optarg; ispan = 1; /* span across input files */ break; case 'a': @@ -161,10 +151,7 @@ main(int argc, char *argv[]) add_compunit(CU_FILE, optarg); break; case 'i': - if (optarg != NULL) - inplace = optarg; - else - inplace = ""; + inplace = optarg; ispan = 0; /* don't span across input files */ break; case 'l': @@ -205,8 +192,8 @@ main(int argc, char *argv[]) static void usage(void) { - (void) fputs(_("usage: sed script [-Ealn] [-i[extension]] [file...]\n" - " sed [-Ealn] [-i[extension]] [-e script]... " + (void) fputs(_("usage: sed script [-Ealn] [-i extension] [file...]\n" + " sed [-Ealn] [-i extension] [-e script]... " "[-f script_file]... [file...]\n"), stderr); exit(1); diff --git a/usr/src/cmd/sendmail/src/Makefile b/usr/src/cmd/sendmail/src/Makefile index 14793754fd..9512a7d976 100644 --- a/usr/src/cmd/sendmail/src/Makefile +++ b/usr/src/cmd/sendmail/src/Makefile @@ -46,7 +46,7 @@ LDFLAGS += $(MAPFILES:%=-M%) LDLIBS += ../libsmutil/libsmutil.a ../libsm/libsm.a -lresolv -lsocket \ -lnsl ../db/libdb.a -lldap -lsldap -lwrap -lumem \ - -lssl -lcrypto -lsasl + -lsunw_ssl -lsunw_crypto -lsasl INCPATH= -I. -I../include -I../db diff --git a/usr/src/cmd/sgs/elfdump/Makefile.targ b/usr/src/cmd/sgs/elfdump/Makefile.targ index f4d74fa9c6..971d9dfeb4 100644 --- a/usr/src/cmd/sgs/elfdump/Makefile.targ +++ b/usr/src/cmd/sgs/elfdump/Makefile.targ @@ -78,6 +78,8 @@ delete: package \ install: all $(VAR_SGSBINPROG) $(VAR_SGSCCSLINK) + -$(RM) $(ROOTPROG) + -$(LN) $(ISAEXEC) $(ROOTPROG) .PARALLEL: $(LINTOUT32) $(LINTOUT64) diff --git a/usr/src/cmd/sgs/elfdump/amd64/Makefile b/usr/src/cmd/sgs/elfdump/amd64/Makefile index be0f2c33f6..039edb65b6 100644 --- a/usr/src/cmd/sgs/elfdump/amd64/Makefile +++ b/usr/src/cmd/sgs/elfdump/amd64/Makefile @@ -38,6 +38,8 @@ LINTFLAGS64 += $(VAR_LINTFLAGS64) VAR_SGSBINPROG= $(VAR_SGSBINPROG64) VAR_SGSCCSLINK= $(VAR_SGSCCSLINK64) +install: all $(ROOTPROG64) + include ../Makefile.targ include ../../Makefile.sub.64 diff --git a/usr/src/cmd/sgs/elfdump/i386/Makefile b/usr/src/cmd/sgs/elfdump/i386/Makefile index d3cb302ac1..95390a2899 100644 --- a/usr/src/cmd/sgs/elfdump/i386/Makefile +++ b/usr/src/cmd/sgs/elfdump/i386/Makefile @@ -30,4 +30,6 @@ include ../Makefile.com ARCH = i386 +install: all $(ROOTPROG32) + include ../Makefile.targ diff --git a/usr/src/cmd/sgs/lex/Makefile.targ b/usr/src/cmd/sgs/lex/Makefile.targ index ea1bee3a62..d1e01f71c9 100644 --- a/usr/src/cmd/sgs/lex/Makefile.targ +++ b/usr/src/cmd/sgs/lex/Makefile.targ @@ -102,4 +102,4 @@ $(LINTPOUT): $(SRCS) $(LINT.c) $(LIBSRCS) $(LDLIBS) 2>&1 | tee -a $(LINTPOUT) $(LINTLIB): $(LINTSRCS) - $(LINT.c) -o $(LIBNAME) $(LINTSRCS) + $(LINT.c) -o $(LIBNAME) $(LINTSRCS) > $(LINTOUT) 2>&1 diff --git a/usr/src/cmd/sgs/lex/common/main.c b/usr/src/cmd/sgs/lex/common/main.c index 17ba4808a4..a1fd526cf9 100644 --- a/usr/src/cmd/sgs/lex/common/main.c +++ b/usr/src/cmd/sgs/lex/common/main.c @@ -30,11 +30,15 @@ /* Copyright 1976, Bell Telephone Laboratories, Inc. */ +/* Copyright (c) 2013, joyent, Inc. All rights reserved. */ + #include <string.h> #include "once.h" #include "sgs.h" #include <locale.h> #include <limits.h> +#include <unistd.h> +#include <libgen.h> static wchar_t L_INITIAL[] = {'I', 'N', 'I', 'T', 'I', 'A', 'L', 0}; static void get1core(void); @@ -46,6 +50,25 @@ static void get3core(void); static void free3core(void); #endif +static int +lex_construct_path(char *buf, size_t size, const char *file, int type) +{ + int ret; + char origin[PATH_MAX]; + + if (type != 0) { + ret = readlink("/proc/self/path/a.out", origin, PATH_MAX - 1); + if (ret < 0) + error( + "lex: failed to read origin from /proc\n"); + origin[ret] = '\0'; + return (snprintf(buf, size, "%s/../%s/%s", dirname(origin), + NBASE, file)); + } + + return (snprintf(buf, size, "%s/%s/%s", NPREFIX, NBASE, file)); +} + int main(int argc, char **argv) { @@ -53,6 +76,7 @@ main(int argc, char **argv) int c; char *apath = NULL; char *ypath; + char pathbuf[PATH_MAX]; Boolean eoption = 0, woption = 0; sargv = argv; @@ -224,6 +248,11 @@ main(int argc, char **argv) free3core(); #endif + /* + * Try to find the file relative to $ORIGIN. Note that we don't touch + * antyhing related to -Y. In fact, unfortunately it's always been + * ignored it seems. + */ if (handleeuc) { if (ratfor) error("Ratfor is not supported by -w or -e option."); @@ -232,9 +261,19 @@ main(int argc, char **argv) else ypath = ratfor ? RATNAME : CNAME; - if (apath != NULL) - ypath = strcat(apath, strrchr(ypath, '/')); - fother = fopen(ypath, "r"); + if (apath == NULL) { + (void) lex_construct_path(pathbuf, sizeof (pathbuf), ypath, 1); + fother = fopen(pathbuf, "r"); + if (fother == NULL) { + (void) lex_construct_path(pathbuf, sizeof (pathbuf), + ypath, 0); + fother = fopen(pathbuf, "r"); + } + } else { + apath = strcat(apath, "/"); + ypath = strcat(apath, ypath); + fother = fopen(ypath, "r"); + } if (fother == NULL) error("Lex driver missing, file %s", ypath); while ((i = getc(fother)) != EOF) diff --git a/usr/src/cmd/sgs/lex/common/once.h b/usr/src/cmd/sgs/lex/common/once.h index 014ca00b17..9e4b0e5e00 100644 --- a/usr/src/cmd/sgs/lex/common/once.h +++ b/usr/src/cmd/sgs/lex/common/once.h @@ -26,11 +26,11 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ +/* Copyright (c) 2013, joyent, Inc. All rights reserved. */ + #ifndef _ONCE_H #define _ONCE_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ldefs.h" /* once.c */ @@ -73,9 +73,11 @@ int peek = '\n'; /* next input character */ CHR *pushptr = pushc; CHR *slptr = slist; -#define CNAME "/usr/share/lib/ccs/ncform" -#define RATNAME "/usr/share/lib/ccs/nrform" -#define EUCNAME "/usr/share/lib/ccs/nceucform" +#define NPREFIX "/usr" +#define NBASE "/share/lib/ccs/" +#define CNAME "ncform" +#define RATNAME "nrform" +#define EUCNAME "nceucform" int ccount = 1; int casecount = 1; diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c index eb998bae45..863c3bc917 100644 --- a/usr/src/cmd/sgs/libconv/common/corenote.c +++ b/usr/src/cmd/sgs/libconv/common/corenote.c @@ -25,7 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ /* @@ -76,7 +76,7 @@ const char * conv_cnote_auxv_type(Word type, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf) { - static const Msg types_0_22[] = { + static const Msg types_0_25[] = { MSG_AUXV_AT_NULL, MSG_AUXV_AT_IGNORE, MSG_AUXV_AT_EXECFD, MSG_AUXV_AT_PHDR, MSG_AUXV_AT_PHENT, MSG_AUXV_AT_PHNUM, @@ -88,10 +88,11 @@ conv_cnote_auxv_type(Word type, Conv_fmt_flags_t fmt_flags, MSG_AUXV_AT_HWCAP, MSG_AUXV_AT_CLKTCK, MSG_AUXV_AT_FPUCW, MSG_AUXV_AT_DCACHEBSIZE, MSG_AUXV_AT_ICACHEBSIZE, MSG_AUXV_AT_UCACHEBSIZE, - MSG_AUXV_AT_IGNOREPPC + MSG_AUXV_AT_IGNOREPPC, MSG_AUXV_AT_SECURE, + MSG_AUXV_AT_BASE_PLATFORM, MSG_AUXV_AT_RANDOM }; - static const conv_ds_msg_t ds_types_0_22 = { - CONV_DS_MSG_INIT(0, types_0_22) }; + static const conv_ds_msg_t ds_types_0_25 = { + CONV_DS_MSG_INIT(0, types_0_25) }; static const Msg types_2000_2011[] = { MSG_AUXV_AT_SUN_UID, MSG_AUXV_AT_SUN_RUID, @@ -104,19 +105,20 @@ conv_cnote_auxv_type(Word type, Conv_fmt_flags_t fmt_flags, static const conv_ds_msg_t ds_types_2000_2011 = { CONV_DS_MSG_INIT(2000, types_2000_2011) }; - static const Msg types_2014_2023[] = { + static const Msg types_2014_2024[] = { MSG_AUXV_AT_SUN_EXECNAME, MSG_AUXV_AT_SUN_MMU, MSG_AUXV_AT_SUN_LDDATA, MSG_AUXV_AT_SUN_AUXFLAGS, MSG_AUXV_AT_SUN_EMULATOR, MSG_AUXV_AT_SUN_BRANDNAME, MSG_AUXV_AT_SUN_BRAND_AUX1, MSG_AUXV_AT_SUN_BRAND_AUX2, - MSG_AUXV_AT_SUN_BRAND_AUX3, MSG_AUXV_AT_SUN_HWCAP2 + MSG_AUXV_AT_SUN_BRAND_AUX3, MSG_AUXV_AT_SUN_HWCAP2, + MSG_AUXV_AT_SUN_BRAND_NROOT }; - static const conv_ds_msg_t ds_types_2014_2023 = { - CONV_DS_MSG_INIT(2014, types_2014_2023) }; + static const conv_ds_msg_t ds_types_2014_2024 = { + CONV_DS_MSG_INIT(2014, types_2014_2024) }; static const conv_ds_t *ds[] = { - CONV_DS_ADDR(ds_types_0_22), CONV_DS_ADDR(ds_types_2000_2011), - CONV_DS_ADDR(ds_types_2014_2023), NULL }; + CONV_DS_ADDR(ds_types_0_25), CONV_DS_ADDR(ds_types_2000_2011), + CONV_DS_ADDR(ds_types_2014_2024), NULL }; return (conv_map_ds(ELFOSABI_NONE, EM_NONE, type, ds, fmt_flags, inv_buf)); diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg index f1cc32dfde..c68b826f72 100644 --- a/usr/src/cmd/sgs/libconv/common/corenote.msg +++ b/usr/src/cmd/sgs/libconv/common/corenote.msg @@ -24,7 +24,7 @@ # Use is subject to license terms. # # Copyright 2012 DEY Storage Systems, Inc. All rights reserved. -# Copyright (c) 2013, Joyent, Inc. All rights reserved. +# Copyright (c) 2014, Joyent, Inc. All rights reserved. # @ MSG_NT_PRSTATUS "[ NT_PRSTATUS ]" @@ -78,6 +78,9 @@ @ MSG_AUXV_AT_ICACHEBSIZE "ICACHEBSIZE" @ MSG_AUXV_AT_UCACHEBSIZE "UCACHEBSIZE" @ MSG_AUXV_AT_IGNOREPPC "IGNOREPPC" +@ MSG_AUXV_AT_SECURE "SECURE" +@ MSG_AUXV_AT_BASE_PLATFORM "BASE_PLATFORM" +@ MSG_AUXV_AT_RANDOM "RANDOM" @ MSG_AUXV_AT_SUN_UID "SUN_UID" @ MSG_AUXV_AT_SUN_RUID "SUN_RUID" @ MSG_AUXV_AT_SUN_GID "SUN_GID" @@ -100,6 +103,7 @@ @ MSG_AUXV_AT_SUN_BRAND_AUX2 "SUN_BRAND_AUX2" @ MSG_AUXV_AT_SUN_BRAND_AUX3 "SUN_BRAND_AUX3" @ MSG_AUXV_AT_SUN_HWCAP2 "SUN_HWCAP2" +@ MSG_AUXV_AT_SUN_BRAND_NROOT "SUN_BRAND_NROOT" @ MSG_CC_CONTENT_STACK "STACK" diff --git a/usr/src/cmd/sgs/librtld_db/common/librtld_db.msg b/usr/src/cmd/sgs/librtld_db/common/librtld_db.msg index fbc595f5f4..5b0ad9533a 100644 --- a/usr/src/cmd/sgs/librtld_db/common/librtld_db.msg +++ b/usr/src/cmd/sgs/librtld_db/common/librtld_db.msg @@ -24,6 +24,10 @@ # Use is subject to license terms. # +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + # Message file for cmd/sgs/librtld_db. @ MSG_ID_LIBRTLD_DB @@ -104,7 +108,7 @@ @ MSG_DB_RDOBJPADE "rtld_db: rd_objpad_enable(padsize=0x%llx)" @ MSG_DB_64BIT_PREFIX "64/" @ MSG_DB_BRAND_HELPERPATH_PREFIX "%s/%s/%s/%s%s_librtld_db.so.1" -@ MSG_DB_BRAND_HELPERPATH "%s/%s/%s%s_librtld_db.so.1" +@ MSG_DB_BRAND_HELPERPATH "%s/%s/%s/%s%s_librtld_db.so.1" @ MSG_DB_HELPERNOOPS "rtld_db: helper lib loaded but ops not preset" @ MSG_DB_HELPERLOADED "rtld_db: helper library loaded for brand \"%s\"" @ MSG_DB_HELPERLOADFAILED "rtld_db: couldn't load brand helper library %s" diff --git a/usr/src/cmd/sgs/librtld_db/common/rd_elf.c b/usr/src/cmd/sgs/librtld_db/common/rd_elf.c index 410b819b30..b3de685b81 100644 --- a/usr/src/cmd/sgs/librtld_db/common/rd_elf.c +++ b/usr/src/cmd/sgs/librtld_db/common/rd_elf.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + #include <stdlib.h> #include <stdio.h> #include <proc_service.h> @@ -38,6 +42,14 @@ #include <sys/param.h> /* + * We want to include zone.h to pull in the prototype for zone_get_nroot(), + * but we need to avoid pulling in <sys/stream.h>, which has a definition + * of M_DATA that conflicts with the ELF-related definition in machdep_*.h. + */ +#define _SYS_STREAM_H +#include <zone.h> + +/* * 64-bit builds are going to compile this module twice, the * second time with _ELF64 defined. These defines should make * all the necessary adjustments to the code. @@ -283,7 +295,9 @@ _rd_reset32(struct rd_agent *rap) * If we are debugging a branded executable, load the appropriate * helper library, and call its initialization routine. Being unable * to load the helper library is not a critical error. (Hopefully - * we'll still be able to access some objects in the target.) + * we'll still be able to access some objects in the target.) Note + * that we pull in the native root here to allow for helper libraries + * to be properly found from within the branded zone. */ ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname"); while ((ps_pbrandname != NULL) && @@ -294,17 +308,23 @@ _rd_reset32(struct rd_agent *rap) isa = MSG_ORIG(MSG_DB_64BIT_PREFIX); #endif /* _LP64 */ - if (rtld_db_helper_path[0] != '\0') + if (rtld_db_helper_path[0] != '\0') { (void) snprintf(brandlib, MAXPATHLEN, MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX), rtld_db_helper_path, MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, brandname); - else + } else { + const char *nroot = zone_get_nroot(); + + if (nroot == NULL) + nroot = ""; + (void) snprintf(brandlib, MAXPATHLEN, - MSG_ORIG(MSG_DB_BRAND_HELPERPATH), + MSG_ORIG(MSG_DB_BRAND_HELPERPATH), nroot, MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, brandname); + } rap->rd_helper.rh_dlhandle = dlopen(brandlib, RTLD_LAZY | RTLD_LOCAL); diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h index ece14a855e..83b7071471 100644 --- a/usr/src/cmd/sgs/rtld/common/_rtld.h +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h @@ -26,7 +26,7 @@ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifndef __RTLD_H #define __RTLD_H @@ -589,6 +589,8 @@ extern const char *rpl_ldflags; /* replaceable LD_FLAGS string */ extern const char *rpl_libpath; /* replaceable LD_LIBRARY string */ extern Alist *rpl_libdirs; /* and its associated Pdesc list */ extern const char *rpl_preload; /* replaceable LD_PRELOAD string */ +extern const char *rpl_ldtoxic; /* replaceable LD_TOXIC_PATH string */ +extern Alist *rpl_toxdirs; /* and associated Pdesc list */ extern const char *prm_audit; /* permanent LD_AUDIT string */ extern const char *prm_debug; /* permanent LD_DEBUG string */ diff --git a/usr/src/cmd/sgs/rtld/common/analyze.c b/usr/src/cmd/sgs/rtld/common/analyze.c index e14c121f07..3cae1036ae 100644 --- a/usr/src/cmd/sgs/rtld/common/analyze.c +++ b/usr/src/cmd/sgs/rtld/common/analyze.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent, Inc. */ /* @@ -834,6 +835,57 @@ is_so_loaded(Lm_list *lml, const char *name, int *in_nfavl) } /* + * Walk the toxic path list and determine if the object in question has violated + * the toxic path. When evaluating the toxic path we need to ensure that we + * match any path that's a subdirectory of a listed entry. In other words if + * /foo/bar is toxic, something in /foo/bar/baz/ is no good. However, we need to + * ensure that we don't mark /foo/barbaz/ as bad. + */ +static int +is_load_toxic(Lm_list *lml, Rt_map *nlmp) +{ + const char *fpath; + size_t flen; + Pdesc *pdp; + Aliste idx; + + fpath = PATHNAME(nlmp); + + /* + * If we have a NULL path name, that indicates that rtld is processing + * an in-memory shared object. For example, trying to run ldd or doing + * an LD_PRELOAD on an object file. In those cases, we'll always allow + * it. + */ + if (fpath == NULL) + return (0); + + flen = strlen(fpath); + + for (ALIST_TRAVERSE(rpl_toxdirs, idx, pdp)) { + if (pdp->pd_plen == 0) + continue; + + if (strncmp(pdp->pd_pname, fpath, pdp->pd_plen) == 0) { + if (pdp->pd_pname[pdp->pd_plen-1] != '/') { + /* + * Path didn't end in a /, make sure + * we're at a directory boundary + * nonetheless. + */ + if (flen > pdp->pd_plen && + fpath[pdp->pd_plen] == '/') + return (1); + continue; + } + return (1); + } + } + + return (0); +} + +/* * Tracing is enabled by the LD_TRACE_LOADED_OPTIONS environment variable which * is normally set from ldd(1). For each link map we load, print the load name * and the full pathname of the associated object. @@ -2169,6 +2221,17 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode, uint_t rdflags; /* + * If this dependency is associated with a toxic path, then we must + * honor the user's request to die. + */ + if (is_load_toxic(lml, nlmp) != 0) { + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TOXIC_FILE), + PATHNAME(nlmp)); + rtldexit(lml, 1); + + } + + /* * If this dependency is associated with a required version ensure that * the version is present in the loaded file. */ diff --git a/usr/src/cmd/sgs/rtld/common/globals.c b/usr/src/cmd/sgs/rtld/common/globals.c index 5f48fafc5f..2e98768551 100644 --- a/usr/src/cmd/sgs/rtld/common/globals.c +++ b/usr/src/cmd/sgs/rtld/common/globals.c @@ -24,6 +24,7 @@ * All Rights Reserved * * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -132,6 +133,8 @@ const char *rpl_ldflags = NULL; /* replaceable LD_FLAGS string */ const char *rpl_libpath = NULL; /* replaceable LD_LIBRARY_PATH string */ Alist *rpl_libdirs = NULL; /* and associated Pdesc list */ const char *rpl_preload = NULL; /* replaceable LD_PRELOAD string */ +const char *rpl_ldtoxic = NULL; /* replaceable LD_TOXIC string */ +Alist *rpl_toxdirs = NULL; /* and associated Pdesc list */ const char *prm_audit = NULL; /* permanent LD_AUDIT string */ const char *prm_debug = NULL; /* permanent LD_DEBUG string */ diff --git a/usr/src/cmd/sgs/rtld/common/rtld.msg b/usr/src/cmd/sgs/rtld/common/rtld.msg index 97e2841b8f..9309d0c62e 100644 --- a/usr/src/cmd/sgs/rtld/common/rtld.msg +++ b/usr/src/cmd/sgs/rtld/common/rtld.msg @@ -21,6 +21,7 @@ # # Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, Joyent, Inc. All rights reserved. # @ _START_ @@ -99,9 +100,14 @@ @ MSG_SYS_MPROT "%s: mprotect failed: %s" @ MSG_SYS_MMAPANON "mmap anon failed: %s" +# Secure path failures + @ MSG_SEC_OPEN "%s: open failed: No such file in secure directories" @ MSG_SEC_ILLEGAL "%s: open failed: illegal insecure pathname" +# Toxic failures + +@ MSG_TOXIC_FILE "%s: dependency marked as toxic" # Configuration failures @@ -395,6 +401,7 @@ @ MSG_LD_PROFILE_OUTPUT "PROFILE_OUTPUT" @ MSG_LD_SFCAP "SFCAP" @ MSG_LD_SIGNAL "SIGNAL" +@ MSG_LD_TOXICPATH "TOXIC_PATH" @ MSG_LD_TRACE_OBJS "TRACE_LOADED_OBJECTS" @ MSG_LD_TRACE_OBJS_E "TRACE_LOADED_OBJECTS_E" @ MSG_LD_TRACE_OBJS_A "TRACE_LOADED_OBJECTS_A" diff --git a/usr/src/cmd/sgs/rtld/common/setup.c b/usr/src/cmd/sgs/rtld/common/setup.c index 862bb7d61f..98e3ba5d33 100644 --- a/usr/src/cmd/sgs/rtld/common/setup.c +++ b/usr/src/cmd/sgs/rtld/common/setup.c @@ -28,7 +28,7 @@ * All Rights Reserved */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ /* @@ -819,6 +819,14 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz, return (0); } + /* + * Initialize our toxic paths + */ + if (rpl_ldtoxic != NULL) { + (void) expand_paths(mlmp, rpl_ldtoxic, &rpl_toxdirs, + AL_CNT_SEARCH, 0, PD_TKN_CAP); + } + #if defined(_ELF64) /* * If this is a 64-bit process, determine whether this process has diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c index 046c8297a0..f10f7a4aed 100644 --- a/usr/src/cmd/sgs/rtld/common/util.c +++ b/usr/src/cmd/sgs/rtld/common/util.c @@ -24,6 +24,7 @@ * All Rights Reserved * * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ /* @@ -1428,6 +1429,7 @@ static u_longlong_t cmdisa = 0; /* command line (-e) ISA */ #define ENV_FLG_CAP_FILES 0x0080000000000ULL #define ENV_FLG_DEFERRED 0x0100000000000ULL #define ENV_FLG_NOENVIRON 0x0200000000000ULL +#define ENV_FLG_TOXICPATH 0x0400000000000ULL #define SEL_REPLACE 0x0001 #define SEL_PERMANT 0x0002 @@ -1601,8 +1603,7 @@ ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags, if ((len == MSG_LD_FLAGS_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_FLAGS), MSG_LD_FLAGS_SIZE) == 0)) { select |= SEL_ACT_SPEC_1; - str = (select & SEL_REPLACE) ? &rpl_ldflags : - &prm_ldflags; + str = &rpl_ldflags; variable = ENV_FLG_FLAGS; } } @@ -1813,6 +1814,8 @@ ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags, * In case an auditor is called, which in turn might exec(2) a * subprocess, this variable is disabled, so that any subprocess * escapes ldd(1) processing. + * + * Also, look for LD_TOXIC_PATH */ else if (*s1 == 'T') { if (((len == MSG_LD_TRACE_OBJS_SIZE) && @@ -1850,7 +1853,13 @@ ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags, select |= SEL_ACT_LML; val = LML_FLG_TRC_SEARCH; variable = ENV_FLG_TRACE_PTHS; + } else if ((len == MSG_LD_TOXICPATH_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_TOXICPATH), MSG_LD_TOXICPATH_SIZE) == 0)) { + select |= SEL_ACT_SPEC_1; + str = &rpl_ldtoxic; + variable = ENV_FLG_TOXICPATH; } + } /* * LD_UNREF and LD_UNUSED (internal, used by ldd(1)). @@ -1974,7 +1983,8 @@ ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags, *lmtflags &= ~val; } else if (select & SEL_ACT_SPEC_1) { /* - * variable is either ENV_FLG_FLAGS or ENV_FLG_LIBPATH + * variable is either ENV_FLG_FLAGS, ENV_FLG_LIBPATH, or + * ENV_FLG_TOXICPATH */ if (env_flags & ENV_TYP_NULL) *str = NULL; diff --git a/usr/src/cmd/sgs/yacc/Makefile.targ b/usr/src/cmd/sgs/yacc/Makefile.targ index 87f8c5221e..e97d36e4ff 100644 --- a/usr/src/cmd/sgs/yacc/Makefile.targ +++ b/usr/src/cmd/sgs/yacc/Makefile.targ @@ -100,4 +100,4 @@ $(LINTPOUT): $(SRCS) $(LINTLIB): $(LINTSRCS) - $(LINT.c) -o $(LIBNAME) $(LINTSRCS) + $(LINT.c) -o $(LIBNAME) $(LINTSRCS) > $(LINTOUT) 2>&1 diff --git a/usr/src/cmd/sgs/yacc/common/dextern.h b/usr/src/cmd/sgs/yacc/common/dextern.h index e90aa60468..54b441cac4 100644 --- a/usr/src/cmd/sgs/yacc/common/dextern.h +++ b/usr/src/cmd/sgs/yacc/common/dextern.h @@ -26,11 +26,13 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #ifndef _DEXTERN_H #define _DEXTERN_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <inttypes.h> #include <ctype.h> @@ -42,6 +44,7 @@ #include <unistd.h> #include <stdlib.h> #include <wctype.h> +#include <limits.h> #ifdef __cplusplus extern "C" { @@ -301,6 +304,12 @@ extern int wscmp(const wchar_t *, const wchar_t *); extern char *parser; +#ifndef PBUFSIZE +#define PBUFSIZE PATH_MAX +#endif + +extern char pbuf[PBUFSIZE]; + /* default settings for a number of macros */ /* name of yacc tempfiles */ @@ -324,7 +333,11 @@ extern char *parser; #endif #ifndef PARSER -#define PARSER "/usr/share/lib/ccs/yaccpar" +#define PARSER "/share/lib/ccs/yaccpar" +#endif + +#ifndef PARSERPREFIX +#define PARSERPREFIX "/usr" #endif /* diff --git a/usr/src/cmd/sgs/yacc/common/y1.c b/usr/src/cmd/sgs/yacc/common/y1.c index 845f82d367..0e67d9047b 100644 --- a/usr/src/cmd/sgs/yacc/common/y1.c +++ b/usr/src/cmd/sgs/yacc/common/y1.c @@ -26,7 +26,9 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #include "dextern.h" #include <sys/param.h> @@ -34,6 +36,7 @@ #include <unistd.h> #include <locale.h> #include <stdarg.h> /* For error() */ +#include <libgen.h> static void mktbls(void); static void others(void); @@ -236,6 +239,25 @@ mktbls() lsetsize = INIT_LSIZE + 1; } +static int +yacc_assemble_path(char *buf, size_t size, const char *file, int type) +{ + int ret; + char origin[PATH_MAX]; + + if (type != 0) { + ret = readlink("/proc/self/path/a.out", origin, PATH_MAX - 1); + if (ret < 0) + error(gettext( + "yacc: failed to read origin from /proc\n")); + origin[ret] = '\0'; + return (snprintf(buf, size, "%s/../%s", dirname(origin), + file)); + } + + return (snprintf(buf, size, "%s/%s", PARSERPREFIX, file)); +} + /* put out other arrays, copy the parsers */ static void others() @@ -244,7 +266,17 @@ others() int c, i, j; int tmpline; - finput = fopen(parser, "r"); + if (parser == NULL) { + parser = pbuf; + (void) yacc_assemble_path(pbuf, PBUFSIZE, PARSER, 1); + finput = fopen(parser, "r"); + if (finput == NULL) { + (void) yacc_assemble_path(pbuf, PBUFSIZE, PARSER, 0); + finput = fopen(parser, "r"); + } + } else { + finput = fopen(parser, "r"); + } if (finput == NULL) /* * TRANSLATION_NOTE -- This is a message from yacc. diff --git a/usr/src/cmd/sgs/yacc/common/y2.c b/usr/src/cmd/sgs/yacc/common/y2.c index 3599d40904..ca8dcc61f5 100644 --- a/usr/src/cmd/sgs/yacc/common/y2.c +++ b/usr/src/cmd/sgs/yacc/common/y2.c @@ -26,7 +26,9 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #include "dextern.h" #include "sgs.h" @@ -60,7 +62,8 @@ char *infile; /* input file name */ static int numbval; /* value of an input number */ static int toksize = NAMESIZE; static wchar_t *tokname; /* input token name */ -char *parser = PARSER; /* location of common parser */ +char *parser = NULL; /* location of common parser */ +char pbuf[PBUFSIZE]; static void finact(void); static wchar_t *cstash(wchar_t *); diff --git a/usr/src/cmd/ssh/Makefile b/usr/src/cmd/ssh/Makefile deleted file mode 100644 index a36a9fb762..0000000000 --- a/usr/src/cmd/ssh/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.cmd - -# libopenbsd-compat and libssh are used by all SSH binaries, and sftp-server is -# also used as an internal part of sshd. -SUBDIRS= \ - etc \ - libopenbsd-compat \ - libssh \ - sftp-server \ - .WAIT \ - ssh \ - sshd \ - scp \ - ssh-add \ - ssh-agent \ - ssh-keygen \ - ssh-keysign \ - ssh-keyscan \ - sftp \ - ssh-http-proxy-connect \ - ssh-socks5-proxy-connect - -MSGFILE=ssh.po -POFILE=_messages.po - -CLOBBERFILES += $(MSGFILE) THIRDPARTYLICENSE - -.KEEP_STATE: - -all := TARGET= all -clean := TARGET= clean -clobber := TARGET= clobber -delete := TARGET= delete -install := TARGET= install -lint := TARGET= lint -catalog := TARGET= catalog -package := TARGET= package -_msg := TARGET= _msg -$(POFILE) := TARGET= $(POFILE) - -all clean install lint $(POFILE): $(SUBDIRS) -clobber: $(SUBDIRS) clobber_local -clobber_local: - $(RM) $(CLOBBERFILES) - -all install: THIRDPARTYLICENSE - -check: $(CHECKHDRS) - -# See Makefile.msg.targ for $(MSGFILE) update instructions -_msg: - $(RM) $(POFILE) - $(TOUCH) $(POFILE) - $(MAKE) $(POFILE) XGETTEXT=/usr/bin/gxgettext - $(CP) $(POFILE) $(MSGFILE) - $(CP) $(MSGFILE) $(MSGDOMAIN) - -$(SUBDIRS): FRC - cd $@; pwd; $(MAKE) $(TARGET) - -# skip the summary; just include the actual license clauses. -THIRDPARTYLICENSE: doc/LICENCE - $(SED) -n '/1)/,$$p' doc/LICENCE > $@ - -FRC: diff --git a/usr/src/cmd/ssh/Makefile.ssh-common b/usr/src/cmd/ssh/Makefile.ssh-common deleted file mode 100644 index 25a9c2560f..0000000000 --- a/usr/src/cmd/ssh/Makefile.ssh-common +++ /dev/null @@ -1,93 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2012 Milan Jurik. All rights reserved. -# -# Common definitions for all of usr/src/cmd/ssh subdirs -# - - -TEXT_DOMAIN=SUNW_OST_OSCMD - -CFLAGS += $(CCVERBOSE) -LDFLAGS += $(MAPFILE.NGB:%=-M%) - -SSH_VERSION=\"Sun_SSH_1.5\" - -C99MODE= $(C99_ENABLE) - -CPPFLAGS = -DSSH_VERSION=$(SSH_VERSION) \ - -I../include -I../../include \ - -D_FILE_OFFSET_BITS=64 \ - -erroff=E_STATEMENT_NOT_REACHED \ - $(CPPFLAGS.master) - -SSH_COMMON_LDLIBS = \ - -L../libssh/$(MACH) -lssh \ - -L../libopenbsd-compat/$(MACH) -lopenbsd-compat - -$(PROG): $(MAPFILE.NGB) - -# -# Some the lint -erroff flags listed below are because of deficiencies in -# lint not because we are hiding real errors or to avoid massive resync- -# hindering changes that will not be returned to OpenSSH. -# -# OpenSSH has several instances of "do {...} while (0);" - a common -# idiom in C macros, but it elicits E_CONSTANT_CONDITION from lint. -# -# The MD5 macros in <openssl/md5.h> trigger E_EXPR_NULL_EFFECT. -# -# Lots of function return values are ignored in OpenSSH. -# -# Lots of globals could be static, sometimes due to portable code paths -# which are dead on Solaris. -# -LINTFLAGS += \ - -erroff=E_FUNC_ARG_UNUSED \ - -erroff=E_NAME_USED_NOT_DEF2 \ - -erroff=E_FUNC_DECL_VAR_ARG2 \ - -erroff=E_INCONS_VAL_TYPE_DECL2 \ - -erroff=E_INCONS_ARG_DECL2 \ - -erroff=E_STATIC_UNUSED \ - -erroff=E_STATEMENT_NOT_REACHED \ - -erroff=E_FUNC_RET_ALWAYS_IGNOR2 \ - -erroff=E_FUNC_RET_MAYBE_IGNORED2 \ - -erroff=E_GLOBAL_COULD_BE_STATIC2 \ - -erroff=E_CONSTANT_CONDITION \ - -erroff=E_EXPR_NULL_EFFECT \ - -erroff=E_STMT_NOT_REACHED \ - -errtags=yes - -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized -CERRWARN += -_gcc=-Wno-unused-function -CERRWARN += -_gcc=-Wno-unused-variable - -ROOTLIBSSH= $(ROOTLIB)/ssh -ROOTLIBSSHPROG= $(PROG:%=$(ROOTLIBSSH)/%) - -POFILE= _messages.po - -$(ROOTLIBSSH)/%: % - $(INS.file) diff --git a/usr/src/cmd/ssh/README.altprivsep b/usr/src/cmd/ssh/README.altprivsep deleted file mode 100644 index f91dbbd2a1..0000000000 --- a/usr/src/cmd/ssh/README.altprivsep +++ /dev/null @@ -1,687 +0,0 @@ - Copyright 2008 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - Sun's Alternative "Privilege Separation" for OpenSSH - - -Table of Contents - -1. Introduction -2. What is "Privilege?" -3. Analysis of the SSH Protocols -3.1. Privileged Resources, Operations, in the SSH Protocols -4. OpenSSH's Privilege Separation -5. SUNWssh's Alternative Privilege Separation -6. Comparison of the OpenSSH and SUNWssh PrivSep Models -7. Future Directions -8. Guide to the AltPrivSep Source Code -A. References - - - - - -1. Introduction - - Implementations of SSH servers require some degree of privilege in - order to function properly. Often such implementations retain such - privilege throughout normal operation even while users are logged - in. This means that vulnerabilities in the implementation of the - protocols can be exploited in such ways as to escalate the privilege - that would normally be accorded to mer-mortal users. - - The OpenSSH team introduced support for "privilege separation" in - the OpenSSH ssh server some years ago to minimize the extent of - extant, undiscovered vulnerabilities in the OpenSSH server source - code. The basic concept is to have a multi-process server - implementation where one process, the "monitor" is privileged and - implements a smaller protocol than the ssh protocols, and thus is, - hopefully, less likely to sport exploitable security bugs. - - The ssh team at Sun agrees with the basic OpenSSH privilege - separation concept, but disagrees with its design. - - Here we present our alternative to the OpenSSH design. We begin - with the question of just what is "privilege" and follow on with an - analysis of the SSH protocols vis-a-vis privilege. Then we briefly - describe the OpenSSH model, followed by an exposition of our - alternative model. - - -2. What is "Privilege?" - - Privilege, in a traditional Unix sense, is that which the "root" - user can do that other users cannot directly do. In Solaris 10 - there is a new approach to this sort of privilege with the aim of - running much of the operating system with the Least Privilege - required; root's privilege is broken down into many privileges and - these are managed through privilege sets. We won't go into the - details of Solaris 10's Least Privilege facility here. - - But privilege is also access to data and resources that can be used - to escalate the privilege of those who have access to them. For - example: secret, or private cryptographic keys used in - authentication. Network security typically requires the use of - cryptographic keys for authentication. - - -3. Analysis of the SSH Protocols - - There are two or, rather three SSH protocols: - - - version 1 - - version 1.5 - - version 2 - - Version 1 and 1.5 are much the same, from our point of view; version - 2 is significantly different from the other two. - - Familiarity by the reader with the specifications for these - protocols is not assumed, but would be beneficial to the reader. - - Quite roughly, these protocols consist of the following: - - a) initial version exchange (for protocol version negotiation) - b) a binary encoding of message data - c) message syntaxes for the protocols' messages - d) specifications on use of cryptography for transport - privacy (encryption) and integrity protection - e) a key exchange protocol (which also authenticates servers to - clients) - f) a protocol for user authentication - g) a session protocol - h) a re-keying protocol (v2-only) - - Some of these parts of the ssh protocols are quite complex, some - quite straightforward. Altogether implementation of the ssh - protocols requires a source code base of significant size. - - The OpenSSH implementation relies on OpenSSL for cryptographic - service, on libz for compression service and miscellaneous other - libraries. Besides these OpenSSH consists of several tens of - thousands of lines of source code in C. - - SUNWssh is based on OpenSSH, so it is comparable in size and - complexity to OpenSSH. - - There is, then, plenty of space for security bugs in the OpenSSH, - and, therefore, also in the SUNWssh source code bases. - - The OpenSSH team designed and implemented a "privilege separation" - feature in their ssh server to reduce the risk that a security bug - in OpenSSH could be successfully exploited and an attacker's - privilege escalated. - - -3.1. Privileged Resources, Operations, in the SSH Protocols - - What privileges does an SSH server need then? - - Observation with Solaris 10's ppriv(1) and truss(1) commands as well - as analysis of the ssh protocols leads to conclude as follows. - - No privilege or privileged resources are needed to implement the - parts (a)-(d) mentioned in section 3. - - - For key exchange and server authentication (e) an ssh server requires: - - - Access to the host's ssh private keys. - - - Access to the host's GSS-API acceptor credentials. [SSHv2-only] - - - An ssh server requires practically all privileges for user - authentication (f) (at least PAM does), particularly - PRIV_PROC_SETID, for logging the user in. - - - Post-authentication an ssh server requires the following privileges: - - - Those required for auditing a user's subsequent logout. - - That is, PRIV_PROC_AUDIT. - - - - Those required for record keeping (i.e., utmpx/wtmpx logging). - - That is, either open file descriptor for those files or - PRIV_FILE_DAC_WRITE or otherwise access to those files, perhaps - through a special user id or group id which would be granted - write access through the ACLs on those files. - - Since SSHv2 allows clients to open many channels with - pseudo-terminals a server may need to open and close utmpx/wtmpx - records multiple times in the lifetime of an SSHv2 connection. - - - - Those required for accessing the host's ssh private keys for - SSHv2 re-keying. [SSHv2-only] - - These keys can be (and are) loaded at server startup time, - requiring PRIV_FILE_DAC_READ, or access through file ACLs, at - that time, but not thence. - - - - Those required for accessing the host's GSS-API acceptor - credentials for SSHv2 re-keying. - - These credentials may require a large set of privileges. The - Solaris 10 Kerberos V GSS-API mechanism, for example, requires - PRIV_FILE_DAC_READ (for access to the system keytab) and - PRIV_FILE_DAC_WRITE (for access to the Kerberos V replay cache). - - - It is worth pointing out that because of a wrinkle in the - specification of the SSHv2 protocol and various implementations, - access to a host's ssh private keys can allow one not only to - impersonate the host as a server (which is, in practice, difficult), - but also to impersonate the host as a client (which is quite easy to - do) using "hostbased" user authentication. - - It is entirely possible to have one-process server implementation - that drops most privileges and access to privileged resources after - user authentication succeeds. Such an implementation would make - some privileges, such as PRIV_PROC_SETID, available to any attacker - that successfully exploited a security bug in the ssh server. - - But such an implementation would also have to retain access to - resources needed for authenticating the server, which, as described - above, can be used to impersonate the server, in some cases with - ease. - - -4. OpenSSH's Privilege Separation - - The OpenSSH privilege separation model is quite complex. - - It consists of a monitor, which retains all privileges and access to - privileged resources, and two processes which run with much less - privilege: one process running as a special user, "sshd," for - hosting all phases of the SSH protocols up to and including - authentication, and one process running as the actual user that logs - in and which hosts all phases of the SSH protocols post-user- - authentication. - - The monitor and its companion processes speak a private protocol - over IPC. This protocol is intended to be smaller and simpler than - the SSH wire protocols. - - In practice the OpenSSH monitor protocols relating to user - authentication are neither smaller nor simpler than the SSH user - authentication protocols; and though they are different they also - transport much the same data, including RSA/DSA signatures, - usernames, PAM conversations, and GSS-API context and MIC tokens. - - The key exchange protocols have been broken down into their - essentials and the monitor serves only services such as signing - server replies with private host keys. - - Note also that the OpenSSH monitor protocol uses the same encodings - as the SSH protocols and uses the same implementation of those - encodings. - - -5. SUNWssh's Alternative Privilege Separation - - The Sun Microsystems ssh team believes that the OpenSSH team has - reached the point of diminishing returns in attempting to separate - processing of the user authentication protocols and that the OpenSSH - approach to privilege separation of the key exchange protocols has - led to a situation in which the monitor acts as an oracle, willing - to sign anything provided by the unprivileged processes that talk to - it. - - The Sun ssh team proposes a somewhat different privilege separation - implementation that shares with the OpenSSH model the goal of - minimizing and simplifying the protocol spoken by the monitor, but - little source code. - - We eschew any temptation to apply the privilege separation concept - to the version negotiation, initial key exchange and user - authentication phases of the ssh protocols (but see section 7). - - Instead we focus on separating processing of auditing, record - keeping and re-keying from processing of the session protocols. We - also wish to avoid creating any oracles in the monitor. - - This approach allows us to have a very simple monitor protocol. Our - monitor protocol consists of the following operations: - - - record a new pseudo-terminal session - - record the end of a pseudo-terminal session - - process a re-key protocol messages - - get keys negotiated during re-keying to the session process to it - can use them - - Logout auditing is done when the session process dies and so does - not require a monitor protocol message. - - By processing all re-key protocol messages in the monitor we prevent - the creation of oracles in the monitor. This is so because the - monitor signs only material which it has generated and over which an - attacker would have little influence (through the attackers offered - DH public key, for example). - - Odds and ends: - - - If the monitor receives SIGHUP, SIGTERM or SIGINT it will call - fatal_cleanup(), and thence will forcibly shutdown(3SOCKET) the - ssh connection socket, causing its child to exit, and audit a - logout. - - - The monitor does not attempt to update utmpx/wtmpx independently - of its child -- it depends on the child asking it to. - - - The child now is unable to chown() ptys back to root. That's Ok, - other services on Solaris do the same and everything still works - because of grantpt(3C). - - - The sshd server process (the one that will become a monitor) - forks a child process before the key exchange starts. The reason - for it is that if we forked after that we would end up using - PKCS#11 sessions initialized in the monitor unless - UseOpenSSLEngine was explicitly set to 'no'. Using any existing - PKCS#11 sessions or object handles over fork is what the PKCS#11 - standard explicitly prohibits. To solve that, we would have to - rekey before fork and then newly initialize the engine in the - child, together with the new crypto contexts initialized with the - keys produced by the key re-exchange. And, that wouldn't help in - situations where the client does not support rekeying which also - includes the whole protocol version 1. The pre-fork solution is - simpler and also much faster. So, the key exchange and - authentication is fully done in the child server process while - the monitor waits aside to read the authentication context that - is needed for further operation. The child drops privileges after - the authentication finishes. - - With the ssh client, the situation is slightly more complicated. - Given the fact that the user can request to go to the background - during the connection using the ~& sequence we must be prepared - to rekey before forking, to reinitialize the engine in the child - after that, and then set the new crypto contexts with the new - keys. If the server we are communicating with does not support - rekeying we will not use the engine at all. We expect this - situation to be extremely rare and will not offer any workaround - for that. This also includes the protocol version 1. However, - this version is already considered obsolete and should not be used - if possible. - -6. Comparison of the OpenSSH and SUNWssh PrivSep Models - - The OpenSSH server involves three processes which we will term - "pre-session," "session" and "monitor." - - The OpenSSH pre-session process implements: - - - the ssh version string exchange - - the ssh message encoding/decoding - - most of the initial key exchange protocols - - transport protection - - part of the user authentication protocols - - The OpenSSH session process implements: - - - the ssh message encoding/decoding - - transport protection - - most of the re-keying protocols - - the session protocols - - The OpenSSH monitor process implements: - - - the ssh message encoding/decoding - - parts of the key exchange and re-key protocols (primarily signing - of server replies with host private keys) - - most of the user authentication protocols, specifically: - - - evaluation of ~/.ssh/authorized_keys (for pubkey userauth) - - evaluation of known hosts files (for hostbased userauth) - - evaluation of .shosts/.rhosts files (for hostbased userauth) - - verification of signatures w/ public keys (pubkey, hostbased) - - PAM API calls, conversation function - - GSS-API calls - - Note that any vulnerabilities in the parsing of authorized_keys, - known hosts and .shosts/rhosts files are as exploitable in the - monitor as in a server w/o privilege separation. - - Similarly for any vulnerabilities in PAM modules and GSS-API - mechanisms. - - The SUNWssh server involves two processes which we will term - "session" and "monitor." - - The SUNWssh monitor process implements: - - - the ssh version string exchange - - the ssh message encoding/decoding - - transport protection - - all of the key exchange and re-key protocols - - all of the user authentication protocols - - The SUNWssh session process implements: - - - the ssh message encoding/decoding - - transport protection - - the session protocols - - Obviously all of these processes also implement their side of the - monitor protocols. - - The OpenSSH 3.5p1 monitor protocol, on Solaris, has approximately 20 - monitor request and corresponding response messages. - - The SUNWssh monitor protocol has 5 monitor request and response - messages; additionally, the monitor processes standard re-key - messages (but note: the monitor and the session process IPC is - completely unencrypted), which amounts to about 14 more messages - altogether. - - Much of the OpenSSH monitor protocol is a variation of the - on-the-wire ssh protocols, with some contents re-packaging. We - believe this does not afford the monitor much additional, if any - protection from attacks in the key exchange and user authentication - protocols. - - The re-packaging that is done in the OpenSSH monitor protocol is - risky business. By separating the act of signing some blob of data - from computing that blob of data one can create an oracle; this is - exactly what happened in the OpenSSH case. - - As you can see in the next section, the SUNWssh privilege separation - could evolve somewhat in the OpenSSH direction by saving the monitor - all transport protection work, but we cannot save the monitor much, - if any work relating to authentication or key exchange. - - -7. Future Directions - - The SUNWssh server privilege separation implementation could stand - several improvements. - - The first improvement would be to have a single system-wide monitor. - This would reduce resource consumption. The work needed to - implement such an enhancement is very similar to the work needed to - produce an SSH API and library, and it is not trivial. If this is - not done then at least dropping PRIV_PROC_SETID and instead setting - the saved-set-user-id in the monitor to that of the logged in user - would be nice. - - The second enhancement would be to add a "none" host key algorithm - to SSHv2 and a corresponding option in SUNWssh to disallow re-keying - with any other host key algorithm. This would allow customers to - configure their server and monitor so that no re-key protocol - messages need be processed by the monitor. - - A third enhancement would be to enhance the GSS-API mechanisms to - require fewer privileges. In practice this means overhauling the - Kerberos V mechanism's replay cache. This would allow the monitor - to run with fewer privileges. - - Further, even without improving the Kerberos V mechanism's replay - cache it should be possible to drop at least PRIV_PROC_FORK/EXEC/ - SESSION. - - A fourth enhancement would to have the unprivileged process handle - all transport protection and proxy to the monitor all key exchange - and user authentication protocol messages. This is a variation on - the OpenSSH model, but without the re-packaging of ssh message - contents seen there. After authentication succeeds the monitor - could either change the unprivileged process' credentials (as can be - done with ppriv(1) or the unprivileged process would, as in OpenSSH, - pass the session keys/IVs/keystate to the monitor which would then - pass them to a new process, the session process, that would then run - as the logged in user. - - -8. Guide to the AltPrivSep Source Code - - - First, a brief introduction to the SUNWssh/OpenSSH source code. - - The source code is organized as follows: - - $SRC/cmd/ssh/etc/ - | - +-> config files - - $SRC/cmd/ssh/include/ - | - +-> header files (note: none are installed/shipped) - - $SRC/cmd/ssh/libopenbsd-compat/common/ - | - +-> misc. portability source code - - $SRC/cmd/ssh/libssh/common/ - | - +-> implementation of encoding, transport protection, - various wrappers around cryptography, the key exchange - and host authentication protocols, the session - protocols, and misc. other code - - cipher.c - mac.c - compress.c - packet.c - | - +-> transport protocol - - buffer.c - bufaux.c - | - +-> encoding - - channels.c - nchan.c - | - +-> session protocol - - kex.c - kexdh.c - kexgex.c - | - +-> key exchange/re-key code common to ssh and sshd - - kexdhs.c - kexgexs.c - kexgsss.c - | - +-> key exchange/re-key code (server only) - - kexdhc.c - kexgexc.c - kexgssc.c - | - +-> key exchange/re-key code (client only) - - dh.c - rsa.c - mpaux.c - ssh-rsa.c - ssh-dss.c - ssh-gss.c - | - +-> crypto wrappers/utilities - - log.c - | - +-> logging, including debug logging, on stderr or - syslog - - - $SRC/cmd/ssh/ssh/ - | - +-> ssh(1) - - $SRC/cmd/ssh/sshd/ - | - +-> sshd(1M), including auditing, implementation of user - authentication and the OpenSSH and SUNWssh monitors - - sshd.c - | - +-> main() - - auth*.c - | - +-> user authentication - - serverloop.c - session.c - | - +-> session protocols - - bsmaudit.[ch] - sshlogin.c - loginrec.c - | - +-> auditing and record-keeping - - $SRC/cmd/ssh/<misc commands>/ - | - +-> scp, sftp, sftp-server, ssh-agent, ssh-add, ... - - - The SUNWssh altprivsep adds two new source files: - - $SRC/cmd/ssh/include/altprivsep.h - $SRC/cmd/ssh/sshd/altprivsep.c - | - +-> monitor start routine, altprivsep_packet_*() routines - for communication with the monitor, routines to help - with key exchanges, service procedures for the monitor, - etc... - - and modifies the following: - - $SRC/cmd/ssh/include/config.h - | - +> adds cpp define "ALTPRIVSEP" - - $SRC/cmd/ssh/include/ssh2.h - | - +-> adds private message type "SSH2_PRIV_MSG_ALTPRIVSEP" (254) - - $SRC/cmd/ssh/include/packet.h - | - +-> adds prototypes for several simple utility functions, - some of which are specifically meant to avoid having to - link altprivsep.c into ssh(1) - - $SRC/cmd/ssh/libssh/common/kex.c - $SRC/cmd/ssh/libssh/common/packet.c - | - +-> implements the hooks needed to proxy re-key messages - to/from the monitor - - $SRC/cmd/ssh/sshd/Makefile - | - +-> adds altprivsep.o to list of objects linked into sshd(1M) - - $SRC/cmd/ssh/sshd/serverloop.c - | - +-> adds an event loop for the monitor - modifies the usual event loops for SSHv2 - - $SRC/cmd/ssh/sshd/session.c - | - +-> modifies do_login() and session_pty_cleanup2() to call - altprivsep_record_login/logout() instead of - record_login/logout(). - - modifies do_exec_pty() so that the server waits for the - call to altprivsep_record_login() in child process to - complete before returning so that the server and the - child processes do not compete for monitor IPC I/O. - - $SRC/cmd/ssh/include/log.h - $SRC/cmd/ssh/libssh/common/log.c - | - +-> adds an internal interface, set_log_txt_prefix() so that - the monitor's debug and log messages get prefixed with a - string ("monitor ") that indicates they are from the - monitor - - $SRC/cmd/ssh/sshd/sshd.c - | - +-> modifies the body of code that follows the user - authentication phase of the ssh protocols so as to start - the monitor and move the relevant code into the monitor - or session processes as appropriate while dropping - privileges and access to privileged resources in the - session process - - The monitor uses the packet.h interfaces to communicate with the - session process as though it were its ssh client peer, but always - uses the "none" cipher, mac and compression algorithms and installs - even handlers only for the relevant key exchange messages and the - private monitor message used for the other monitor services. - - The monitor serves the following services: - - - APS_MSG_NEWKEYS_REQ -> used to obtain keys/IVs after re-keys - - APS_MSG_RECORD_LOGIN -> used to update utmpx/wtmpx - - APS_MSG_RECORD_LOGOUT -> used to update utmpx/wtmpx - - The session and monitor processes communicate over a pipe. - - All monitor IPC I/O from the session process is blocking (though the - pipe is set to non-blocking I/O). The monitor protocol is entirely - synchronous and relies on the re-key protocols being entirely - synchronous also (which they are, unlike the session protocols). - - The kex.c and packet.c files are minimally modified, primarily to - prevent the monitor from handling SSH_MSG_NEWKEYS messages as a - normal ssh server should, instead letting the session process - process SSH_MSG_NEWKEYS messages by requesting the new keys - negotiated with client from the monitor. - - Note that for SSHv1 no on-the-wire messages are processed by the - monitor after authentication. In fact, the monitor thinks it's - running SSHv2, even if the on-the-wire protocol is v1. - - -A. References - - The IETF SECSH Working Group: - - http://www.ietf.org/html.charters/secsh-charter.html - - The SSHv2 architecture, assigned numbers: - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-architecture-16.txt - http://www.ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-06.txt - - New cipher modes for SSHv2: - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-newmodes-02.txt - - The SSHv2 "transport," including initial key exchange and re-key - protocols, but excluding negotiable DH group size and GSS-API-based - key exchange: - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-transport-18.txt - - Additional key exchange protocols for SSHv2: - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-gsskeyex-08.txt - http://www.ietf.org/internet-drafts/draft-ietf-secsh-dh-group-exchange-04.txt - - Base user authentication spec for SSHv2 (includes none, password, - pubkey and hostbased user authentication): - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-userauth-21.txt - - SSHv2 user authentication using PAM-style prompting: - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-auth-kbdinteract-06.txt - - SSHv2 user authentication using the GSS-API: - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-gsskeyex-08.txt - - SSHv2 "session" protocol (i.e., the protocol used for pty sessions, - port forwarding, agent forwarding, X display forwarding, etc...): - - http://www.ietf.org/internet-drafts/draft-ietf-secsh-connect-19.txt diff --git a/usr/src/cmd/ssh/THIRDPARTYLICENSE.descrip b/usr/src/cmd/ssh/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 7e936fffc7..0000000000 --- a/usr/src/cmd/ssh/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -OPENSSH SOFTWARE diff --git a/usr/src/cmd/ssh/doc/COPYING.Ylonen b/usr/src/cmd/ssh/doc/COPYING.Ylonen deleted file mode 100644 index ad17df17a0..0000000000 --- a/usr/src/cmd/ssh/doc/COPYING.Ylonen +++ /dev/null @@ -1,70 +0,0 @@ -This file is part of the ssh software, Copyright (c) 1995 Tatu Ylonen, Finland - - -COPYING POLICY AND OTHER LEGAL ISSUES - -As far as I am concerned, the code I have written for this software -can be used freely for any purpose. Any derived versions of this -software must be clearly marked as such, and if the derived work is -incompatible with the protocol description in the RFC file, it must be -called by a name other than "ssh" or "Secure Shell". - -However, I am not implying to give any licenses to any patents or -copyrights held by third parties, and the software includes parts that -are not under my direct control. As far as I know, all included -source code is used in accordance with the relevant license agreements -and can be used freely for any purpose (the GNU license being the most -restrictive); see below for details. - -[ RSA is no longer included. ] -[ IDEA is no longer included. ] -[ DES is now external. ] -[ GMP is now external. No more GNU licence. ] -[ Zlib is now external. ] -[ The make-ssh-known-hosts script is no longer included. ] -[ TSS has been removed. ] -[ MD5 is now external. ] -[ RC4 support has been removed (RC4 is used internally for arc4random). ] -[ Blowfish is now external. ] - -The 32-bit CRC implementation in crc32.c is due to Gary S. Brown. -Comments in the file indicate it may be used for any purpose without -restrictions. - -The 32-bit CRC compensation attack detector in deattack.c was -contributed by CORE SDI S.A. under a BSD-style license. See -http://www.core-sdi.com/english/ssh/ for details. - -Note that any information and cryptographic algorithms used in this -software are publicly available on the Internet and at any major -bookstore, scientific library, and patent office worldwide. More -information can be found e.g. at "http://www.cs.hut.fi/crypto". - -The legal status of this program is some combination of all these -permissions and restrictions. Use only at your own responsibility. -You will be responsible for any legal consequences yourself; I am not -making any claims whether possessing or using this is legal or not in -your country, and I am not taking any responsibility on your behalf. - - - NO WARRANTY - -BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. diff --git a/usr/src/cmd/ssh/doc/CREDITS b/usr/src/cmd/ssh/doc/CREDITS deleted file mode 100644 index 8831cdd5ac..0000000000 --- a/usr/src/cmd/ssh/doc/CREDITS +++ /dev/null @@ -1,87 +0,0 @@ -Tatu Ylonen <ylo@cs.hut.fi> - Creator of SSH - -Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, -Theo de Raadt, and Dug Song - Creators of OpenSSH - -Alain St-Denis <Alain.St-Denis@ec.gc.ca> - Irix fix -Alexandre Oliva <oliva@lsd.ic.unicamp.br> - AIX fixes -Andre Lucas <andre.lucas@dial.pipex.com> - new login code, many fixes -Andreas Steinmetz <ast@domdv.de> - Shadow password expiry support -Andrew McGill <andrewm@datrix.co.za> - SCO fixes -Andrew Stribblehill <a.d.stribblehill@durham.ac.uk> - Bugfixes -Andy Sloane <andy@guildsoftware.com> - bugfixes -Aran Cox <acox@cv.telegroup.com> - SCO bugfixes -Arkadiusz Miskiewicz <misiek@pld.org.pl> - IPv6 compat fixes -Ben Lindstrom <mouring@pconline.com> - NeXT support -Ben Taylor <bent@clark.net> - Solaris debugging and fixes -Bratislav ILICH <bilic@zepter.ru> - Configure fix -Charles Levert <charles@comm.polymtl.ca> - SunOS 4 & bug fixes -Chip Salzenberg <chip@valinux.com> - Assorted patches -Chris Adams <cmadams@hiwaay.net> - OSF SIA support -Chris Saia <csaia@wtower.com> - SuSE packaging -Chris, the Young One <cky@pobox.com> - Password auth fixes -Christos Zoulas <christos@zoulas.com> - Autoconf fixes -Chun-Chung Chen <cjj@u.washington.edu> - RPM fixes -Corinna Vinschen <vinschen@cygnus.com> - Cygwin support -Dan Brosemer <odin@linuxfreak.com> - Autoconf support, build fixes -Darren Hall <dhall@virage.org> - AIX patches -David Agraz <dagraz@jahoopa.com> - Build fixes -David Del Piero <David.DelPiero@qed.qld.gov.au> - bug fixes -David Hesprich <darkgrue@gue-tech.org> - Configure fixes -David Rankin <drankin@bohemians.lexington.ky.us> - libwrap, AIX, NetBSD fixes -Ed Eden <ede370@stl.rural.usda.gov> - configure fixes -Garrick James <garrick@james.net> - configure fixes -Gary E. Miller <gem@rellim.com> - SCO support -Ged Lodder <lodder@yacc.com.au> - HPUX fixes and enhancements -Gert Doering <gd@hilb1.medat.de> - bug and portability fixes -HARUYAMA Seigo <haruyama@nt.phys.s.u-tokyo.ac.jp> - Translations & doc fixes -Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp> - IPv6 and bug fixes -Hiroshi Takekawa <takekawa@sr3.t.u-tokyo.ac.jp> - Configure fixes -Holger Trapp <Holger.Trapp@Informatik.TU-Chemnitz.DE> - KRB4/AFS config patch -IWAMURO Motonori <iwa@mmp.fujitsu.co.jp> - bugfixes -Jani Hakala <jahakala@cc.jyu.fi> - Patches -Jarno Huuskonen <jhuuskon@hytti.uku.fi> - Bugfixes -Jim Knoble <jmknoble@pobox.com> - Many patches -Jonchen (email unknown) - the original author of PAM support of SSH -Juergen Keil <jk@tools.de> - scp bugfixing -KAMAHARA Junzo <kamahara@cc.kshosen.ac.jp> - Configure fixes -Kees Cook <cook@cpoint.net> - scp fixes -Kenji Miyake <kenji@miyake.org> - Configure fixes -Kevin O'Connor <kevin_oconnor@standardandpoors.com> - RSAless operation -Kevin Steves <stevesk@sweden.hp.com> - HP support, bugfixes, improvements -Kiyokazu SUTO <suto@ks-and-ks.ne.jp> - Bugfixes -Larry Jones <larry.jones@sdrc.com> - Bugfixes -Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> - Bugfixes -Marc G. Fournier <marc.fournier@acadiau.ca> - Solaris patches -Martin Johansson <fatbob@acc.umu.se> - Linux fixes -Mark Miller <markm@swoon.net> - Bugfixes -Matt Richards <v2matt@btv.ibm.com> - AIX patches -Michael Stone <mstone@cs.loyola.edu> - Irix enhancements -Nakaji Hiroyuki <nakaji@tutrp.tut.ac.jp> - Sony News-OS patch -Nalin Dahyabhai <nalin.dahyabhai@pobox.com> - PAM environment patch -Nate Itkin <nitkin@europa.com> - SunOS 4.1.x fixes -Niels Kristian Bech Jensen <nkbj@image.dk> - Assorted patches -Pavel Kankovsky <peak@argo.troja.mff.cuni.cz> - Security fixes -Pavel Troller <patrol@omni.sinus.cz> - Bugfixes -Pekka Savola <pekkas@netcore.fi> - Bugfixes -Peter Kocks <peter.kocks@baygate.com> - Makefile fixes -Phil Hands <phil@hands.com> - Debian scripts, assorted patches -Phil Karn <karn@ka9q.ampr.org> - Autoconf fixes -Philippe WILLEM <Philippe.WILLEM@urssaf.fr> - Bugfixes -Phill Camp <P.S.S.Camp@ukc.ac.uk> - login code fix -Rip Loomis <loomisg@cist.saic.com> - Solaris package support, fixes -SAKAI Kiyotaka <ksakai@kso.netwk.ntt-at.co.jp> - Multiple bugfixes -Simon Wilkinson <sxw@dcs.ed.ac.uk> - PAM fixes -Svante Signell <svante.signell@telia.com> - Bugfixes -Thomas Neumann <tom@smart.ruhr.de> - Shadow passwords -Tim Rice <tim@multitalents.net> - Portability & SCO fixes -Tobias Oetiker <oetiker@ee.ethz.ch> - Bugfixes -Tom Bertelson's <tbert@abac.com> - AIX auth fixes -Tor-Ake Fransson <torake@hotmail.com> - AIX support -Tudor Bosman <tudorb@jm.nu> - MD5 password support -Udo Schweigert <ust@cert.siemens.de> - ReliantUNIX support -Zack Weinberg <zack@wolery.cumb.org> - GNOME askpass enhancement - -Apologies to anyone I have missed. - -Damien Miller <djm@mindrot.org> diff --git a/usr/src/cmd/ssh/doc/ChangeLog b/usr/src/cmd/ssh/doc/ChangeLog deleted file mode 100644 index 7333c81a3e..0000000000 --- a/usr/src/cmd/ssh/doc/ChangeLog +++ /dev/null @@ -1,2590 +0,0 @@ -20001106 - - (djm) Use Jim's new 1.0.3 askpass in Redhat RPMs - - (djm) Manually fix up missed diff hunks (mainly RCS idents) - - (djm) Remove UPGRADING document in favour of a link to the better - maintained FAQ on www.openssh.com - - (djm) Fix multiple dependancy on gnome-libs from Pekka Savola - <pekkas@netcore.fi> - - (djm) Don't need X11-askpass in RPM spec file if building without it - from Pekka Savola <pekkas@netcore.fi> - - (djm) Release 2.3.0p1 - -20001105 - - (bal) Sync with OpenBSD: - - markus@cvs.openbsd.org 2000/10/31 9:31:58 - [compat.c] - handle all old openssh versions - - markus@cvs.openbsd.org 2000/10/31 13:1853 - [deattack.c] - so that large packets do not wrap "n"; from netbsd - - (bal) rijndel.c - fix up RCSID to match OpenBSD tree - - (bal) auth2-skey.c - Checked in. Missing from portable tree. - - (bal) Reworked NEWS-OS and NeXT ports to extract waitpid() and - setsid() into more common files - - (stevesk) pty.c: use __hpux to identify HP-UX. - - (bal) Missed auth-skey.o in Makefile.in and minor correction to - bsd-waitpid.c - -20001029 - - (stevesk) Fix typo in auth.c: USE_PAM not PAM - - (stevesk) Create contrib/cygwin/ directory; patch from - Corinna Vinschen <vinschen@redhat.com> - - (bal) Resolved more $xno and $xyes issues in configure.in - - (bal) next-posix.h - spelling and forgot a prototype - -20001028 - - (djm) fix select hack in serverloop.c from Philippe WILLEM - <Philippe.WILLEM@urssaf.fr> - - (djm) Fix mangled AIXAUTHENTICATE code - - (djm) authctxt->pw may be NULL. Fix from Markus Friedl - <markus.friedl@informatik.uni-erlangen.de> - - (djm) Sync with OpenBSD: - - markus@cvs.openbsd.org 2000/10/16 15:46:32 - [ssh.1] - fixes from pekkas@netcore.fi - - markus@cvs.openbsd.org 2000/10/17 14:28:11 - [atomicio.c] - return number of characters processed; ok deraadt@ - - markus@cvs.openbsd.org 2000/10/18 12:04:02 - [atomicio.c] - undo - - markus@cvs.openbsd.org 2000/10/18 12:23:02 - [scp.c] - replace atomicio(read,...) with read(); ok deraadt@ - - markus@cvs.openbsd.org 2000/10/18 12:42:00 - [session.c] - restore old record login behaviour - - deraadt@cvs.openbsd.org 2000/10/19 10:41:13 - [auth-skey.c] - fmt string problem in unused code - - provos@cvs.openbsd.org 2000/10/19 10:45:16 - [sshconnect2.c] - don't reference freed memory. okay deraadt@ - - markus@cvs.openbsd.org 2000/10/21 11:04:23 - [canohost.c] - typo, eramore@era-t.ericsson.se; ok niels@ - - markus@cvs.openbsd.org 2000/10/23 13:31:55 - [cipher.c] - non-alignment dependent swap_bytes(); from - simonb@wasabisystems.com/netbsd - - markus@cvs.openbsd.org 2000/10/26 12:38:28 - [compat.c] - add older vandyke products - - markus@cvs.openbsd.org 2000/10/27 01:32:19 - [channels.c channels.h clientloop.c serverloop.c session.c] - [ssh.c util.c] - enable non-blocking IO on channels, and tty's (except for the - client ttys). - -20001027 - - (djm) Increase REKEY_BYTES to 2^24 for arc4random - -20001025 - - (djm) Added WARNING.RNG file and modified configure to ask users of the - builtin entropy code to read it. - - (djm) Prefer builtin regex to PCRE. - - (bal) Added USE_PIPS defined to NeXT configure.in since scp hangs randomly. - - (bal) Apply fixes to configure.in pointed out by Pavel Roskin - <proski@gnu.org> - -20001020 - - (djm) Don't define _REENTRANT for SNI/Reliant Unix - - (bal) Imported NEWS-OS waitpid() macros into NeXT. Since implementation - is more correct then current version. - -20001018 - - (stevesk) Add initial support for setproctitle(). Current - support is for the HP-UX pstat(PSTAT_SETCMD, ...) method. - - (stevesk) Add egd startup scripts to contrib/hpux/ - -20001017 - - (djm) Add -lregex to cywin libs from Corinna Vinschen - <vinschen@cygnus.com> - - (djm) Don't rely on atomicio's retval to determine length of askpass - supplied passphrase. Problem report from Lutz Jaenicke - <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - (bal) Changed from GNU rx to PCRE on suggestion from djm. - - (bal) Integrated Sony NEWS-OS patches from NAKAJI Hirouyuki - <nakaji@tutrp.tut.ac.jp> - -20001016 - - (djm) Sync with OpenBSD: - - markus@cvs.openbsd.org 2000/10/14 04:01:15 - [cipher.c] - debug3 - - markus@cvs.openbsd.org 2000/10/14 04:07:23 - [scp.c] - remove spaces from arguments; from djm@mindrot.org - - markus@cvs.openbsd.org 2000/10/14 06:09:46 - [ssh.1] - Cipher is for SSH-1 only - - markus@cvs.openbsd.org 2000/10/14 06:12:09 - [servconf.c servconf.h serverloop.c session.c sshd.8] - AllowTcpForwarding; from naddy@ - - markus@cvs.openbsd.org 2000/10/14 06:16:56 - [auth2.c compat.c compat.h sshconnect2.c version.h] - OpenSSH_2.3; note that is is not complete, but the version number - needs to be changed for interoperability reasons - - markus@cvs.openbsd.org 2000/10/14 06:19:45 - [auth-rsa.c] - do not send RSA challenge if key is not allowed by key-options; from - eivind@ThinkSec.com - - markus@cvs.openbsd.org 2000/10/15 08:14:01 - [rijndael.c session.c] - typos; from stevesk@sweden.hp.com - - markus@cvs.openbsd.org 2000/10/15 08:18:31 - [rijndael.c] - typo - - (djm) Copy manpages back over from OpenBSD - too tedious to wade - through diffs - - (djm) Added condrestart to Redhat init script. Patch from Pekka Savola - <pekkas@netcore.fi> - - (djm) Update version in Redhat spec file - - (djm) Merge some of Nalin Dahyabhai <nalin@redhat.com> changes from the - Redhat 7.0 spec file - - (djm) Make inability to read/write PRNG seedfile non-fatal - - -20001015 - - (djm) Fix ssh2 hang on background processes at logout. - -20001014 - - (bal) Add support for realpath and getcwd for platforms with broken - or missing realpath implementations for sftp-server. - - (bal) Corrected mistake in INSTALL in regards to GNU rx library - - (bal) Add support for GNU rx library for those lacking regexp support - - (djm) Don't accept PAM_PROMPT_ECHO_ON messages during initial auth - - (djm) Revert SSH2 serverloop hack, will find a better way. - - (djm) Add workaround for Linux 2.4's gratuitious errno change. Patch - from Martin Johansson <fatbob@acc.umu.se> - - (djm) Big OpenBSD sync: - - markus@cvs.openbsd.org 2000/09/30 10:27:44 - [log.c] - allow loglevel debug - - markus@cvs.openbsd.org 2000/10/03 11:59:57 - [packet.c] - hmac->mac - - markus@cvs.openbsd.org 2000/10/03 12:03:03 - [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] - move fake-auth from auth1.c to individual auth methods, disables s/key in - debug-msg - - markus@cvs.openbsd.org 2000/10/03 12:16:48 - ssh.c - do not resolve canonname, i have no idea why this was added oin ossh - - markus@cvs.openbsd.org 2000/10/09 15:30:44 - ssh-keygen.1 ssh-keygen.c - -X now reads private ssh.com DSA keys, too. - - markus@cvs.openbsd.org 2000/10/09 15:32:34 - auth-options.c - clear options on every call. - - markus@cvs.openbsd.org 2000/10/09 15:51:00 - authfd.c authfd.h - interop with ssh-agent2, from <res@shore.net> - - markus@cvs.openbsd.org 2000/10/10 14:20:45 - compat.c - use rexexp for version string matching - - provos@cvs.openbsd.org 2000/10/10 22:02:18 - [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] - First rough implementation of the diffie-hellman group exchange. The - client can ask the server for bigger groups to perform the diffie-hellman - in, thus increasing the attack complexity when using ciphers with longer - keys. University of Windsor provided network, T the company. - - markus@cvs.openbsd.org 2000/10/11 13:59:52 - [auth-rsa.c auth2.c] - clear auth options unless auth sucessfull - - markus@cvs.openbsd.org 2000/10/11 14:00:27 - [auth-options.h] - clear auth options unless auth sucessfull - - markus@cvs.openbsd.org 2000/10/11 14:03:27 - [scp.1 scp.c] - support 'scp -o' with help from mouring@pconline.com - - markus@cvs.openbsd.org 2000/10/11 14:11:35 - [dh.c] - Wall - - markus@cvs.openbsd.org 2000/10/11 14:14:40 - [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] - [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] - add support for s/key (kbd-interactive) to ssh2, based on work by - mkiernan@avantgo.com and me - - markus@cvs.openbsd.org 2000/10/11 14:27:24 - [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] - [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] - [sshconnect2.c sshd.c] - new cipher framework - - markus@cvs.openbsd.org 2000/10/11 14:45:21 - [cipher.c] - remove DES - - markus@cvs.openbsd.org 2000/10/12 03:59:20 - [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] - enable DES in SSH-1 clients only - - markus@cvs.openbsd.org 2000/10/12 08:21:13 - [kex.h packet.c] - remove unused - - markus@cvs.openbsd.org 2000/10/13 12:34:46 - [sshd.c] - Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - - markus@cvs.openbsd.org 2000/10/13 12:59:15 - [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] - rijndael/aes support - - markus@cvs.openbsd.org 2000/10/13 13:10:54 - [sshd.8] - more info about -V - - markus@cvs.openbsd.org 2000/10/13 13:12:02 - [myproposal.h] - prefer no compression - - (djm) Fix scp user@host handling - - (djm) Don't clobber ssh_prng_cmds on install - - (stevesk) Include config.h in rijndael.c so we define intXX_t and - u_intXX_t types on all platforms. - - (stevesk) rijndael.c: cleanup missing declaration warnings. - - (stevesk) ~/.hushlogin shouldn't cause required password change to - be bypassed. - - (stevesk) Display correct path to ssh-askpass in configure output. - Report from Lutz Jaenicke. - -20001007 - - (stevesk) Print PAM return value in PAM log messages to aid - with debugging. - - (stevesk) Fix detection of pw_class struct member in configure; - patch from KAMAHARA Junzo <kamahara@cc.kshosen.ac.jp> - -20001002 - - (djm) Fix USER_PATH, report from Kevin Steves <stevesk@sweden.hp.com> - - (djm) Add host system and CC to end-of-configure report. Suggested by - Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> - -20000931 - - (djm) Cygwin fixes from Corinna Vinschen <vinschen@cygnus.com> - -20000930 - - (djm) Irix ssh_prng_cmds path fix from Pekka Savola <pekkas@netcore.fi> - - (djm) Support in bsd-snprintf.c for long long conversions from - Ben Lindstrom <mouring@pconline.com> - - (djm) Cleanup NeXT support from Ben Lindstrom <mouring@pconline.com> - - (djm) Ignore SIGPIPEs from serverloop to child. Fixes crashes with - very short lived X connections. Bug report from Tobias Oetiker - <oetiker@ee.ethz.ch>. Fix from Markus Friedl <markus@cvs.openbsd.org> - - (djm) Add recent InitScripts as a RPM dependancy for openssh-server - patch from Pekka Savola <pekkas@netcore.fi> - - (djm) Forgot to cvs add LICENSE file - - (djm) Add LICENSE to RPM spec files - - (djm) CVS OpenBSD sync: - - markus@cvs.openbsd.org 2000/09/26 13:59:59 - [clientloop.c] - use debug2 - - markus@cvs.openbsd.org 2000/09/27 15:41:34 - [auth2.c sshconnect2.c] - use key_type() - - markus@cvs.openbsd.org 2000/09/28 12:03:18 - [channels.c] - debug -> debug2 cleanup - - (djm) Irix strips "/dev/tty" from [uw]tmp entries (other systems only - strip "/dev/"). Fix loginrec.c based on patch from Alain St-Denis - <Alain.St-Denis@ec.gc.ca> - - (djm) Fix 9 character passphrase failure with gnome-ssh-askpass. - Problem was caused by interrupted read in ssh-add. Report from Donald - J. Barry <don@astro.cornell.edu> - -20000929 - - (djm) Fix SSH2 not terminating until all background tasks done problem. - - (djm) Another off-by-one fix from Pavel Kankovsky - <peak@argo.troja.mff.cuni.cz> - - (djm) Clean up. Strip some unnecessary differences with OpenBSD's code, - tidy necessary differences. Use Markus' new debugN() in entropy.c - - (djm) Merged big SCO portability patch from Tim Rice - <tim@multitalents.net> - -20000926 - - (djm) Update X11-askpass to 1.0.2 in RPM spec file - - (djm) Define _REENTRANT to pickup strtok_r() on HP/UX - - (djm) Security: fix off-by-one buffer overrun in fake-getnameinfo.c. - Report and fix from Pavel Kankovsky <peak@argo.troja.mff.cuni.cz> - -20000924 - - (djm) Merged cleanup patch from Mark Miller <markm@swoon.net> - - (djm) A bit more cleanup - created cygwin_util.h - - (djm) Include strtok_r() from OpenBSD libc. Fixes report from Mark Miller - <markm@swoon.net> - -20000923 - - (djm) Fix address logging in utmp from Kevin Steves - <stevesk@sweden.hp.com> - - (djm) Redhat spec and manpage fixes from Pekka Savola <pekkas@netcore.fi> - - (djm) Seperate tests for int64_t and u_int64_t types - - (djm) Tweak password expiry checking at suggestion of Kevin Steves - <stevesk@sweden.hp.com> - - (djm) NeXT patch from Ben Lindstrom <mouring@pconline.com> - - (djm) Use printf %lld instead of %qd in sftp-server.c. Fix from - Michael Stone <mstone@cs.loyola.edu> - - (djm) OpenBSD CVS sync: - - markus@cvs.openbsd.org 2000/09/17 09:38:59 - [sshconnect2.c sshd.c] - fix DEBUG_KEXDH - - markus@cvs.openbsd.org 2000/09/17 09:52:51 - [sshconnect.c] - yes no; ok niels@ - - markus@cvs.openbsd.org 2000/09/21 04:55:11 - [sshd.8] - typo - - markus@cvs.openbsd.org 2000/09/21 05:03:54 - [serverloop.c] - typo - - markus@cvs.openbsd.org 2000/09/21 05:11:42 - scp.c - utime() to utimes(); mouring@pconline.com - - markus@cvs.openbsd.org 2000/09/21 05:25:08 - sshconnect2.c - change login logic in ssh2, allows plugin of other auth methods - - markus@cvs.openbsd.org 2000/09/21 05:25:35 - [auth2.c channels.c channels.h clientloop.c dispatch.c dispatch.h] - [serverloop.c] - add context to dispatch_run - - markus@cvs.openbsd.org 2000/09/21 05:07:52 - authfd.c authfd.h ssh-agent.c - bug compat for old ssh.com software - -20000920 - - (djm) Fix bad path substitution. Report from Andrew Miner - <asminer@cs.iastate.edu> - -20000916 - - (djm) Fix SSL search order from Lutz Jaenicke - <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - (djm) New SuSE spec from Corinna Vinschen <corinna@vinschen.de> - - (djm) Update CygWin support from Corinna Vinschen <vinschen@cygnus.com> - - (djm) Use a real struct sockaddr inside the fake struct sockaddr_storage. - Patch from Larry Jones <larry.jones@sdrc.com> - - (djm) Add Steve VanDevender's <stevev@darkwing.uoregon.edu> PAM - password change patch. - - (djm) Bring licenses on my stuff in line with OpenBSD's - - (djm) Cleanup auth-passwd.c and unify HP/UX authentication. Patch from - Kevin Steves <stevesk@sweden.hp.com> - - (djm) Shadow expiry check fix from Pavel Troller <patrol@omni.sinus.cz> - - (djm) Re-enable int64_t types - we need them for sftp - - (djm) Use libexecdir from configure , rather than libexecdir/ssh - - (djm) Update Redhat SPEC file accordingly - - (djm) Add Kevin Steves <stevesk@sweden.hp.com> HP/UX contrib files - - (djm) Add Charles Levert <charles@comm.polymtl.ca> getpgrp patch - - (djm) Fix password auth on HP/UX 10.20. Patch from Dirk De Wachter - <Dirk.DeWachter@rug.ac.be> - - (djm) Fixprogs and entropy list fixes from Larry Jones - <larry.jones@sdrc.com> - - (djm) Fix for SuSE spec file from Takashi YOSHIDA - <tyoshida@gemini.rc.kyushu-u.ac.jp> - - (djm) Merge OpenBSD changes: - - markus@cvs.openbsd.org 2000/09/05 02:59:57 - [session.c] - print hostname (not hushlogin) - - markus@cvs.openbsd.org 2000/09/05 13:18:48 - [authfile.c ssh-add.c] - enable ssh-add -d for DSA keys - - markus@cvs.openbsd.org 2000/09/05 13:20:49 - [sftp-server.c] - cleanup - - markus@cvs.openbsd.org 2000/09/06 03:46:41 - [authfile.h] - prototype - - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 - [ALL] - cleanup copyright notices on all files. I have attempted to be - accurate with the details. everything is now under Tatu's licence - (which I copied from his readme), and/or the core-sdi bsd-ish thing - for deattack, or various openbsd developers under a 2-term bsd - licence. We're not changing any rules, just being accurate. - - markus@cvs.openbsd.org 2000/09/07 14:40:30 - [channels.c channels.h clientloop.c serverloop.c ssh.c] - cleanup window and packet sizes for ssh2 flow control; ok niels - - markus@cvs.openbsd.org 2000/09/07 14:53:00 - [scp.c] - typo - - markus@cvs.openbsd.org 2000/09/07 15:13:37 - [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] - [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] - [pty.c readconf.c] - some more Copyright fixes - - markus@cvs.openbsd.org 2000/09/08 03:02:51 - [README.openssh2] - bye bye - - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 - [LICENCE cipher.c] - a few more comments about it being ARC4 not RC4 - - markus@cvs.openbsd.org 2000/09/12 14:53:11 - [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] - multiple debug levels - - markus@cvs.openbsd.org 2000/09/14 14:25:15 - [clientloop.c] - typo - - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 - [ssh-agent.c] - check return value for setenv(3) for failure, and deal appropriately - -20000913 - - (djm) Fix server not exiting with jobs in background. - -20000905 - - (djm) Import OpenBSD CVS changes - - markus@cvs.openbsd.org 2000/08/31 15:52:24 - [Makefile sshd.8 sshd_config sftp-server.8 sftp-server.c] - implement a SFTP server. interops with sftp2, scp2 and the windows - client from ssh.com - - markus@cvs.openbsd.org 2000/08/31 15:56:03 - [README.openssh2] - sync - - markus@cvs.openbsd.org 2000/08/31 16:05:42 - [session.c] - Wall - - markus@cvs.openbsd.org 2000/08/31 16:09:34 - [authfd.c ssh-agent.c] - add a flag to SSH2_AGENTC_SIGN_REQUEST for future extensions - - deraadt@cvs.openbsd.org 2000/09/01 09:25:13 - [scp.1 scp.c] - cleanup and fix -S support; stevesk@sweden.hp.com - - markus@cvs.openbsd.org 2000/09/01 16:29:32 - [sftp-server.c] - portability fixes - - markus@cvs.openbsd.org 2000/09/01 16:32:41 - [sftp-server.c] - fix cast; mouring@pconline.com - - itojun@cvs.openbsd.org 2000/09/03 09:23:28 - [ssh-add.1 ssh.1] - add missing .El against .Bl. - - markus@cvs.openbsd.org 2000/09/04 13:03:41 - [session.c] - missing close; ok theo - - markus@cvs.openbsd.org 2000/09/04 13:07:21 - [session.c] - fix get_last_login_time order; from andre@van-veen.de - - markus@cvs.openbsd.org 2000/09/04 13:10:09 - [sftp-server.c] - more cast fixes; from mouring@pconline.com - - markus@cvs.openbsd.org 2000/09/04 13:06:04 - [session.c] - set SSH_ORIGINAL_COMMAND; from Leakin@dfw.nostrum.com, bet@rahul.net - - (djm) Cleanup after import. Fix sftp-server compilation, Makefile - - (djm) Merge cygwin support from Corinna Vinschen <vinschen@cygnus.com> - -20000903 - - (djm) Fix Redhat init script - -20000901 - - (djm) Pick up Jim's new X11-askpass - - (djm) Release 2.2.0p1 - -20000831 - - (djm) Workaround SIGPIPE problems on SCO. Fix from Aran Cox - <acox@cv.telegroup.com> - - (djm) Pick up new version (2.2.0) from OpenBSD CVS - -20000830 - - (djm) Compile warning fixes from Mark Miller <markm@swoon.net> - - (djm) Periodically rekey arc4random - - (djm) Clean up diff against OpenBSD. - - (djm) HPUX 11 needs USE_PIPES as well: Kevin Steves - <stevesk@sweden.hp.com> - - (djm) Quieten the pam delete credentials error message - - (djm) Fix printing of $DISPLAY hack if set by system type. Report from - Kevin Steves <stevesk@sweden.hp.com> - - (djm) NeXT patch from Ben Lindstrom <mouring@pconline.com> - - (djm) Fix doh in bsd-arc4random.c - -20000829 - - (djm) Fix ^C ignored issue on Solaris. Diagnosis from Gert - Doering <gert@greenie.muc.de>, John Horne <J.Horne@plymouth.ac.uk> and - Garrick James <garrick@james.net> - - (djm) Check for SCO pty naming style (ptyp%d/ttyp%d). Based on fix from - Bastian Trompetter <btrompetter@firemail.de> - - (djm) NeXT tweaks from Ben Lindstrom <mouring@pconline.com> - - More OpenBSD updates: - - deraadt@cvs.openbsd.org 2000/08/24 15:46:59 - [scp.c] - off_t in sink, to fix files > 2GB, i think, test is still running ;-) - - deraadt@cvs.openbsd.org 2000/08/25 10:10:06 - [session.c] - Wall - - markus@cvs.openbsd.org 2000/08/26 04:33:43 - [compat.c] - ssh.com-2.3.0 - - markus@cvs.openbsd.org 2000/08/27 12:18:05 - [compat.c] - compatibility with future ssh.com versions - - deraadt@cvs.openbsd.org 2000/08/27 21:50:55 - [auth-krb4.c session.c ssh-add.c sshconnect.c uidswap.c] - print uid/gid as unsigned - - markus@cvs.openbsd.org 2000/08/28 13:51:00 - [ssh.c] - enable -n and -f for ssh2 - - markus@cvs.openbsd.org 2000/08/28 14:19:53 - [ssh.c] - allow combination of -N and -f - - markus@cvs.openbsd.org 2000/08/28 14:20:56 - [util.c] - util.c - - markus@cvs.openbsd.org 2000/08/28 14:22:02 - [util.c] - undo - - markus@cvs.openbsd.org 2000/08/28 14:23:38 - [util.c] - don't complain if setting NONBLOCK fails with ENODEV - -20000823 - - (djm) Define USE_PIPES to avoid socketpair problems on HPUX 10 and SunOS 4 - Avoids "scp never exits" problem. Reports from Lutz Jaenicke - <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA - <kajiyama@grad.sccs.chukyo-u.ac.jp> - - (djm) Pick up LOGIN_PROGRAM from environment or PATH if not set by headers - - (djm) Add local version to version.h - - (djm) Don't reseed arc4random everytime it is used - - (djm) OpenBSD CVS updates: - - deraadt@cvs.openbsd.org 2000/08/18 20:07:23 - [ssh.c] - accept remsh as a valid name as well; roman@buildpoint.com - - deraadt@cvs.openbsd.org 2000/08/18 20:17:13 - [deattack.c crc32.c packet.c] - rename crc32() to ssh_crc32() to avoid zlib name clash. do not move to - libz crc32 function yet, because it has ugly "long"'s in it; - oneill@cs.sfu.ca - - deraadt@cvs.openbsd.org 2000/08/18 20:26:08 - [scp.1 scp.c] - -S prog support; tv@debian.org - - deraadt@cvs.openbsd.org 2000/08/18 20:50:07 - [scp.c] - knf - - deraadt@cvs.openbsd.org 2000/08/18 20:57:33 - [log-client.c] - shorten - - markus@cvs.openbsd.org 2000/08/19 12:48:11 - [channels.c channels.h clientloop.c ssh.c ssh.h] - support for ~. in ssh2 - - deraadt@cvs.openbsd.org 2000/08/19 15:29:40 - [crc32.h] - proper prototype - - markus@cvs.openbsd.org 2000/08/19 15:34:44 - [authfd.c authfd.h key.c key.h ssh-add.1 ssh-add.c ssh-agent.1] - [ssh-agent.c ssh-keygen.c sshconnect1.c sshconnect2.c Makefile] - [fingerprint.c fingerprint.h] - add SSH2/DSA support to the agent and some other DSA related cleanups. - (note that we cannot talk to ssh.com's ssh2 agents) - - markus@cvs.openbsd.org 2000/08/19 15:55:52 - [channels.c channels.h clientloop.c] - more ~ support for ssh2 - - markus@cvs.openbsd.org 2000/08/19 16:21:19 - [clientloop.c] - oops - - millert@cvs.openbsd.org 2000/08/20 12:25:53 - [session.c] - We have to stash the result of get_remote_name_or_ip() before we - close our socket or getpeername() will get EBADF and the process - will exit. Only a problem for "UseLogin yes". - - millert@cvs.openbsd.org 2000/08/20 12:30:59 - [session.c] - Only check /etc/nologin if "UseLogin no" since login(1) may have its - own policy on determining who is allowed to login when /etc/nologin - is present. Also use the _PATH_NOLOGIN define. - - millert@cvs.openbsd.org 2000/08/20 12:42:43 - [auth1.c auth2.c session.c ssh.c] - Add calls to setusercontext() and login_get*(). We basically call - setusercontext() in most places where previously we did a setlogin(). - Add default login.conf file and put root in the "daemon" login class. - - millert@cvs.openbsd.org 2000/08/21 10:23:31 - [session.c] - Fix incorrect PATH setting; noted by Markus. - -20000818 - - (djm) OpenBSD CVS changes: - - markus@cvs.openbsd.org 2000/07/22 03:14:37 - [servconf.c servconf.h sshd.8 sshd.c sshd_config] - random early drop; ok theo, niels - - deraadt@cvs.openbsd.org 2000/07/26 11:46:51 - [ssh.1] - typo - - deraadt@cvs.openbsd.org 2000/08/01 11:46:11 - [sshd.8] - many fixes from pepper@mail.reppep.com - - provos@cvs.openbsd.org 2000/08/01 13:01:42 - [Makefile.in util.c aux.c] - rename aux.c to util.c to help with cygwin port - - deraadt@cvs.openbsd.org 2000/08/02 00:23:31 - [authfd.c] - correct sun_len; Alexander@Leidinger.net - - provos@cvs.openbsd.org 2000/08/02 10:27:17 - [readconf.c sshd.8] - disable kerberos authentication by default - - provos@cvs.openbsd.org 2000/08/02 11:27:05 - [sshd.8 readconf.c auth-krb4.c] - disallow kerberos authentication if we can't verify the TGT; from - dugsong@ - kerberos authentication is on by default only if you have a srvtab. - - markus@cvs.openbsd.org 2000/08/04 14:30:07 - [auth.c] - unused - - markus@cvs.openbsd.org 2000/08/04 14:30:35 - [sshd_config] - MaxStartups - - markus@cvs.openbsd.org 2000/08/15 13:20:46 - [authfd.c] - cleanup; ok niels@ - - markus@cvs.openbsd.org 2000/08/17 14:05:10 - [session.c] - cleanup login(1)-like jobs, no duplicate utmp entries - - markus@cvs.openbsd.org 2000/08/17 14:06:34 - [session.c sshd.8 sshd.c] - sshd -u len, similar to telnetd - - (djm) Lastlog was not getting closed after writing login entry - - (djm) Add Solaris package support from Rip Loomis <loomisg@cist.saic.com> - -20000816 - - (djm) Replacement for inet_ntoa for Irix (which breaks on gcc) - - (djm) Fix strerror replacement for old SunOS. Based on patch from - Charles Levert <charles@comm.polymtl.ca> - - (djm) Seperate arc4random into seperate file and use OpenSSL's RC4 - implementation. - - (djm) SUN_LEN macro for systems which lack it - -20000815 - - (djm) More SunOS 4.1.x fixes from Nate Itkin <nitkin@europa.com> - - (djm) Avoid failures on Irix when ssh is not setuid. Fix from - Michael Stone <mstone@cs.loyola.edu> - - (djm) Don't seek in directory based lastlogs - - (djm) Fix --with-ipaddr-display configure option test. Patch from - Jarno Huuskonen <jhuuskon@messi.uku.fi> - - (djm) Fix AIX limits from Alexandre Oliva <oliva@lsd.ic.unicamp.br> - -20000813 - - (djm) Add $(srcdir) to includes when compiling (for VPATH). Report from - Fabrice bacchella <fabrice.bacchella@marchfirst.fr> - -20000809 - - (djm) Define AIX hard limits if headers don't. Report from - Bill Painter <william.t.painter@lmco.com> - - (djm) utmp direct write & SunOS 4 patch from Charles Levert - <charles@comm.polymtl.ca> - -20000808 - - (djm) Cleanup Redhat RPMs. Generate keys at runtime rather than install - time, spec file cleanup. - -20000807 - - (djm) Set 0755 on binaries during install. Report from Lutz Jaenicke - - (djm) Suppress error messages on channel close shutdown() failurs - works around Linux bug. Patch from Zack Weinberg <zack@wolery.cumb.org> - - (djm) Add some more entropy collection commands from Lutz Jaenicke - -20000725 - - (djm) Fix autoconf typo: HAVE_BINRESVPORT_AF -> HAVE_BINDRESVPORT_AF - -20000721 - - (djm) OpenBSD CVS updates: - - markus@cvs.openbsd.org 2000/07/16 02:27:22 - [authfd.c authfd.h channels.c clientloop.c ssh-add.c ssh-agent.c ssh.c] - [sshconnect1.c sshconnect2.c] - make ssh-add accept dsa keys (the agent does not) - - djm@cvs.openbsd.org 2000/07/17 19:25:02 - [sshd.c] - Another closing of stdin; ok deraadt - - markus@cvs.openbsd.org 2000/07/19 18:33:12 - [dsa.c] - missing free, reorder - - markus@cvs.openbsd.org 2000/07/20 16:23:14 - [ssh-keygen.1] - document input and output files - -20000720 - - (djm) Spec file fix from Petr Novotny <Petr.Novotny@antek.cz> - -20000716 - - (djm) Release 2.1.1p4 - -20000715 - - (djm) OpenBSD CVS updates - - provos@cvs.openbsd.org 2000/07/13 16:53:22 - [aux.c readconf.c servconf.c ssh.h] - allow multiple whitespace but only one '=' between tokens, bug report from - Ralf S. Engelschall <rse@engelschall.com> but different fix. okay deraadt@ - - provos@cvs.openbsd.org 2000/07/13 17:14:09 - [clientloop.c] - typo; todd@fries.net - - provos@cvs.openbsd.org 2000/07/13 17:19:31 - [scp.c] - close can fail on AFS, report error; from Greg Hudson <ghudson@mit.edu> - - markus@cvs.openbsd.org 2000/07/14 16:59:46 - [readconf.c servconf.c] - allow leading whitespace. ok niels - - djm@cvs.openbsd.org 2000/07/14 22:01:38 - [ssh-keygen.c ssh.c] - Always create ~/.ssh with mode 700; ok Markus - - Fixes for SunOS 4.1.4 from Gordon Atwood <gordon@cs.ualberta.ca> - - Include floatingpoint.h for entropy.c - - strerror replacement - -20000712 - - (djm) Remove -lresolve for Reliant Unix - - (djm) OpenBSD CVS Updates: - - deraadt@cvs.openbsd.org 2000/07/11 02:11:34 - [session.c sshd.c ] - make MaxStartups code still work with -d; djm - - deraadt@cvs.openbsd.org 2000/07/11 13:17:45 - [readconf.c ssh_config] - disable FallBackToRsh by default - - (djm) Replace in_addr_t with u_int32_t in bsd-inet_aton.c. Report from - Ben Lindstrom <mouring@pconline.com> - - (djm) Make building of X11-Askpass and GNOME-Askpass optional in RPM - spec file. - - (djm) Released 2.1.1p3 - -20000711 - - (djm) Fixup for AIX getuserattr() support from Tom Bertelson - <tbert@abac.com> - - (djm) ReliantUNIX support from Udo Schweigert <ust@cert.siemens.de> - - (djm) NeXT: dirent structures to get scp working from Ben Lindstrom - <mouring@pconline.com> - - (djm) Fix broken inet_ntoa check and ut_user/ut_name confusion, report - from Jim Watt <jimw@peisj.pebio.com> - - (djm) Replaced bsd-snprintf.c with one from Mutt source tree, it is known - to compile on more platforms (incl NeXT). - - (djm) Added bsd-inet_aton and configure support for NeXT - - (djm) Misc NeXT fixes from Ben Lindstrom <mouring@pconline.com> - - (djm) OpenBSD CVS updates: - - markus@cvs.openbsd.org 2000/06/26 03:22:29 - [authfd.c] - cleanup, less cut&paste - - markus@cvs.openbsd.org 2000/06/26 15:59:19 - [servconf.c servconf.h session.c sshd.8 sshd.c] - MaxStartups: limit number of unauthenticated connections, work by - theo and me - - deraadt@cvs.openbsd.org 2000/07/05 14:18:07 - [session.c] - use no_x11_forwarding_flag correctly; provos ok - - provos@cvs.openbsd.org 2000/07/05 15:35:57 - [sshd.c] - typo - - aaron@cvs.openbsd.org 2000/07/05 22:06:58 - [scp.1 ssh-agent.1 ssh-keygen.1 sshd.8] - Insert more missing .El directives. Our troff really should identify - these and spit out a warning. - - todd@cvs.openbsd.org 2000/07/06 21:55:04 - [auth-rsa.c auth2.c ssh-keygen.c] - clean code is good code - - deraadt@cvs.openbsd.org 2000/07/07 02:14:29 - [serverloop.c] - sense of port forwarding flag test was backwards - - provos@cvs.openbsd.org 2000/07/08 17:17:31 - [compat.c readconf.c] - replace strtok with strsep; from David Young <dyoung@onthejob.net> - - deraadt@cvs.openbsd.org 2000/07/08 19:21:15 - [auth.h] - KNF - - ho@cvs.openbsd.org 2000/07/08 19:27:33 - [compat.c readconf.c] - Better conditions for strsep() ending. - - ho@cvs.openbsd.org 2000/07/10 10:27:05 - [readconf.c] - Get the correct message on errors. (niels@ ok) - - ho@cvs.openbsd.org 2000/07/10 10:30:25 - [cipher.c kex.c servconf.c] - strtok() --> strsep(). (niels@ ok) - - (djm) Fix problem with debug mode and MaxStartups - - (djm) Don't generate host keys when $(DESTDIR) is set (e.g. during RPM - builds) - - (djm) Add strsep function from OpenBSD libc for systems that lack it - -20000709 - - (djm) Only enable PAM_TTY kludge for Linux. Problem report from - Kevin Steves <stevesk@sweden.hp.com> - - (djm) Match prototype and function declaration for rresvport_af. - Problem report from Niklas Edmundsson <nikke@ing.umu.se> - - (djm) Missing $(DESTDIR) on host-key target causing problems with RPM - builds. Problem report from Gregory Leblanc <GLeblanc@cu-portland.edu> - - (djm) Replace ut_name with ut_user. Patch from Jim Watt - <jimw@peisj.pebio.com> - - (djm) Fix pam sprintf fix - - (djm) Cleanup entropy collection code a little more. Split initialisation - from seeding, perform intialisation immediatly at start, be careful with - uids. Based on problem report from Jim Watt <jimw@peisj.pebio.com> - - (djm) More NeXT compatibility from Ben Lindstrom <mouring@pconline.com> - Including sigaction() et al. replacements - - (djm) AIX getuserattr() session initialisation from Tom Bertelson - <tbert@abac.com> - -20000708 - - (djm) Fix bad fprintf format handling in auth-pam.c. Patch from - Aaron Hopkins <aaron@die.net> - - (djm) Fix incorrect configure handling of --with-rsh-path option. Fix from - Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - (djm) Fixed undefined variables for OSF SIA. Report from - Baars, Henk <Hendrik.Baars@nl.origin-it.com> - - (djm) Handle EWOULDBLOCK returns from read() and write() in atomicio.c - Fix from Marquess, Steve Mr JMLFDC <Steve.Marquess@DET.AMEDD.ARMY.MIL> - - (djm) Don't use inet_addr. - -20000702 - - (djm) Fix brace mismatch from Corinna Vinschen <vinschen@cygnus.com> - - (djm) Stop shadow expiry checking from preventing logins with NIS. Based - on fix from HARUYAMA Seigo <haruyama@nt.phys.s.u-tokyo.ac.jp> - - (djm) Use standard OpenSSL functions in auth-skey.c. Patch from - Chris, the Young One <cky@pobox.com> - - (djm) Fix scp progress meter on really wide terminals. Based on patch - from James H. Cloos Jr. <cloos@jhcloos.com> - -20000701 - - (djm) Fix Tru64 SIA problems reported by John P Speno <speno@isc.upenn.edu> - - (djm) Login fixes from Tom Bertelson <tbert@abac.com> - - (djm) Replace "/bin/sh" with _PATH_BSHELL. Report from Corinna Vinschen - <vinschen@cygnus.com> - - (djm) Replace "/usr/bin/login" with LOGIN_PROGRAM - - (djm) Added check for broken snprintf() functions which do not correctly - terminate output string and attempt to use replacement. - - (djm) Released 2.1.1p2 - -20000628 - - (djm) Fixes to lastlog code for Irix - - (djm) Use atomicio in loginrec - - (djm) Patch from Michael Stone <mstone@cs.loyola.edu> to add support for - Irix 6.x array sessions, project id's, and system audit trail id. - - (djm) Added 'distprep' make target to simplify packaging - - (djm) Added patch from Chris Adams <cmadams@hiwaay.net> to add OSF SIA - support. Enable using "USE_SIA=1 ./configure [options]" - -20000627 - - (djm) Fixes to login code - not setting li->uid, cleanups - - (djm) Formatting - -20000626 - - (djm) Better fix to aclocal tests from Garrick James <garrick@james.net> - - (djm) Account expiry support from Andreas Steinmetz <ast@domdv.de> - - (djm) Added password expiry checking (no password change support) - - (djm) Make EGD failures non-fatal if OpenSSL's entropy pool is still OK - based on patch from Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - (djm) Fix fixed EGD code. - - OpenBSD CVS update - - provos@cvs.openbsd.org 2000/06/25 14:17:58 - [channels.c] - correct check for bad channel ids; from Wei Dai <weidai@eskimo.com> - -20000623 - - (djm) Use sa_family_t in prototype for rresvport_af. Patch from - Svante Signell <svante.signell@telia.com> - - (djm) Autoconf logic to define sa_family_t if it is missing - - OpenBSD CVS Updates: - - markus@cvs.openbsd.org 2000/06/22 10:32:27 - [sshd.c] - missing atomicio; report from Steve.Marquess@DET.AMEDD.ARMY.MIL - - djm@cvs.openbsd.org 2000/06/22 17:55:00 - [auth-krb4.c key.c radix.c uuencode.c] - Missing CVS idents; ok markus - -20000622 - - (djm) Automatically generate host key during "make install". Suggested - by Gary E. Miller <gem@rellim.com> - - (djm) Paranoia before kill() system call - - OpenBSD CVS Updates: - - markus@cvs.openbsd.org 2000/06/18 18:50:11 - [auth2.c compat.c compat.h sshconnect2.c] - make userauth+pubkey interop with ssh.com-2.2.0 - - markus@cvs.openbsd.org 2000/06/18 20:56:17 - [dsa.c] - mem leak + be more paranoid in dsa_verify. - - markus@cvs.openbsd.org 2000/06/18 21:29:50 - [key.c] - cleanup fingerprinting, less hardcoded sizes - - markus@cvs.openbsd.org 2000/06/19 19:39:45 - [atomicio.c auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c] - [auth-rsa.c auth-skey.c authfd.c authfd.h authfile.c bufaux.c bufaux.h] - [buffer.c buffer.h canohost.c channels.c channels.h cipher.c cipher.h] - [clientloop.c compat.c compat.h compress.c compress.h crc32.c crc32.h] - [deattack.c dispatch.c dsa.c fingerprint.c fingerprint.h getput.h hmac.c] - [kex.c log-client.c log-server.c login.c match.c mpaux.c mpaux.h nchan.c] - [nchan.h packet.c packet.h pty.c pty.h readconf.c readconf.h readpass.c] - [rsa.c rsa.h scp.c servconf.c servconf.h ssh-add.c ssh-keygen.c ssh.c] - [ssh.h tildexpand.c ttymodes.c ttymodes.h uidswap.c xmalloc.c xmalloc.h] - OpenBSD tag - - markus@cvs.openbsd.org 2000/06/21 10:46:10 - sshconnect2.c missing free; nuke old comment - -20000620 - - (djm) Replace use of '-o' and '-a' logical operators in configure tests - with '||' and '&&'. As suggested by Jim Knoble <jmknoble@pint-stowp.cx> - to fix SCO Unixware problem reported by Gary E. Miller <gem@rellim.com> - - (djm) Typo in loginrec.c - -20000618 - - (djm) Add summary of configure options to end of ./configure run - - (djm) Not all systems define RUSAGE_SELF & RUSAGE_CHILDREN. Report from - Michael Stone <mstone@cs.loyola.edu> - - (djm) rusage is a privileged operation on some Unices (incl. - Solaris 2.5.1). Report from Paul D. Smith <pausmith@nortelnetworks.com> - - (djm) Avoid PAM failures when running without a TTY. Report from - Martin Petrak <petrak@spsknm.schools.sk> - - (djm) Include sys/types.h when including netinet/in.h in configure tests. - Patch from Jun-ichiro itojun Hagino <itojun@iijlab.net> - - (djm) Started merge of Ben Lindstrom's <mouring@pconline.com> NeXT support - - OpenBSD CVS updates: - - deraadt@cvs.openbsd.org 2000/06/17 09:58:46 - [channels.c] - everyone says "nix it" (remove protocol 2 debugging message) - - markus@cvs.openbsd.org 2000/06/17 13:24:34 - [sshconnect.c] - allow extended server banners - - markus@cvs.openbsd.org 2000/06/17 14:30:10 - [sshconnect.c] - missing atomicio, typo - - jakob@cvs.openbsd.org 2000/06/17 16:52:34 - [servconf.c servconf.h session.c sshd.8 sshd_config] - add support for ssh v2 subsystems. ok markus@. - - deraadt@cvs.openbsd.org 2000/06/17 18:57:48 - [readconf.c servconf.c] - include = in WHITESPACE; markus ok - - markus@cvs.openbsd.org 2000/06/17 19:09:10 - [auth2.c] - implement bug compatibility with ssh-2.0.13 pubkey, server side - - markus@cvs.openbsd.org 2000/06/17 21:00:28 - [compat.c] - initial support for ssh.com's 2.2.0 - - markus@cvs.openbsd.org 2000/06/17 21:16:09 - [scp.c] - typo - - markus@cvs.openbsd.org 2000/06/17 22:05:02 - [auth-rsa.c auth2.c serverloop.c session.c auth-options.c auth-options.h] - split auth-rsa option parsing into auth-options - add options support to authorized_keys2 - - markus@cvs.openbsd.org 2000/06/17 22:42:54 - [session.c] - typo - -20000613 - - (djm) Fixes from Andrew McGill <andrewm@datrix.co.za>: - - Platform define for SCO 3.x which breaks on /dev/ptmx - - Detect and try to fix missing MAXPATHLEN - - (djm) Fix short copy in loginrec.c (based on patch from Phill Camp - <P.S.S.Camp@ukc.ac.uk> - -20000612 - - (djm) Glob manpages in RPM spec files to catch compressed files - - (djm) Full license in auth-pam.c - - (djm) Configure fixes from SAKAI Kiyotaka <ksakai@kso.netwk.ntt-at.co.jp> - - (andre) AIX, lastlog, configure fixes from Tom Bertelson <tbert@abac.com>: - - Don't try to retrieve lastlog from wtmp/wtmpx if DISABLE_LASTLOG is - def'd - - Set AIX to use preformatted manpages - -20000610 - - (djm) Minor doc tweaks - - (djm) Fix for configure on bash2 from Jim Knoble <jmknoble@jmknoble.cx> - -20000609 - - (djm) Patch from Kenji Miyake <kenji@miyake.org> to disable utmp usage - (in favour of utmpx) on Solaris 8 - -20000606 - - (djm) Cleanup of entropy.c. Reorganised code, removed second pass through - list of commands (by default). Removed verbose debugging (by default). - - (djm) Increased command entropy estimates and default entropy collection - timeout - - (djm) Remove duplicate headers from loginrec.c - - (djm) Don't add /usr/local/lib to library search path on Irix - - (djm) Fix rsh path in RPMs. Report from Jason L Tibbitts III - <tibbs@math.uh.edu> - - (djm) Warn user if grabs fail in GNOME askpass. Patch from Zack Weinberg - <zack@wolery.cumb.org> - - (djm) OpenBSD CVS updates: - - todd@cvs.openbsd.org - [sshconnect2.c] - teach protocol v2 to count login failures properly and also enable an - explanation of why the password prompt comes up again like v1; this is NOT - crypto - - markus@cvs.openbsd.org - [readconf.c readconf.h servconf.c servconf.h session.c ssh.1 ssh.c sshd.8] - xauth_location support; pr 1234 - [readconf.c sshconnect2.c] - typo, unused - [session.c] - allow use_login only for login sessions, otherwise remote commands are - execed with uid==0 - [sshd.8] - document UseLogin better - [version.h] - OpenSSH 2.1.1 - [auth-rsa.c] - fix match_hostname() logic for auth-rsa: deny access if we have a - negative match or no match at all - [channels.c hostfile.c match.c] - don't panic if mkdtemp fails for authfwd; jkb@yahoo-inc.com via - kris@FreeBSD.org - -20000606 - - (djm) Added --with-cflags, --with-ldflags and --with-libs options to - configure. - -20000604 - - Configure tweaking for new login code on Irix 5.3 - - (andre) login code changes based on djm feedback - -20000603 - - (andre) New login code - - Remove bsd-login.[ch] and all the OpenBSD-derived code in login.c - - Add loginrec.[ch], logintest.c and autoconf code - -20000531 - - Cleanup of auth.c, login.c and fake-* - - Cleanup of auth-pam.c, save and print "account expired" error messages - - Fix EGD read bug by IWAMURO Motonori <iwa@mmp.fujitsu.co.jp> - - Rewrote bsd-login to use proper utmp API if available. Major cleanup - of fallback DIY code. - -20000530 - - Define atexit for old Solaris - - Fix buffer overrun in login.c for systems which use syslen in utmpx. - patch from YOSHIFUJI Hideaki <yoshfuji@cerberus.nemoto.ecei.tohoku.ac.jp> - - OpenBSD CVS updates: - - markus@cvs.openbsd.org - [session.c] - make x11-fwd work w/ localhost (xauth add host/unix:11) - [cipher.c compat.c readconf.c servconf.c] - check strtok() != NULL; ok niels@ - [key.c] - fix key_read() for uuencoded keys w/o '=' - [serverloop.c] - group ssh1 vs. ssh2 in serverloop - [kex.c kex.h myproposal.h sshconnect2.c sshd.c] - split kexinit/kexdh, factor out common code - [readconf.c ssh.1 ssh.c] - forwardagent defaults to no, add ssh -A - - theo@cvs.openbsd.org - [session.c] - just some line shortening - - Released 2.1.0p3 - -20000520 - - Xauth fix from Markus Friedl <markus.friedl@informatik.uni-erlangen.de> - - Don't touch utmp if USE_UTMPX defined - - SunOS 4.x support from Todd C. Miller <Todd.Miller@courtesan.com> - - SIGCHLD fix for AIX and HPUX from Tom Bertelson <tbert@abac.com> - - HPUX and Configure fixes from Lutz Jaenicke - <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - Use mkinstalldirs script to make directories instead of non-portable - "install -d". Suggested by Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - Doc cleanup - -20000518 - - Include Andre Lucas' fixprogs script. Forgot to "cvs add" it yesterday - - OpenBSD CVS updates: - - markus@cvs.openbsd.org - [sshconnect.c] - copy only ai_addrlen bytes; misiek@pld.org.pl - [auth.c] - accept an empty shell in authentication; bug reported by - chris@tinker.ucr.edu - [serverloop.c] - we don't have stderr for interactive terminal sessions (fcntl errors) - -20000517 - - Fix from Andre Lucas <andre.lucas@dial.pipex.com> - - Fixes command line printing segfaults (spotter: Bladt Norbert) - - Fixes erroneous printing of debug messages to syslog - - Fixes utmp for MacOS X (spotter: Aristedes Maniatis) - - Gives useful error message if PRNG initialisation fails - - Reduced ssh startup delay - - Measures cumulative command time rather than the time between reads - after select() - - 'fixprogs' perl script to eliminate non-working entropy commands, and - optionally run 'ent' to measure command entropy - - Applied Tom Bertelson's <tbert@abac.com> AIX authentication fix - - Avoid WCOREDUMP complation errors for systems that lack it - - Avoid SIGCHLD warnings from entropy commands - - Fix HAVE_PAM_GETENVLIST setting from Simon Wilkinson <sxw@dcs.ed.ac.uk> - - OpenBSD CVS update: - - markus@cvs.openbsd.org - [ssh.c] - fix usage() - [ssh2.h] - draft-ietf-secsh-architecture-05.txt - [ssh.1] - document ssh -T -N (ssh2 only) - [channels.c serverloop.c ssh.h sshconnect.c sshd.c aux.c] - enable nonblocking IO for sshd w/ proto 1, too; split out common code - [aux.c] - missing include - - Several patches from SAKAI Kiyotaka <ksakai@kso.netwk.ntt-at.co.jp> - - INSTALL typo and URL fix - - Makefile fix - - Solaris fixes - - Checking for ssize_t and memmove. Based on patch from SAKAI Kiyotaka - <ksakai@kso.netwk.ntt-at.co.jp> - - RSAless operation patch from kevin_oconnor@standardandpoors.com - - Detect OpenSSL seperatly from RSA - - Better test for RSA (more compatible with RSAref). Based on work by - Ed Eden <ede370@stl.rural.usda.gov> - -20000513 - - Fix for non-recognised DSA keys from Arkadiusz Miskiewicz - <misiek@pld.org.pl> - -20000511 - - Fix for prng_seed permissions checking from Lutz Jaenicke - <Lutz.Jaenicke@aet.TU-Cottbus.DE> - - "make host-key" fix for Irix - -20000509 - - OpenBSD CVS update - - markus@cvs.openbsd.org - [cipher.h myproposal.h readconf.c readconf.h servconf.c ssh.1 ssh.c] - [ssh.h sshconnect1.c sshconnect2.c sshd.8] - - complain about invalid ciphers in SSH1 (e.g. arcfour is SSH2 only) - - hugh@cvs.openbsd.org - [ssh.1] - - zap typo - [ssh-keygen.1] - - One last nit fix. (markus approved) - [sshd.8] - - some markus certified spelling adjustments - - markus@cvs.openbsd.org - [auth2.c channels.c clientloop.c compat compat.h dsa.c kex.c] - [sshconnect2.c ] - - bug compat w/ ssh-2.0.13 x11, split out bugs - [nchan.c] - - no drain if ibuf_empty, fixes x11fwd problems; tests by fries@ - [ssh-keygen.c] - - handle escapes in real and original key format, ok millert@ - [version.h] - - OpenSSH-2.1 - - Moved all the bsd-* and fake-* stuff into new libopenbsd-compat.a - - Doc updates - - Cleanup of bsd-base64 headers, bugfix definitions of __b64_*. Reported - by Andre Lucas <andre.lucas@dial.pipex.com> - -20000508 - - Makefile and RPM spec fixes - - Generate DSA host keys during "make key" or RPM installs - - OpenBSD CVS update - - markus@cvs.openbsd.org - [clientloop.c sshconnect2.c] - - make x11-fwd interop w/ ssh-2.0.13 - [README.openssh2] - - interop w/ SecureFX - - Release 2.0.0beta2 - - - Configure caching and cleanup patch from Andre Lucas' - <andre.lucas@dial.pipex.com> - -20000507 - - Remove references to SSLeay. - - Big OpenBSD CVS update - - markus@cvs.openbsd.org - [clientloop.c] - - typo - [session.c] - - update proctitle on pty alloc/dealloc, e.g. w/ windows client - [session.c] - - update proctitle for proto 1, too - [channels.h nchan.c serverloop.c session.c sshd.c] - - use c-style comments - - deraadt@cvs.openbsd.org - [scp.c] - - more atomicio - - markus@cvs.openbsd.org - [channels.c] - - set O_NONBLOCK - [ssh.1] - - update AUTHOR - [readconf.c ssh-keygen.c ssh.h] - - default DSA key file ~/.ssh/id_dsa - [clientloop.c] - - typo, rm verbose debug - - deraadt@cvs.openbsd.org - [ssh-keygen.1] - - document DSA use of ssh-keygen - [sshd.8] - - a start at describing what i understand of the DSA side - [ssh-keygen.1] - - document -X and -x - [ssh-keygen.c] - - simplify usage - - markus@cvs.openbsd.org - [sshd.8] - - there is no rhosts_dsa - [ssh-keygen.1] - - document -y, update -X,-x - [nchan.c] - - fix close for non-open ssh1 channels - [servconf.c servconf.h ssh.h sshd.8 sshd.c ] - - s/DsaKey/HostDSAKey/, document option - [sshconnect2.c] - - respect number_of_password_prompts - [channels.c channels.h servconf.c servconf.h session.c sshd.8] - - GatewayPorts for sshd, ok deraadt@ - [ssh-add.1 ssh-agent.1 ssh.1] - - more doc on: DSA, id_dsa, known_hosts2, authorized_keys2 - [ssh.1] - - more info on proto 2 - [sshd.8] - - sync AUTHOR w/ ssh.1 - [key.c key.h sshconnect.c] - - print key type when talking about host keys - [packet.c] - - clear padding in ssh2 - [dsa.c key.c radix.c ssh.h sshconnect1.c uuencode.c uuencode.h] - - replace broken uuencode w/ libc b64_ntop - [auth2.c] - - log failure before sending the reply - [key.c radix.c uuencode.c] - - remote trailing comments before calling __b64_pton - [auth2.c readconf.c readconf.h servconf.c servconf.h ssh.1] - [sshconnect2.c sshd.8] - - add DSAAuthetication option to ssh/sshd, document SSH2 in sshd.8 - - Bring in b64_ntop and b64_pton from OpenBSD libc (bsd-base64.[ch]) - -20000502 - - OpenBSD CVS update - [channels.c] - - init all fds, close all fds. - [sshconnect2.c] - - check whether file exists before asking for passphrase - [servconf.c servconf.h sshd.8 sshd.c] - - PidFile, pr 1210 - [channels.c] - - EINTR - [channels.c] - - unbreak, ok niels@ - [sshd.c] - - unlink pid file, ok niels@ - [auth2.c] - - Add missing #ifdefs; ok - markus - - Add Andre Lucas' <andre.lucas@dial.pipex.com> patch to read entropy - gathering commands from a text file - - Release 2.0.0beta1 - -20000501 - - OpenBSD CVS update - [packet.c] - - send debug messages in SSH2 format - [scp.c] - - fix very rare EAGAIN/EINTR issues; based on work by djm - [packet.c] - - less debug, rm unused - [auth2.c] - - disable kerb,s/key in ssh2 - [sshd.8] - - Minor tweaks and typo fixes. - [ssh-keygen.c] - - Put -d into usage and reorder. markus ok. - - Include missing headers for OpenSSL tests. Fix from Phil Karn - <karn@ka9q.ampr.org> - - Fixed __progname symbol collisions reported by Andre Lucas - <andre.lucas@dial.pipex.com> - - Merged bsd-login ttyslot and AIX utmp patch from Gert Doering - <gd@hilb1.medat.de> - - Add some missing ifdefs to auth2.c - - Deprecate perl-tk askpass. - - Irix portability fixes - don't include netinet headers more than once - - Make sure we don't save PRNG seed more than once - -20000430 - - Merge HP-UX fixes and TCB support from Ged Lodder <lodder@yacc.com.au> - - Integrate Andre Lucas' <andre.lucas@dial.pipex.com> entropy collection - patch. - - Adds timeout to entropy collection - - Disables slow entropy sources - - Load and save seed file - - Changed entropy seed code to user per-user seeds only (server seed is - saved in root's .ssh directory) - - Use atexit() and fatal cleanups to save seed on exit - - More OpenBSD updates: - [session.c] - - don't call chan_write_failed() if we are not writing - [auth-rsa.c auth1.c authfd.c hostfile.c ssh-agent.c] - - keysize warnings error() -> log() - -20000429 - - Merge big update to OpenSSH-2.0 from OpenBSD CVS - [README.openssh2] - - interop w/ F-secure windows client - - sync documentation - - ssh_host_dsa_key not ssh_dsa_key - [auth-rsa.c] - - missing fclose - [auth.c authfile.c compat.c dsa.c dsa.h hostfile.c key.c key.h radix.c] - [readconf.c readconf.h ssh-add.c ssh-keygen.c ssh.c ssh.h sshconnect.c] - [sshd.c uuencode.c uuencode.h authfile.h] - - add DSA pubkey auth and other SSH2 fixes. use ssh-keygen -[xX] - for trading keys with the real and the original SSH, directly from the - people who invented the SSH protocol. - [auth.c auth.h authfile.c sshconnect.c auth1.c auth2.c sshconnect.h] - [sshconnect1.c sshconnect2.c] - - split auth/sshconnect in one file per protocol version - [sshconnect2.c] - - remove debug - [uuencode.c] - - add trailing = - [version.h] - - OpenSSH-2.0 - [ssh-keygen.1 ssh-keygen.c] - - add -R flag: exit code indicates if RSA is alive - [sshd.c] - - remove unused - silent if -Q is specified - [ssh.h] - - host key becomes /etc/ssh_host_dsa_key - [readconf.c servconf.c ] - - ssh/sshd default to proto 1 and 2 - [uuencode.c] - - remove debug - [auth2.c ssh-keygen.c sshconnect2.c sshd.c] - - xfree DSA blobs - [auth2.c serverloop.c session.c] - - cleanup logging for sshd/2, respect PasswordAuth no - [sshconnect2.c] - - less debug, respect .ssh/config - [README.openssh2 channels.c channels.h] - - clientloop.c session.c ssh.c - - support for x11-fwding, client+server - -20000421 - - Merge fix from OpenBSD CVS - [ssh-agent.c] - - Fix memory leak per connection. Report from Andy Spiegl <Andy@Spiegl.de> - via Debian bug #59926 - - Define __progname in session.c if libc doesn't - - Remove indentation on autoconf #include statements to avoid bug in - DEC Tru64 compiler. Report and fix from David Del Piero - <David.DelPiero@qed.qld.gov.au> - -20000420 - - Make fixpaths work with perl4, patch from Andre Lucas - <andre.lucas@dial.pipex.com> - - Sync with OpenBSD CVS: - [clientloop.c login.c serverloop.c ssh-agent.c ssh.h sshconnect.c sshd.c] - - pid_t - [session.c] - - remove bogus chan_read_failed. this could cause data - corruption (missing data) at end of a SSH2 session. - - Merge fixes from Debian patch from Phil Hands <phil@hands.com> - - Allow setting of PAM service name through CFLAGS (SSHD_PAM_SERVICE) - - Use vhangup to clean up Linux ttys - - Force posix getopt processing on GNU libc systems - - Debian bug #55910 - remove references to ssl(8) manpages - - Debian bug #58031 - ssh_config lies about default cipher - -20000419 - - OpenBSD CVS updates - [channels.c] - - fix pr 1196, listen_port and port_to_connect interchanged - [scp.c] - - after completion, replace the progress bar ETA counter with a final - elapsed time; my idea, aaron wrote the patch - [ssh_config sshd_config] - - show 'Protocol' as an example, ok markus@ - [sshd.c] - - missing xfree() - - Add missing header to bsd-misc.c - -20000416 - - Reduce diff against OpenBSD source - - All OpenSSL includes are now unconditionally referenced as - openssl/foo.h - - Pick up formatting changes - - Other minor changed (typecasts, etc) that I missed - -20000415 - - OpenBSD CVS updates. - [ssh.1 ssh.c] - - ssh -2 - [auth.c channels.c clientloop.c packet.c packet.h serverloop.c] - [session.c sshconnect.c] - - check payload for (illegal) extra data - [ALL] - whitespace cleanup - -20000413 - - INSTALL doc updates - - Merged OpenBSD updates to include paths. - -20000412 - - OpenBSD CVS updates: - - [channels.c] - repair x11-fwd - - [sshconnect.c] - fix passwd prompt for ssh2, less debugging output. - - [clientloop.c compat.c dsa.c kex.c sshd.c] - less debugging output - - [kex.c kex.h sshconnect.c sshd.c] - check for reasonable public DH values - - [README.openssh2 cipher.c cipher.h compat.c compat.h readconf.c] - [readconf.h servconf.c servconf.h ssh.c ssh.h sshconnect.c sshd.c] - add Cipher and Protocol options to ssh/sshd, e.g.: - ssh -o 'Protocol 1,2' if you prefer proto 1, ssh -o 'Ciphers - arcfour,3des-cbc' - - [sshd.c] - print 1.99 only if server supports both - -20000408 - - Avoid some compiler warnings in fake-get*.c - - Add IPTOS macros for systems which lack them - - Only set define entropy collection macros if they are found - - More large OpenBSD CVS updates: - - [auth.c auth.h servconf.c servconf.h serverloop.c session.c] - [session.h ssh.h sshd.c README.openssh2] - ssh2 server side, see README.openssh2; enable with 'sshd -2' - - [channels.c] - no adjust after close - - [sshd.c compat.c ] - interop w/ latest ssh.com windows client. - -20000406 - - OpenBSD CVS update: - - [channels.c] - close efd on eof - - [clientloop.c compat.c ssh.c sshconnect.c myproposal.h] - ssh2 client implementation, interops w/ ssh.com and lsh servers. - - [sshconnect.c] - missing free. - - [authfile.c cipher.c cipher.h packet.c sshconnect.c sshd.c] - remove unused argument, split cipher_mask() - - [clientloop.c] - re-order: group ssh1 vs. ssh2 - - Make Redhat spec require openssl >= 0.9.5a - -20000404 - - Add tests for RAND_add function when searching for OpenSSL - - OpenBSD CVS update: - - [packet.h packet.c] - ssh2 packet format - - [packet.h packet.c nchan2.ms nchan.h compat.h compat.c] - [channels.h channels.c] - channel layer support for ssh2 - - [kex.h kex.c hmac.h hmac.c dsa.c dsa.h] - DSA, keyexchange, algorithm agreement for ssh2 - - Generate manpages before make install not at the end of make all - - Don't seed the rng quite so often - - Always reseed rng when requested - -20000403 - - Wrote entropy collection routines for systems that lack /dev/random - and EGD - - Disable tests and typedefs for 64 bit types. They are currently unused. - -20000401 - - Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure) - - [auth.c session.c sshd.c auth.h] - split sshd.c -> auth.c session.c sshd.c plus cleanup and goto-removal - - [bufaux.c bufaux.h] - support ssh2 bignums - - [channels.c channels.h clientloop.c sshd.c nchan.c nchan.h packet.c] - [readconf.c ssh.c ssh.h serverloop.c] - replace big switch() with function tables (prepare for ssh2) - - [ssh2.h] - ssh2 message type codes - - [sshd.8] - reorder Xr to avoid cutting - - [serverloop.c] - close(fdin) if fdin != fdout, shutdown otherwise, ok theo@ - - [channels.c] - missing close - allow bigger packets - - [cipher.c cipher.h] - support ssh2 ciphers - - [compress.c] - cleanup, less code - - [dispatch.c dispatch.h] - function tables for different message types - - [log-server.c] - do not log() if debuggin to stderr - rename a cpp symbol, to avoid param.h collision - - [mpaux.c] - KNF - - [nchan.c] - sync w/ channels.c - -20000326 - - Better tests for OpenSSL w/ RSAref - - Added replacement setenv() function from OpenBSD libc. Suggested by - Ben Lindstrom <mouring@pconline.com> - - OpenBSD CVS update - - [auth-krb4.c] - -Wall - - [auth-rh-rsa.c auth-rsa.c hostfile.c hostfile.h key.c key.h match.c] - [match.h ssh.c ssh.h sshconnect.c sshd.c] - initial support for DSA keys. ok deraadt@, niels@ - - [cipher.c cipher.h] - remove unused cipher_attack_detected code - - [scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8] - Fix some formatting problems I missed before. - - [ssh.1 sshd.8] - fix spelling errors, From: FreeBSD - - [ssh.c] - switch to raw mode only if he _get_ a pty (not if we _want_ a pty). - -20000324 - - Released 1.2.3 - -20000317 - - Clarified --with-default-path option. - - Added -blibpath handling for AIX to work around stupid runtime linking. - Problem elucidated by gshapiro@SENDMAIL.ORG by way of Jim Knoble - <jmknoble@pobox.com> - - Checks for 64 bit int types. Problem report from Mats Fredholm - <matsf@init.se> - - OpenBSD CVS updates: - - [atomicio.c auth-krb4.c bufaux.c channels.c compress.c fingerprint.c] - [packet.h radix.c rsa.c scp.c ssh-agent.c ssh-keygen.c sshconnect.c] - [sshd.c] - pedantic: signed vs. unsigned, void*-arithm, etc - - [ssh.1 sshd.8] - Various cleanups and standardizations. - - Runtime error fix for HPUX from Otmar Stahl - <O.Stahl@lsw.uni-heidelberg.de> - -20000316 - - Fixed configure not passing LDFLAGS to Solaris. Report from David G. - Hesprich <dghespri@sprintparanet.com> - - Propogate LD through to Makefile - - Doc cleanups - - Added blurb about "scp: command not found" errors to UPGRADING - -20000315 - - Fix broken CFLAGS handling during search for OpenSSL. Fixes va_list - problems with gcc/Solaris. - - Don't free argument to putenv() after use (in setenv() replacement). - Report from Seigo Tanimura <tanimura@r.dl.itc.u-tokyo.ac.jp> - - Created contrib/ subdirectory. Included helpers from Phil Hands' - Debian package, README file and chroot patch from Ricardo Cerqueira - <rmcc@clix.pt> - - Moved gnome-ssh-askpass.c to contrib directory and removed config - option. - - Slight cleanup to doc files - - Configure fix from Bratislav ILICH <bilic@zepter.ru> - -20000314 - - Include macro for IN6_IS_ADDR_V4MAPPED. Report from - peter@frontierflying.com - - Include /usr/local/include and /usr/local/lib for systems that don't - do it themselves - - -R/usr/local/lib for Solaris - - Fix RSAref detection - - Fix IN6_IS_ADDR_V4MAPPED macro - -20000311 - - Detect RSAref - - OpenBSD CVS change - [sshd.c] - - disallow guessing of root password - - More configure fixes - - IPv6 workarounds from Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp> - -20000309 - - OpenBSD CVS updates to v1.2.3 - [ssh.h atomicio.c] - - int atomicio -> ssize_t (for alpha). ok deraadt@ - [auth-rsa.c] - - delay MD5 computation until client sends response, free() early, cleanup. - [cipher.c] - - void* -> unsigned char*, ok niels@ - [hostfile.c] - - remove unused variable 'len'. fix comments. - - remove unused variable - [log-client.c log-server.c] - - rename a cpp symbol, to avoid param.h collision - [packet.c] - - missing xfree() - - getsockname() requires initialized tolen; andy@guildsoftware.com - - use getpeername() in packet_connection_is_on_socket(), fixes sshd -i; - from Holger.Trapp@Informatik.TU-Chemnitz.DE - [pty.c pty.h] - - register cleanup for pty earlier. move code for pty-owner handling to - pty.c ok provos@, dugsong@ - [readconf.c] - - turn off x11-fwd for the client, too. - [rsa.c] - - PKCS#1 padding - [scp.c] - - allow '.' in usernames; from jedgar@fxp.org - [servconf.c] - - typo: ignore_user_known_hosts int->flag; naddy@mips.rhein-neckar.de - - sync with sshd_config - [ssh-keygen.c] - - enable ssh-keygen -l -f ~/.ssh/known_hosts, ok deraadt@ - [ssh.1] - - Change invalid 'CHAT' loglevel to 'VERBOSE' - [ssh.c] - - suppress AAAA query host when '-4' is used; from shin@nd.net.fujitsu.co.jp - - turn off x11-fwd for the client, too. - [sshconnect.c] - - missing xfree() - - retry rresvport_af(), too. from sumikawa@ebina.hitachi.co.jp. - - read error vs. "Connection closed by remote host" - [sshd.8] - - ie. -> i.e., - - do not link to a commercial page.. - - sync with sshd_config - [sshd.c] - - no need for poll.h; from bright@wintelcom.net - - log with level log() not fatal() if peer behaves badly. - - don't panic if client behaves strange. ok deraadt@ - - make no-port-forwarding for RSA keys deny both -L and -R style fwding - - delay close() of pty until the pty has been chowned back to root - - oops, fix comment, too. - - missing xfree() - - move XAUTHORITY to subdir. ok dugsong@. fixes debian bug #57907, too. - (http://cgi.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=57907) - - register cleanup for pty earlier. move code for pty-owner handling to - pty.c ok provos@, dugsong@ - - create x11 cookie file - - fix pr 1113, fclose() -> pclose(), todo: remote popen() - - version 1.2.3 - - Cleaned up - - Removed warning workaround for Linux and devpts filesystems (no longer - required after OpenBSD updates) - -20000308 - - Configure fix from Hiroshi Takekawa <takekawa@sr3.t.u-tokyo.ac.jp> - -20000307 - - Released 1.2.2p1 - -20000305 - - Fix DEC compile fix - - Explicitly seed OpenSSL's PRNG before checking rsa_alive() - - Check for getpagesize in libucb.a if not found in libc. Fix for old - Solaris from Andre Lucas <andre.lucas@dial.pipex.com> - - Check for libwrap if --with-tcp-wrappers option specified. Suggestion - Mate Wierdl <mw@moni.msci.memphis.edu> - -20000303 - - Added "make host-key" target, Suggestion from Dominik Brettnacher - <domi@saargate.de> - - Don't permanently fail on bind() if getaddrinfo has more choices left for - us. Needed to work around messy IPv6 on Linux. Patch from Arkadiusz - Miskiewicz <misiek@pld.org.pl> - - DEC Unix compile fix from David Del Piero <David.DelPiero@qed.qld.gov.au> - - Manpage fix from David Del Piero <David.DelPiero@qed.qld.gov.au> - -20000302 - - Big cleanup of autoconf code - - Rearranged to be a little more logical - - Added -R option for Solaris - - Rewrote OpenSSL detection code. Now uses AC_TRY_RUN with a test program - to detect library and header location _and_ ensure library has proper - RSA support built in (this is a problem with OpenSSL 0.9.5). - - Applied pty cleanup patch from markus.friedl@informatik.uni-erlangen.de - - Avoid warning message with Unix98 ptys - - Warning was valid - possible race condition on PTYs. Avoided using - platform-specific code. - - Document some common problems - - Allow root access to any key. Patch from - markus.friedl@informatik.uni-erlangen.de - -20000207 - - Removed SOCKS code. Will support through a ProxyCommand. - -20000203 - - Fixed SEGVs in authloop, fix from vbzoli@hbrt.hu - - Add --with-ssl-dir option - -20000202 - - Fix lastlog code for directory based lastlogs. Fix from Josh Durham - <jmd@aoe.vt.edu> - - Documentation fixes from HARUYAMA Seigo <haruyama@nt.phys.s.u-tokyo.ac.jp> - - Added URLs to Japanese translations of documents by HARUYAMA Seigo - <haruyama@nt.phys.s.u-tokyo.ac.jp> - -20000201 - - Use socket pairs by default (instead of pipes). Prevents race condition - on several (buggy) OSs. Report and fix from tridge@linuxcare.com - -20000127 - - Seed OpenSSL's random number generator before generating RSA keypairs - - Split random collector into seperate file - - Compile fix from Andre Lucas <andre.lucas@dial.pipex.com> - -20000126 - - Released 1.2.2 stable - - - NeXT keeps it lastlog in /usr/adm. Report from - mouring@newton.pconline.com - - Added note in UPGRADING re interop with commercial SSH using idea. - Report from Jim Knoble <jmknoble@pobox.com> - - Fix linking order for Kerberos/AFS. Fix from Holget Trapp - <Holger.Trapp@Informatik.TU-Chemnitz.DE> - -20000125 - - Fix NULL pointer dereference in login.c. Fix from Andre Lucas - <andre.lucas@dial.pipex.com> - - Reorder PAM initialisation so it does not mess up lastlog. Reported - by Andre Lucas <andre.lucas@dial.pipex.com> - - Use preformatted manpages on SCO, report from Gary E. Miller - <gem@rellim.com> - - New URL for x11-ssh-askpass. - - Fixpaths was missing /etc/ssh_known_hosts. Report from Jim Knoble - <jmknoble@pobox.com> - - Added 'DESTDIR' option to Makefile to ease package building. Patch from - Jim Knoble <jmknoble@pobox.com> - - Updated RPM spec files to use DESTDIR - -20000124 - - Pick up version 1.2.2 from OpenBSD CVS (no changes, just version number - increment) - -20000123 - - OpenBSD CVS: - - [packet.c] - getsockname() requires initialized tolen; andy@guildsoftware.com - - AIX patch from Matt Richards <v2matt@btv.ibm.com> and David Rankin - <drankin@bohemians.lexington.ky.us> - - Fix lastlog support, patch from Andre Lucas <andre.lucas@dial.pipex.com> - -20000122 - - Fix compilation of bsd-snprintf.c on Solaris, fix from Ben Taylor - <bent@clark.net> - - Merge preformatted manpage patch from Andre Lucas - <andre.lucas@dial.pipex.com> - - Make IPv4 use the default in RPM packages - - Irix uses preformatted manpages - - Missing htons() in bsd-bindresvport.c, fix from Holger Trapp - <Holger.Trapp@Informatik.TU-Chemnitz.DE> - - OpenBSD CVS updates: - - [packet.c] - use getpeername() in packet_connection_is_on_socket(), fixes sshd -i; - from Holger.Trapp@Informatik.TU-Chemnitz.DE - - [sshd.c] - log with level log() not fatal() if peer behaves badly. - - [readpass.c] - instead of blocking SIGINT, catch it ourselves, so that we can clean - the tty modes up and kill ourselves -- instead of our process group - leader (scp, cvs, ...) going away and leaving us in noecho mode. - people with cbreak shells never even noticed.. - - [ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8] - ie. -> i.e., - -20000120 - - Don't use getaddrinfo on AIX - - Update to latest OpenBSD CVS: - - [auth-rsa.c] - - fix user/1056, sshd keeps restrictions; dbt@meat.net - - [sshconnect.c] - - disable agent fwding for proto 1.3, remove abuse of auth-rsa flags. - - destroy keys earlier - - split key exchange (kex) and user authentication (user-auth), - ok: provos@ - - [sshd.c] - - no need for poll.h; from bright@wintelcom.net - - disable agent fwding for proto 1.3, remove abuse of auth-rsa flags. - - split key exchange (kex) and user authentication (user-auth), - ok: provos@ - - Big manpage and config file cleanup from Andre Lucas - <andre.lucas@dial.pipex.com> - - Re-added latest (unmodified) OpenBSD manpages - - Doc updates - - NetBSD patch from David Rankin <drankin@bohemians.lexington.ky.us> and - Christos Zoulas <christos@netbsd.org> - -20000119 - - SCO compile fixes from Gary E. Miller <gem@rellim.com> - - Compile fix from Darren_Hall@progressive.com - - Linux/glibc-2.1.2 takes a *long* time to look up names for AF_UNSPEC - addresses using getaddrinfo(). Added a configure switch to make the - default lookup mode AF_INET - -20000118 - - Fixed --with-pid-dir option - - Makefile fix from Gary E. Miller <gem@rellim.com> - - Compile fix for HPUX and Solaris from Andre Lucas - <andre.lucas@dial.pipex.com> - -20000117 - - Clean up bsd-bindresvport.c. Use arc4random() for picking initial - port, ignore EINVAL errors (Linux) when searching for free port. - - Revert __snprintf -> snprintf aliasing. Apparently Solaris - __snprintf isn't. Report from Theo de Raadt <theo@cvs.openbsd.org> - - Document location of Redhat PAM file in INSTALL. - - Fixed X11 forwarding bug on Linux. libc advertises AF_INET6 - INADDR_ANY_INIT addresses via getaddrinfo, but may not be able to - deliver (no IPv6 kernel support) - - Released 1.2.1pre27 - - - Fix rresvport_af failure errors (logic error in bsd-bindresvport.c) - - Fix --with-ipaddr-display option test. Fix from Jarno Huuskonen - <jhuuskon@hytti.uku.fi> - - Fix hang on logout if processes are still using the pty. Needs - further testing. - - Patch from Christos Zoulas <christos@zoulas.com> - - Try $prefix first when looking for OpenSSL. - - Include sys/types.h when including sys/socket.h in test programs - - Substitute PID directory in sshd.8. Suggestion from Andrew - Stribblehill <a.d.stribblehill@durham.ac.uk> - -20000116 - - Renamed --with-xauth-path to --with-xauth - - Added --with-pid-dir option - - Released 1.2.1pre26 - - - Compilation fix from Kiyokazu SUTO <suto@ks-and-ks.ne.jp> - - Fixed broken bugfix for /dev/ptmx on Linux systems which lack - openpty(). Report from Kiyokazu SUTO <suto@ks-and-ks.ne.jp> - -20000115 - - Add --with-xauth-path configure directive and explicit test for - /usr/openwin/bin/xauth for Solaris systems. Report from Anders - Nordby <anders@fix.no> - - Fix incorrect detection of /dev/ptmx on Linux systems that lack - openpty. Report from John Seifarth <john@waw.be> - - Look for intXX_t and u_intXX_t in sys/bitypes.h if they are not in - sys/types.h. Fixes problems on SCO, report from Gary E. Miller - <gem@rellim.com> - - Use __snprintf and __vnsprintf if they are found where snprintf and - vnsprintf are lacking. Suggested by Ben Taylor <bent@shell.clark.net> - and others. - -20000114 - - Merged OpenBSD IPv6 patch: - - [sshd.c sshd.8 sshconnect.c ssh.h ssh.c servconf.h servconf.c scp.1] - [scp.c packet.h packet.c login.c log.c canohost.c channels.c] - [hostfile.c sshd_config] - ipv6 support: mostly gethostbyname->getaddrinfo/getnameinfo, new - features: sshd allows multiple ListenAddress and Port options. note - that libwrap is not IPv6-ready. (based on patches from - fujiwara@rcac.tdi.co.jp) - - [ssh.c canohost.c] - more hints (hints.ai_socktype=SOCK_STREAM) for getaddrinfo, - from itojun@ - - [channels.c] - listen on _all_ interfaces for X11-Fwd (hints.ai_flags = AI_PASSIVE) - - [packet.h] - allow auth-kerberos for IPv4 only - - [scp.1 sshd.8 servconf.h scp.c] - document -4, -6, and 'ssh -L 2022/::1/22' - - [ssh.c] - 'ssh @host' is illegal (null user name), from - karsten@gedankenpolizei.de - - [sshconnect.c] - better error message - - [sshd.c] - allow auth-kerberos for IPv4 only - - Big IPv6 merge: - - Cleanup overrun in sockaddr copying on RHL 6.1 - - Replacements for getaddrinfo, getnameinfo, etc based on versions - from patch from KIKUCHI Takahiro <kick@kyoto.wide.ad.jp> - - Replacement for missing structures on systems that lack IPv6 - - record_login needed to know about AF_INET6 addresses - - Borrowed more code from OpenBSD: rresvport_af and requisites - -20000110 - - Fixes to auth-skey to enable it to use the standard OpenSSL libraries - -20000107 - - New config.sub and config.guess to fix problems on SCO. Supplied - by Gary E. Miller <gem@rellim.com> - - SCO build fix from Gary E. Miller <gem@rellim.com> - - Released 1.2.1pre25 - -20000106 - - Documentation update & cleanup - - Better KrbIV / AFS detection, based on patch from: - Holger Trapp <Holger.Trapp@Informatik.TU-Chemnitz.DE> - -20000105 - - Fixed annoying DES corruption problem. libcrypt has been - overriding symbols in libcrypto. Removed libcrypt and crypt.h - altogether (libcrypto includes its own crypt(1) replacement) - - Added platform-specific rules for Irix 6.x. Included warning that - they are untested. - -20000103 - - Add explicit make rules for files proccessed by fixpaths. - - Fix "make install" in RPM spec files. Report from Tenkou N. Hattori - <tnh@kondara.org> - - Removed "nullok" directive from default PAM configuration files. - Added information on enabling EmptyPasswords on openssh+PAM in - UPGRADING file. - - OpenBSD CVS updates - - [ssh-agent.c] - cleanup_exit() for SIGTERM/SIGHUP, too. from fgsch@ and - dgaudet@arctic.org - - [sshconnect.c] - compare correct version for 1.3 compat mode - -20000102 - - Prevent multiple inclusion of config.h and defines.h. Suggested - by Andre Lucas <andre.lucas@dial.pipex.com> - - Properly clean up on exit of ssh-agent. Patch from Dean Gaudet - <dgaudet@arctic.org> - -19991231 - - Fix password support on systems with a mixture of shadowed and - non-shadowed passwords (e.g. NIS). Report and fix from - HARUYAMA Seigo <haruyama@nt.phys.s.u-tokyo.ac.jp> - - Fix broken autoconf typedef detection. Report from Marc G. - Fournier <marc.fournier@acadiau.ca> - - Fix occasional crash on LinuxPPC. Patch from Franz Sirl - <Franz.Sirl-kernel@lauterbach.com> - - Prevent typedefs from being compiled more than once. Report from - Marc G. Fournier <marc.fournier@acadiau.ca> - - Fill in ut_utaddr utmp field. Report from Benjamin Charron - <iretd@bigfoot.com> - - Really fix broken default path. Fix from Jim Knoble - <jmknoble@pobox.com> - - Remove test for quad_t. No longer needed. - - Released 1.2.1pre24 - - - Added support for directory-based lastlogs - - Really fix typedefs, patch from Ben Taylor <bent@clark.net> - -19991230 - - OpenBSD CVS updates: - - [auth-passwd.c] - check for NULL 1st - - Removed most of the pam code into its own file auth-pam.[ch]. This - cleaned up sshd.c up significantly. - - PAM authentication was incorrectly interpreting - "PermitRootLogin without-password". Report from Matthias Andree - <ma@dt.e-technik.uni-dortmund.de - - Several other cleanups - - Merged Dante SOCKS support patch from David Rankin - <drankin@bohemians.lexington.ky.us> - - Updated documentation with ./configure options - - Released 1.2.1pre23 - -19991229 - - Applied another NetBSD portability patch from David Rankin - <drankin@bohemians.lexington.ky.us> - - Fix --with-default-path option. - - Autodetect perl, patch from David Rankin - <drankin@bohemians.lexington.ky.us> - - Print whether OpenSSH was compiled with RSARef, patch from - Nalin Dahyabhai <nalin@thermo.stat.ncsu.edu> - - Calls to pam_setcred, patch from Nalin Dahyabhai - <nalin@thermo.stat.ncsu.edu> - - Detect missing size_t and typedef it. - - Rename helper.[ch] to (more appropriate) bsd-misc.[ch] - - Minor Makefile cleaning - -19991228 - - Replacement for getpagesize() for systems which lack it - - NetBSD login.c compile fix from David Rankin - <drankin@bohemians.lexington.ky.us> - - Fully set ut_tv if present in utmp or utmpx - - Portability fixes for Irix 5.3 (now compiles OK!) - - autoconf and other misc cleanups - - Merged AIX patch from Darren Hall <dhall@virage.org> - - Cleaned up defines.h - - Released 1.2.1pre22 - -19991227 - - Automatically correct paths in manpages and configuration files. Patch - and script from Andre Lucas <andre.lucas@dial.pipex.com> - - Removed credits from README to CREDITS file, updated. - - Added --with-default-path to specify custom path for server - - Removed #ifdef trickery from acconfig.h into defines.h - - PAM bugfix. PermitEmptyPassword was being ignored. - - Fixed PAM config files to allow empty passwords if server does. - - Explained spurious PAM auth warning workaround in UPGRADING - - Use last few chars of tty line as ut_id - - New SuSE RPM spec file from Chris Saia <csaia@wtower.com> - - OpenBSD CVS updates: - - [packet.h auth-rhosts.c] - check format string for packet_disconnect and packet_send_debug, too - - [channels.c] - use packet_get_maxsize for channels. consistence. - -19991226 - - Enabled utmpx support by default for Solaris - - Cleanup sshd.c PAM a little more - - Revised RPM package to include Jim Knoble's <jmknoble@pobox.com> - X11 ssh-askpass program. - - Disable logging of PAM success and failures, PAM is verbose enough. - Unfortunatly there is currently no way to disable auth failure - messages. Mention this in UPGRADING file and sent message to PAM - developers - - OpenBSD CVS update: - - [ssh-keygen.1 ssh.1] - remove ref to .ssh/random_seed, mention .ssh/environment in - .Sh FILES, too - - Released 1.2.1pre21 - - Fixed implicit '.' in default path, report from Jim Knoble - <jmknoble@pobox.com> - - Redhat RPM spec fixes from Jim Knoble <jmknoble@pobox.com> - -19991225 - - More fixes from Andre Lucas <andre.lucas@dial.pipex.com> - - Cleanup of auth-passwd.c for shadow and MD5 passwords - - Cleanup and bugfix of PAM authentication code - - Released 1.2.1pre20 - - - Merged fixes from Ben Taylor <bent@clark.net> - - Fixed configure support for PAM. Reported by Naz <96na@eng.cam.ac.uk> - - Disabled logging of PAM password authentication failures when password - is empty. (e.g start of authentication loop). Reported by Naz - <96na@eng.cam.ac.uk>) - -19991223 - - Merged later HPUX patch from Andre Lucas - <andre.lucas@dial.pipex.com> - - Above patch included better utmpx support from Ben Taylor - <bent@clark.net> - -19991222 - - Fix undefined fd_set type in ssh.h from Povl H. Pedersen - <pope@netguide.dk> - - Fix login.c breakage on systems which lack ut_host in struct - utmp. Reported by Willard Dawson <willard.dawson@sbs.siemens.com> - -19991221 - - Integration of large HPUX patch from Andre Lucas - <andre.lucas@dial.pipex.com>. Integrating it had a few other - benefits: - - Ability to disable shadow passwords at configure time - - Ability to disable lastlog support at configure time - - Support for IP address in $DISPLAY - - OpenBSD CVS update: - - [sshconnect.c] - say "REMOTE HOST IDENTIFICATION HAS CHANGED" - - Fix DISABLE_SHADOW support - - Allow MD5 passwords even if shadow passwords are disabled - - Release 1.2.1pre19 - -19991218 - - Redhat init script patch from Chun-Chung Chen - <cjj@u.washington.edu> - - Avoid breakage on systems without IPv6 headers - -19991216 - - Makefile changes for Solaris from Peter Kocks - <peter.kocks@baygate.com> - - Minor updates to docs - - Merged OpenBSD CVS changes: - - [authfd.c ssh-agent.c] - keysize warnings talk about identity files - - [packet.c] - "Connection closed by x.x.x.x": fatal() -> log() - - Correctly handle empty passwords in shadow file. Patch from: - "Chris, the Young One" <cky@pobox.com> - - Released 1.2.1pre18 - -19991215 - - Integrated patchs from Juergen Keil <jk@tools.de> - - Avoid void* pointer arithmatic - - Use LDFLAGS correctly - - Fix SIGIO error in scp - - Simplify status line printing in scp - - Added better test for inline functions compiler support from - Darren_Hall@progressive.com - -19991214 - - OpenBSD CVS Changes - - [canohost.c] - fix get_remote_port() and friends for sshd -i; - Holger.Trapp@Informatik.TU-Chemnitz.DE - - [mpaux.c] - make code simpler. no need for memcpy. niels@ ok - - [pty.c] - namebuflen not sizeof namebuflen; bnd@ep-ag.com via djm@mindrot.org - fix proto; markus - - [ssh.1] - typo; mark.baushke@solipsa.com - - [channels.c ssh.c ssh.h sshd.c] - type conflict for 'extern Type *options' in channels.c; dot@dotat.at - - [sshconnect.c] - move checking of hostkey into own function. - - [version.h] - OpenSSH-1.2.1 - - Clean up broken includes in pty.c - - Some older systems don't have poll.h, they use sys/poll.h instead - - Doc updates - -19991211 - - Fix compilation on systems with AFS. Reported by - aloomis@glue.umd.edu - - Fix installation on Solaris. Reported by - Gordon Rowell <gordonr@gormand.com.au> - - Fix gccisms (__attribute__ and inline). Report by edgy@us.ibm.com, - patch from Markus Friedl <markus.friedl@informatik.uni-erlangen.de> - - Auto-locate xauth. Patch from David Agraz <dagraz@jahoopa.com> - - Compile fix from David Agraz <dagraz@jahoopa.com> - - Avoid compiler warning in bsd-snprintf.c - - Added pam_limits.so to default PAM config. Suggested by - Jim Knoble <jmknoble@pobox.com> - -19991209 - - Import of patch from Ben Taylor <bent@clark.net>: - - Improved PAM support - - "uninstall" rule for Makefile - - utmpx support - - Should fix PAM problems on Solaris - - OpenBSD CVS updates: - - [readpass.c] - avoid stdio; based on work by markus, millert, and I - - [sshd.c] - make sure the client selects a supported cipher - - [sshd.c] - fix sighup handling. accept would just restart and daemon handled - sighup only after the next connection was accepted. use poll on - listen sock now. - - [sshd.c] - make that a fatal - - Applied patch from David Rankin <drankin@bohemians.lexington.ky.us> - to fix libwrap support on NetBSD - - Released 1.2pre17 - -19991208 - - Compile fix for Solaris with /dev/ptmx from - David Agraz <dagraz@jahoopa.com> - -19991207 - - sshd Redhat init script patch from Jim Knoble <jmknoble@pobox.com> - fixes compatability with 4.x and 5.x - - Fixed default SSH_ASKPASS - - Fix PAM account and session being called multiple times. Problem - reported by Adrian Baugh <adrian@merlin.keble.ox.ac.uk> - - Merged more OpenBSD changes: - - [atomicio.c authfd.c scp.c serverloop.c ssh.h sshconnect.c sshd.c] - move atomicio into it's own file. wrap all socket write()s which - were doing write(sock, buf, len) != len, with atomicio() calls. - - [auth-skey.c] - fd leak - - [authfile.c] - properly name fd variable - - [channels.c] - display great hatred towards strcpy - - [pty.c pty.h sshd.c] - use openpty() if it exists (it does on BSD4_4) - - [tildexpand.c] - check for ~ expansion past MAXPATHLEN - - Modified helper.c to use new atomicio function. - - Reformat Makefile a little - - Moved RC4 routines from rc4.[ch] into helper.c - - Added autoconf code to detect /dev/ptmx (Solaris) and /dev/ptc (AIX) - - Updated SuSE spec from Chris Saia <csaia@wtower.com> - - Tweaked Redhat spec - - Clean up bad imports of a few files (forgot -kb) - - Released 1.2pre16 - -19991204 - - Small cleanup of PAM code in sshd.c - - Merged OpenBSD CVS changes: - - [auth-krb4.c auth-passwd.c auth-skey.c ssh.h] - move skey-auth from auth-passwd.c to auth-skey.c, same for krb4 - - [auth-rsa.c] - warn only about mismatch if key is _used_ - warn about keysize-mismatch with log() not error() - channels.c readconf.c readconf.h ssh.c ssh.h sshconnect.c - ports are u_short - - [hostfile.c] - indent, shorter warning - - [nchan.c] - use error() for internal errors - - [packet.c] - set loglevel for SSH_MSG_DISCONNECT to log(), not fatal() - serverloop.c - indent - - [ssh-add.1 ssh-add.c ssh.h] - document $SSH_ASKPASS, reasonable default - - [ssh.1] - CheckHostIP is not available for connects via proxy command - - [sshconnect.c] - typo - easier to read client code for passwd and skey auth - turn of checkhostip for proxy connects, since we don't know the remote ip - -19991126 - - Add definition for __P() - - Added [v]snprintf() replacement for systems that lack it - -19991125 - - More reformatting merged from OpenBSD CVS - - Merged OpenBSD CVS changes: - - [channels.c] - fix packet_integrity_check() for !have_hostname_in_open. - report from mrwizard@psu.edu via djm@ibs.com.au - - [channels.c] - set SO_REUSEADDR and SO_LINGER for forwarded ports. - chip@valinux.com via damien@ibs.com.au - - [nchan.c] - it's not an error() if shutdown_write failes in nchan. - - [readconf.c] - remove dead #ifdef-0-code - - [readconf.c servconf.c] - strcasecmp instead of tolower - - [scp.c] - progress meter overflow fix from damien@ibs.com.au - - [ssh-add.1 ssh-add.c] - SSH_ASKPASS support - - [ssh.1 ssh.c] - postpone fork_after_authentication until command execution, - request/patch from jahakala@cc.jyu.fi via damien@ibs.com.au - plus: use daemon() for backgrounding - - Added BSD compatible install program and autoconf test, thanks to - Niels Kristian Bech Jensen <nkbj@image.dk> - - Solaris fixing, thanks to Ben Taylor <bent@clark.net> - - Merged beginnings of AIX support from Tor-Ake Fransson <torake@hotmail.com> - - Release 1.2pre15 - -19991124 - - Merged very large OpenBSD source code reformat - - OpenBSD CVS updates - - [channels.c cipher.c compat.c log-client.c scp.c serverloop.c] - [ssh.h sshd.8 sshd.c] - syslog changes: - * Unified Logmessage for all auth-types, for success and for failed - * Standard connections get only ONE line in the LOG when level==LOG: - Auth-attempts are logged only, if authentication is: - a) successfull or - b) with passwd or - c) we had more than AUTH_FAIL_LOG failues - * many log() became verbose() - * old behaviour with level=VERBOSE - - [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c] - tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE - messages. allows use of s/key in windows (ttssh, securecrt) and - ssh-1.2.27 clients without 'ssh -v', ok: niels@ - - [sshd.8] - -V, for fallback to openssh in SSH2 compatibility mode - - [sshd.c] - fix sigchld race; cjc5@po.cwru.edu - -19991123 - - Added SuSE package files from Chris Saia <csaia@wtower.com> - - Restructured package-related files under packages/* - - Added generic PAM config - - Numerous little Solaris fixes - - Add recommendation to use GNU make to INSTALL document - -19991122 - - Make <enter> close gnome-ssh-askpass (Debian bug #50299) - - OpenBSD CVS Changes - - [ssh-keygen.c] - don't create ~/.ssh only if the user wants to store the private - key there. show fingerprint instead of public-key after - keygeneration. ok niels@ - - Added OpenBSD bsd-strlcat.c, created bsd-strlcat.h - - Added timersub() macro - - Tidy RCSIDs of bsd-*.c - - Added autoconf test and macro to deal with old PAM libraries - pam_strerror definition (one arg vs two). - - Fix EGD problems (Thanks to Ben Taylor <bent@clark.net>) - - Retry /dev/urandom reads interrupted by signal (report from - Robert Hardy <rhardy@webcon.net>) - - Added a setenv replacement for systems which lack it - - Only display public key comment when presenting ssh-askpass dialog - - Released 1.2pre14 - - - Configure, Make and changelog corrections from Tudor Bosman - <tudorb@jm.nu> and Niels Kristian Bech Jensen <nkbj@image.dk> - -19991121 - - OpenBSD CVS Changes: - - [channels.c] - make this compile, bad markus - - [log.c readconf.c servconf.c ssh.h] - bugfix: loglevels are per host in clientconfig, - factor out common log-level parsing code. - - [servconf.c] - remove unused index (-Wall) - - [ssh-agent.c] - only one 'extern char *__progname' - - [sshd.8] - document SIGHUP, -Q to synopsis - - [sshconnect.c serverloop.c sshd.c packet.c packet.h] - [channels.c clientloop.c] - SSH_CMSG_MAX_PACKET_SIZE, some clients use this, some need this, niels@ - [hope this time my ISP stays alive during commit] - - [OVERVIEW README] typos; green@freebsd - - [ssh-keygen.c] - replace xstrdup+strcat with strlcat+fixed buffer, fixes OF (bad me) - exit if writing the key fails (no infinit loop) - print usage() everytime we get bad options - - [ssh-keygen.c] overflow, djm@mindrot.org - - [sshd.c] fix sigchld race; cjc5@po.cwru.edu - -19991120 - - Merged more Solaris support from Marc G. Fournier - <marc.fournier@acadiau.ca> - - Wrote autoconf tests for integer bit-types - - Fixed enabling kerberos support - - Fix segfault in ssh-keygen caused by buffer overrun in filename - handling. - -19991119 - - Merged PAM buffer overrun patch from Chip Salzenberg <chip@valinux.com> - - Merged OpenBSD CVS changes - - [auth-rhosts.c auth-rsa.c ssh-agent.c sshconnect.c sshd.c] - more %d vs. %s in fmt-strings - - [authfd.c] - Integers should not be printed with %s - - EGD uses a socket, not a named pipe. Duh. - - Fix includes in fingerprint.c - - Fix scp progress bar bug again. - - Move ssh-askpass from ${libdir}/ssh to ${libexecdir}/ssh at request of - David Rankin <drankin@bohemians.lexington.ky.us> - - Added autoconf option to enable Kerberos 4 support (untested) - - Added autoconf option to enable AFS support (untested) - - Added autoconf option to enable S/Key support (untested) - - Added autoconf option to enable TCP wrappers support (compiles OK) - - Renamed BSD helper function files to bsd-* - - Added tests for login and daemon and enable OpenBSD replacements for - when they are absent. - - Added non-PAM MD5 password support patch from Tudor Bosman <tudorb@jm.nu> - -19991118 - - Merged OpenBSD CVS changes - - [scp.c] foregroundproc() in scp - - [sshconnect.h] include fingerprint.h - - [sshd.c] bugfix: the log() for passwd-auth escaped during logging - changes. - - [ssh.1] Spell my name right. - - Added openssh.com info to README - -19991117 - - Merged OpenBSD CVS changes - - [ChangeLog.Ylonen] noone needs this anymore - - [authfd.c] close-on-exec for auth-socket, ok deraadt - - [hostfile.c] - in known_hosts key lookup the entry for the bits does not need - to match, all the information is contained in n and e. This - solves the problem with buggy servers announcing the wrong - modulus length. markus and me. - - [serverloop.c] - bugfix: check for space if child has terminated, from: - iedowse@maths.tcd.ie - - [ssh-add.1 ssh-add.c ssh-keygen.1 ssh-keygen.c sshconnect.c] - [fingerprint.c fingerprint.h] - rsa key fingerprints, idea from Bjoern Groenvall <bg@sics.se> - - [ssh-agent.1] typo - - [ssh.1] add OpenSSH information to AUTHOR section. okay markus@ - - [sshd.c] - force logging to stderr while loading private key file - (lost while converting to new log-levels) - -19991116 - - Fix some Linux libc5 problems reported by Miles Wilson <mw@mctitle.com> - - Merged OpenBSD CVS changes: - - [auth-rh-rsa.c auth-rsa.c authfd.c authfd.h hostfile.c mpaux.c] - [mpaux.h ssh-add.c ssh-agent.c ssh.h ssh.c sshd.c] - the keysize of rsa-parameter 'n' is passed implizit, - a few more checks and warnings about 'pretended' keysizes. - - [cipher.c cipher.h packet.c packet.h sshd.c] - remove support for cipher RC4 - - [ssh.c] - a note for legay systems about secuity issues with permanently_set_uid(), - the private hostkey and ptrace() - - [sshconnect.c] - more detailed messages about adding and checking hostkeys - -19991115 - - Merged OpenBSD CVS changes: - - [ssh-add.c] change passphrase loop logic and remove ref to - $DISPLAY, ok niels - - Changed to ssh-add.c broke askpass support. Revised it to be a little more - modular. - - Revised autoconf support for enabling/disabling askpass support. - - Merged more OpenBSD CVS changes: - [auth-krb4.c] - - disconnect if getpeername() fails - - missing xfree(*client) - [canohost.c] - - disconnect if getpeername() fails - - fix comment: we _do_ disconnect if ip-options are set - [sshd.c] - - disconnect if getpeername() fails - - move checking of remote port to central place - [auth-rhosts.c] move checking of remote port to central place - [log-server.c] avoid extra fd per sshd, from millert@ - [readconf.c] print _all_ bad config-options in ssh(1), too - [readconf.h] print _all_ bad config-options in ssh(1), too - [ssh.c] print _all_ bad config-options in ssh(1), too - [sshconnect.c] disconnect if getpeername() fails - - OpenBSD's changes to sshd.c broke the PAM stuff, re-merged it. - - Various small cleanups to bring diff (against OpenBSD) size down. - - Merged more Solaris compability from Marc G. Fournier - <marc.fournier@acadiau.ca> - - Wrote autoconf tests for __progname symbol - - RPM spec file fixes from Jim Knoble <jmknoble@pobox.com> - - Released 1.2pre12 - - - Another OpenBSD CVS update: - - [ssh-keygen.1] fix .Xr - -19991114 - - Solaris compilation fixes (still imcomplete) - -19991113 - - Build patch from Niels Kristian Bech Jensen <nkbj@image.dk> - - Don't install config files if they already exist - - Fix inclusion of additional preprocessor directives from acconfig.h - - Removed redundant inclusions of config.h - - Added 'Obsoletes' lines to RPM spec file - - Merged OpenBSD CVS changes: - - [bufaux.c] save a view malloc/memcpy/memset/free's, ok niels - - [scp.c] fix overflow reported by damien@ibs.com.au: off_t - totalsize, ok niels,aaron - - Delay fork (-f option) in ssh until after port forwarded connections - have been initialised. Patch from Jani Hakala <jahakala@cc.jyu.fi> - - Added shadow password patch from Thomas Neumann <tom@smart.ruhr.de> - - Added ifdefs to auth-passwd.c to exclude it when PAM is enabled - - Tidied default config file some more - - Revised Redhat initscript to fix bug: sshd (re)start would fail - if executed from inside a ssh login. - -19991112 - - Merged changes from OpenBSD CVS - - [sshd.c] session_key_int may be zero - - [auth-rh-rsa.c servconf.c servconf.h ssh.h sshd.8 sshd.c sshd_config] - IgnoreUserKnownHosts(default=no), used for RhostRSAAuth, ok - deraadt,millert - - Brought default sshd_config more in line with OpenBSD's - - Grab server in gnome-ssh-askpass (Debian bug #49872) - - Released 1.2pre10 - - - Added INSTALL documentation - - Merged yet more changes from OpenBSD CVS - - [auth-rh-rsa.c auth-rhosts.c auth-rsa.c channels.c clientloop.c] - [ssh.c ssh.h sshconnect.c sshd.c] - make all access to options via 'extern Options options' - and 'extern ServerOptions options' respectively; - options are no longer passed as arguments: - * make options handling more consistent - * remove #include "readconf.h" from ssh.h - * readconf.h is only included if necessary - - [mpaux.c] clear temp buffer - - [servconf.c] print _all_ bad options found in configfile - - Make ssh-askpass support optional through autoconf - - Fix nasty division-by-zero error in scp.c - - Released 1.2pre11 - -19991111 - - Added (untested) Entropy Gathering Daemon (EGD) support - - Fixed /dev/urandom fd leak (Debian bug #49722) - - Merged OpenBSD CVS changes: - - [auth-rh-rsa.c] user/958: check ~/.ssh/known_hosts for rhosts-rsa, too - - [ssh.1] user/958: check ~/.ssh/known_hosts for rhosts-rsa, too - - [sshd.8] user/958: check ~/.ssh/known_hosts for rhosts-rsa, too - - Fix integer overflow which was messing up scp's progress bar for large - file transfers. Fix submitted to OpenBSD developers. Report and fix - from Kees Cook <cook@cpoint.net> - - Merged more OpenBSD CVS changes: - - [auth-krb4.c auth-passwd.c] remove x11- and krb-cleanup from fatal() - + krb-cleanup cleanup - - [clientloop.c log-client.c log-server.c ] - [readconf.c readconf.h servconf.c servconf.h ] - [ssh.1 ssh.c ssh.h sshd.8] - add LogLevel {QUIET, FATAL, ERROR, INFO, CHAT, DEBUG} to ssh/sshd, - obsoletes QuietMode and FascistLogging in sshd. - - [sshd.c] fix fatal/assert() bug reported by damien@ibs.com.au: - allow session_key_int != sizeof(session_key) - [this should fix the pre-assert-removal-core-files] - - Updated default config file to use new LogLevel option and to improve - readability - -19991110 - - Merged several minor fixes: - - ssh-agent commandline parsing - - RPM spec file now installs ssh setuid root - - Makefile creates libdir - - Merged beginnings of Solaris compability from Marc G. Fournier - <marc.fournier@acadiau.ca> - -19991109 - - Autodetection of SSL/Crypto library location via autoconf - - Fixed location of ssh-askpass to follow autoconf - - Integrated Makefile patch from Niels Kristian Bech Jensen <nkbj@image.dk> - - Autodetection of RSAref library for US users - - Minor doc updates - - Merged OpenBSD CVS changes: - - [rsa.c] bugfix: use correct size for memset() - - [sshconnect.c] warn if announced size of modulus 'n' != real size - - Added GNOME passphrase requestor (use --with-gnome-askpass) - - RPM build now creates subpackages - - Released 1.2pre9 - -19991108 - - Removed debian/ directory. This is now being maintained separately. - - Added symlinks for slogin in RPM spec file - - Fixed permissions on manpages in RPM spec file - - Added references to required libraries in README file - - Removed config.h.in from CVS - - Removed pwdb support (better pluggable auth is provided by glibc) - - Made PAM and requisite libdl optional - - Removed lots of unnecessary checks from autoconf - - Added support and autoconf test for openpty() function (Unix98 pty support) - - Fix for scp not finding ssh if not installed as /usr/bin/ssh - - Added TODO file - - Merged parts of Debian patch From Phil Hands <phil@hands.com>: - - Added ssh-askpass program - - Added ssh-askpass support to ssh-add.c - - Create symlinks for slogin on install - - Fix "distclean" target in makefile - - Added example for ssh-agent to manpage - - Added support for PAM_TEXT_INFO messages - - Disable internal /etc/nologin support if PAM enabled - - Merged latest OpenBSD CVS changes: - - [all] replace assert() with error, fatal or packet_disconnect - - [sshd.c] don't send fail-msg but disconnect if too many authentication - failures - - [sshd.c] remove unused argument. ok dugsong - - [sshd.c] typo - - [rsa.c] clear buffers used for encryption. ok: niels - - [rsa.c] replace assert() with error, fatal or packet_disconnect - - [auth-krb4.c] remove unused argument. ok dugsong - - Fixed coredump after merge of OpenBSD rsa.c patch - - Released 1.2pre8 - -19991102 - - Merged change from OpenBSD CVS - - One-line cleanup in sshd.c - -19991030 - - Integrated debian package support from Dan Brosemer <odin@linuxfreak.com> - - Merged latest updates for OpenBSD CVS: - - channels.[ch] - remove broken x11 fix and document istate/ostate - - ssh-agent.c - call setsid() regardless of argv[] - - ssh.c - save a few lines when disabling rhosts-{rsa-}auth - - Documentation cleanups - - Renamed README -> README.Ylonen - - Renamed README.openssh ->README - -19991029 - - Renamed openssh* back to ssh* at request of Theo de Raadt - - Incorporated latest changes from OpenBSD's CVS - - Integrated Makefile patch from Niels Kristian Bech Jensen <nkbj@image.dk> - - Integrated PAM env patch from Nalin Dahyabhai <nalin.dahyabhai@pobox.com> - - Make distclean now removed configure script - - Improved PAM logging - - Added some debug() calls for PAM - - Removed redundant subdirectories - - Integrated part of a patch from Dan Brosemer <odin@linuxfreak.com> for - building on Debian. - - Fixed off-by-one error in PAM env patch - - Released 1.2pre6 - -19991028 - - Further PAM enhancements. - - Much cleaner - - Now uses account and session modules for all logins. - - Integrated patch from Dan Brosemer <odin@linuxfreak.com> - - Build fixes - - Autoconf - - Change binary names to open* - - Fixed autoconf script to detect PAM on RH6.1 - - Added tests for libpwdb, and OpenBSD functions to autoconf - - Released 1.2pre4 - - - Imported latest OpenBSD CVS code - - Updated README.openssh - - Released 1.2pre5 - -19991027 - - Adapted PAM patch. - - Released 1.0pre2 - - - Excised my buggy replacements for strlcpy and mkdtemp - - Imported correct OpenBSD strlcpy and mkdtemp routines. - - Reduced arc4random_stir entropy read to 32 bytes (256 bits) - - Picked up correct version number from OpenBSD - - Added sshd.pam PAM configuration file - - Added sshd.init Redhat init script - - Added openssh.spec RPM spec file - - Released 1.2pre3 - -19991026 - - Fixed include paths of OpenSSL functions - - Use OpenSSL MD5 routines - - Imported RC4 code from nanocrypt - - Wrote replacements for OpenBSD arc4random* functions - - Wrote replacements for strlcpy and mkdtemp - - Released 1.0pre1 diff --git a/usr/src/cmd/ssh/doc/INSTALL b/usr/src/cmd/ssh/doc/INSTALL deleted file mode 100644 index 9112b92b57..0000000000 --- a/usr/src/cmd/ssh/doc/INSTALL +++ /dev/null @@ -1,199 +0,0 @@ -1. Prerequisites ----------------- - -You will need working installations of Zlib and OpenSSL. - -Zlib: -http://www.freesoftware.com/pub/infozip/zlib/ - -OpenSSL 0.9.5a or greater: -http://www.openssl.org/ - -RPMs of OpenSSL are available at http://violet.ibs.com.au/openssh/files/support - -OpenSSH can utilise Pluggable Authentication Modules (PAM) if your system -supports it. PAM is standard on Redhat and Debian Linux and on Solaris. - -PAM: -http://www.kernel.org/pub/linux/libs/pam/ - -If you wish to build the GNOME passphrase requester, you will need the GNOME -libraries and headers. - -GNOME: -http://www.gnome.org/ - -Alternatively, Jim Knoble <jmknoble@pobox.com> has written an excellent X11 -passphrase requester. This is maintained separately at: - -http://www.ntrnet.net/~jmknoble/software/x11-ssh-askpass/index.html - -The Entropy Gathering Daemon (EGD) is supported if you have a system which -lacks /dev/random and don't want to use OpenSSH's internal entropy collection. - -EGD: -http://www.lothar.com/tech/crypto/ - -GNU Make: -ftp://ftp.gnu.org/gnu/make/ - -OpenSSH has only been tested with GNU make. It may work with other -'make' programs, but you are on your own. - -pcre (POSIX Regular Expression library): -ftp://ftp.cus.cam.ac.uk/pub/software/programs/pcre/ - -Most platforms do not required this. However older 4.3 BSD do not -have a posix regex library. - - -2. Building / Installation --------------------------- - -To install OpenSSH with default options: - -./configure -make -make install - -This will install the OpenSSH binaries in /usr/local/bin, configuration files -in /usr/local/etc, the server in /usr/local/sbin, etc. To specify a different -installation prefix, use the --prefix option to configure: - -./configure --prefix=/opt -make -make install - -Will install OpenSSH in /opt/{bin,etc,lib,sbin}. You can also override -specific paths, for example: - -./configure --prefix=/opt --sysconfdir=/etc/ssh -make -make install - -This will install the binaries in /opt/{bin,lib,sbin}, but will place the -configuration files in /etc/ssh. - -If you are using PAM, you will need to manually install a PAM -control file as "/etc/pam.d/sshd" (or wherever your system -prefers to keep them). A generic PAM configuration is included as -"contrib/sshd.pam.generic", you may need to edit it before using it on -your system. If you are using a recent version of Redhat Linux, the -config file in contrib/redhat/sshd.pam should be more useful. -Failure to install a valid PAM file may result in an inability to -use password authentication. - -There are a few other options to the configure script: - ---with-rsh=PATH allows you to specify the path to your rsh program. -Normally ./configure will search the current $PATH for 'rsh'. You -may need to specify this option if rsh is not in your path or has a -different name. - ---without-pam will disable PAM support. PAM is automatically detected -and switched on if found. - ---enable-gnome-askpass will build the GNOME passphrase dialog. You -need a working installation of GNOME, including the development -headers, for this to work. - ---with-random=/some/file allows you to specify an alternate source of -random numbers (the default is /dev/urandom). Unless you are absolutely -sure of what you are doing, it is best to leave this alone. - ---with-egd-pool=/some/file allows you to enable Entropy Gathering -Daemon support and to specify a EGD pool socket. Use this if your -Unix lacks /dev/random and you don't want to use OpenSSH's builtin -entropy collection support. - ---with-lastlog=FILE will specify the location of the lastlog file. -./configure searches a few locations for lastlog, but may not find -it if lastlog is installed in a different place. - ---without-lastlog will disable lastlog support entirely. - ---with-kerberos4=PATH will enable Kerberos IV support. You will need -to have the Kerberos libraries and header files installed for this -to work. Use the optional PATH argument to specify the root of your -Kerberos installation. - ---with-afs=PATH will enable AFS support. You will need to have the -Kerberos IV and the AFS libraries and header files installed for this -to work. Use the optional PATH argument to specify the root of your -AFS installation. AFS requires Kerberos support to be enabled. - ---with-skey will enable S/Key one time password support. You will need -the S/Key libraries and header files installed for this to work. - ---with-tcp-wrappers will enable TCP Wrappers (/etc/hosts.allow|deny) -support. You will need libwrap.a and tcpd.h installed. - ---with-md5-passwords will enable the use of MD5 passwords. Enable this -if your operating system uses MD5 passwords without using PAM. - ---with-utmpx enables utmpx support. utmpx support is automatic for -some platforms. - ---without-shadow disables shadow password support. - ---with-ipaddr-display forces the use of a numeric IP address in the -$DISPLAY environment variable. Some broken systems need this. - ---with-default-path=PATH allows you to specify a default $PATH for sessions -started by sshd. This replaces the standard path entirely. - ---with-pid-dir=PATH specifies the directory in which the ssh.pid file is -created. - ---with-xauth=PATH specifies the location of the xauth binary - ---with-ipv4-default instructs OpenSSH to use IPv4 by default for new -connections. Normally OpenSSH will try attempt to lookup both IPv6 and -IPv4 addresses. On Linux/glibc-2.1.2 this causes long delays in name -resolution. If this option is specified, you can still attempt to -connect to IPv6 addresses using the command line option '-6'. - ---with-ssl-dir=DIR allows you to specify where your OpenSSL libraries -are installed. - ---with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to -real (AF_INET) IPv4 addresses. Works around some quirks on Linux. - -If you need to pass special options to the compiler or linker, you -can specify these as environment variables before running ./configure. -For example: - -CFLAGS="-O -m486" LDFLAGS="-s" LIBS="-lrubbish" LD="/usr/foo/ld" ./configure - -3. Configuration ----------------- - -The runtime configuration files are installed by in ${prefix}/etc or -whatever you specified as your --sysconfdir (/usr/local/etc by default). - -The default configuration should be instantly usable, though you should -review it to ensure that it matches your security requirements. - -To generate a host key, run "make host-key". Alternately you can do so -manually using the following commands: - - ssh-keygen -b 1024 -f /etc/ssh/ssh_host_key -N "" - ssh-keygen -d -f /etc/ssh/ssh_host_dsa_key -N "" - -Replacing /etc/ssh with the correct path to the configuration directory. -(${prefix}/etc or whatever you specified with --sysconfdir during -configuration) - -If you have configured OpenSSH with EGD support, ensure that EGD is -running and has collected some Entropy. - -For more information on configuration, please refer to the manual pages -for sshd, ssh and ssh-agent. - -4. Problems? ------------- - -If you experience problems compiling, installing or running OpenSSH. -Please refer to the "reporting bugs" section of the webpage at -http://www.openssh.com/ - diff --git a/usr/src/cmd/ssh/doc/LICENCE b/usr/src/cmd/ssh/doc/LICENCE deleted file mode 100644 index 04d6fe18e3..0000000000 --- a/usr/src/cmd/ssh/doc/LICENCE +++ /dev/null @@ -1,194 +0,0 @@ -This file is part of the ssh software. - -The licences which components of this software falls under are as -follows. First, we will summarize and say that that all components -are under a BSD licence, or a licence more free than that. - -OpenSSH contains no GPL code. - -1) - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - - [Tatu continues] - * However, I am not implying to give any licenses to any patents or - * copyrights held by third parties, and the software includes parts that - * are not under my direct control. As far as I know, all included - * source code is used in accordance with the relevant license agreements - * and can be used freely for any purpose (the GNU license being the most - * restrictive); see below for details. - - [However, none of that term is relevant at this point in time. All of - these restrictively licenced software components which he talks about - have been removed from OpenSSH, ie. - - - RSA is no longer included, found in the OpenSSL library - - IDEA is no longer included, it's use is depricated - - DES is now external, in the OpenSSL library - - GMP is no longer used, and instead we call BN code from OpenSSL - - Zlib is now external, in a library - - The make-ssh-known-hosts script is no longer included - - TSS has been removed - - MD5 is now external, in the OpenSSL library - - RC4 support has been replaced with ARC4 support from OpenSSL - - Blowfish is now external, in the OpenSSL library - - [The licence continues] - - Note that any information and cryptographic algorithms used in this - software are publicly available on the Internet and at any major - bookstore, scientific library, and patent office worldwide. More - information can be found e.g. at "http://www.cs.hut.fi/crypto". - - The legal status of this program is some combination of all these - permissions and restrictions. Use only at your own responsibility. - You will be responsible for any legal consequences yourself; I am not - making any claims whether possessing or using this is legal or not in - your country, and I am not taking any responsibility on your behalf. - - - NO WARRANTY - - BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY - FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN - OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES - PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED - OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS - TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE - PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, - REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR - REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, - INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING - OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED - TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY - YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER - PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGES. - -2) - The 32-bit CRC implementation in crc32.c is due to Gary S. Brown. - Comments in the file indicate it may be used for any purpose without - restrictions: - - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - -3) - The 32-bit CRC compensation attack detector in deattack.c was - contributed by CORE SDI S.A. under a BSD-style license. See - http://www.core-sdi.com/english/ssh/ for details. - - * Cryptographic attack detector for ssh - source code - * - * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. - * - * All rights reserved. Redistribution and use in source and binary - * forms, with or without modification, are permitted provided that - * this copyright notice is retained. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR - * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS - * SOFTWARE. - * - * Ariel Futoransky <futo@core-sdi.com> - * <http://www.core-sdi.com> - -3a) - Various parts are from the University of California. - - * Copyright (c) 1983, 1987, 1989-1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - - * Copyright (c) 1989, 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - -4) - Remaining components of the software are provided under a standard - 2-term BSD licence with the following names as copyright holders: - - Markus Friedl - Theo de Raadt - Niels Provos - Dug Song - Aaron Campbell - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/usr/src/cmd/ssh/doc/OVERVIEW b/usr/src/cmd/ssh/doc/OVERVIEW deleted file mode 100644 index 7f34ac45bd..0000000000 --- a/usr/src/cmd/ssh/doc/OVERVIEW +++ /dev/null @@ -1,164 +0,0 @@ -This document is intended for those who wish to read the ssh source -code. This tries to give an overview of the structure of the code. - -Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi> -Updated 17 Nov 1995. -Updated 19 Oct 1999 for OpenSSH-1.2 - -The software consists of ssh (client), sshd (server), scp, sdist, and -the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and -make-ssh-known-hosts. The main program for each of these is in a .c -file with the same name. - -There are some subsystems/abstractions that are used by a number of -these programs. - - Buffer manipulation routines - - - These provide an arbitrary size buffer, where data can be appended. - Data can be consumed from either end. The code is used heavily - throughout ssh. The basic buffer manipulation functions are in - buffer.c (header buffer.h), and additional code to manipulate specific - data types is in bufaux.c. - - Compression Library - - - Ssh uses the GNU GZIP compression library (ZLIB). - - Encryption/Decryption - - - Ssh contains several encryption algorithms. These are all - accessed through the cipher.h interface. The interface code is - in cipher.c, and the implementations are in libc. - - Multiple Precision Integer Library - - - Uses the SSLeay BIGNUM sublibrary. - - Some auxiliary functions for mp-int manipulation are in mpaux.c. - - Random Numbers - - - Uses arc4random() and such. - - RSA key generation, encryption, decryption - - - Ssh uses the RSA routines in libssl. - - RSA key files - - - RSA keys are stored in files with a special format. The code to - read/write these files is in authfile.c. The files are normally - encrypted with a passphrase. The functions to read passphrases - are in readpass.c (the same code is used to read passwords). - - Binary packet protocol - - - The ssh binary packet protocol is implemented in packet.c. The - code in packet.c does not concern itself with packet types or their - execution; it contains code to build packets, to receive them and - extract data from them, and the code to compress and/or encrypt - packets. CRC code comes from crc32.c. - - - The code in packet.c calls the buffer manipulation routines - (buffer.c, bufaux.c), compression routines (compress.c, zlib), - and the encryption routines. - - X11, TCP/IP, and Agent forwarding - - - Code for various types of channel forwarding is in channels.c. - The file defines a generic framework for arbitrary communication - channels inside the secure channel, and uses this framework to - implement X11 forwarding, TCP/IP forwarding, and authentication - agent forwarding. - The new, Protocol 1.5, channel close implementation is in nchan.c - - Authentication agent - - - Code to communicate with the authentication agent is in authfd.c. - - Authentication methods - - - Code for various authentication methods resides in auth-*.c - (auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This - code is linked into the server. The routines also manipulate - known hosts files using code in hostfile.c. Code in canohost.c - is used to retrieve the canonical host name of the remote host. - Code in match.c is used to match host names. - - - In the client end, authentication code is in sshconnect.c. It - reads Passwords/passphrases using code in readpass.c. It reads - RSA key files with authfile.c. It communicates the - authentication agent using authfd.c. - - The ssh client - - - The client main program is in ssh.c. It first parses arguments - and reads configuration (readconf.c), then calls ssh_connect (in - sshconnect.c) to open a connection to the server (possibly via a - proxy), and performs authentication (ssh_login in sshconnect.c). - It then makes any pty, forwarding, etc. requests. It may call - code in ttymodes.c to encode current tty modes. Finally it - calls client_loop in clientloop.c. This does the real work for - the session. - - - The client is suid root. It tries to temporarily give up this - rights while reading the configuration data. The root - privileges are only used to make the connection (from a - privileged socket). Any extra privileges are dropped before - calling ssh_login. - - Pseudo-tty manipulation and tty modes - - - Code to allocate and use a pseudo tty is in pty.c. Code to - encode and set terminal modes is in ttymodes.c. - - Logging in (updating utmp, lastlog, etc.) - - - The code to do things that are done when a user logs in are in - login.c. This includes things such as updating the utmp, wtmp, - and lastlog files. Some of the code is in sshd.c. - - Writing to the system log and terminal - - - The programs use the functions fatal(), log(), debug(), error() - in many places to write messages to system log or user's - terminal. The implementation that logs to system log is in - log-server.c; it is used in the server program. The other - programs use an implementation that sends output to stderr; it - is in log-client.c. The definitions are in ssh.h. - - The sshd server (daemon) - - - The sshd daemon starts by processing arguments and reading the - configuration file (servconf.c). It then reads the host key, - starts listening for connections, and generates the server key. - The server key will be regenerated every hour by an alarm. - - - When the server receives a connection, it forks, disables the - regeneration alarm, and starts communicating with the client. - They first perform identification string exchange, then - negotiate encryption, then perform authentication, preparatory - operations, and finally the server enters the normal session - mode by calling server_loop in serverloop.c. This does the real - work, calling functions in other modules. - - - The code for the server is in sshd.c. It contains a lot of - stuff, including: - - server main program - - waiting for connections - - processing new connection - - authentication - - preparatory operations - - building up the execution environment for the user program - - starting the user program. - - Auxiliary files - - - There are several other files in the distribution that contain - various auxiliary routines: - ssh.h the main header file for ssh (various definitions) - getput.h byte-order independent storage of integers - includes.h includes most system headers. Lots of #ifdefs. - tildexpand.c expand tilde in file names - uidswap.c uid-swapping - xmalloc.c "safe" malloc routines diff --git a/usr/src/cmd/ssh/doc/README b/usr/src/cmd/ssh/doc/README deleted file mode 100644 index f94e2ed1c5..0000000000 --- a/usr/src/cmd/ssh/doc/README +++ /dev/null @@ -1,70 +0,0 @@ -[ A Japanese translation of this document is available at -[ http://www.unixuser.org/%7Eharuyama/security/openssh/index.html -[ Thanks to HARUYAMA Seigo <haruyama@nt.phys.s.u-tokyo.ac.jp> - -******* IMPORTANT -* On systmes which lack a /dev/random driver, version of this port -* prior to 1.2.2 were not correctly seeding OpenSSL's random number -* pool. This resulted in lower quality RSA keys being generated. If -* you generated host or user keys with v1.2.2 or previous versions, -* please generate new ones using a more recent version. - -This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other -Unices. - -OpenSSH is based on the last free version of Tatu Ylonen's SSH with -all patent-encumbered algorithms removed (to external libraries), all -known security bugs fixed, new features reintroduced and many other -clean-ups. More information about SSH itself can be found in the file -README.Ylonen. OpenSSH has been created by Aaron Campbell, Bob Beck, -Markus Friedl, Niels Provos, Theo de Raadt, and Dug Song. It has a -homepage at http://www.openssh.com/ - -This port consists of the re-introduction of autoconf support, PAM -support (for Linux and Solaris), EGD[1] support and replacements for -OpenBSD library functions that are (regrettably) absent from other -unices. This port has been best tested on Linux, Solaris, HPUX, NetBSD -and Irix. Support for AIX, SCO, NeXT and other Unices is underway. -This version actively tracks changes in the OpenBSD CVS repository. - -The PAM support is now more functional than the popular packages of -commercial ssh-1.2.x. It checks "account" and "session" modules for -all logins, not just when using password authentication. - -OpenSSH depends on Zlib[2], OpenSSL[3] and optionally PAM[4]. - -There is now several mailing lists for this port of OpenSSH. Please -refer to http://www.openssh.com/list.html for details on how to join. - -Please send bug reports and patches to the mailing list -openssh-unix-dev@mindrot.org. The list is open to posting by -unsubscribed users. - -If you are a citizen of the USA or another country which restricts -export of cryptographic products, then please refrain from sending -crypto-related code or patches to the list. We cannot accept them. -Other code contribution are accepted, but please follow the OpenBSD -style guidelines[5]. - -Please refer to the INSTALL document for information on how to install -OpenSSH on your system. There are a number of differences between this -port of OpenSSH and F-Secure SSH 1.x, please refer to the OpenSSH FAQ[6] -for details and general tips. - -Damien Miller <djm@mindrot.org> - -Miscellania - - -This version of SSH is based upon code retrieved from the OpenBSD CVS -repository which in turn was based on the last free -version of SSH released by Tatu Ylonen. - -References - - -[0] http://www.openssh.com/faq.html -[1] http://www.lothar.com/tech/crypto/ -[2] ftp://ftp.freesoftware.com/pub/infozip/zlib/ -[3] http://www.openssl.org/ -[4] http://www.kernel.org/pub/linux/libs/pam/ (PAM is standard on Solaris) -[5] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9&apropos=0&manpath=OpenBSD+Current -[6] http://www.openssh.com/faq.html diff --git a/usr/src/cmd/ssh/doc/README.Ylonen b/usr/src/cmd/ssh/doc/README.Ylonen deleted file mode 100644 index 38987b926a..0000000000 --- a/usr/src/cmd/ssh/doc/README.Ylonen +++ /dev/null @@ -1,567 +0,0 @@ - -[ Please note that this file has not been updated for OpenSSH and - covers the ssh-1.2.12 release from Dec 1995 only. ] - -Ssh (Secure Shell) is a program to log into another computer over a -network, to execute commands in a remote machine, and to move files -from one machine to another. It provides strong authentication and -secure communications over insecure channels. It is inteded as a -replacement for rlogin, rsh, rcp, and rdist. - -See the file INSTALL for installation instructions. See COPYING for -license terms and other legal issues. See RFC for a description of -the protocol. There is a WWW page for ssh; see http://www.cs.hut.fi/ssh. - -This file has been updated to match ssh-1.2.12. - - -FEATURES - - o Strong authentication. Closes several security holes (e.g., IP, - routing, and DNS spoofing). New authentication methods: .rhosts - together with RSA based host authentication, and pure RSA - authentication. - - o Improved privacy. All communications are automatically and - transparently encrypted. RSA is used for key exchange, and a - conventional cipher (normally IDEA, DES, or triple-DES) for - encrypting the session. Encryption is started before - authentication, and no passwords or other information is - transmitted in the clear. Encryption is also used to protect - against spoofed packets. - - o Secure X11 sessions. The program automatically sets DISPLAY on - the server machine, and forwards any X11 connections over the - secure channel. Fake Xauthority information is automatically - generated and forwarded to the remote machine; the local client - automatically examines incoming X11 connections and replaces the - fake authorization data with the real data (never telling the - remote machine the real information). - - o Arbitrary TCP/IP ports can be redirected through the encrypted channel - in both directions (e.g., for e-cash transactions). - - o No retraining needed for normal users; everything happens - automatically, and old .rhosts files will work with strong - authentication if administration installs host key files. - - o Never trusts the network. Minimal trust on the remote side of - the connection. Minimal trust on domain name servers. Pure RSA - authentication never trusts anything but the private key. - - o Client RSA-authenticates the server machine in the beginning of - every connection to prevent trojan horses (by routing or DNS - spoofing) and man-in-the-middle attacks, and the server - RSA-authenticates the client machine before accepting .rhosts or - /etc/hosts.equiv authentication (to prevent DNS, routing, or - IP-spoofing). - - o Host authentication key distribution can be centrally by the - administration, automatically when the first connection is made - to a machine (the key obtained on the first connection will be - recorded and used for authentication in the future), or manually - by each user for his/her own use. The central and per-user host - key repositories are both used and complement each other. Host - keys can be generated centrally or automatically when the software - is installed. Host authentication keys are typically 1024 bits. - - o Any user can create any number of user authentication RSA keys for - his/her own use. Each user has a file which lists the RSA public - keys for which proof of possession of the corresponding private - key is accepted as authentication. User authentication keys are - typically 1024 bits. - - o The server program has its own server RSA key which is - automatically regenerated every hour. This key is never saved in - any file. Exchanged session keys are encrypted using both the - server key and the server host key. The purpose of the separate - server key is to make it impossible to decipher a captured session by - breaking into the server machine at a later time; one hour from - the connection even the server machine cannot decipher the session - key. The key regeneration interval is configurable. The server - key is normally 768 bits. - - o An authentication agent, running in the user's laptop or local - workstation, can be used to hold the user's RSA authentication - keys. Ssh automatically forwards the connection to the - authentication agent over any connections, and there is no need to - store the RSA authentication keys on any machine in the network - (except the user's own local machine). The authentication - protocols never reveal the keys; they can only be used to verify - that the user's agent has a certain key. Eventually the agent - could rely on a smart card to perform all authentication - computations. - - o The software can be installed and used (with restricted - functionality) even without root privileges. - - o The client is customizable in system-wide and per-user - configuration files. Most aspects of the client's operation can - be configured. Different options can be specified on a per-host basis. - - o Automatically executes conventional rsh (after displaying a - warning) if the server machine is not running sshd. - - o Optional compression of all data with gzip (including forwarded X11 - and TCP/IP port data), which may result in significant speedups on - slow connections. - - o Complete replacement for rlogin, rsh, and rcp. - - -WHY TO USE SECURE SHELL - -Currently, almost all communications in computer networks are done -without encryption. As a consequence, anyone who has access to any -machine connected to the network can listen in on any communication. -This is being done by hackers, curious administrators, employers, -criminals, industrial spies, and governments. Some networks leak off -enough electromagnetic radiation that data may be captured even from a -distance. - -When you log in, your password goes in the network in plain -text. Thus, any listener can then use your account to do any evil he -likes. Many incidents have been encountered worldwide where crackers -have started programs on workstations without the owners knowledge -just to listen to the network and collect passwords. Programs for -doing this are available on the Internet, or can be built by a -competent programmer in a few hours. - -Any information that you type or is printed on your screen can be -monitored, recorded, and analyzed. For example, an intruder who has -penetrated a host connected to a major network can start a program -that listens to all data flowing in the network, and whenever it -encounters a 16-digit string, it checks if it is a valid credit card -number (using the check digit), and saves the number plus any -surrounding text (to catch expiration date and holder) in a file. -When the intruder has collected a few thousand credit card numbers, he -makes smallish mail-order purchases from a few thousand stores around -the world, and disappears when the goods arrive but before anyone -suspects anything. - -Businesses have trade secrets, patent applications in preparation, -pricing information, subcontractor information, client data, personnel -data, financial information, etc. Currently, anyone with access to -the network (any machine on the network) can listen to anything that -goes in the network, without any regard to normal access restrictions. - -Many companies are not aware that information can so easily be -recovered from the network. They trust that their data is safe -since nobody is supposed to know that there is sensitive information -in the network, or because so much other data is transferred in the -network. This is not a safe policy. - -Individual persons also have confidential information, such as -diaries, love letters, health care documents, information about their -personal interests and habits, professional data, job applications, -tax reports, political documents, unpublished manuscripts, etc. - -One should also be aware that economical intelligence and industrial -espionage has recently become a major priority of the intelligence -agencies of major governments. President Clinton recently assigned -economical espionage as the primary task of the CIA, and the French -have repeatedly been publicly boasting about their achievements on -this field. - - -There is also another frightening aspect about the poor security of -communications. Computer storage and analysis capability has -increased so much that it is feasible for governments, major -companies, and criminal organizations to automatically analyze, -identify, classify, and file information about millions of people over -the years. Because most of the work can be automated, the cost of -collecting this information is getting very low. - -Government agencies may be able to monitor major communication -systems, telephones, fax, computer networks, etc., and passively -collect huge amounts of information about all people with any -significant position in the society. Most of this information is not -sensitive, and many people would say there is no harm in someone -getting that information. However, the information starts to get -sensitive when someone has enough of it. You may not mind someone -knowing what you bought from the shop one random day, but you might -not like someone knowing every small thing you have bought in the last -ten years. - -If the government some day starts to move into a more totalitarian -direction (one should remember that Nazi Germany was created by -democratic elections), there is considerable danger of an ultimate -totalitarian state. With enough information (the automatically -collected records of an individual can be manually analyzed when the -person becomes interesting), one can form a very detailed picture of -the individual's interests, opinions, beliefs, habits, friends, -lovers, weaknesses, etc. This information can be used to 1) locate -any persons who might oppose the new system 2) use deception to -disturb any organizations which might rise against the government 3) -eliminate difficult individuals without anyone understanding what -happened. Additionally, if the government can monitor communications -too effectively, it becomes too easy to locate and eliminate any -persons distributing information contrary to the official truth. - -Fighting crime and terrorism are often used as grounds for domestic -surveillance and restricting encryption. These are good goals, but -there is considerable danger that the surveillance data starts to get -used for questionable purposes. I find that it is better to tolerate -a small amount of crime in the society than to let the society become -fully controlled. I am in favor of a fairly strong state, but the -state must never get so strong that people become unable to spread -contra-offical information and unable to overturn the government if it -is bad. The danger is that when you notice that the government is -too powerful, it is too late. Also, the real power may not be where -the official government is. - -For these reasons (privacy, protecting trade secrets, and making it -more difficult to create a totalitarian state), I think that strong -cryptography should be integrated to the tools we use every day. -Using it causes no harm (except for those who wish to monitor -everything), but not using it can cause huge problems. If the society -changes in undesirable ways, then it will be to late to start -encrypting. - -Encryption has had a "military" or "classified" flavor to it. There -are no longer any grounds for this. The military can and will use its -own encryption; that is no excuse to prevent the civilians from -protecting their privacy and secrets. Information on strong -encryption is available in every major bookstore, scientific library, -and patent office around the world, and strong encryption software is -available in every country on the Internet. - -Some people would like to make it illegal to use encryption, or to -force people to use encryption that governments can break. This -approach offers no protection if the government turns bad. Also, the -"bad guys" will be using true strong encryption anyway. Good -encryption techniques are too widely known to make them disappear. -Thus, any "key escrow encryption" or other restrictions will only help -monitor ordinary people and petty criminals. It does not help against -powerful criminals, terrorists, or espionage, because they will know -how to use strong encryption anyway. (One source for internationally -available encryption software is http://www.cs.hut.fi/crypto.) - - -OVERVIEW OF SECURE SHELL - -The software consists of a number of programs. - - sshd Server program run on the server machine. This - listens for connections from client machines, and - whenever it receives a connection, it performs - authentication and starts serving the client. - - ssh This is the client program used to log into another - machine or to execute commands on the other machine. - "slogin" is another name for this program. - - scp Securely copies files from one machine to another. - - ssh-keygen Used to create RSA keys (host keys and user - authentication keys). - - ssh-agent Authentication agent. This can be used to hold RSA - keys for authentication. - - ssh-add Used to register new keys with the agent. - - make-ssh-known-hosts - Used to create the /etc/ssh_known_hosts file. - - -Ssh is the program users normally use. It is started as - - ssh host - -or - - ssh host command - -The first form opens a new shell on the remote machine (after -authentication). The latter form executes the command on the remote -machine. - -When started, the ssh connects sshd on the server machine, verifies -that the server machine really is the machine it wanted to connect, -exchanges encryption keys (in a manner which prevents an outside -listener from getting the keys), performs authentication using .rhosts -and /etc/hosts.equiv, RSA authentication, or conventional password -based authentication. The server then (normally) allocates a -pseudo-terminal and starts an interactive shell or user program. - -The TERM environment variable (describing the type of the user's -terminal) is passed from the client side to the remote side. Also, -terminal modes will be copied from the client side to the remote side -to preserve user preferences (e.g., the erase character). - -If the DISPLAY variable is set on the client side, the server will -create a dummy X server and set DISPLAY accordingly. Any connections -to the dummy X server will be forwarded through the secure channel, -and will be made to the real X server from the client side. An -arbitrary number of X programs can be started during the session, and -starting them does not require anything special from the user. (Note -that the user must not manually set DISPLAY, because then it would -connect directly to the real display instead of going through the -encrypted channel). This behavior can be disabled in the -configuration file or by giving the -x option to the client. - -Arbitrary IP ports can be forwarded over the secure channel. The -program then creates a port on one side, and whenever a connection is -opened to this port, it will be passed over the secure channel, and a -connection will be made from the other side to a specified host:port -pair. Arbitrary IP forwarding must always be explicitly requested, -and cannot be used to forward privileged ports (unless the user is -root). It is possible to specify automatic forwards in a per-user -configuration file, for example to make electronic cash systems work -securely. - -If there is an authentication agent on the client side, connection to -it will be automatically forwarded to the server side. - -For more infomation, see the manual pages ssh(1), sshd(8), scp(1), -ssh-keygen(1), ssh-agent(1), ssh-add(1), and make-ssh-known-hosts(1) -included in this distribution. - - -X11 CONNECTION FORWARDING - -X11 forwarding serves two purposes: it is a convenience to the user -because there is no need to set the DISPLAY variable, and it provides -encrypted X11 connections. I cannot think of any other easy way to -make X11 connections encrypted; modifying the X server, clients or -libraries would require special work for each machine, vendor and -application. Widely used IP-level encryption does not seem likely for -several years. Thus what we have left is faking an X server on the -same machine where the clients are run, and forwarding the connections -to a real X server over the secure channel. - -X11 forwarding works as follows. The client extracts Xauthority -information for the server. It then creates random authorization -data, and sends the random data to the server. The server allocates -an X11 display number, and stores the (fake) Xauthority data for this -display. Whenever an X11 connection is opened, the server forwards -the connection over the secure channel to the client, and the client -parses the first packet of the X11 protocol, substitutes real -authentication data for the fake data (if the fake data matched), and -forwards the connection to the real X server. - -If the display does not have Xauthority data, the server will create a -unix domain socket in /tmp/.X11-unix, and use the unix domain socket -as the display. No authentication information is forwarded in this -case. X11 connections are again forwarded over the secure channel. -To the X server the connections appear to come from the client -machine, and the server must have connections allowed from the local -machine. Using authentication data is always recommended because not -using it makes the display insecure. If XDM is used, it automatically -generates the authentication data. - -One should be careful not to use "xin" or "xstart" or other similar -scripts that explicitly set DISPLAY to start X sessions in a remote -machine, because the connection will then not go over the secure -channel. The recommended way to start a shell in a remote machine is - - xterm -e ssh host & - -and the recommended way to execute an X11 application in a remote -machine is - - ssh -n host emacs & - -If you need to type a password/passphrase for the remote machine, - - ssh -f host emacs - -may be useful. - - - -RSA AUTHENTICATION - -RSA authentication is based on public key cryptograpy. The idea is -that there are two encryption keys, one for encryption and another for -decryption. It is not possible (on human timescale) to derive the -decryption key from the encryption key. The encryption key is called -the public key, because it can be given to anyone and it is not -secret. The decryption key, on the other hand, is secret, and is -called the private key. - -RSA authentication is based on the impossibility of deriving the -private key from the public key. The public key is stored on the -server machine in the user's $HOME/.ssh/authorized_keys file. The -private key is only kept on the user's local machine, laptop, or other -secure storage. Then the user tries to log in, the client tells the -server the public key that the user wishes to use for authentication. -The server then checks if this public key is admissible. If so, it -generates a 256 bit random number, encrypts it with the public key, -and sends the value to the client. The client then decrypts the -number with its private key, computes a 128 bit MD5 checksum from the -resulting data, and sends the checksum back to the server. (Only a -checksum is sent to prevent chosen-plaintext attacks against RSA.) -The server checks computes a checksum from the correct data, -and compares the checksums. Authentication is accepted if the -checksums match. (Theoretically this indicates that the client -only probably knows the correct key, but for all practical purposes -there is no doubt.) - -The RSA private key can be protected with a passphrase. The -passphrase can be any string; it is hashed with MD5 to produce an -encryption key for IDEA, which is used to encrypt the private part of -the key file. With passphrase, authorization requires access to the key -file and the passphrase. Without passphrase, authorization only -depends on possession of the key file. - -RSA authentication is the most secure form of authentication supported -by this software. It does not rely on the network, routers, domain -name servers, or the client machine. The only thing that matters is -access to the private key. - -All this, of course, depends on the security of the RSA algorithm -itself. RSA has been widely known since about 1978, and no effective -methods for breaking it are known if it is used properly. Care has -been taken to avoid the well-known pitfalls. Breaking RSA is widely -believed to be equivalent to factoring, which is a very hard -mathematical problem that has received considerable public research. -So far, no effective methods are known for numbers bigger than about -512 bits. However, as computer speeds and factoring methods are -increasing, 512 bits can no longer be considered secure. The -factoring work is exponential, and 768 or 1024 bits are widely -considered to be secure in the near future. - - -RHOSTS AUTHENTICATION - -Conventional .rhosts and hosts.equiv based authentication mechanisms -are fundamentally insecure due to IP, DNS (domain name server) and -routing spoofing attacks. Additionally this authentication method -relies on the integrity of the client machine. These weaknesses is -tolerable, and been known and exploited for a long time. - -Ssh provides an improved version of these types of authentication, -because they are very convenient for the user (and allow easy -transition from rsh and rlogin). It permits these types of -authentication, but additionally requires that the client host be -authenticated using RSA. - -The server has a list of host keys stored in /etc/ssh_known_host, and -additionally each user has host keys in $HOME/.ssh/known_hosts. Ssh -uses the name servers to obtain the canonical name of the client host, -looks for its public key in its known host files, and requires the -client to prove that it knows the private host key. This prevents IP -and routing spoofing attacks (as long as the client machine private -host key has not been compromized), but is still vulnerable to DNS -attacks (to a limited extent), and relies on the integrity of the -client machine as to who is requesting to log in. This prevents -outsiders from attacking, but does not protect against very powerful -attackers. If maximal security is desired, only RSA authentication -should be used. - -It is possible to enable conventional .rhosts and /etc/hosts.equiv -authentication (without host authentication) at compile time by giving -the option --with-rhosts to configure. However, this is not -recommended, and is not done by default. - -These weaknesses are present in rsh and rlogin. No improvement in -security will be obtained unless rlogin and rsh are completely -disabled (commented out in /etc/inetd.conf). This is highly -recommended. - - -WEAKEST LINKS IN SECURITY - -One should understand that while this software may provide -cryptographically secure communications, it may be easy to -monitor the communications at their endpoints. - -Basically, anyone with root access on the local machine on which you -are running the software may be able to do anything. Anyone with root -access on the server machine may be able to monitor your -communications, and a very talented root user might even be able to -send his/her own requests to your authentication agent. - -One should also be aware that computers send out electromagnetic -radition that can sometimes be picked up hundreds of meters away. -Your keyboard is particularly easy to listen to. The image on your -monitor might also be seen on another monitor in a van parked behind -your house. - -Beware that unwanted visitors might come to your home or office and -use your machine while you are away. They might also make -modifications or install bugs in your hardware or software. - -Beware that the most effective way for someone to decrypt your data -may be with a rubber hose. - - -LEGAL ISSUES - -As far as I am concerned, anyone is permitted to use this software -freely. However, see the file COPYING for detailed copying, -licensing, and distribution information. - -In some countries, particularly France, Russia, Iraq, and Pakistan, -it may be illegal to use any encryption at all without a special -permit, and the rumor has it that you cannot get a permit for any -strong encryption. - -This software may be freely imported into the United States; however, -the United States Government may consider re-exporting it a criminal -offence. - -Note that any information and cryptographic algorithms used in this -software are publicly available on the Internet and at any major -bookstore, scientific library, or patent office worldwide. - -THERE IS NO WARRANTY FOR THIS PROGRAM. Please consult the file -COPYING for more information. - - -MAILING LISTS AND OTHER INFORMATION - -There is a mailing list for ossh. It is ossh@sics.se. If you would -like to join, send a message to majordomo@sics.se with "subscribe -ssh" in body. - -The WWW home page for ssh is http://www.cs.hut.fi/ssh. It contains an -archive of the mailing list, and detailed information about new -releases, mailing lists, and other relevant issues. - -Bug reports should be sent to ossh-bugs@sics.se. - - -ABOUT THE AUTHOR - -This software was written by Tatu Ylonen <ylo@cs.hut.fi>. I work as a -researcher at Helsinki University of Technology, Finland. For more -information, see http://www.cs.hut.fi/~ylo/. My PGP public key is -available via finger from ylo@cs.hut.fi and from the key servers. I -prefer PGP encrypted mail. - -The author can be contacted via ordinary mail at - Tatu Ylonen - Helsinki University of Technology - Otakaari 1 - FIN-02150 ESPOO - Finland - - Fax. +358-0-4513293 - - -ACKNOWLEDGEMENTS - -I thank Tero Kivinen, Timo Rinne, Janne Snabb, and Heikki Suonsivu for -their help and comments in the design, implementation and porting of -this software. I also thank numerous contributors, including but not -limited to Walker Aumann, Jurgen Botz, Hans-Werner Braun, Stephane -Bortzmeyer, Adrian Colley, Michael Cooper, David Dombek, Jerome -Etienne, Bill Fithen, Mark Fullmer, Bert Gijsbers, Andreas Gustafsson, -Michael Henits, Steve Johnson, Thomas Koenig, Felix Leitner, Gunnar -Lindberg, Andrew Macpherson, Marc Martinec, Paul Mauvais, Donald -McKillican, Leon Mlakar, Robert Muchsel, Mark Treacy, Bryan -O'Sullivan, Mikael Suokas, Ollivier Robert, Jakob Schlyter, Tomasz -Surmacz, Alvar Vinacua, Petri Virkkula, Michael Warfield, and -Cristophe Wolfhugel. - -Thanks also go to Philip Zimmermann, whose PGP software and the -associated legal battle provided inspiration, motivation, and many -useful techniques, and to Bruce Schneier whose book Applied -Cryptography has done a great service in widely distributing knowledge -about cryptographic methods. - - -Copyright (c) 1995 Tatu Ylonen, Espoo, Finland. diff --git a/usr/src/cmd/ssh/doc/WARNING.RNG b/usr/src/cmd/ssh/doc/WARNING.RNG deleted file mode 100644 index 21f4901c98..0000000000 --- a/usr/src/cmd/ssh/doc/WARNING.RNG +++ /dev/null @@ -1,79 +0,0 @@ -This document contains a description of portable OpenSSH's random -number collection code. An alternate reading of this text could -well be titled "Why I should pressure my system vendor to supply -/dev/random in their OS". - -Why is this important? OpenSSH depends on good, unpredictable numbers -for generating keys, performing digital signatures and forming -cryptographic challenges. If the random numbers that it uses are -predictable, then the strength of the whole system is compromised. - -A particularly pernicious problem arises with DSA keys (used by the -ssh2 protocol). Performing a DSA signature (which is required for -authentication), entails the use of a 160 bit random number. If an -attacker can predict this number, then they can deduce your *private* -key and impersonate you or your hosts. - -If you are using the builtin random number support (configure will -tell you if this is the case), then read this document in its entirety. - -Please also request that your OS vendor provides a kernel-based random -number collector (/dev/random) in future versions of your operating -systems by default. - -On to the description... - -The portable OpenSSH contains random number collection support for -systems which lack a kernel entropy pool (/dev/random). - -This collector operates by executing the programs listed in -($etcdir)/ssh_prng_cmds, reading their output and adding it to the -PRNG supplied by OpenSSL (which is hash-based). It also stirs in the -output of several system calls and timings from the execution of the -programs that it runs. - -The ssh_prng_cmds file also specifies a 'rate' for each program. This -represents the number of bits of randomness per byte of output from -the specified program. - -The random number code will also read and save a seed file to -~/.ssh/prng_seed. This contents of this file are added to the random -number generator at startup. The goal here is to maintain as much -randomness between sessions as possible. - -The entropy collection code has two main problems: - -1. It is slow. - -Executing each program in the list can take a large amount of time, -especially on slower machines. Additionally some program can take a -disproportionate time to execute. - -This can be tuned by the administrator. To debug the entropy -collection is great detail, turn on full debugging ("ssh -v -v -v" or -"sshd -d -d -d"). This will list each program as it is executed, how -long it took to execute, its exit status and whether and how much data -it generated. You can the find the culprit programs which are causing -the real slow-downs. - -The entropy collector will timeout programs which take too long -to execute, the actual timeout used can be adjusted with the ---with-entropy-timeout configure option. OpenSSH will not try to -re-execute programs which have not been found, have had a non-zero -exit status or have timed out more than a couple of times. - -2. Estimating the real 'rate' of program outputs is non-trivial - -The shear volume of the task is problematic: there are currently -around 50 commands in the ssh_prng_cmds list, portable OpenSSH -supports at least 12 different OSs. That is already 600 sets of data -to be analysed, without taking into account the numerous differences -between versions of each OS. - -On top of this, the different commands can produce varying amounts of -usable data depending on how busy the machine is, how long it has been -up and various other factors. - -To make matters even more complex, some of the commands are reporting -largely the same data as other commands (eg. the various "ps" calls). - diff --git a/usr/src/cmd/ssh/doc/nchan.ms b/usr/src/cmd/ssh/doc/nchan.ms deleted file mode 100644 index 1679d39f30..0000000000 --- a/usr/src/cmd/ssh/doc/nchan.ms +++ /dev/null @@ -1,97 +0,0 @@ -.\" -.\" Copyright (c) 1999 Markus Friedl. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.TL -OpenSSH Channel Close Protocol 1.5 Implementation -.SH -Channel Input State Diagram -.PS -reset -l=1 -s=1.2 -ellipsewid=s*ellipsewid -boxwid=s*boxwid -ellipseht=s*ellipseht -S1: ellipse "INPUT" "OPEN" -move right 2*l from last ellipse.e -S4: ellipse "INPUT" "CLOSED" -move down l from last ellipse.s -S3: ellipse "INPUT" "WAIT" "OCLOSED" -move down l from 1st ellipse.s -S2: ellipse "INPUT" "WAIT" "DRAIN" -arrow "" "rcvd OCLOSE/" "shutdown_read" "send IEOF" from S1.e to S4.w -arrow "ibuf_empty/" "send IEOF" from S2.e to S3.w -arrow from S1.s to S2.n -box invis "read_failed/" "shutdown_read" with .e at last arrow.c -arrow from S3.n to S4.s -box invis "rcvd OCLOSE/" "-" with .w at last arrow.c -ellipse wid .9*ellipsewid ht .9*ellipseht at S4 -arrow "start" "" from S1.w+(-0.5,0) to S1.w -arrow from S2.ne to S4.sw -box invis "rcvd OCLOSE/ " with .e at last arrow.c -box invis " send IEOF" with .w at last arrow.c -.PE -.SH -Channel Output State Diagram -.PS -S1: ellipse "OUTPUT" "OPEN" -move right 2*l from last ellipse.e -S3: ellipse "OUTPUT" "WAIT" "IEOF" -move down l from last ellipse.s -S4: ellipse "OUTPUT" "CLOSED" -move down l from 1st ellipse.s -S2: ellipse "OUTPUT" "WAIT" "DRAIN" -arrow "" "write_failed/" "shutdown_write" "send OCLOSE" from S1.e to S3.w -arrow "obuf_empty ||" "write_failed/" "shutdown_write" "send OCLOSE" from S2.e to S4.w -arrow from S1.s to S2.n -box invis "rcvd IEOF/" "-" with .e at last arrow.c -arrow from S3.s to S4.n -box invis "rcvd IEOF/" "-" with .w at last arrow.c -ellipse wid .9*ellipsewid ht .9*ellipseht at S4 -arrow "start" "" from S1.w+(-0.5,0) to S1.w -.PE -.SH -Notes -.PP -The input buffer is filled with data from the socket -(the socket represents the local consumer/producer of the -forwarded channel). -The data is then sent over the INPUT-end (transmit-end) of the channel to the -remote peer. -Data sent by the peer is received on the OUTPUT-end (receive-end), -saved in the output buffer and written to the socket. -.PP -If the local protocol instance has forwarded all data on the -INPUT-end of the channel, it sends an IEOF message to the peer. -If the peer receives the IEOF and has consumed all -data he replies with an OCLOSE. -When the local instance receives the OCLOSE -he considers the INPUT-half of the channel closed. -The peer has his OUTOUT-half closed. -.PP -A channel can be deallocated by a protocol instance -if both the INPUT- and the OUTOUT-half on his -side of the channel are closed. -Note that when an instance is unable to consume the -received data, he is permitted to send an OCLOSE -before the matching IEOF is received. diff --git a/usr/src/cmd/ssh/doc/nchan2.ms b/usr/src/cmd/ssh/doc/nchan2.ms deleted file mode 100644 index 1b119d1353..0000000000 --- a/usr/src/cmd/ssh/doc/nchan2.ms +++ /dev/null @@ -1,64 +0,0 @@ -.TL -OpenSSH Channel Close Protocol 2.0 Implementation -.SH -Channel Input State Diagram -.PS -reset -l=1 -s=1.2 -ellipsewid=s*ellipsewid -boxwid=s*boxwid -ellipseht=s*ellipseht -S1: ellipse "INPUT" "OPEN" -move right 2*l from last ellipse.e -S3: ellipse invis -move down l from last ellipse.s -S4: ellipse "INPUT" "CLOSED" -move down l from 1st ellipse.s -S2: ellipse "INPUT" "WAIT" "DRAIN" -arrow from S1.e to S4.n -box invis "rcvd CLOSE/" "shutdown_read" with .sw at last arrow.c -arrow "ibuf_empty ||" "rcvd CLOSE/" "send EOF" "" from S2.e to S4.w -arrow from S1.s to S2.n -box invis "read_failed/" "shutdown_read" with .e at last arrow.c -ellipse wid .9*ellipsewid ht .9*ellipseht at S4 -arrow "start" "" from S1.w+(-0.5,0) to S1.w -.PE -.SH -Channel Output State Diagram -.PS -S1: ellipse "OUTPUT" "OPEN" -move right 2*l from last ellipse.e -S3: ellipse invis -move down l from last ellipse.s -S4: ellipse "OUTPUT" "CLOSED" -move down l from 1st ellipse.s -S2: ellipse "OUTPUT" "WAIT" "DRAIN" -arrow from S1.e to S4.n -box invis "write_failed/" "shutdown_write" with .sw at last arrow.c -arrow "obuf_empty ||" "write_failed/" "shutdown_write" "" from S2.e to S4.w -arrow from S1.s to S2.n -box invis "rcvd EOF ||" "rcvd CLOSE/" "-" with .e at last arrow.c -ellipse wid .9*ellipsewid ht .9*ellipseht at S4 -arrow "start" "" from S1.w+(-0.5,0) to S1.w -.PE -.SH -Notes -.PP -The input buffer is filled with data from the socket -(the socket represents the local consumer/producer of the -forwarded channel). -The data is then sent over the INPUT-end (transmit-end) of the channel to the -remote peer. -Data sent by the peer is received on the OUTPUT-end (receive-end), -saved in the output buffer and written to the socket. -.PP -If the local protocol instance has forwarded all data on the -INPUT-end of the channel, it sends an EOF message to the peer. -.PP -A CLOSE message is sent to the peer if -both the INPUT- and the OUTOUT-half of the local -end of the channel are closed. -.PP -The channel can be deallocated by a protocol instance -if a CLOSE message he been both sent and received. diff --git a/usr/src/cmd/ssh/etc/Makefile b/usr/src/cmd/ssh/etc/Makefile deleted file mode 100644 index 305f328f34..0000000000 --- a/usr/src/cmd/ssh/etc/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -MANIFEST = ssh.xml -SVCMETHOD = sshd - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -SSHASKPASS= $(ROOTLIBSSH)/ssh-askpass -ETCSSHDIR= $(ROOTETC)/ssh -DIRS= $(ETCSSHDIR) $(ROOTLIBSSH) - -FILES= sshd_config ssh_config moduli - -ETCSSHFILES= $(FILES:%=$(ETCSSHDIR)/%) - -$(ETCSSHFILES) := FILEMODE= 644 - -ROOTMANIFESTDIR = $(ROOTSVCNETWORK) - -$(ETCSSHDIR)/% : % - $(INS.file) - -$(DIRS): - $(INS.dir) - -$(ROOTLIBSSH)/%: % - $(INS.file) - -$(POFILE): - -all lint clean clobber _msg: - -install: all $(DIRS) $(ETCSSHFILES) $(ROOTMANIFEST) $(ROOTSVCMETHOD) \ - $(SSHASKPASS) - -check: $(CHKMANIFEST) - -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/etc/moduli b/usr/src/cmd/ssh/etc/moduli deleted file mode 100644 index c4a77c93a1..0000000000 --- a/usr/src/cmd/ssh/etc/moduli +++ /dev/null @@ -1,163 +0,0 @@ -#ident "%Z%%M% %I% %E% SMI" -# -# This document does not constitute an API. The /etc/ssh/moduli file -# may not exist or may have a different content or interpretation in a -# future release. The existence of this notice does not imply that any -# other documentation that lacks this notice constitutes an API. -# -# Time Type Tests Tries Size Generator Modulus -20010328182134 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449C221CB -20010328182222 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449C95A43 -20010328182256 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449CC8CFB -20010328182409 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449D9BDB7 -20010328182628 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449FB6EF3 -20010328182708 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A000153 -20010328182758 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A06E9EB -20010328182946 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A1F2C93 -20010328183015 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A206ADB -20010328183112 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A2A109B -20010328183143 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A2BC1BB -20010328183301 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A3ADCEB -20010328183532 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A5E8BAF -20010328183646 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A6D54D7 -20010328183712 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A6EC46F -20010328184223 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AB8626F -20010328184337 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AC7DC73 -20010328184634 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AEFF073 -20010328184714 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AF594FF -20010328184807 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AFEEC53 -20010328184910 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B0B3513 -20010328185030 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B165707 -20010328185334 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B3A9673 -20010328185423 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B426623 -20010328185451 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B4427DB -20010328185637 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B5E3FC7 -20010328185720 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B65964B -20010328185757 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B6A9373 -20010328185844 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B7203B3 -20010328185933 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B7A9FFF -20010328190006 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B7DAAD3 -20010328190054 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B855C2F -20010328190139 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B8C53EB -20010328190304 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B9F26C3 -20010328190329 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BA00697 -20010328190412 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BA54313 -20010328190506 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BAEEF27 -20010328190550 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BB5CE0B -20010328200734 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC33395187 -20010328201124 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC334ED15B -20010328201358 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3359FC07 -20010328201537 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC335F7A83 -20010328201829 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC336D1433 -20010328202120 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC337B253B -20010328202848 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC33A3D43F -20010328203335 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC33BF24A3 -20010328204332 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC34011B8B -20010328204443 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3402A92F -20010328204617 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3406D343 -20010328205458 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3436FA2B -20010328210413 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3471CF1B -20010328213513 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC352AF5EF -20010328215014 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC358CC3CB -20010328215520 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35A9B7FF -20010328215733 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35B2927F -20010328220114 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35C47323 -20010328220334 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35CFA9C3 -20010328220653 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35E0BB37 -20010328220915 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35E9CC23 -20010328221256 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35FD7D67 -20010328221457 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC36052CCB -20010328222639 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC364A1E07 -20010328224126 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC36AD5557 -20010328225125 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC36EE57BF -20010328225751 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3716A70B -20010328225943 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC371D010B -20010328230054 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC371EB5C7 -20010328230301 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC37275F4B -20010328230628 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3738C3F3 -20010329000424 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853ACAACAB -20010329001637 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853AE5BE0F -20010329002229 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853AEDE2D3 -20010329003652 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853B0F32CB -20010329005040 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853B30E503 -20010329014643 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853BC9AF57 -20010329021950 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853C205263 -20010329023256 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853C3F2E53 -20010329031049 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853CA28BBF -20010329032045 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853CB81103 -20010329052113 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853DF13B47 -20010329052449 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853DF3ED53 -20010329060404 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853E5D25E7 -20010329062856 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853E9CF013 -20010329063152 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853E9E1CEB -20010329070601 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853EF58B7F -20010329071302 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F017697 -20010329072011 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F0E72D3 -20010329072445 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F14CE17 -20010329073641 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F2EEBA3 -20010329075209 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F52E927 -20010329080750 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F776F8B -20010329084002 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853FC98043 -20010329084744 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853FD7EAAF -20010329090209 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853FF9AF5F -20010329093527 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385404E330B -20010329094652 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938540672D1F -20010329103445 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938540E4B213 -20010329111418 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993854144947F -20010329112031 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385414F223B -20010329112413 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938541522073 -20010329114209 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385417C8E53 -20010329125026 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385422E41AB -20010329132045 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385427DD3FF -20010329134105 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938542AFA2D7 -20010329134914 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938542C04A37 -20010403222140 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0AB16DAF -20010403225231 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0AC56CFF -20010404053436 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0C2F4B7F -20010404092851 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D04E7F7 -20010404093943 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D07794B -20010404102659 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D2BE8CF -20010404112553 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D5D012B -20010404174625 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0EA59E17 -20010404184645 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0ED6DA4F -20010404193402 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0EFB39B3 -20010404230716 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0FB07C1B -20010405044433 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B10DD9FC3 -20010405053429 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B11038737 -20010405062826 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B112E24E7 -20010405092601 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B11C9E9FB -20010405113007 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B123803EB -20010405122212 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B12612ED3 -20010405182035 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B13A25087 -20010405210758 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B142C4E23 -20010405220222 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B145878F3 -20010406020130 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B152AF6AB -20010406053538 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B15E78C8B -20010406073014 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1649BFEF -20010406074100 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B164D4E3F -20010406103625 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B16E07B33 -20010406131946 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B17706243 -20010406170234 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B182FD957 -20010406182949 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B18768903 -20010406203157 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B18DCFC3B -20010407022825 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1A1AF797 -20010407071024 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1B1551E7 -20010407112402 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1BF78EC7 -20010407123215 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1C30021B -20010407161504 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1CF27743 -20010407171629 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1D25FAD7 -20010407191502 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1D8C2753 -20010420002705 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10C1E08F3 -20010420005243 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10C219FB3 -20010420035225 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10C660B3F -20010420145749 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10D741313 -20010420205718 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10DD41193 -20010420232458 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10E0AB4EF -20010421003952 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10E22F857 -20010421013245 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10E31828B -20010421085157 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10EE28B2B -20010421092617 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10EE97A3B -20010421135621 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10F52C463 -20010422012438 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C110627AF3 -20010422042530 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C110A793B3 -20010422163438 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C111D2A227 diff --git a/usr/src/cmd/ssh/etc/ssh.xml b/usr/src/cmd/ssh/etc/ssh.xml deleted file mode 100644 index 3a08195ff1..0000000000 --- a/usr/src/cmd/ssh/etc/ssh.xml +++ /dev/null @@ -1,169 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> -<!-- - 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 2009 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - NOTE: This service manifest is not editable; its contents will - be overwritten by package or patch operations, including - operating system upgrade. Make customizations in a different - file. ---> - -<service_bundle type='manifest' name='SUNWsshdr:ssh'> - -<service - name='network/ssh' - type='service' - version='1'> - - <create_default_instance enabled='false' /> - - <single_instance /> - - <dependency name='fs-local' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/local' /> - </dependency> - - <dependency name='fs-autofs' - grouping='optional_all' - restart_on='none' - type='service'> - <service_fmri value='svc:/system/filesystem/autofs' /> - </dependency> - - <dependency name='net-loopback' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri value='svc:/network/loopback' /> - </dependency> - - <dependency name='net-physical' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri value='svc:/network/physical' /> - </dependency> - - <dependency name='cryptosvc' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri value='svc:/system/cryptosvc' /> - </dependency> - - <dependency name='utmp' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri value='svc:/system/utmp' /> - </dependency> - - <dependency name='network_ipfilter' - grouping='optional_all' - restart_on='error' - type='service'> - <service_fmri value='svc:/network/ipfilter:default' /> - </dependency> - - <dependency name='config_data' - grouping='require_all' - restart_on='restart' - type='path'> - <service_fmri - value='file://localhost/etc/ssh/sshd_config' /> - </dependency> - - <dependent - name='ssh_multi-user-server' - grouping='optional_all' - restart_on='none'> - <service_fmri - value='svc:/milestone/multi-user-server' /> - </dependent> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/sshd start' - timeout_seconds='60'/> - - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='60' /> - - <exec_method - type='method' - name='refresh' - exec='/lib/svc/method/sshd restart' - timeout_seconds='60' /> - - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop sshd --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.ssh' /> - </property_group> - - <property_group name='firewall_context' type='com.sun,fw_definition'> - <propval name='name' type='astring' value='ssh' /> - <propval name='ipf_method' type='astring' - value='/lib/svc/method/sshd ipfilter' /> - </property_group> - - <property_group name='firewall_config' type='com.sun,fw_configuration'> - <propval name='policy' type='astring' value='use_global' /> - <propval name='apply_to' type='astring' value='' /> - <propval name='exceptions' type='astring' value='' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.firewall.config' /> - </property_group> - - <stability value='Unstable' /> - - <template> - <common_name> - <loctext xml:lang='C'> - SSH server - </loctext> - </common_name> - <documentation> - <manpage title='sshd' section='1M' manpath='/usr/share/man' /> - </documentation> - </template> - -</service> - -</service_bundle> diff --git a/usr/src/cmd/ssh/etc/ssh_config b/usr/src/cmd/ssh/etc/ssh_config deleted file mode 100644 index cdb9d97d45..0000000000 --- a/usr/src/cmd/ssh/etc/ssh_config +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This file provides defaults for ssh(1). -# The values can be changed in per-user configuration files $HOME/.ssh/config -# or on the command line of ssh(1). - -# Configuration data is parsed as follows: -# 1. command line options -# 2. user-specific file -# 3. system-wide file /etc/ssh/ssh_config -# -# Any configuration value is only changed the first time it is set. -# host-specific definitions should be at the beginning of the -# configuration file, and defaults at the end. - -# Example (matches compiled in defaults): -# -# Host * -# ForwardAgent no -# ForwardX11 no -# PubkeyAuthentication yes -# PasswordAuthentication yes -# FallBackToRsh no -# UseRsh no -# BatchMode no -# CheckHostIP yes -# StrictHostKeyChecking ask -# EscapeChar ~ diff --git a/usr/src/cmd/ssh/etc/sshd b/usr/src/cmd/ssh/etc/sshd deleted file mode 100644 index 043ce20f7e..0000000000 --- a/usr/src/cmd/ssh/etc/sshd +++ /dev/null @@ -1,116 +0,0 @@ -#!/sbin/sh -# -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -. /lib/svc/share/ipf_include.sh -. /lib/svc/share/smf_include.sh - -SSHDIR=/etc/ssh -KEYGEN="/usr/bin/ssh-keygen -q" -PIDFILE=/var/run/sshd.pid - -# Checks to see if RSA, and DSA host keys are available -# if any of these keys are not present, the respective keys are created. -create_key() -{ - keypath=$1 - keytype=$2 - - if [ ! -f $keypath ]; then - # - # HostKey keywords in sshd_config may be preceded or - # followed by a mix of any number of space or tabs, - # and optionally have an = between keyword and - # argument. We use two grep invocations such that we - # can match HostKey case insensitively but still have - # the case of the path name be significant, keeping - # the pattern somewhat more readable. - # - # The character classes below contain one literal - # space and one literal tab. - # - grep -i "^[ ]*HostKey[ ]*=\{0,1\}[ ]*$keypath" \ - $SSHDIR/sshd_config | grep "$keypath" > /dev/null 2>&1 - - if [ $? -eq 0 ]; then - echo Creating new $keytype public/private host key pair - $KEYGEN -f $keypath -t $keytype -N '' - if [ $? -ne 0 ]; then - echo "Could not create $keytype key: $keypath" - exit $SMF_EXIT_ERR_CONFIG - fi - fi - fi -} - -create_ipf_rules() -{ - FMRI=$1 - ipf_file=`fmri_to_file ${FMRI} $IPF_SUFFIX` - policy=`get_policy ${FMRI}` - - # - # Get port from /etc/ssh/sshd_config - # - tports=`grep "^Port" /etc/ssh/sshd_config 2>/dev/null | \ - awk '{print $2}'` - - echo "# $FMRI" >$ipf_file - for port in $tports; do - generate_rules $FMRI $policy "tcp" "any" $port $ipf_file - done -} - -# This script is being used for two purposes: as part of an SMF -# start/stop/refresh method, and as a sysidconfig(1M)/sys-unconfig(1M) -# application. -# -# Both, the SMF methods and sysidconfig/sys-unconfig use different -# arguments.. - -case $1 in - # sysidconfig/sys-unconfig arguments (-c and -u) -'-c') - create_key $SSHDIR/ssh_host_rsa_key rsa - create_key $SSHDIR/ssh_host_dsa_key dsa - ;; - -'-u') - # sys-unconfig(1M) knows how to remove ssh host keys, so there's - # nothing to do here. - : - ;; - - # SMF arguments (start and restart [really "refresh"]) - -'ipfilter') - create_ipf_rules $2 - ;; - -'start') - # - # If host keys don't exist when the service is started, create - # them; sysidconfig is not run in every situation (such as on - # the install media). - # - create_key $SSHDIR/ssh_host_rsa_key rsa - create_key $SSHDIR/ssh_host_dsa_key dsa - - /usr/lib/ssh/sshd - ;; - -'restart') - if [ -f "$PIDFILE" ]; then - /usr/bin/kill -HUP `/usr/bin/cat $PIDFILE` - fi - ;; - -*) - echo "Usage: $0 { start | restart }" - exit 1 - ;; -esac - -exit $? diff --git a/usr/src/cmd/ssh/etc/sshd_config b/usr/src/cmd/ssh/etc/sshd_config deleted file mode 100644 index fd4aa5df46..0000000000 --- a/usr/src/cmd/ssh/etc/sshd_config +++ /dev/null @@ -1,145 +0,0 @@ -# -# Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. -# -# Configuration file for sshd(1m) (see also sshd_config(4)) -# - -# Protocol versions supported -# -# The sshd shipped in this release of Solaris has support for major versions -# 1 and 2. It is recommended due to security weaknesses in the v1 protocol -# that sites run only v2 if possible. Support for v1 is provided to help sites -# with existing ssh v1 clients/servers to transition. -# Support for v1 may not be available in a future release of Solaris. -# -# To enable support for v1 an RSA1 key must be created with ssh-keygen(1). -# RSA and DSA keys for protocol v2 are created by /etc/init.d/sshd if they -# do not already exist, RSA1 keys for protocol v1 are not automatically created. - -# Uncomment ONLY ONE of the following Protocol statements. - -# Only v2 (recommended) -Protocol 2 - -# Both v1 and v2 (not recommended) -#Protocol 2,1 - -# Only v1 (not recommended) -#Protocol 1 - -# Listen port (the IANA registered port number for ssh is 22) -Port 22 - -# The default listen address is all interfaces, this may need to be changed -# if you wish to restrict the interfaces sshd listens on for a multi homed host. -# Multiple ListenAddress entries are allowed. - -# IPv4 only -#ListenAddress 0.0.0.0 -# IPv4 & IPv6 -ListenAddress :: - -# If port forwarding is enabled (default), specify if the server can bind to -# INADDR_ANY. -# This allows the local port forwarding to work when connections are received -# from any remote host. -GatewayPorts no - -# X11 tunneling options -X11Forwarding yes -X11DisplayOffset 10 -X11UseLocalhost yes - -# The maximum number of concurrent unauthenticated connections to sshd. -# start:rate:full see sshd(1) for more information. -# The default is 10 unauthenticated clients. -#MaxStartups 10:30:60 - -# Banner to be printed before authentication starts. -#Banner /etc/issue - -# Should sshd print the /etc/motd file and check for mail. -# On Solaris it is assumed that the login shell will do these (eg /etc/profile). -PrintMotd no - -# KeepAlive specifies whether keep alive messages are sent to the client. -# See sshd(1) for detailed description of what this means. -# Note that the client may also be sending keep alive messages to the server. -KeepAlive yes - -# Syslog facility and level -SyslogFacility auth -LogLevel info - -# -# Authentication configuration -# - -# Host private key files -# Must be on a local disk and readable only by the root user (root:sys 600). -HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_dsa_key - -# Length of the server key -# Default 768, Minimum 512 -ServerKeyBits 768 - -# sshd regenerates the key every KeyRegenerationInterval seconds. -# The key is never stored anywhere except the memory of sshd. -# The default is 1 hour (3600 seconds). -KeyRegenerationInterval 3600 - -# Ensure secure permissions on users .ssh directory. -StrictModes yes - -# Length of time in seconds before a client that hasn't completed -# authentication is disconnected. -# Default is 600 seconds. 0 means no time limit. -LoginGraceTime 600 - -# Maximum number of retries for authentication -# Default is 6. Default (if unset) for MaxAuthTriesLog is MaxAuthTries / 2 -MaxAuthTries 6 -MaxAuthTriesLog 3 - -# Are logins to accounts with empty passwords allowed. -# If PermitEmptyPasswords is no, pass PAM_DISALLOW_NULL_AUTHTOK -# to pam_authenticate(3PAM). -PermitEmptyPasswords no - -# To disable tunneled clear text passwords, change PasswordAuthentication to no. -PasswordAuthentication yes - -# Are root logins permitted using sshd. -# Note that sshd uses pam_authenticate(3PAM) so the root (or any other) user -# maybe denied access by a PAM module regardless of this setting. -# Valid options are yes, without-password, no. -PermitRootLogin no - -# sftp subsystem -Subsystem sftp internal-sftp - - -# SSH protocol v1 specific options -# -# The following options only apply to the v1 protocol and provide -# some form of backwards compatibility with the very weak security -# of /usr/bin/rsh. Their use is not recommended and the functionality -# will be removed when support for v1 protocol is removed. - -# Should sshd use .rhosts and .shosts for password less authentication. -IgnoreRhosts yes -RhostsAuthentication no - -# Rhosts RSA Authentication -# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts. -# If the user on the client side is not root then this won't work on -# Solaris since /usr/bin/ssh is not installed setuid. -RhostsRSAAuthentication no - -# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication. -#IgnoreUserKnownHosts yes - -# Is pure RSA authentication allowed. -# Default is yes -RSAAuthentication yes diff --git a/usr/src/cmd/ssh/include/altprivsep.h b/usr/src/cmd/ssh/include/altprivsep.h deleted file mode 100644 index fb230d28a7..0000000000 --- a/usr/src/cmd/ssh/include/altprivsep.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _ALTPRIVSEP_H -#define _ALTPRIVSEP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include "auth.h" -#include "kex.h" - -#define APS_MSG_NEWKEYS_REQ 0 -#define APS_MSG_NEWKEYS_REP 1 -#define APS_MSG_RECORD_LOGIN 2 -#define APS_MSG_RECORD_LOGOUT 3 -#define APS_MSG_START_REKEX 4 -#define APS_MSG_AUTH_CONTEXT 5 - -void altprivsep_start_and_do_monitor(int use_engine, int inetd, int newsock, - int statup_pipe); -int altprivsep_get_pipe_fd(void); - -/* child-side handler of re-key packets */ -void altprivsep_rekey(int type, u_int32_t seq, void *ctxt); - -/* Calls _to_ monitor from unprivileged process */ -void altprivsep_process_input(fd_set *rset); -void altprivsep_record_login(pid_t pid, const char *ttyname); -void altprivsep_record_logout(pid_t pid); -void altprivsep_start_rekex(void); -void altprivsep_send_auth_context(Authctxt *authctxt); - -/* Functions for use in the monitor */ -void aps_input_altpriv_msg(int type, u_int32_t seq, void *ctxt); - -#ifdef __cplusplus -} -#endif - -#endif /* _ALTPRIVSEP_H */ diff --git a/usr/src/cmd/ssh/include/atomicio.h b/usr/src/cmd/ssh/include/atomicio.h deleted file mode 100644 index e1ba7b21e6..0000000000 --- a/usr/src/cmd/ssh/include/atomicio.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2006 Damien Miller. All rights reserved. - * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _ATOMICIO_H -#define _ATOMICIO_H - -/* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Ensure all of data on socket comes through. f==read || f==write - */ -ssize_t atomicio(ssize_t (*)(), int, void *, size_t); - -#define vwrite (ssize_t (*)(int, void *, size_t))write - -/* - * ensure all of data on socket comes through. f==readv || f==writev - */ -size_t atomiciov(ssize_t (*)(int, const struct iovec *, int), - int, const struct iovec *, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _ATOMICIO_H */ diff --git a/usr/src/cmd/ssh/include/auth-options.h b/usr/src/cmd/ssh/include/auth-options.h deleted file mode 100644 index 31d7fd6ce1..0000000000 --- a/usr/src/cmd/ssh/include/auth-options.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $OpenBSD: auth-options.h,v 1.12 2002/07/21 18:34:43 stevesk Exp $ */ - -#ifndef _AUTH_OPTIONS_H -#define _AUTH_OPTIONS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* Linked list of custom environment strings */ -struct envstring { - struct envstring *next; - char *s; -}; - -/* Flags that may be set in authorized_keys options. */ -extern int no_port_forwarding_flag; -extern int no_agent_forwarding_flag; -extern int no_x11_forwarding_flag; -extern int no_pty_flag; -extern char *forced_command; -extern struct envstring *custom_environment; - -int auth_parse_options(struct passwd *, char *, char *, u_long); -void auth_clear_options(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _AUTH_OPTIONS_H */ diff --git a/usr/src/cmd/ssh/include/auth-pam.h b/usr/src/cmd/ssh/include/auth-pam.h deleted file mode 100644 index 3c3dd409fd..0000000000 --- a/usr/src/cmd/ssh/include/auth-pam.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -/* $Id: auth-pam.h,v 1.16 2002/07/23 00:44:07 stevesk Exp $ */ - -#ifndef _AUTH_PAM_H -#define _AUTH_PAM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "includes.h" -#ifdef USE_PAM - -char * derive_pam_svc_name(Authmethod *method); -void new_start_pam(Authctxt *authctxt, struct pam_conv *conv); -int auth_pam_password(Authctxt *authctxt, const char *password); -int do_pam_non_initial_userauth(Authctxt *authctxt); -int finish_userauth_do_pam(Authctxt *authctxt); -void finish_pam(Authctxt *authctxt); -char **fetch_pam_environment(Authctxt *authctxt); -void free_pam_environment(char **env); -void message_cat(char **p, const char *a); -void print_pam_messages(void); - -#define AUTHPAM_DONE(ac) (ac != NULL && \ - ac->pam != NULL && \ - ac->pam->h != NULL && \ - ac->pam->state == PAM_S_DONE) - -#define AUTHPAM_RETVAL(ac, rv) ((ac != NULL && ac->pam != NULL) ? \ - ac->pam->last_pam_retval : rv) - -#define AUTHPAM_ERROR(ac, rv) ((ac != NULL && ac->pam != NULL && \ - ac->pam->last_pam_retval != PAM_SUCCESS) ? \ - ac->pam->last_pam_retval : rv) - -#endif /* USE_PAM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AUTH_PAM_H */ diff --git a/usr/src/cmd/ssh/include/auth.h b/usr/src/cmd/ssh/include/auth.h deleted file mode 100644 index c932fafa6d..0000000000 --- a/usr/src/cmd/ssh/include/auth.h +++ /dev/null @@ -1,325 +0,0 @@ -/* $OpenBSD: auth.h,v 1.41 2002/09/26 11:38:43 markus Exp $ */ - -#ifndef _AUTH_H -#define _AUTH_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "key.h" -#include "hostfile.h" -#include <openssl/rsa.h> - -#ifdef USE_PAM -#include <security/pam_appl.h> -#endif /* USE_PAM */ - -#ifdef HAVE_LOGIN_CAP -#include <login_cap.h> -#endif -#ifdef BSD_AUTH -#include <bsd_auth.h> -#endif -#ifdef KRB5 -#include <krb5.h> -#endif - -typedef struct Authctxt Authctxt; -typedef struct Authmethod Authmethod; -typedef struct KbdintDevice KbdintDevice; - -#ifdef USE_PAM -typedef struct pam_stuff pam_stuff; - -struct pam_stuff { - Authctxt *authctxt; - pam_handle_t *h; - int state; - int last_pam_retval; -}; - -/* See auth-pam.h and auth-pam.c */ - -#define PAM_S_DONE_ACCT_MGMT 0x01 /* acct_mgmt done */ -#define PAM_S_DONE_SETCRED 0x02 /* setcred done */ -#define PAM_S_DONE_OPEN_SESSION 0x04 /* open_session done */ -#define PAM_S_DONE 0x07 /* all done */ -#endif /* USE_PAM */ - -struct Authctxt { - int success; - int valid; - int attempt; /* all userauth attempt count */ - int init_attempt; /* passwd/kbd-int attempt count */ - int failures; - int init_failures; - int unwind_dispatch_loop; - int v1_auth_type; - char *v1_auth_name; - Authmethod *method; - char *user; - char *service; - struct passwd *pw; - char *style; - void *kbdintctxt; /* XXX Switch to method_data; - v1 still needs this*/ -#ifdef USE_PAM - pam_stuff *pam; - char *cuser; /* client side user, needed for setting - PAM_AUSER for hostbased authentication - using roles */ - u_long last_login_time; /* need to get the time of - last login before calling - pam_open_session() */ - char last_login_host[MAXHOSTNAMELEN]; - int pam_retval; /* pam_stuff is cleaned before - BSM login failure auditing */ -#endif /* USE_PAM */ - - /* SUNW - What follows remains to reduce diffs with OpenSSH but - * is not used in Solaris. The Solaris SSH internal - * architecture requires that this stuff move into the - * Authmethod method_data. - */ -#ifndef SUNW_SSH -#ifdef BSD_AUTH - auth_session_t *as; -#endif -#ifdef KRB4 - char *krb4_ticket_file; -#endif -#ifdef KRB5 - krb5_context krb5_ctx; - krb5_auth_context krb5_auth_ctx; - krb5_ccache krb5_fwd_ccache; - krb5_principal krb5_user; - char *krb5_ticket_file; -#endif - void *methoddata; -#endif /* SUNW_SSH */ -}; - -struct Authmethod { - char *name; - int *enabled; - /* - * Userauth method state tracking fields updated in - * input_userauth_request() and auth-pam.c. - * - * The "void (*userauth)(Authctxt *authctxt)" function - * communicates the userauth result (success, failure, - * "postponed," abandoned) through the 'authenticated', - * 'postponed' and 'abandoned' fields. Partial success is - * indicated by requiring other userauths to be used by setting - * their 'required' or 'sufficient' fields. - * - * Individual methods should only ever set 'not_again' if it - * makes no sense to complete the same userauth more than once, - * and they should set any methods' sufficient or required flags - * in order to force partial authentication and require that - * more userauths be tried. The (void *) 'method_data' and - * 'hist_method_data' pointers can be used by methods such as - * pubkey which may make sense to run more than once during - * userauth or which may require multiple round tripes (e.g., - * keyboard-interactive) and which need to keep some state; - * 'hist_method_data' is there specifically for pubkey userauth - * where multiple successful attempts should all use different - * keys. - * - * The "attempts," "abandons," "successes" and "failures" fields - * count the number of times a method has been attempted, - * abandoned, and has succeeded or failed. Note that pubkey - * userauth does not double-count sig-less probes that are - * followed by a pubkey request for the same pubkey anw with a - * signature. - */ - void (*userauth)(Authctxt *authctxt); - void (*abandon)(Authctxt *, Authmethod *); - void *method_data; - void *hist_method_data; - unsigned int is_initial; - unsigned int attempts:8; - unsigned int abandons:8; - unsigned int successes:8; - unsigned int failures:8; - /* - * Post-attempt state booleans (authenticated, abandoned, etc...) - */ - unsigned int authenticated:1; - unsigned int not_again:1; - unsigned int sufficient:1; - unsigned int required:1; - unsigned int postponed:1; - unsigned int abandoned:1; - /* - * NOTE: multi-round-trip userauth methods can either - * recursively call dispatch_run and detect abandonment - * within their message handlers (as PAM kbd-int does) or - * set the postponed flag and let input_userauth_request() - * detect abandonment (i.e., initiation of some userauth - * method before completion of a started, multi-round-trip - * userauth method). - * - */ -}; - -/* - * Keyboard interactive device: - * init_ctx returns: non NULL upon success - * query returns: 0 - success, otherwise failure - * respond returns: 0 - success, 1 - need further interaction, - * otherwise - failure - */ -struct KbdintDevice -{ - const char *name; - void* (*init_ctx)(Authctxt*); - int (*query)(void *ctx, char **name, char **infotxt, - u_int *numprompts, char ***prompts, u_int **echo_on); - int (*respond)(void *ctx, u_int numresp, char **responses); - void (*free_ctx)(void *ctx); -}; - -int auth_rhosts(struct passwd *, const char *); -int -auth_rhosts2(struct passwd *, const char *, const char *, const char *); - -int auth_rhosts_rsa(struct passwd *, char *, Key *); -int auth_password(Authctxt *, const char *); -int auth_rsa(struct passwd *, BIGNUM *); -int auth_rsa_challenge_dialog(Key *); -BIGNUM *auth_rsa_generate_challenge(Key *); -int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]); -int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); - -int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); -int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); -int user_key_allowed(struct passwd *, Key *); - -#ifdef KRB4 -#include <krb.h> -int auth_krb4(Authctxt *, KTEXT, char **, KTEXT); -int auth_krb4_password(Authctxt *, const char *); -void krb4_cleanup_proc(void *); - -#ifdef AFS -#include <kafs.h> -int auth_krb4_tgt(Authctxt *, const char *); -int auth_afs_token(Authctxt *, const char *); -#endif /* AFS */ - -#endif /* KRB4 */ - -#ifdef KRB5 -int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *); -int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt); -int auth_krb5_password(Authctxt *authctxt, const char *password); -void krb5_cleanup_proc(void *authctxt); -#endif /* KRB5 */ - -#include "auth-pam.h" -#include "auth2-pam.h" - -Authctxt *do_authentication(void); -Authctxt *do_authentication2(void); - -#ifdef HAVE_BSM -void audit_failed_login_cleanup(void *); -#endif /* HAVE_BSM */ - -int userauth_check_partial_failure(Authctxt *authctxt); -void userauth_force_kbdint(void); - -Authctxt *authctxt_new(void); -void auth_log(Authctxt *, int, char *, char *); -void userauth_finish(Authctxt *, char *); -void userauth_user_svc_change(Authctxt *authctxt, - char *user, - char *service); -int auth_root_allowed(char *); - -char *auth2_read_banner(void); - -void privsep_challenge_enable(void); - -void auth2_challenge(Authctxt *, char *); -void auth2_challenge_abandon(Authctxt *); -int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); -int bsdauth_respond(void *, u_int, char **); -int skey_query(void *, char **, char **, u_int *, char ***, u_int **); -int skey_respond(void *, u_int, char **); - -struct passwd * getpwnamallow(const char *user); - -int run_auth_hook(const char *, const char *, const char *); - -char *get_challenge(Authctxt *); -int verify_response(Authctxt *, const char *); - -struct passwd * auth_get_user(void); - -char *authorized_keys_file(struct passwd *); -char *authorized_keys_file2(struct passwd *); - -int -secure_filename(FILE *, const char *, struct passwd *, char *, size_t); - -HostStatus -check_key_in_hostfiles(struct passwd *, Key *, const char *, - const char *, const char *); - -/* hostkey handling */ -#ifndef lint -Key *get_hostkey_by_index(int); -Key *get_hostkey_by_type(int); -int get_hostkey_index(Key *); -#endif /* lint */ -int ssh1_session_key(BIGNUM *); - -/* debug messages during authentication */ -void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void auth_debug_send(void); -void auth_debug_reset(void); - -#define AUTH_FAIL_MAX 6 -#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) -#define AUTH_FAIL_MSG "Too many authentication failures for %.100s" - -#define SKEY_PROMPT "\nS/Key Password: " - -#ifdef __cplusplus -} -#endif - -#endif /* _AUTH_H */ diff --git a/usr/src/cmd/ssh/include/auth2-pam.h b/usr/src/cmd/ssh/include/auth2-pam.h deleted file mode 100644 index dae25c0819..0000000000 --- a/usr/src/cmd/ssh/include/auth2-pam.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $Id: auth2-pam.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AUTH2_PAM_H -#define _AUTH2_PAM_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "includes.h" -#ifdef USE_PAM - -typedef struct Convctxt Convctxt; - -struct Convctxt { - int abandoned, finished, num_received, num_expected; - int *prompts; - struct pam_response *responses; -}; - -int kbdint_pam_abandon_chk(Authctxt *authctxt, Authmethod *method); -void kbdint_pam_abandon(Authctxt *authctxt, Authmethod *method); - -void auth2_pam(Authctxt *authctxt); - -#endif /* USE_PAM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AUTH2_PAM_H */ diff --git a/usr/src/cmd/ssh/include/authfd.h b/usr/src/cmd/ssh/include/authfd.h deleted file mode 100644 index 81b27cc0e6..0000000000 --- a/usr/src/cmd/ssh/include/authfd.h +++ /dev/null @@ -1,103 +0,0 @@ -/* $OpenBSD: authfd.h,v 1.31 2002/09/11 18:27:25 stevesk Exp $ */ - -#ifndef _AUTHFD_H -#define _AUTHFD_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions to interface with the SSH_AUTHENTICATION_FD socket. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "buffer.h" - -/* Messages for the authentication agent connection. */ -#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 -#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 -#define SSH_AGENTC_RSA_CHALLENGE 3 -#define SSH_AGENT_RSA_RESPONSE 4 -#define SSH_AGENT_FAILURE 5 -#define SSH_AGENT_SUCCESS 6 -#define SSH_AGENTC_ADD_RSA_IDENTITY 7 -#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 -#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 - -/* private OpenSSH extensions for SSH2 */ -#define SSH2_AGENTC_REQUEST_IDENTITIES 11 -#define SSH2_AGENT_IDENTITIES_ANSWER 12 -#define SSH2_AGENTC_SIGN_REQUEST 13 -#define SSH2_AGENT_SIGN_RESPONSE 14 -#define SSH2_AGENTC_ADD_IDENTITY 17 -#define SSH2_AGENTC_REMOVE_IDENTITY 18 -#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 - -/* smartcard */ -#define SSH_AGENTC_ADD_SMARTCARD_KEY 20 -#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 - -/* lock/unlock the agent */ -#define SSH_AGENTC_LOCK 22 -#define SSH_AGENTC_UNLOCK 23 - -/* add key with constraints */ -#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 -#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 - -#define SSH_AGENT_CONSTRAIN_LIFETIME 1 -#define SSH_AGENT_CONSTRAIN_CONFIRM 2 - -/* extended failure messages */ -#define SSH2_AGENT_FAILURE 30 - -/* additional error code for ssh.com's ssh-agent2 */ -#define SSH_COM_AGENT2_FAILURE 102 - -#define SSH_AGENT_OLD_SIGNATURE 0x01 - -typedef struct { - int fd; - Buffer identities; - int howmany; -} AuthenticationConnection; - -int ssh_agent_present(void); -int ssh_get_authentication_socket(void); -void ssh_close_authentication_socket(int); - -AuthenticationConnection *ssh_get_authentication_connection(void); -void ssh_close_authentication_connection(AuthenticationConnection *); -int ssh_get_num_identities(AuthenticationConnection *, int); -Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); -Key *ssh_get_next_identity(AuthenticationConnection *, char **, int); -int ssh_add_identity(AuthenticationConnection *, Key *, const char *); -int ssh_add_identity_constrained(AuthenticationConnection *, Key *, const char *, u_int); -int ssh_remove_identity(AuthenticationConnection *, Key *); -int ssh_remove_all_identities(AuthenticationConnection *, int); -int ssh_lock_agent(AuthenticationConnection *, int, const char *); -int ssh_update_card(AuthenticationConnection *, int, const char *, const char *); - -int -ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], - u_int, u_char[16]); - -int -ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *, - u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _AUTHFD_H */ diff --git a/usr/src/cmd/ssh/include/authfile.h b/usr/src/cmd/ssh/include/authfile.h deleted file mode 100644 index 68031d32cb..0000000000 --- a/usr/src/cmd/ssh/include/authfile.h +++ /dev/null @@ -1,36 +0,0 @@ -/* $OpenBSD: authfile.h,v 1.10 2002/05/23 19:24:30 markus Exp $ */ - -#ifndef _AUTHFILE_H -#define _AUTHFILE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -int key_save_private(Key *, const char *, const char *, const char *); -Key *key_load_public(const char *, char **); -Key *key_load_public_type(int, const char *, char **); -Key *key_load_private(const char *, const char *, char **); -Key *key_load_private_type(int, const char *, const char *, char **); -Key *key_load_private_pem(int, int, const char *, char **); - -#ifdef __cplusplus -} -#endif - -#endif /* _AUTHFILE_H */ diff --git a/usr/src/cmd/ssh/include/base64.h b/usr/src/cmd/ssh/include/base64.h deleted file mode 100644 index 7e2ccf7d3e..0000000000 --- a/usr/src/cmd/ssh/include/base64.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _BASE64_H -#define _BASE64_H - -/* $Id: base64.h,v 1.3 2002/02/26 16:59:59 stevesk Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "config.h" - -#ifndef HAVE___B64_NTOP -# ifndef HAVE_B64_NTOP -int b64_ntop(u_char const *src, size_t srclength, char *target, - size_t targsize); -int b64_pton(u_char const *src, u_char *target, size_t targsize); -# endif /* !HAVE_B64_NTOP */ -# define __b64_ntop b64_ntop -# define __b64_pton b64_pton -#endif /* HAVE___B64_NTOP */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BASE64_H */ diff --git a/usr/src/cmd/ssh/include/bindresvport.h b/usr/src/cmd/ssh/include/bindresvport.h deleted file mode 100644 index 9cd968bf9b..0000000000 --- a/usr/src/cmd/ssh/include/bindresvport.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id: bindresvport.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _BINDRESVPORT_H -#define _BINDRESVPORT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#ifndef HAVE_BINDRESVPORT_SA -int bindresvport_sa(int sd, struct sockaddr *sa); -#endif /* !HAVE_BINDRESVPORT_SA */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BINDRESVPORT_H */ diff --git a/usr/src/cmd/ssh/include/bsd-arc4random.h b/usr/src/cmd/ssh/include/bsd-arc4random.h deleted file mode 100644 index c9238636c5..0000000000 --- a/usr/src/cmd/ssh/include/bsd-arc4random.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1999-2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _BSD_ARC4RANDOM_H -#define _BSD_ARC4RANDOM_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* $Id: bsd-arc4random.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#include "config.h" - -#ifndef HAVE_ARC4RANDOM -unsigned int arc4random(void); -void arc4random_stir(void); -#endif /* !HAVE_ARC4RANDOM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_ARC4RANDOM_H */ diff --git a/usr/src/cmd/ssh/include/bsd-cray.h b/usr/src/cmd/ssh/include/bsd-cray.h deleted file mode 100644 index 8b8f9113c7..0000000000 --- a/usr/src/cmd/ssh/include/bsd-cray.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * $Id: bsd-cray.h,v 1.5 2002/09/26 00:38:51 tim Exp $ - * - * bsd-cray.h - * - * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>) - * Significant portions provided by - * Wayne Schroeder, SDSC <schroeder@sdsc.edu> - * William Jones, UTexas <jones@tacc.utexas.edu> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Created: Apr 22 16.34:00 2002 wp - * - * This file contains functions required for proper execution - * on UNICOS systems. - * - */ - -#ifndef _BSD_CRAY_H -#define _BSD_CRAY_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _UNICOS -void cray_init_job(struct passwd *); /* init cray job */ -void cray_job_termination_handler(int); /* process end of job signal */ -void cray_login_failure(char *username, int errcode); -int cray_access_denied(char *username); -extern char cray_tmpdir[]; /* cray tmpdir */ -#ifndef IA_SSHD -#define IA_SSHD IA_LOGIN -#endif -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_CRAY_H */ diff --git a/usr/src/cmd/ssh/include/bsd-cygwin_util.h b/usr/src/cmd/ssh/include/bsd-cygwin_util.h deleted file mode 100644 index dc44268563..0000000000 --- a/usr/src/cmd/ssh/include/bsd-cygwin_util.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: bsd-cygwin_util.h,v 1.7 2002/04/15 22:00:52 stevesk Exp $ */ - -#ifndef _BSD_CYGWIN_UTIL_H -#define _BSD_CYGWIN_UTIL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * cygwin_util.c - * - * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Created: Sat Sep 02 12:17:00 2000 cv - * - * This file contains functions for forcing opened file descriptors to - * binary mode on Windows systems. - */ - -#ifdef HAVE_CYGWIN - -#include <io.h> - -int binary_open(const char *filename, int flags, ...); -int binary_pipe(int fd[2]); -int check_nt_auth(int pwd_authenticated, struct passwd *pw); -int check_ntsec(const char *filename); -void register_9x_service(void); - -#define open binary_open -#define pipe binary_pipe - -#endif /* HAVE_CYGWIN */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_CYGWIN_UTIL_H */ diff --git a/usr/src/cmd/ssh/include/bsd-getpeereid.h b/usr/src/cmd/ssh/include/bsd-getpeereid.h deleted file mode 100644 index 44430f7619..0000000000 --- a/usr/src/cmd/ssh/include/bsd-getpeereid.h +++ /dev/null @@ -1,24 +0,0 @@ -/* $Id: bsd-getpeereid.h,v 1.1 2002/09/12 00:33:02 djm Exp $ */ - -#ifndef _BSD_GETPEEREID_H -#define _BSD_GETPEEREID_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#include <sys/types.h> /* For uid_t, gid_t */ - -#ifndef HAVE_GETPEEREID -int getpeereid(int , uid_t *, gid_t *); -#endif /* HAVE_GETPEEREID */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_GETPEEREID_H */ diff --git a/usr/src/cmd/ssh/include/bsd-misc.h b/usr/src/cmd/ssh/include/bsd-misc.h deleted file mode 100644 index 9990c87f3d..0000000000 --- a/usr/src/cmd/ssh/include/bsd-misc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 1999-2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _BSD_MISC_H -#define _BSD_MISC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* $Id: bsd-misc.h,v 1.6 2002/06/13 21:34:58 mouring Exp $ */ - -#include "config.h" - -char *get_progname(char *argv0); - -#ifndef HAVE_SETSID -#define setsid() setpgrp(0, getpid()) -#endif /* !HAVE_SETSID */ - -#ifndef HAVE_SETENV -int setenv(const char *name, const char *value, int overwrite); -#endif /* !HAVE_SETENV */ - -#ifndef HAVE_SETLOGIN -int setlogin(const char *name); -#endif /* !HAVE_SETLOGIN */ - -#ifndef HAVE_INNETGR -int innetgr(const char *netgroup, const char *host, - const char *user, const char *domain); -#endif /* HAVE_INNETGR */ - -#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) -int seteuid(uid_t euid); -#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ - -#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) -int setegid(uid_t egid); -#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ - -#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) -const char *strerror(int e); -#endif - - -#ifndef HAVE_UTIMES -#ifndef HAVE_STRUCT_TIMEVAL -struct timeval { - long tv_sec; - long tv_usec; -} -#endif /* HAVE_STRUCT_TIMEVAL */ - -int utimes(char *filename, struct timeval *tvp); -#endif /* HAVE_UTIMES */ - -#ifndef HAVE_TRUNCATE -int truncate (const char *path, off_t length); -#endif /* HAVE_TRUNCATE */ - -#if !defined(HAVE_SETGROUPS) && defined(SETGROUPS_NOOP) -int setgroups(size_t size, const gid_t *list); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_MISC_H */ diff --git a/usr/src/cmd/ssh/include/bsd-snprintf.h b/usr/src/cmd/ssh/include/bsd-snprintf.h deleted file mode 100644 index 71691a01d3..0000000000 --- a/usr/src/cmd/ssh/include/bsd-snprintf.h +++ /dev/null @@ -1,28 +0,0 @@ -/* $Id: bsd-snprintf.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _BSD_SNPRINTF_H -#define _BSD_SNPRINTF_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#include <sys/types.h> /* For size_t */ - -#ifndef HAVE_SNPRINTF -int snprintf(char *str, size_t count, const char *fmt, ...); -#endif /* !HAVE_SNPRINTF */ - -#ifndef HAVE_VSNPRINTF -int vsnprintf(char *str, size_t count, const char *fmt, va_list args); -#endif /* !HAVE_SNPRINTF */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_SNPRINTF_H */ diff --git a/usr/src/cmd/ssh/include/bsd-waitpid.h b/usr/src/cmd/ssh/include/bsd-waitpid.h deleted file mode 100644 index 9c6385fdb8..0000000000 --- a/usr/src/cmd/ssh/include/bsd-waitpid.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _BSD_WAITPID_H -#define _BSD_WAITPID_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* $Id: bsd-waitpid.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef HAVE_WAITPID -/* Clean out any potental issues */ -#undef WIFEXITED -#undef WIFSTOPPED -#undef WIFSIGNALED - -/* Define required functions to mimic a POSIX look and feel */ -#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */ -#define WIFEXITED(w) (!((_W_INT(w)) & 0377)) -#define WIFSTOPPED(w) ((_W_INT(w)) & 0100) -#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w)) -#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1) -#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1) -#define WCOREFLAG 0x80 -#define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG) - -/* Prototype */ -pid_t waitpid(int pid, int *stat_loc, int options); - -#endif /* !HAVE_WAITPID */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BSD_WAITPID_H */ diff --git a/usr/src/cmd/ssh/include/bufaux.h b/usr/src/cmd/ssh/include/bufaux.h deleted file mode 100644 index aa673cccb1..0000000000 --- a/usr/src/cmd/ssh/include/bufaux.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* $OpenBSD: bufaux.h,v 1.18 2002/04/20 09:14:58 markus Exp $ */ - -#ifndef _BUFAUX_H -#define _BUFAUX_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "buffer.h" -#include <openssl/bn.h> - -void buffer_put_bignum(Buffer *, const BIGNUM *); -void buffer_put_bignum2(Buffer *, const BIGNUM *); -void buffer_get_bignum(Buffer *, BIGNUM *); -void buffer_get_bignum2(Buffer *, BIGNUM *); - -u_short buffer_get_short(Buffer *); -void buffer_put_short(Buffer *, u_short); - -u_int buffer_get_int(Buffer *); -void buffer_put_int(Buffer *, u_int); - -#ifdef HAVE_U_INT64_T -u_int64_t buffer_get_int64(Buffer *); -void buffer_put_int64(Buffer *, u_int64_t); -#endif - -int buffer_get_char(Buffer *); -void buffer_put_char(Buffer *, int); - -void *buffer_get_string(Buffer *, u_int *); -char *buffer_get_utf8_string(Buffer *, uint_t *); -void buffer_put_string(Buffer *, const void *, u_int); -void buffer_put_cstring(Buffer *, const char *); -void buffer_put_utf8_string(Buffer *, const char *, uint_t len); -void buffer_put_utf8_cstring(Buffer *, const char *); - -#define buffer_skip_string(b) \ - do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while(0) - -int buffer_put_bignum_ret(Buffer *, const BIGNUM *); -int buffer_get_bignum_ret(Buffer *, BIGNUM *); -int buffer_put_bignum2_ret(Buffer *, const BIGNUM *); -int buffer_get_bignum2_ret(Buffer *, BIGNUM *); -int buffer_get_short_ret(u_short *, Buffer *); -int buffer_get_int_ret(u_int *, Buffer *); -#ifdef HAVE_U_INT64_T -int buffer_get_int64_ret(u_int64_t *, Buffer *); -#endif -void *buffer_get_string_ret(Buffer *, u_int *); -int buffer_get_char_ret(char *, Buffer *); - -#ifdef __cplusplus -} -#endif - -#endif /* _BUFAUX_H */ diff --git a/usr/src/cmd/ssh/include/buffer.h b/usr/src/cmd/ssh/include/buffer.h deleted file mode 100644 index 4a6c7ad5e1..0000000000 --- a/usr/src/cmd/ssh/include/buffer.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD: buffer.h,v 1.11 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _BUFFER_H -#define _BUFFER_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Code for manipulating FIFO buffers. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -typedef struct { - u_char *buf; /* Buffer for data. */ - u_int alloc; /* Number of bytes allocated for data. */ - u_int offset; /* Offset of first byte containing data. */ - u_int end; /* Offset of last byte containing data. */ -} Buffer; - -void buffer_init(Buffer *); -void buffer_clear(Buffer *); -void buffer_free(Buffer *); - -u_int buffer_len(Buffer *); -void *buffer_ptr(Buffer *); - -void buffer_append(Buffer *, const void *, u_int); -void *buffer_append_space(Buffer *, u_int); - -int buffer_check_alloc(Buffer *, u_int); - -void buffer_get(Buffer *, void *, u_int); - -void buffer_consume(Buffer *, u_int); -void buffer_consume_end(Buffer *, u_int); - -void buffer_dump(Buffer *); - -int buffer_get_ret(Buffer *, void *, u_int); -int buffer_consume_ret(Buffer *, u_int); -int buffer_consume_end_ret(Buffer *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _BUFFER_H */ diff --git a/usr/src/cmd/ssh/include/canohost.h b/usr/src/cmd/ssh/include/canohost.h deleted file mode 100644 index a60c0ef7e9..0000000000 --- a/usr/src/cmd/ssh/include/canohost.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $OpenBSD: canohost.h,v 1.8 2001/06/26 17:27:23 markus Exp $ */ - -#ifndef _CANOHOST_H -#define _CANOHOST_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -const char *get_canonical_hostname(int); -const char *get_remote_ipaddr(void); -const char *get_remote_name_or_ip(u_int, int); - -char *get_peer_ipaddr(int); -int get_peer_port(int); -char *get_local_ipaddr(int); -char *get_local_name(int); - -int get_remote_port(void); -int get_local_port(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _CANOHOST_H */ diff --git a/usr/src/cmd/ssh/include/channels.h b/usr/src/cmd/ssh/include/channels.h deleted file mode 100644 index 4440f1996a..0000000000 --- a/usr/src/cmd/ssh/include/channels.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ -/* $OpenBSD: channels.h,v 1.70 2002/06/24 14:33:27 markus Exp $ */ - - -#ifndef _CHANNELS_H -#define _CHANNELS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "buffer.h" - -/* Definitions for channel types. */ -#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ -#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */ -#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */ -#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */ -#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */ -#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */ -#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */ -#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ -#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */ -#define SSH_CHANNEL_LARVAL 10 /* larval session */ -#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ -#define SSH_CHANNEL_CONNECTING 12 -#define SSH_CHANNEL_DYNAMIC 13 -#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */ -#define SSH_CHANNEL_MAX_TYPE 15 - -#define SSH_CHANNEL_PATH_LEN 256 - -struct Channel; -typedef struct Channel Channel; - -typedef void channel_callback_fn(int, void *); -typedef int channel_filter_fn(struct Channel *, char *, int); - -struct Channel { - int type; /* channel type/state */ - int self; /* my own channel identifier */ - int remote_id; /* channel identifier for remote peer */ - u_int istate; /* input from channel (state of receive half) */ - u_int ostate; /* output to channel (state of transmit half) */ - int wait_for_exit; /* no close till after exit-status is sent */ - int flags; /* close sent/rcvd */ - int rfd; /* read fd */ - int wfd; /* write fd */ - int efd; /* extended fd */ - int sock; /* sock fd */ - int isatty; /* rfd is a tty */ - int wfd_isatty; /* wfd is a tty */ - int force_drain; /* force close on iEOF */ - int delayed; /* post-select handlers for newly created - * channels are delayed until the first call - * to a matching pre-select handler. - * this way post-select handlers are not - * accidenly called if a FD gets reused */ - Buffer input; /* data read from socket, to be sent over - * encrypted connection */ - Buffer output; /* data received over encrypted connection for - * send on socket */ - Buffer extended; - char path[SSH_CHANNEL_PATH_LEN]; - /* path for unix domain sockets, or host name for forwards */ - int listening_port; /* port being listened for forwards */ - int host_port; /* remote port to connect for forwards */ - char *remote_name; /* remote hostname */ - - u_int remote_window; - u_int remote_maxpacket; - u_int local_window; - u_int local_window_max; - u_int local_consumed; - u_int local_maxpacket; - int extended_usage; - int single_connection; - - char *ctype; /* type */ - - /* callback */ - channel_callback_fn *confirm; - channel_callback_fn *detach_user; - - /* filter */ - channel_filter_fn *input_filter; -}; - -#define CHAN_EXTENDED_IGNORE 0 -#define CHAN_EXTENDED_READ 1 -#define CHAN_EXTENDED_WRITE 2 - -/* default window/packet sizes for tcp/x11-fwd-channel */ -#define CHAN_SES_PACKET_DEFAULT (32*1024) -#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) -#define CHAN_TCP_PACKET_DEFAULT (32*1024) -#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) -#define CHAN_X11_PACKET_DEFAULT (16*1024) -#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) - -/* possible input states */ -#define CHAN_INPUT_OPEN 0 -#define CHAN_INPUT_WAIT_DRAIN 1 -#define CHAN_INPUT_WAIT_OCLOSE 2 -#define CHAN_INPUT_CLOSED 3 - -/* possible output states */ -#define CHAN_OUTPUT_OPEN 0 -#define CHAN_OUTPUT_WAIT_DRAIN 1 -#define CHAN_OUTPUT_WAIT_IEOF 2 -#define CHAN_OUTPUT_CLOSED 3 - -/* - * Other channel flag bits are specific to each type of channel and are - * defined locally with the code that uses them. - */ -#define CHAN_CLOSE_SENT 0x01 -#define CHAN_CLOSE_RCVD 0x02 -#define CHAN_EOF_SENT 0x04 -#define CHAN_EOF_RCVD 0x08 - -#define CHAN_RBUF 16*1024 - -/* check whether 'efd' is still in use */ -#define CHANNEL_EFD_INPUT_ACTIVE(c) \ - (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \ - (c->efd != -1 || \ - buffer_len(&c->extended) > 0)) -#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ - (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \ - ((c->efd != -1 && !(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD))) || \ - buffer_len(&c->extended) > 0)) - -/* channel management */ - -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, u_int); -void channel_set_wait_for_exit(int, int); -void channel_free(Channel *); -void channel_free_all(void); -void channel_stop_listening(void); - -void channel_send_open(int); -void channel_request_start(int, char *, int); -void channel_register_cleanup(int, channel_callback_fn *); -void channel_register_confirm(int, channel_callback_fn *); -void channel_register_filter(int, channel_filter_fn *); -void channel_cancel_cleanup(int); -int channel_close_fd(int *); - -/* protocol handler */ - -void channel_input_close(int, u_int32_t, void *); -void channel_input_close_confirmation(int, u_int32_t, void *); -void channel_input_data(int, u_int32_t, void *); -void channel_input_extended_data(int, u_int32_t, void *); -void channel_input_ieof(int, u_int32_t, void *); -void channel_input_oclose(int, u_int32_t, void *); -void channel_input_open_confirmation(int, u_int32_t, void *); -void channel_input_open_failure(int, u_int32_t, void *); -void channel_input_port_open(int, u_int32_t, void *); -void channel_input_window_adjust(int, u_int32_t, void *); - -/* file descriptor handling (read/write) */ - -void channel_prepare_select(fd_set **, fd_set **, int *, int*, int); -void channel_after_select(fd_set *, fd_set *); -void channel_output_poll(void); - -int channel_not_very_much_buffered_data(void); -void channel_close_all(void); -int channel_still_open(void); -char *channel_open_message(void); -int channel_find_open(void); - -/* tcp forwarding */ -void channel_set_af(int af); -void channel_permit_all_opens(void); -void channel_add_permitted_opens(char *, int); -void channel_clear_permitted_opens(void); -void channel_input_port_forward_request(int, int); -int channel_connect_to(const char *, u_short); -int channel_connect_by_listen_address(u_short); -int channel_request_remote_forwarding(const char *, u_short, - const char *, u_short); -int channel_setup_local_fwd_listener(const char *, u_short, - const char *, u_short, int); -void channel_request_rforward_cancel(const char *host, u_short port); -int channel_setup_remote_fwd_listener(const char *, u_short, int); -int channel_cancel_rport_listener(const char *, u_short); - -/* x11 forwarding */ - -int x11_connect_display(void); -int x11_create_display_inet(int, int, int, u_int *); -void x11_input_open(int, u_int32_t, void *); -void x11_request_forwarding_with_spoofing(int, const char *, const char *, - const char *); -void deny_input_open(int, u_int32_t, void *); - -/* agent forwarding */ - -void auth_request_forwarding(void); -void auth_input_open_request(int, u_int32_t, void *); - -/* channel close */ - -int chan_is_dead(Channel *, int); -void chan_mark_dead(Channel *); - -/* channel events */ - -void chan_rcvd_oclose(Channel *); -void chan_rcvd_eow(Channel *); /* SSH2-only */ -void chan_read_failed(Channel *); -void chan_ibuf_empty(Channel *); - -void chan_rcvd_ieof(Channel *); -void chan_write_failed(Channel *); -void chan_obuf_empty(Channel *); - -#ifdef __cplusplus -} -#endif - -#endif /* _CHANNELS_H */ diff --git a/usr/src/cmd/ssh/include/cipher.h b/usr/src/cmd/ssh/include/cipher.h deleted file mode 100644 index e9362fedc4..0000000000 --- a/usr/src/cmd/ssh/include/cipher.h +++ /dev/null @@ -1,103 +0,0 @@ -/* $OpenBSD: cipher.h,v 1.33 2002/03/18 17:13:15 markus Exp $ */ - -#ifndef _CIPHER_H -#define _CIPHER_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <openssl/evp.h> -/* - * Cipher types for SSH-1. New types can be added, but old types should not - * be removed for compatibility. The maximum allowed value is 31. - */ -#define SSH_CIPHER_SSH2 -3 -#define SSH_CIPHER_ILLEGAL -2 /* No valid cipher selected. */ -#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */ -#define SSH_CIPHER_NONE 0 /* no encryption */ -#define SSH_CIPHER_IDEA 1 /* IDEA CFB */ -#define SSH_CIPHER_DES 2 /* DES CBC */ -#define SSH_CIPHER_3DES 3 /* 3DES CBC */ -#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */ -#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */ -#define SSH_CIPHER_BLOWFISH 6 -#define SSH_CIPHER_RESERVED 7 -#define SSH_CIPHER_MAX 31 - -#define CIPHER_ENCRYPT 1 -#define CIPHER_DECRYPT 0 - -typedef struct Cipher Cipher; -typedef struct CipherContext CipherContext; - -struct Cipher; -struct CipherContext { - int plaintext; - EVP_CIPHER_CTX evp; - Cipher *cipher; -}; - -u_int cipher_mask_ssh1(int); -Cipher *cipher_by_name(const char *); -Cipher *cipher_by_number(int); -int cipher_number(const char *); -char *cipher_name(int); -int ciphers_valid(const char *); -void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, - const u_char *, u_int, int); -void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); -void cipher_cleanup(CipherContext *); -void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); -u_int cipher_blocksize(Cipher *); -u_int cipher_keylen(Cipher *); - -u_int cipher_get_number(Cipher *); -void cipher_get_keyiv(CipherContext *, u_char *, u_int); -void cipher_set_keyiv(CipherContext *, u_char *); -int cipher_get_keyiv_len(CipherContext *); -int cipher_get_keycontext(CipherContext *, u_char *); -void cipher_set_keycontext(CipherContext *, u_char *); - -#ifdef __cplusplus -} -#endif - -#endif /* _CIPHER_H */ diff --git a/usr/src/cmd/ssh/include/clientloop.h b/usr/src/cmd/ssh/include/clientloop.h deleted file mode 100644 index 46c801e405..0000000000 --- a/usr/src/cmd/ssh/include/clientloop.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _CLIENTLOOP_H -#define _CLIENTLOOP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* $OpenBSD: clientloop.h,v 1.7 2002/04/22 21:04:52 markus Exp $ */ - -/* Client side main loop for the interactive session. */ -int client_loop(int, int, int); -void client_x11_get_proto(const char *, const char *, uint_t, - char **, char **); -void client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt); -void client_daemonize(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _CLIENTLOOP_H */ diff --git a/usr/src/cmd/ssh/include/compat.h b/usr/src/cmd/ssh/include/compat.h deleted file mode 100644 index 63b845017a..0000000000 --- a/usr/src/cmd/ssh/include/compat.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _COMPAT_H -#define _COMPAT_H - -/* $OpenBSD: compat.h,v 1.33 2002/09/27 10:42:09 mickey Exp $ */ - -#ifdef __cplusplus -extern "C" { -#endif - - -#define SSH_PROTO_UNKNOWN 0x00 -#define SSH_PROTO_1 0x01 -#define SSH_PROTO_1_PREFERRED 0x02 -#define SSH_PROTO_2 0x04 - -#define SSH_BUG_SIGBLOB 0x00000001 -#define SSH_BUG_PKSERVICE 0x00000002 -#define SSH_BUG_HMAC 0x00000004 -#define SSH_BUG_X11FWD 0x00000008 -#define SSH_OLD_SESSIONID 0x00000010 -#define SSH_BUG_PKAUTH 0x00000020 -#define SSH_BUG_DEBUG 0x00000040 -#define SSH_BUG_BANNER 0x00000080 -#define SSH_BUG_IGNOREMSG 0x00000100 -#define SSH_BUG_PKOK 0x00000200 -#define SSH_BUG_PASSWORDPAD 0x00000400 -#define SSH_BUG_SCANNER 0x00000800 -#define SSH_BUG_BIGENDIANAES 0x00001000 -#define SSH_BUG_RSASIGMD5 0x00002000 -#define SSH_OLD_DHGEX 0x00004000 -#define SSH_BUG_NOREKEY 0x00008000 -#define SSH_BUG_HBSERVICE 0x00010000 -#define SSH_BUG_OPENFAILURE 0x00020000 -#define SSH_BUG_DERIVEKEY 0x00040000 -/*#define this is free slot 0x00080000 */ -#define SSH_BUG_DUMMYCHAN 0x00100000 -#define SSH_BUG_EXTEOF 0x00200000 -#define SSH_BUG_K5USER 0x00400000 -#define SSH_BUG_PROBE 0x00800000 -#define SSH_BUG_LOCALES_NOT_LANGTAGS 0x01000000 -#define SSH_OLD_GSSAPI 0x02000000 -#define SSH_BUG_GSSAPI_BER 0x04000000 -#define SSH_BUG_FIRSTKEX 0x08000000 -#define SSH_BUG_RFWD_ADDR 0x10000000 -#define SSH_BUG_GSSKEX_HOSTKEY 0x20000000 -/* SSH_OLD_FORWARD_ADDR flag bumped up the SunSSH version to 1.2 */ -#define SSH_OLD_FORWARD_ADDR 0x40000000 -/* SSH_BUG_STRING_ENCODING flag bumped up the SunSSH version to 1.4 */ -#define SSH_BUG_STRING_ENCODING 0x80000000 - -void enable_compat13(void); -void enable_compat20(void); -void compat_datafellows(const char *); -int proto_spec(const char *); -char *compat_cipher_proposal(char *); - -extern int compat13; -extern int compat20; -extern uint32_t datafellows; - -#ifdef __cplusplus -} -#endif - -#endif /* _COMPAT_H */ diff --git a/usr/src/cmd/ssh/include/compress.h b/usr/src/cmd/ssh/include/compress.h deleted file mode 100644 index ad87892227..0000000000 --- a/usr/src/cmd/ssh/include/compress.h +++ /dev/null @@ -1,36 +0,0 @@ -/* $OpenBSD: compress.h,v 1.11 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _COMPRESS_H -#define _COMPRESS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Interface to packet compression for ssh. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -void buffer_compress_init_send(int); -void buffer_compress_init_recv(void); -void buffer_compress_uninit(void); -void buffer_compress(Buffer *, Buffer *); -void buffer_uncompress(Buffer *, Buffer *); - -#ifdef __cplusplus -} -#endif - -#endif /* _COMPRESS_H */ diff --git a/usr/src/cmd/ssh/include/config.h b/usr/src/cmd/ssh/include/config.h deleted file mode 100644 index 437b120029..0000000000 --- a/usr/src/cmd/ssh/include/config.h +++ /dev/null @@ -1,983 +0,0 @@ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ -/* $Id: acconfig.h,v 1.145 2002/09/26 00:38:48 tim Exp $ */ - -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013 Gary Mills - */ - -#ifndef _CONFIG_H -#define _CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Generated automatically from acconfig.h by autoheader. */ -/* Please make your changes there */ - - -/* Define to a Set Process Title type if your system is */ -/* supported by bsd-setproctitle.c */ -/* #undef SPT_TYPE */ - -/* setgroups() NOOP allowed */ -/* #undef SETGROUPS_NOOP */ - -/* SCO workaround */ -/* #undef BROKEN_SYS_TERMIO_H */ - -/* If your header files don't define LOGIN_PROGRAM, then use this (detected) */ -/* from environment and PATH */ -#define LOGIN_PROGRAM_FALLBACK "/usr/bin/login" - -/* Define if your password has a pw_class field */ -/* #undef HAVE_PW_CLASS_IN_PASSWD */ - -/* Define if your password has a pw_expire field */ -/* #undef HAVE_PW_EXPIRE_IN_PASSWD */ - -/* Define if your password has a pw_change field */ -/* #undef HAVE_PW_CHANGE_IN_PASSWD */ - -/* Define if your system uses access rights style file descriptor passing */ -#define HAVE_ACCRIGHTS_IN_MSGHDR 1 - -/* Define if your system uses ancillary data style file descriptor passing */ -/* #undef HAVE_CONTROL_IN_MSGHDR */ - -/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ -/* #undef BROKEN_INET_NTOA */ - -/* Define if your system defines sys_errlist[] */ -#define HAVE_SYS_ERRLIST 1 - -/* Define if your system defines sys_nerr */ -#define HAVE_SYS_NERR 1 - -/* Define if your system choked on IP TOS setting */ -#define IP_TOS_IS_BROKEN 1 - -/* Define if you have the getuserattr function. */ -/* #undef HAVE_GETUSERATTR */ - -/* Work around problematic Linux PAM modules handling of PAM_TTY */ -#define PAM_TTY_KLUDGE 1 - -/* Define if your snprintf is busted */ -/* #undef BROKEN_SNPRINTF */ - -/* Define if you are on Cygwin */ -/* #undef HAVE_CYGWIN */ - -/* Define if you have a broken realpath. */ -/* #undef BROKEN_REALPATH */ - -/* Define if you are on NEWS-OS */ -/* #undef HAVE_NEWS4 */ - -/* Define if you want to enable PAM support */ -#define USE_PAM 1 - -/* Define if you want to enable AIX4's authenticate function */ -/* #undef WITH_AIXAUTHENTICATE */ - -/* - * Define if you have/want arrays (cluster-wide session managment, not C - * arrays) - */ -/* #undef WITH_IRIX_ARRAY */ - -/* Define if you want IRIX project management */ -/* #undef WITH_IRIX_PROJECT */ - -/* Define if you want IRIX audit trails */ -/* #undef WITH_IRIX_AUDIT */ - -/* Define if you want IRIX kernel jobs */ -/* #undef WITH_IRIX_JOBS */ - -/* Location of PRNGD/EGD random number socket */ -/* #undef PRNGD_SOCKET */ - -/* Port number of PRNGD/EGD random number socket */ -/* #undef PRNGD_PORT */ - -/* Builtin PRNG command timeout */ -#define ENTROPY_TIMEOUT_MSEC 200 - -/* non-privileged user for privilege separation */ -#define SSH_PRIVSEP_USER "sshd" - -/* Define if you want to install preformatted manpages. */ -/* #undef MANTYPE */ - -/* Define if your ssl headers are included with #include <openssl/header.h> */ -#define HAVE_OPENSSL 1 - -/* Define if Solaris' OpenSSL lacks AES support */ -#define SOLARIS_OPENSSL_NO_AES 1 - -/* Define if Solaris-style Least Privilege is available */ -#define HAVE_SOLARIS_PRIVILEGE 1 - -/* Define if you want Sun's alternative privilege separation */ -#define ALTPRIVSEP - -/* Define if you have Solaris-style Contracts */ -#define HAVE_SOLARIS_CONTRACTS 1 - -/* Define if SVR4-style libcmd (for accessing /etc/default/ files) */ -#define HAVE_DEFOPEN 1 - -/* - * Define if you are linking against RSAref. Used only to print the right - * message at run-time. - */ -/* #undef RSAREF */ - -/* struct timeval */ -#define HAVE_STRUCT_TIMEVAL 1 - -/* struct utmp and struct utmpx fields */ -/* #undef HAVE_HOST_IN_UTMP */ -#define HAVE_HOST_IN_UTMPX 1 -/* #undef HAVE_ADDR_IN_UTMP */ -/* #undef HAVE_ADDR_IN_UTMPX */ -/* #undef HAVE_ADDR_V6_IN_UTMP */ -/* #undef HAVE_ADDR_V6_IN_UTMPX */ -#define HAVE_SYSLEN_IN_UTMPX 1 -#define HAVE_PID_IN_UTMP 1 -#define HAVE_TYPE_IN_UTMP 1 -#define HAVE_TYPE_IN_UTMPX 1 -/* #undef HAVE_TV_IN_UTMP */ -#define HAVE_TV_IN_UTMPX 1 -#define HAVE_ID_IN_UTMP 1 -#define HAVE_ID_IN_UTMPX 1 -#define HAVE_EXIT_IN_UTMP 1 -#define HAVE_TIME_IN_UTMP 1 -#define HAVE_TIME_IN_UTMPX 1 - -/* Define if you don't want to use your system's login() call */ -/* #undef DISABLE_LOGIN */ - -/* Define if you don't want to use pututline() etc. to write [uw]tmp */ -/* #undef DISABLE_PUTUTLINE */ - -/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */ -/* #undef DISABLE_PUTUTXLINE */ - -/* Define if you don't want to use lastlog */ -/* #undef DISABLE_LASTLOG */ - -/* Define if you don't want to use lastlog in session.c */ -/* #undef NO_SSH_LASTLOG */ - -/* Define if you don't want to use utmp */ -#define DISABLE_UTMP 1 - -/* Define if you don't want to use utmpx */ -/* #undef DISABLE_UTMPX */ - -/* Define if you don't want to use wtmp */ -#define DISABLE_WTMP 1 - -/* Define if you don't want to use wtmpx */ -/* #undef DISABLE_WTMPX */ - -/* Some systems need a utmpx entry for /bin/login to work */ -#define LOGIN_NEEDS_UTMPX 1 - -/* Some versions of /bin/login need the TERM supplied on the commandline */ -#define LOGIN_NEEDS_TERM 1 - -/* Define if your login program cannot handle end of options ("--") */ -/* #undef LOGIN_NO_ENDOPT */ - -/* Define if you want to specify the path to your lastlog file */ -#define CONF_LASTLOG_FILE "/var/adm/lastlog" - -/* Define if you want to specify the path to your utmp file */ -/* #undef CONF_UTMP_FILE */ - -/* Define if you want to specify the path to your wtmp file */ -/* #undef CONF_WTMP_FILE */ - -/* Define if you want to specify the path to your utmpx file */ -/* #undef CONF_UTMPX_FILE */ - -/* Define if you want to specify the path to your wtmpx file */ -/* #undef CONF_WTMPX_FILE */ - -/* Define if you want external askpass support */ -/* #undef USE_EXTERNAL_ASKPASS */ - -/* Define if libc defines __progname */ -#define HAVE___PROGNAME 1 - -/* Define if compiler implements __FUNCTION__ */ -#define HAVE___FUNCTION__ 1 - -/* Define if compiler implements __func__ */ -#define HAVE___func__ 1 - -/* Define if you want GSS-API support */ -#define GSSAPI 1 - -/* Define if you have <gssapi/gssapi.h> */ -#define SUNW_GSSAPI 1 - -/* Define if you have GSS_Store_cred() */ -#define HAVE_GSS_STORE_CRED 1 - -/* Define if you have __gss_userok() */ -#define HAVE___GSS_USEROK 1 - -/* Define for simple authorization of GSS-API principals */ -/* #undef GSSAPI_SIMPLE_USEROK */ - -/* Define if you have gsscred_name_to_unix_cred() (Solaris) */ -#define HAVE_GSSCRED_API 1 - -/* Define if you have __gss_oid_to_mech() */ -#define HAVE_GSS_OID_TO_MECH 1 - -/* Define if you have gss_oid_to_str() */ -#define HAVE_GSS_OID_TO_STR 1 - -/* Define if you want support for MIT krb5 GSS internals */ -/* #undef KRB5_GSS */ - -/* Define if you want support for GSI GSS internals */ -/* #undef GSI_GSS */ - -/* Define if you want raw Kerberos 5 support */ -/* #undef KRB5 */ - -/* Define if you want GSI/Globus authentication support */ -/* #undef GSI */ - -/* Define this if you are using the Heimdal version of Kerberos V5 */ -/* #undef HEIMDAL */ - -/* Define if you want Kerberos 4 support */ -/* #undef KRB4 */ - -/* Define if you want AFS support */ -/* #undef AFS */ - -/* Define if you want S/Key support */ -/* #undef SKEY */ - -/* Define if you want TCP Wrappers support */ -#define LIBWRAP 1 - -/* Define if your libraries define login() */ -/* #undef HAVE_LOGIN */ - -/* Define if your libraries define getpagesize() */ -#define HAVE_GETPAGESIZE 1 - -/* Define if xauth is found in your path */ -#define XAUTH_PATH "/usr/X11/bin/xauth" - -/* Define if rsh is found in your path */ -#define RSH_PATH "/usr/bin/rsh" - -/* Define if you want to allow MD5 passwords */ -/* #undef HAVE_MD5_PASSWORDS */ - -/* Define if you want to disable shadow passwords */ -/* #undef DISABLE_SHADOW */ - -/* Define if you want to use shadow password expire field */ -/* #undef HAS_SHADOW_EXPIRE */ - -/* Define if you have Digital Unix Security Integration Architecture */ -/* #undef HAVE_OSF_SIA */ - -/* Define if you have getpwanam(3) [SunOS 4.x] */ -/* #undef HAVE_GETPWANAM */ - -/* Define if you have an old version of PAM which takes only one argument */ -/* to pam_strerror */ -/* #undef HAVE_OLD_PAM */ - -/* Define if you are using Solaris-derived PAM which passes pam_messages */ -/* to the conversation function with an extra level of indirection */ -#define PAM_SUN_CODEBASE 1 - -/* Set this to your mail directory if you don't have maillock.h */ -/* #undef MAIL_DIRECTORY */ - -/* Data types */ -#define HAVE_U_INT 1 -#define HAVE_INTXX_T 1 -/* #undef HAVE_U_INTXX_T */ -#define HAVE_UINTXX_T 1 -#define HAVE_INT64_T 1 -/* #undef HAVE_U_INT64_T */ -#define HAVE_U_CHAR 1 -#define HAVE_SIZE_T 1 -#define HAVE_SSIZE_T 1 -#define HAVE_CLOCK_T 1 -#define HAVE_MODE_T 1 -#define HAVE_PID_T 1 -#define HAVE_SA_FAMILY_T 1 -#define HAVE_STRUCT_SOCKADDR_STORAGE 1 -#define HAVE_STRUCT_ADDRINFO 1 -#define HAVE_STRUCT_IN6_ADDR 1 -#define HAVE_STRUCT_SOCKADDR_IN6 1 - -/* Fields in struct sockaddr_storage */ -#define HAVE_SS_FAMILY_IN_SS 1 -/* #undef HAVE___SS_FAMILY_IN_SS */ - -/* Define if you have /dev/ptmx */ -#define HAVE_DEV_PTMX 1 - -/* Define if you have /dev/ptc */ -/* #undef HAVE_DEV_PTS_AND_PTC */ - -/* Define if you need to use IP address instead of hostname in $DISPLAY */ -/* #undef IPADDR_IN_DISPLAY */ - -/* - * Specify the default $PATH. While /bin is a symbolic link to /usr/bin in - * Solaris, to include both of them there may help when users use - * ChrootDirectory options with plain SSH connections, without their own shell - * profiles. - */ -#define USER_PATH "/usr/bin:/bin" - -/* Specify location of ssh.pid */ -#define _PATH_SSH_PIDDIR "/var/run" - -/* Use IPv4 for connection by default, IPv6 can still if explicity asked */ -/* #undef IPV4_DEFAULT */ - -/* getaddrinfo is broken (if present) */ -/* #undef BROKEN_GETADDRINFO */ - -/* Workaround more Linux IPv6 quirks */ -/* #undef DONT_TRY_OTHER_AF */ - -/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */ -#define IPV4_IN_IPV6 1 - -/* Define if you have BSD auth support */ -/* #undef BSD_AUTH */ - -/* Define if X11 doesn't support AF_UNIX sockets on that system */ -/* #undef NO_X11_UNIX_SOCKETS */ - -/* Define if the concept of ports only accessible to superusers isn't known */ -/* #undef NO_IPPORT_RESERVED_CONCEPT */ - -/* Needed for SCO and NeXT */ -/* #undef BROKEN_SAVED_UIDS */ - -/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */ -#define GLOB_HAS_ALTDIRFUNC 1 - -/* Define if your system glob() function has gl_matchc options in glob_t */ -#define GLOB_HAS_GL_MATCHC 1 - -/* - * Define in your struct dirent expects you to allocate extra space for - * d_name - */ -#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1 - -/* Define if your getopt(3) defines and uses optreset */ -/* #undef HAVE_GETOPT_OPTRESET */ - -/* Define on *nto-qnx systems */ -/* #undef MISSING_NFDBITS */ - -/* Define on *nto-qnx systems */ -/* #undef MISSING_HOWMANY */ - -/* Define on *nto-qnx systems */ -/* #undef MISSING_FD_MASK */ - -/* - * Use libedit or libtecla for sftp - * If both USE_LIBEDIT and USE_LIBTECLA are defined, then USE_LIBEDIT will - * have higher precedence. - */ -#undef USE_LIBEDIT -#define USE_LIBTECLA 1 - -/* Define if you want to use OpenSSL's internally seeded PRNG only */ -#define OPENSSL_PRNG_ONLY 1 - -/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ -/* #undef WITH_ABBREV_NO_TTY */ - -/* Define if you want a different $PATH for the superuser */ -#define SUPERUSER_PATH "/usr/sbin:/usr/bin" - -/* Path that unprivileged child will chroot() to in privep mode */ -/* #undef PRIVSEP_PATH */ - -/* Define if your platform needs to skip post auth file descriptor passing */ -/* #undef DISABLE_FD_PASSING */ - - -/* Define to 1 if the `getpgrp' function requires zero arguments. */ -#define GETPGRP_VOID 1 - -/* Define to 1 if you have the `arc4random' function. */ -/* #undef HAVE_ARC4RANDOM */ - -/* Define to 1 if you have the `asprintf' function. */ -#define HAVE_ASPRINTF 1 - -/* Define to 1 if you have the `b64_ntop' function. */ -/* #undef HAVE_B64_NTOP */ - -/* Define to 1 if you have the `bcopy' function. */ -#define HAVE_BCOPY 1 - -/* Define to 1 if you have the `bindresvport_sa' function. */ -/* #undef HAVE_BINDRESVPORT_SA */ - -/* Define to 1 if you have the <bstring.h> header file. */ -/* #undef HAVE_BSTRING_H */ - -/* Define to 1 if you have the `clock' function. */ -#define HAVE_CLOCK 1 - -/* Define to 1 if you have the <crypt.h> header file. */ -#define HAVE_CRYPT_H 1 - -/* Define to 1 if you have the `dirname' function. */ -#define HAVE_DIRNAME 1 - -/* Define to 1 if you have the <endian.h> header file. */ -/* #undef HAVE_ENDIAN_H */ - -/* Define to 1 if you have the `endutent' function. */ -#define HAVE_ENDUTENT 1 - -/* Define to 1 if you have the `endutxent' function. */ -#define HAVE_ENDUTXENT 1 - -/* Define to 1 if you have the `fchmod' function. */ -#define HAVE_FCHMOD 1 - -/* Define to 1 if you have the `fchown' function. */ -#define HAVE_FCHOWN 1 - -/* Define to 1 if you have the <floatingpoint.h> header file. */ -#define HAVE_FLOATINGPOINT_H 1 - -/* Define to 1 if you have the `freeaddrinfo' function. */ -#define HAVE_FREEADDRINFO 1 - -/* Define to 1 if you have the `futimes' function. */ -/* #undef HAVE_FUTIMES */ - -/* Define to 1 if you have the `gai_strerror' function. */ -#define HAVE_GAI_STRERROR 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getcwd' function. */ -#define HAVE_GETCWD 1 - -/* Define to 1 if you have the `getgrouplist' function. */ -/* #undef HAVE_GETGROUPLIST */ - -/* Define to 1 if you have the `getluid' function. */ -/* #undef HAVE_GETLUID */ - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `getopt' function. */ -#define HAVE_GETOPT 1 - -/* Define to 1 if you have the <getopt.h> header file. */ -/* #undef HAVE_GETOPT_H */ - -/* Define to 1 if you have the `getpeereid' function. */ -/* #undef HAVE_GETPEEREID */ - -/* Define to 1 if you have the `getpeerucred' function. */ -#define HAVE_GETPEERUCRED 1 - -/* Define to 1 if you have the `getpwanam' function. */ -/* #undef HAVE_GETPWANAM */ - -/* Define to 1 if you have the `getrlimit' function. */ -#define HAVE_GETRLIMIT 1 - -/* Define to 1 if you have the `getrusage' function. */ -#define HAVE_GETRUSAGE 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `getttyent' function. */ -/* #undef HAVE_GETTTYENT */ - -/* Define to 1 if you have the `getutent' function. */ -#define HAVE_GETUTENT 1 - -/* Define to 1 if you have the `getutid' function. */ -#define HAVE_GETUTID 1 - -/* Define to 1 if you have the `getutline' function. */ -#define HAVE_GETUTLINE 1 - -/* Define to 1 if you have the `getutxent' function. */ -#define HAVE_GETUTXENT 1 - -/* Define to 1 if you have the `getutxid' function. */ -#define HAVE_GETUTXID 1 - -/* Define to 1 if you have the `getutxline' function. */ -#define HAVE_GETUTXLINE 1 - -/* Define to 1 if you have the `glob' function. */ -#define HAVE_GLOB 1 - -/* Define to 1 if you have the <glob.h> header file. */ -#define HAVE_GLOB_H 1 - -/* Define to 1 if you have the <ia.h> header file. */ -/* #undef HAVE_IA_H */ - -/* Define to 1 if you have the `inet_aton' function. */ -/* #undef HAVE_INET_ATON */ - -/* Define to 1 if you have the `inet_ntoa' function. */ -#define HAVE_INET_NTOA 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the `innetgr' function. */ -#define HAVE_INNETGR 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the <krb.h> header file. */ -/* #undef HAVE_KRB_H */ - -/* Define to 1 if you have the <lastlog.h> header file. */ -#define HAVE_LASTLOG_H 1 - -/* Define to 1 if you have the `crypt' library (-lcrypt). */ -/* #undef HAVE_LIBCRYPT */ - -/* Define to 1 if you have the `des' library (-ldes). */ -/* #undef HAVE_LIBDES */ - -/* Define to 1 if you have the `des425' library (-ldes425). */ -/* #undef HAVE_LIBDES425 */ - -/* Define to 1 if you have the `dl' library (-ldl). */ -#define HAVE_LIBDL 1 - -/* Define to 1 if you have the <libgen.h> header file. */ -#define HAVE_LIBGEN_H 1 - -/* Define to 1 if you have the `krb' library (-lkrb). */ -/* #undef HAVE_LIBKRB */ - -/* Define to 1 if you have the `krb4' library (-lkrb4). */ -/* #undef HAVE_LIBKRB4 */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define to 1 if you have the `pam' library (-lpam). */ -#define HAVE_LIBPAM 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -/* #undef HAVE_LIBRESOLV */ - -/* Define to 1 if you have the `sectok' library (-lsectok). */ -/* #undef HAVE_LIBSECTOK */ - -/* Define to 1 if you have the `socket' library (-lsocket). */ -#define HAVE_LIBSOCKET 1 - -/* Define to 1 if you have the <libutil.h> header file. */ -/* #undef HAVE_LIBUTIL_H */ - -/* Define to 1 if you have the `xnet' library (-lxnet). */ -/* #undef HAVE_LIBXNET */ - -/* Define to 1 if you have the `z' library (-lz). */ -#define HAVE_LIBZ 1 - -/* Define to 1 if you have the <limits.h> header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the <login.h> header file. */ -/* #undef HAVE_LOGIN_H */ - -/* Define to 1 if you have the `logout' function. */ -/* #undef HAVE_LOGOUT */ - -/* Define to 1 if you have the `logwtmp' function. */ -/* #undef HAVE_LOGWTMP */ - -/* Define to 1 if you have the <maillock.h> header file. */ -#define HAVE_MAILLOCK_H 1 - -/* Define to 1 if you have the `md5_crypt' function. */ -/* #undef HAVE_MD5_CRYPT */ - -/* Define to 1 if you have the `memmove' function. */ -#define HAVE_MEMMOVE 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have mkstemp, mkstemps and mkdtemp */ -#define HAVE_MKDTEMP 1 - -/* Define to 1 if you have the `mmap' function. */ -#define HAVE_MMAP 1 - -/* Define to 1 if you have the <netdb.h> header file. */ -#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the <netgroup.h> header file. */ -/* #undef HAVE_NETGROUP_H */ - -/* Define to 1 if you have the <netinet/in_systm.h> header file. */ -#define HAVE_NETINET_IN_SYSTM_H 1 - -/* Define to 1 if you have the `ngetaddrinfo' function. */ -/* #undef HAVE_NGETADDRINFO */ - -/* Define to 1 if you have the `ogetaddrinfo' function. */ -/* #undef HAVE_OGETADDRINFO */ - -/* Define to 1 if you have the `openpty' function. */ -/* #undef HAVE_OPENPTY */ - -/* Define to 1 if you have the `pam_getenvlist' function. */ -#define HAVE_PAM_GETENVLIST 1 - -/* Define to 1 if you have the <paths.h> header file. */ -/* #undef HAVE_PATHS_H */ - -/* Define to 1 if you have the <pty.h> header file. */ -/* #undef HAVE_PTY_H */ - -/* Define to 1 if you have the `pututline' function. */ -#define HAVE_PUTUTLINE 1 - -/* Define to 1 if you have the `pututxline' function. */ -#define HAVE_PUTUTXLINE 1 - -/* Define to 1 if you have the `readpassphrase' function. */ -/* #undef HAVE_READPASSPHRASE */ - -/* Define to 1 if you have the <readpassphrase.h> header file. */ -/* #undef HAVE_READPASSPHRASE_H */ - -/* Define to 1 if you have the `realpath' function. */ -#define HAVE_REALPATH 1 - -/* Define to 1 if you have the `recvmsg' function. */ -#define HAVE_RECVMSG 1 - -/* Define to 1 if you have the <rpc/types.h> header file. */ -#define HAVE_RPC_TYPES_H 1 - -/* Define to 1 if you have the `rresvport_af' function. */ -#define HAVE_RRESVPORT_AF 1 - -/* Define to 1 if you have the <sectok.h> header file. */ -/* #undef HAVE_SECTOK_H */ - -/* Define to 1 if you have the <security/pam_appl.h> header file. */ -#define HAVE_SECURITY_PAM_APPL_H 1 - -/* Define to 1 if you have the `sendmsg' function. */ -#define HAVE_SENDMSG 1 - -/* Define to 1 if you have the `setdtablesize' function. */ -/* #undef HAVE_SETDTABLESIZE */ - -/* Define to 1 if you have the `setegid' function. */ -#define HAVE_SETEGID 1 - -/* Define to 1 if you have the `setenv' function. */ -#define HAVE_SETENV 1 - -/* Define to 1 if you have the `seteuid' function. */ -#define HAVE_SETEUID 1 - -/* Define to 1 if you have the `setgroups' function. */ -#define HAVE_SETGROUPS 1 - -/* Define to 1 if you have the `setlogin' function. */ -/* #undef HAVE_SETLOGIN */ - -/* Define to 1 if you have the `setluid' function. */ -/* #undef HAVE_SETLUID */ - -/* Define to 1 if you have the `setpcred' function. */ -/* #undef HAVE_SETPCRED */ - -/* Define to 1 if you have the `setproctitle' function. */ -/* #undef HAVE_SETPROCTITLE */ - -/* Define to 1 if you have the `setresgid' function. */ -/* #undef HAVE_SETRESGID */ - -/* Define to 1 if you have the `setreuid' function. */ -#define HAVE_SETREUID 1 - -/* Define to 1 if you have the `setrlimit' function. */ -#define HAVE_SETRLIMIT 1 - -/* Define to 1 if you have the `setsid' function. */ -#define HAVE_SETSID 1 - -/* Define to 1 if you have the `setutent' function. */ -#define HAVE_SETUTENT 1 - -/* Define to 1 if you have the `setutxent' function. */ -#define HAVE_SETUTXENT 1 - -/* Define to 1 if you have the `setvbuf' function. */ -#define HAVE_SETVBUF 1 - -/* Define to 1 if you have the <shadow.h> header file. */ -#define HAVE_SHADOW_H 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `sigvec' function. */ -/* #undef HAVE_SIGVEC */ - -/* Define to 1 if the system has the type `sig_atomic_t'. */ -#define HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 - -/* Define to 1 if you have the `socketpair' function. */ -#define HAVE_SOCKETPAIR 1 - -/* Define to 1 if you have the <stddef.h> header file. */ -#define HAVE_STDDEF_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the `strftime' function. */ -#define HAVE_STRFTIME 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcat' function. */ -#define HAVE_STRLCAT 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strmode' function. */ -/* #undef HAVE_STRMODE */ - -/* Define to 1 if `st_blksize' is member of `struct stat'. */ -#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 - -/* Define to 1 if you have the `sysconf' function. */ -#define HAVE_SYSCONF 1 - -/* Define to 1 if you have the <sys/bitypes.h> header file. */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Define to 1 if you have the <sys/bsdtty.h> header file. */ -/* #undef HAVE_SYS_BSDTTY_H */ - -/* Define to 1 if you have the <sys/cdefs.h> header file. */ -/* #undef HAVE_SYS_CDEFS_H */ - - -/* Define to 1 if you have the <sys/mman.h> header file. */ -#define HAVE_SYS_MMAN_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/stropts.h> header file. */ -#define HAVE_SYS_STROPTS_H 1 - -/* Define to 1 if you have the <sys/sysmacros.h> header file. */ -#define HAVE_SYS_SYSMACROS_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the <sys/un.h> header file. */ -#define HAVE_SYS_UN_H 1 - -/* Define to 1 if you have the `tcgetpgrp' function. */ -#define HAVE_TCGETPGRP 1 - -/* Define to 1 if you have the `time' function. */ -#define HAVE_TIME 1 - -/* Define to 1 if you have the <time.h> header file. */ -#define HAVE_TIME_H 1 - -/* Define to 1 if you have the <tmpdir.h> header file. */ -/* #undef HAVE_TMPDIR_H */ - -/* Define to 1 if you have the `truncate' function. */ -#define HAVE_TRUNCATE 1 - -/* Define to 1 if you have the <ttyent.h> header file. */ -/* #undef HAVE_TTYENT_H */ - -/* Define to 1 if you have the <ucred.h> header file. */ -#define HAVE_UCRED_H 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `updwtmp' function. */ -#define HAVE_UPDWTMP 1 - -/* Define to 1 if you have the <usersec.h> header file. */ -/* #undef HAVE_USERSEC_H */ - -/* Define to 1 if you have the <util.h> header file. */ -/* #undef HAVE_UTIL_H */ - -/* Define to 1 if you have the `utimes' function. */ -#define HAVE_UTIMES 1 - -/* Define to 1 if you have the <utime.h> header file. */ -#define HAVE_UTIME_H 1 - -/* Define to 1 if you have the `utmpname' function. */ -#define HAVE_UTMPNAME 1 - -/* Define to 1 if you have the `utmpxname' function. */ -#define HAVE_UTMPXNAME 1 - -/* Define to 1 if you have the <utmpx.h> header file. */ -#define HAVE_UTMPX_H 1 - -/* Define to 1 if you have the <utmp.h> header file. */ -#define HAVE_UTMP_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define to 1 if you have the `vhangup' function. */ -#define HAVE_VHANGUP 1 - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 - -/* Define to 1 if you have the `waitpid' function. */ -#define HAVE_WAITPID 1 - -/* Define to 1 if you have the `_getpty' function. */ -/* #undef HAVE__GETPTY */ - -/* Define to 1 if you have the `__b64_ntop' function. */ -/* #undef HAVE___B64_NTOP */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of a `char', as computed by sizeof. */ -#define SIZEOF_CHAR 1 - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long int', as computed by sizeof. */ -#define SIZEOF_LONG_INT 4 - -/* The size of a `long long int', as computed by sizeof. */ -#define SIZEOF_LONG_LONG_INT 8 - -/* The size of a `short int', as computed by sizeof. */ -#define SIZEOF_SHORT_INT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* - * Define to 1 if your processor stores words with the most significant byte - * first (like Motorola and SPARC, unlike Intel and VAX). - */ -#define WORDS_BIGENDIAN 1 - -/* Number of bits in a file offset, on hosts where this is settable. */ -#define _FILE_OFFSET_BITS 64 - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* - * Define as `__inline' if that's what the C compiler calls it, or to nothing if - * it is not supported. - */ -/* #undef inline */ - -/* type to use in place of socklen_t if not defined */ -/* #undef socklen_t */ - -/* Define for BSM auditing (Solaris) support */ -#define HAVE_BSM 1 - -/* Define if compiling in ON */ -#define SUNW_SSH 1 - -/* ******************* Shouldn't need to edit below this line ************** */ - -#ifdef __cplusplus -} -#endif - -#endif /* _CONFIG_H */ diff --git a/usr/src/cmd/ssh/include/crc32.h b/usr/src/cmd/ssh/include/crc32.h deleted file mode 100644 index 3218cc925c..0000000000 --- a/usr/src/cmd/ssh/include/crc32.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $OpenBSD: crc32.h,v 1.13 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _CRC32_H -#define _CRC32_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1992 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for computing 32-bit CRC. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -u_int ssh_crc32(const u_char *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _CRC32_H */ diff --git a/usr/src/cmd/ssh/include/deattack.h b/usr/src/cmd/ssh/include/deattack.h deleted file mode 100644 index fa7fc82312..0000000000 --- a/usr/src/cmd/ssh/include/deattack.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $OpenBSD: deattack.h,v 1.7 2001/06/26 17:27:23 markus Exp $ */ - -#ifndef _DEATTACK_H -#define _DEATTACK_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Cryptographic attack detector for ssh - Header file - * - * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. - * - * All rights reserved. Redistribution and use in source and binary - * forms, with or without modification, are permitted provided that - * this copyright notice is retained. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR - * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS - * SOFTWARE. - * - * Ariel Futoransky <futo@core-sdi.com> - * <http://www.core-sdi.com> - */ - -/* Return codes */ -#define DEATTACK_OK 0 -#define DEATTACK_DETECTED 1 -#define DEATTACK_DOS_DETECTED 2 - -int detect_attack(u_char *, u_int32_t, u_char[8]); - -#ifdef __cplusplus -} -#endif - -#endif /* _DEATTACK_H */ diff --git a/usr/src/cmd/ssh/include/defines.h b/usr/src/cmd/ssh/include/defines.h deleted file mode 100644 index 13eb012162..0000000000 --- a/usr/src/cmd/ssh/include/defines.h +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright (c) 1999-2003 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _DEFINES_H -#define _DEFINES_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* $Id: defines.h,v 1.96 2002/09/26 00:38:48 tim Exp $ */ - - -/* Constants */ -#ifndef SHUT_RDWR -enum -{ - SHUT_RD = 0, /* No more receptions. */ - SHUT_WR, /* No more transmissions. */ - SHUT_RDWR /* No more receptions or transmissions. */ -}; -#define SHUT_RD SHUT_RD -#define SHUT_WR SHUT_WR -#define SHUT_RDWR SHUT_RDWR -#endif - -#ifndef IPTOS_LOWDELAY -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IPTOS_LOWCOST 0x02 -#define IPTOS_MINCOST IPTOS_LOWCOST -#endif /* IPTOS_LOWDELAY */ - -#ifndef MAXPATHLEN -#ifdef PATH_MAX -#define MAXPATHLEN PATH_MAX -#else /* PATH_MAX */ -#define MAXPATHLEN 64 /* Should be safe */ -#endif /* PATH_MAX */ -#endif /* MAXPATHLEN */ - -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif - -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif - -/* Disable groupaccess if NGROUPS_UMAX, NGROUPS_MAX and NGROUPS are not set */ -#ifndef NGROUPS_UMAX -#ifdef NGROUPS_MAX -#define NGROUPS_UMAX NGROUPS_MAX -#elif defined(NGROUPS) -#define NGROUPS_UMAX NGROUPS -#else -#define NGROUPS_UMAX 0 -#endif -#endif - -#ifndef O_NONBLOCK /* Non Blocking Open */ -#define O_NONBLOCK 00004 -#endif - -#ifndef S_ISDIR -#define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR)) -#endif /* S_ISDIR */ - -#ifndef S_ISREG -#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG)) -#endif /* S_ISREG */ - -#ifndef S_ISLNK -#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#endif /* S_ISLNK */ - -#ifndef S_IXUSR -#define S_IXUSR 0000100 /* execute/search permission, */ -#define S_IXGRP 0000010 /* execute/search permission, */ -#define S_IXOTH 0000001 /* execute/search permission, */ -#define _S_IWUSR 0000200 /* write permission, */ -#define S_IWUSR _S_IWUSR /* write permission, owner */ -#define S_IWGRP 0000020 /* write permission, group */ -#define S_IWOTH 0000002 /* write permission, other */ -#define S_IRUSR 0000400 /* read permission, owner */ -#define S_IRGRP 0000040 /* read permission, group */ -#define S_IROTH 0000004 /* read permission, other */ -#define S_IRWXU 0000700 /* read, write, execute */ -#define S_IRWXG 0000070 /* read, write, execute */ -#define S_IRWXO 0000007 /* read, write, execute */ -#endif /* S_IXUSR */ - -#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) -#define MAP_ANON MAP_ANONYMOUS -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -/* *-*-nto-qnx doesn't define this constant in the system headers */ -#ifdef MISSING_NFDBITS -#define NFDBITS (8 * sizeof (unsigned long)) -#endif - -/* - * SCO Open Server 3 has INADDR_LOOPBACK defined in rpc/rpc.h but including - * rpc/rpc.h breaks Solaris 6 - */ -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK ((ulong_t)0x7f000001) -#endif - -/* Types */ - -/* - * If sys/types.h does not supply intXX_t, supply them ourselves (or die trying) - */ -#ifndef HAVE_U_INT -/* for now, we can't remove u_int without changing almost all other files */ -/* CSTYLED */ -typedef unsigned int u_int; -#endif - -#ifndef HAVE_INTXX_T -#if (SIZEOF_CHAR == 1) -typedef char int8_t; -#else -#error "8 bit int type not found." -#endif -#if (SIZEOF_SHORT_INT == 2) -typedef short int int16_t; -#else -#ifdef _UNICOS -#if (SIZEOF_SHORT_INT == 4) -typedef short int16_t; -#else -typedef long int16_t; -#endif -#else -#error "16 bit int type not found." -#endif /* _UNICOS */ -#endif -#if (SIZEOF_INT == 4) -typedef int int32_t; -#else -#ifdef _UNICOS -typedef long int32_t; -#else -#error "32 bit int type not found." -#endif /* _UNICOS */ -#endif -#endif - -/* If sys/types.h does not supply u_intXX_t, supply them ourselves */ -#ifndef HAVE_U_INTXX_T -#ifdef HAVE_UINTXX_T -typedef uint8_t u_int8_t; -typedef uint16_t u_int16_t; -typedef uint32_t u_int32_t; -#define HAVE_U_INTXX_T 1 -#else -#if (SIZEOF_CHAR == 1) -typedef unsigned char u_int8_t; -#else -#error "8 bit int type not found." -#endif -#if (SIZEOF_SHORT_INT == 2) -typedef unsigned short int u_int16_t; -#else -#ifdef _UNICOS -#if (SIZEOF_SHORT_INT == 4) -typedef unsigned short u_int16_t; -#else -typedef unsigned long u_int16_t; -#endif -#else -#error "16 bit int type not found." -#endif -#endif -#if (SIZEOF_INT == 4) -typedef unsigned int u_int32_t; -#else -#ifdef _UNICOS -typedef unsigned long u_int32_t; -#else -#error "32 bit int type not found." -#endif -#endif -#endif -#define __BIT_TYPES_DEFINED__ -#endif - -/* 64-bit types */ -#ifndef HAVE_INT64_T -#if (SIZEOF_LONG_INT == 8) -typedef long int int64_t; -#define HAVE_INT64_T 1 -#else -#if (SIZEOF_LONG_LONG_INT == 8) -typedef long long int int64_t; -#define HAVE_INT64_T 1 -#endif -#endif -#endif - -#ifndef HAVE_U_INT64_T -#if (SIZEOF_LONG_INT == 8) -typedef unsigned long int u_int64_t; -#define HAVE_U_INT64_T 1 -#else -#if (SIZEOF_LONG_LONG_INT == 8) -typedef unsigned long long int u_int64_t; -#define HAVE_U_INT64_T 1 -#endif -#endif -#endif - -#if !defined(HAVE_LONG_LONG_INT) && (SIZEOF_LONG_LONG_INT == 8) -#define HAVE_LONG_LONG_INT 1 -#endif - -#ifndef HAVE_U_CHAR -/* for now, we can't remove u_char without changing almost all other files */ -/* CSTYLED */ -typedef unsigned char u_char; -#define HAVE_U_CHAR -#endif /* HAVE_U_CHAR */ - -#ifndef SIZE_T_MAX -#define SIZE_T_MAX ULONG_MAX -#endif /* SIZE_T_MAX */ - -#ifndef HAVE_SIZE_T -typedef unsigned int size_t; -#define HAVE_SIZE_T -#endif /* HAVE_SIZE_T */ - -#ifndef HAVE_SSIZE_T -typedef int ssize_t; -#define HAVE_SSIZE_T -#endif /* HAVE_SSIZE_T */ - -#ifndef HAVE_CLOCK_T -typedef long clock_t; -#define HAVE_CLOCK_T -#endif /* HAVE_CLOCK_T */ - -#ifndef HAVE_SA_FAMILY_T -typedef int sa_family_t; -#define HAVE_SA_FAMILY_T -#endif /* HAVE_SA_FAMILY_T */ - -#ifndef HAVE_PID_T -typedef int pid_t; -#define HAVE_PID_T -#endif /* HAVE_PID_T */ - -#ifndef HAVE_SIG_ATOMIC_T -typedef int sig_atomic_t; -#define HAVE_SIG_ATOMIC_T -#endif /* HAVE_SIG_ATOMIC_T */ - -#ifndef HAVE_MODE_T -typedef int mode_t; -#define HAVE_MODE_T -#endif /* HAVE_MODE_T */ - -#if !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE___SS_FAMILY_IN_SS) -#define ss_family __ss_family -#endif /* !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE_SA_FAMILY_IN_SS) */ - -#ifndef HAVE_SYS_UN_H -struct sockaddr_un { - short sun_family; /* AF_UNIX */ - char sun_path[108]; /* path name (gag) */ -}; -#endif /* HAVE_SYS_UN_H */ - -#if defined(BROKEN_SYS_TERMIO_H) && !defined(_STRUCT_WINSIZE) -#define _STRUCT_WINSIZE -struct winsize { - unsigned short ws_row; /* rows, in characters */ - unsigned short ws_col; /* columns, in character */ - unsigned short ws_xpixel; /* horizontal size, pixels */ - unsigned short ws_ypixel; /* vertical size, pixels */ -}; -#endif - -/* *-*-nto-qnx does not define this type in the system headers */ -#ifdef MISSING_FD_MASK -typedef unsigned long int fd_mask; -#endif - -/* Paths */ - -#ifndef _PATH_BSHELL -#define _PATH_BSHELL "/bin/sh" -#endif - -#ifndef _PATH_CSHELL -#define _PATH_CSHELL "/bin/csh" -#endif - -#ifndef _PATH_SHELLS -#define _PATH_SHELLS "/etc/shells" -#endif - -#ifdef USER_PATH -#ifdef _PATH_STDPATH -#undef _PATH_STDPATH -#endif -#define _PATH_STDPATH USER_PATH -#endif - -#ifndef _PATH_STDPATH -#define _PATH_STDPATH "/usr/bin" -#endif - -#ifndef _PATH_DEVNULL -#define _PATH_DEVNULL "/dev/null" -#endif - -#ifndef MAIL_DIRECTORY -#define MAIL_DIRECTORY "/var/spool/mail" -#endif - -#ifndef MAILDIR -#define MAILDIR MAIL_DIRECTORY -#endif - -#if !defined(_PATH_MAILDIR) && defined(MAILDIR) -#define _PATH_MAILDIR MAILDIR -#endif /* !defined(_PATH_MAILDIR) && defined(MAILDIR) */ - -#ifndef _PATH_RSH -#ifdef RSH_PATH -#define _PATH_RSH RSH_PATH -#else /* RSH_PATH */ -#define _PATH_RSH "/usr/bin/rsh" -#endif /* RSH_PATH */ -#endif /* _PATH_RSH */ - -#ifndef _PATH_NOLOGIN -#define _PATH_NOLOGIN "/etc/nologin" -#endif - -/* Define this to be the path of the xauth program. */ -#ifdef XAUTH_PATH -#define _PATH_XAUTH XAUTH_PATH -#endif /* XAUTH_PATH */ - -/* derived from XF4/xc/lib/dps/Xlibnet.h */ -#ifndef X_UNIX_PATH -#ifdef __hpux -#define X_UNIX_PATH "/var/spool/sockets/X11/%u" -#else -#define X_UNIX_PATH "/tmp/.X11-unix/X%u" -#endif -#endif /* X_UNIX_PATH */ - -#define _PATH_UNIX_X X_UNIX_PATH - -#ifndef _PATH_TTY -#define _PATH_TTY "/dev/tty" -#endif - -/* Macros */ - -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef roundup -#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) -#endif - -#ifndef timersub -#define timersub(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ - } while (0) -#endif - -#ifndef __P -#define __P(x) x -#endif - -#if !defined(IN6_IS_ADDR_V4MAPPED) -#define IN6_IS_ADDR_V4MAPPED(a) \ - ((((u_int32_t *)(a))[0] == 0) && (((u_int32_t *)(a))[1] == 0) && \ - (((u_int32_t *)(a))[2] == htonl(0xffff))) -#endif /* !defined(IN6_IS_ADDR_V4MAPPED) */ - -#if !defined(__GNUC__) || (__GNUC__ < 2) -#define __attribute__(x) -#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */ - -#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__) -#define __bounded__(x, y, z) -#endif - -/* *-*-nto-qnx doesn't define this macro in the system headers */ -#ifdef MISSING_HOWMANY -#define howmany(x, y) (((x) + ((y) - 1)) / (y)) -#endif - -#ifndef OSSH_ALIGNBYTES -#define OSSH_ALIGNBYTES (sizeof (int) - 1) -#endif - -#ifndef __CMSG_ALIGN -#define __CMSG_ALIGN(p) (((uint_t)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES) -#endif - -/* Length of the contents of a control message of length len */ -#ifndef CMSG_LEN -#define CMSG_LEN(len) (__CMSG_ALIGN(sizeof (struct cmsghdr)) + (len)) -#endif - -/* Length of the space taken up by a padded control message of length len */ -#ifndef CMSG_SPACE -#define CMSG_SPACE(len) \ - (__CMSG_ALIGN(sizeof (struct cmsghdr)) + __CMSG_ALIGN(len)) -#endif - -/* Function replacement / compatibility hacks */ - -#if !defined(HAVE_GETADDRINFO) && (defined(HAVE_OGETADDRINFO) || \ - defined(HAVE_NGETADDRINFO)) -#define HAVE_GETADDRINFO -#endif - -#ifndef HAVE_GETOPT_OPTRESET -#undef getopt -#undef opterr -#undef optind -#undef optopt -#undef optreset -#undef optarg -#define getopt(ac, av, o) BSDgetopt(ac, av, o) -#define opterr BSDopterr -#define optind BSDoptind -#define optopt BSDoptopt -#define optreset BSDoptreset -#define optarg BSDoptarg -#endif - -/* In older versions of libpam, pam_strerror takes a single argument */ -#ifdef HAVE_OLD_PAM -#define PAM_STRERROR(a, b) pam_strerror((b)) -#else -#define PAM_STRERROR(a, b) pam_strerror((a), (b)) -#endif - -#ifdef PAM_SUN_CODEBASE -#define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member) -#else -#define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member) -#endif - -#if defined(BROKEN_GETADDRINFO) && defined(HAVE_GETADDRINFO) -#undef HAVE_GETADDRINFO -#endif - -#if defined(BROKEN_GETADDRINFO) && defined(HAVE_FREEADDRINFO) -#undef HAVE_FREEADDRINFO -#endif - -#if defined(BROKEN_GETADDRINFO) && defined(HAVE_GAI_STRERROR) -#undef HAVE_GAI_STRERROR -#endif - -#if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) -#define memmove(s1, s2, n) bcopy((s2), (s1), (n)) -#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ - -#if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) -#define USE_VHANGUP -#endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */ - -#ifndef GETPGRP_VOID -#define getpgrp() getpgrp(0) -#endif - -/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */ -#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f) -#define OPENSSL_free(x) Free(x) -#endif - -#if !defined(HAVE___func__) && defined(HAVE___FUNCTION__) -#define __func__ __FUNCTION__ -#elif !defined(HAVE___func__) -#define __func__ "" -#endif - -/* - * login recorder definitions - */ - -/* FIXME: put default paths back in */ -#ifndef UTMP_FILE -#ifdef _PATH_UTMP -#define UTMP_FILE _PATH_UTMP -#else -#ifdef CONF_UTMP_FILE -#define UTMP_FILE CONF_UTMP_FILE -#endif -#endif -#endif - -#ifndef WTMP_FILE -#ifdef _PATH_WTMP -#define WTMP_FILE _PATH_WTMP -#else -#ifdef CONF_WTMP_FILE -#define WTMP_FILE CONF_WTMP_FILE -#endif -#endif -#endif - -/* pick up the user's location for lastlog if given */ -#ifndef LASTLOG_FILE -#ifdef _PATH_LASTLOG -#define LASTLOG_FILE _PATH_LASTLOG -#else -#ifdef CONF_LASTLOG_FILE -#define LASTLOG_FILE CONF_LASTLOG_FILE -#endif -#endif -#endif - -/* The login() library function in libutil is first choice */ -#if defined(HAVE_LOGIN) && !defined(DISABLE_LOGIN) -#define USE_LOGIN -#else -/* Simply select your favourite login types. */ -/* Can't do if-else because some systems use several... <sigh> */ -#if defined(UTMPX_FILE) && !defined(DISABLE_UTMPX) -#define USE_UTMPX -#endif -#if defined(UTMP_FILE) && !defined(DISABLE_UTMP) -#define USE_UTMP -#endif -#if defined(WTMPX_FILE) && !defined(DISABLE_WTMPX) -#define USE_WTMPX -#endif -#if defined(WTMP_FILE) && !defined(DISABLE_WTMP) -#define USE_WTMP -#endif -#endif - -/* I hope that the presence of LASTLOG_FILE is enough to detect this */ -#if defined(LASTLOG_FILE) && !defined(DISABLE_LASTLOG) -#define USE_LASTLOG -#endif - -/* end of login recorder definitions */ - -#ifdef __cplusplus -} -#endif - -#endif /* _DEFINES_H */ diff --git a/usr/src/cmd/ssh/include/dh.h b/usr/src/cmd/ssh/include/dh.h deleted file mode 100644 index e977847119..0000000000 --- a/usr/src/cmd/ssh/include/dh.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD: dh.h,v 1.7 2001/06/26 17:27:23 markus Exp $ */ - -#ifndef _DH_H -#define _DH_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -struct dhgroup { - int size; - BIGNUM *g; - BIGNUM *p; -}; - -DH *choose_dh(int, int, int); -DH *dh_new_group_asc(const char *, const char *); -DH *dh_new_group(BIGNUM *, BIGNUM *); -DH *dh_new_group1(void); - -void dh_gen_key(DH *, int); -int dh_pub_is_valid(DH *, BIGNUM *); - -int dh_estimate(int); - -#define DH_GRP_MIN 1024 -#define DH_GRP_MAX 8192 - -#ifdef __cplusplus -} -#endif - -#endif /* _DH_H */ diff --git a/usr/src/cmd/ssh/include/dirname.h b/usr/src/cmd/ssh/include/dirname.h deleted file mode 100644 index 4201e3399d..0000000000 --- a/usr/src/cmd/ssh/include/dirname.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * XXX - Add OpenSSH copyright... - */ - -#ifndef _DIRNAME_H -#define _DIRNAME_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef HAVE_DIRNAME - -char *dirname(const char *path); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _DIRNAME_H */ diff --git a/usr/src/cmd/ssh/include/dispatch.h b/usr/src/cmd/ssh/include/dispatch.h deleted file mode 100644 index 9262c9a034..0000000000 --- a/usr/src/cmd/ssh/include/dispatch.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $OpenBSD: dispatch.h,v 1.9 2002/01/11 13:39:36 markus Exp $ */ - -#ifndef _DISPATCH_H -#define _DISPATCH_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -enum { - DISPATCH_BLOCK, - DISPATCH_NONBLOCK -}; - -typedef void dispatch_fn(int, u_int32_t, void *); - -void dispatch_init(dispatch_fn *); -void dispatch_set(int, dispatch_fn *); -void dispatch_range(u_int, u_int, dispatch_fn *); -void dispatch_run(int, int *, void *); -void dispatch_protocol_error(int, u_int32_t, void *); -void dispatch_protocol_ignore(int, u_int32_t, void *); - -#ifdef __cplusplus -} -#endif - -#endif /* _DISPATCH_H */ diff --git a/usr/src/cmd/ssh/include/entropy.h b/usr/src/cmd/ssh/include/entropy.h deleted file mode 100644 index 79a2884eca..0000000000 --- a/usr/src/cmd/ssh/include/entropy.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 1999-2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _ENTROPY_H -#define _ENTROPY_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* $Id: entropy.h,v 1.4 2001/02/09 01:55:36 djm Exp $ */ - -void seed_rng(void); -void init_rng(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _ENTROPY_H */ diff --git a/usr/src/cmd/ssh/include/fake-gai-errnos.h b/usr/src/cmd/ssh/include/fake-gai-errnos.h deleted file mode 100644 index 8df9159f18..0000000000 --- a/usr/src/cmd/ssh/include/fake-gai-errnos.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * fake library for ssh - * - * This file is included in getaddrinfo.c and getnameinfo.c. - * See getaddrinfo.c and getnameinfo.c. - */ - -#ifndef _FAKE_GAI_ERRNOS_H -#define _FAKE_GAI_ERRNOS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* $Id: fake-gai-errnos.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -/* for old netdb.h */ -#ifndef EAI_NODATA -#define EAI_NODATA 1 -#define EAI_MEMORY 2 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _FAKE_GAI_ERRNOS_H */ diff --git a/usr/src/cmd/ssh/include/fake-getaddrinfo.h b/usr/src/cmd/ssh/include/fake-getaddrinfo.h deleted file mode 100644 index b5a1a6441e..0000000000 --- a/usr/src/cmd/ssh/include/fake-getaddrinfo.h +++ /dev/null @@ -1,57 +0,0 @@ -/* $Id: fake-getaddrinfo.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _FAKE_GETADDRINFO_H -#define _FAKE_GETADDRINFO_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#include "fake-gai-errnos.h" - -#ifndef AI_PASSIVE -# define AI_PASSIVE 1 -# define AI_CANONNAME 2 -#endif - -#ifndef NI_NUMERICHOST -# define NI_NUMERICHOST 2 -# define NI_NAMEREQD 4 -# define NI_NUMERICSERV 8 -#endif - -#ifndef HAVE_STRUCT_ADDRINFO -struct addrinfo { - int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ - int ai_family; /* PF_xxx */ - int ai_socktype; /* SOCK_xxx */ - int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ - char *ai_canonname; /* canonical name for hostname */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ -}; -#endif /* !HAVE_STRUCT_ADDRINFO */ - -#ifndef HAVE_GETADDRINFO -int getaddrinfo(const char *hostname, const char *servname, - const struct addrinfo *hints, struct addrinfo **res); -#endif /* !HAVE_GETADDRINFO */ - -#ifndef HAVE_GAI_STRERROR -char *gai_strerror(int ecode); -#endif /* !HAVE_GAI_STRERROR */ - -#ifndef HAVE_FREEADDRINFO -void freeaddrinfo(struct addrinfo *ai); -#endif /* !HAVE_FREEADDRINFO */ - -#ifdef __cplusplus -} -#endif - -#endif /* _FAKE_GETADDRINFO_H */ diff --git a/usr/src/cmd/ssh/include/fake-getnameinfo.h b/usr/src/cmd/ssh/include/fake-getnameinfo.h deleted file mode 100644 index 2527882ad0..0000000000 --- a/usr/src/cmd/ssh/include/fake-getnameinfo.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: fake-getnameinfo.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _FAKE_GETNAMEINFO_H -#define _FAKE_GETNAMEINFO_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#ifndef HAVE_GETNAMEINFO -int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, - size_t hostlen, char *serv, size_t servlen, int flags); -#endif /* !HAVE_GETNAMEINFO */ - -#ifndef NI_MAXSERV -# define NI_MAXSERV 32 -#endif /* !NI_MAXSERV */ -#ifndef NI_MAXHOST -# define NI_MAXHOST 1025 -#endif /* !NI_MAXHOST */ - -#ifdef __cplusplus -} -#endif - -#endif /* _FAKE_GETNAMEINFO_H */ diff --git a/usr/src/cmd/ssh/include/fake-socket.h b/usr/src/cmd/ssh/include/fake-socket.h deleted file mode 100644 index 30444dd91c..0000000000 --- a/usr/src/cmd/ssh/include/fake-socket.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $Id: fake-socket.h,v 1.3 2002/04/12 03:35:40 tim Exp $ */ - -#ifndef _FAKE_SOCKET_H -#define _FAKE_SOCKET_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "includes.h" -#include "sys/types.h" - -#ifndef HAVE_STRUCT_SOCKADDR_STORAGE -# define _SS_MAXSIZE 128 /* Implementation specific max size */ -# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) - -struct sockaddr_storage { - struct sockaddr ss_sa; - char __ss_pad2[_SS_PADSIZE]; -}; -# define ss_family ss_sa.sa_family -#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ - -#ifndef IN6_IS_ADDR_LOOPBACK -# define IN6_IS_ADDR_LOOPBACK(a) \ - (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ - ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) -#endif /* !IN6_IS_ADDR_LOOPBACK */ - -#ifndef HAVE_STRUCT_IN6_ADDR -struct in6_addr { - u_int8_t s6_addr[16]; -}; -#endif /* !HAVE_STRUCT_IN6_ADDR */ - -#ifndef HAVE_STRUCT_SOCKADDR_IN6 -struct sockaddr_in6 { - unsigned short sin6_family; - u_int16_t sin6_port; - u_int32_t sin6_flowinfo; - struct in6_addr sin6_addr; -}; -#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ - -#ifndef AF_INET6 -/* Define it to something that should never appear */ -#define AF_INET6 AF_MAX -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _FAKE_SOCKET_H */ diff --git a/usr/src/cmd/ssh/include/g11n.h b/usr/src/cmd/ssh/include/g11n.h deleted file mode 100644 index 64acf8e630..0000000000 --- a/usr/src/cmd/ssh/include/g11n.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _G11N_H -#define _G11N_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "includes.h" -#include <sys/types.h> - -/* - * Functions for language tag negotiation - */ - -/* boolean */ -uint_t g11n_langtag_is_default(char *langtag); - -/* return 0 if not, 1 if yes, 2 if the country is matched too */ -uint_t g11n_langtag_matches_locale(char *langtag, char *locale); - -/* get current locale */ -char *g11n_getlocale(); - -/* get current locale */ -void g11n_setlocale(int category, const char *locale); - -/* get list of locales - returns pointer to array of pointers to char */ -char **g11n_getlocales(); - -/* get list of langs spoken by the user, from SSH_LANGS env var */ -char *g11n_getlangs(); - -/* make a comma-separated list of language tags from list of locales */ -char *g11n_locales2langs(char **locale_set); - -int g11n_langtag_match(char *langtag1, char *langtag2); - -/* intersect comma-separated lists of IETF language tags */ -char *g11n_langtag_set_intersect(char *set1, char *set2); - -char *g11n_clnt_langtag_negotiate(char *clnt_langtags, char *srvr_langtags); - -char **g11n_langtag_set_locale_set_intersect(char *langtag_set, - char **locale_set); - -char *g11n_srvr_locale_negotiate(char *clnt_langtags, char **srvr_locales); - -/* auxiliary functions */ -void g11n_freelist(char **list); - -/* - * Functions for converting to ASCII or UTF-8 from the local codeset - * Functions for converting from ASCII or UTF-8 to the local codeset - * - * The error_str parameter is an optional pointer to a char variable - * where to store a string suitable for use with error() or fatal() or - * friends. - * - */ -extern char *g11n_convert_from_utf8(const char *str, uint_t *lenp, - char **error_str); - -extern char *g11n_convert_to_utf8(const char *str, uint_t *lenp, int native, - char **error_str); - -extern char *g11n_filter_string(char *); -extern void g11n_test_langtag(const char *, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _G11N_H */ diff --git a/usr/src/cmd/ssh/include/getcwd.h b/usr/src/cmd/ssh/include/getcwd.h deleted file mode 100644 index 2d9069e6e4..0000000000 --- a/usr/src/cmd/ssh/include/getcwd.h +++ /dev/null @@ -1,24 +0,0 @@ -/* $Id: getcwd.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _GETCWD_H -#define _GETCWD_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#if !defined(HAVE_GETCWD) - -char *getcwd(char *pt, size_t size); - -#endif /* !defined(HAVE_GETCWD) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _GETCWD_H */ diff --git a/usr/src/cmd/ssh/include/getgrouplist.h b/usr/src/cmd/ssh/include/getgrouplist.h deleted file mode 100644 index 587402800f..0000000000 --- a/usr/src/cmd/ssh/include/getgrouplist.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: getgrouplist.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _GETGROUPLIST_H -#define _GETGROUPLIST_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#ifndef HAVE_GETGROUPLIST - -#include <grp.h> - -int getgrouplist(const char *, gid_t, gid_t *, int *); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _GETGROUPLIST_H */ diff --git a/usr/src/cmd/ssh/include/getopt.h b/usr/src/cmd/ssh/include/getopt.h deleted file mode 100644 index 7ae4576d0c..0000000000 --- a/usr/src/cmd/ssh/include/getopt.h +++ /dev/null @@ -1,24 +0,0 @@ -/* $Id: getopt.h,v 1.4 2001/09/18 05:05:21 djm Exp $ */ - -#ifndef _GETOPT_H -#define _GETOPT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) - -int BSDgetopt(int argc, char * const *argv, const char *opts); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H */ diff --git a/usr/src/cmd/ssh/include/getput.h b/usr/src/cmd/ssh/include/getput.h deleted file mode 100644 index 1a33883507..0000000000 --- a/usr/src/cmd/ssh/include/getput.h +++ /dev/null @@ -1,69 +0,0 @@ -/* $OpenBSD: getput.h,v 1.8 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _GETPUT_H -#define _GETPUT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Macros for storing and retrieving data in msb first and lsb first order. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/*------------ macros for storing/extracting msb first words -------------*/ - -#define GET_64BIT(cp) (((u_int64_t)(u_char)(cp)[0] << 56) | \ - ((u_int64_t)(u_char)(cp)[1] << 48) | \ - ((u_int64_t)(u_char)(cp)[2] << 40) | \ - ((u_int64_t)(u_char)(cp)[3] << 32) | \ - ((u_int64_t)(u_char)(cp)[4] << 24) | \ - ((u_int64_t)(u_char)(cp)[5] << 16) | \ - ((u_int64_t)(u_char)(cp)[6] << 8) | \ - ((u_int64_t)(u_char)(cp)[7])) - -#define GET_32BIT(cp) (((u_long)(u_char)(cp)[0] << 24) | \ - ((u_long)(u_char)(cp)[1] << 16) | \ - ((u_long)(u_char)(cp)[2] << 8) | \ - ((u_long)(u_char)(cp)[3])) - -#define GET_16BIT(cp) (((u_long)(u_char)(cp)[0] << 8) | \ - ((u_long)(u_char)(cp)[1])) - -#define PUT_64BIT(cp, value) do { \ - (cp)[0] = (value) >> 56; \ - (cp)[1] = (value) >> 48; \ - (cp)[2] = (value) >> 40; \ - (cp)[3] = (value) >> 32; \ - (cp)[4] = (value) >> 24; \ - (cp)[5] = (value) >> 16; \ - (cp)[6] = (value) >> 8; \ - (cp)[7] = (value); } while (0) - -#define PUT_32BIT(cp, value) do { \ - (cp)[0] = (value) >> 24; \ - (cp)[1] = (value) >> 16; \ - (cp)[2] = (value) >> 8; \ - (cp)[3] = (value); } while (0) - -#define PUT_16BIT(cp, value) do { \ - (cp)[0] = (value) >> 8; \ - (cp)[1] = (value); } while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* _GETPUT_H */ diff --git a/usr/src/cmd/ssh/include/groupaccess.h b/usr/src/cmd/ssh/include/groupaccess.h deleted file mode 100644 index bc40898888..0000000000 --- a/usr/src/cmd/ssh/include/groupaccess.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $OpenBSD: groupaccess.h,v 1.4 2001/06/26 17:27:23 markus Exp $ */ - -#ifndef _GROUPACCESS_H -#define _GROUPACCESS_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2001 Kevin Steves. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <grp.h> - -int ga_init(const char *, gid_t); -int ga_match(char * const *, int); -int ga_match_pattern_list(const char *); -void ga_free(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _GROUPACCESS_H */ diff --git a/usr/src/cmd/ssh/include/hostfile.h b/usr/src/cmd/ssh/include/hostfile.h deleted file mode 100644 index 3a2c7e6a06..0000000000 --- a/usr/src/cmd/ssh/include/hostfile.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#ifndef _HOSTFILE_H -#define _HOSTFILE_H - -/* $OpenBSD: hostfile.h,v 1.12 2002/09/08 20:24:08 markus Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - HOST_OK, HOST_NEW, HOST_CHANGED, HOST_FOUND -} HostStatus; - -int hostfile_read_key(char **, u_int *, Key *); -HostStatus -check_host_in_hostfile(const char *, const char *, const Key *, Key *, int *); -int add_host_to_hostfile(const char *, const char *, const Key *, int); -int -lookup_key_in_hostfile_by_type(const char *, const char *, int , Key *, int *); - -#define HASH_MAGIC "|1|" -#define HASH_DELIM '|' - -char *host_hash(const char *, const char *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _HOSTFILE_H */ diff --git a/usr/src/cmd/ssh/include/includes.h b/usr/src/cmd/ssh/include/includes.h deleted file mode 100644 index ecd55ea737..0000000000 --- a/usr/src/cmd/ssh/include/includes.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file includes most of the needed system headers. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _INCLUDES_H -#define _INCLUDES_H - -/* $OpenBSD: includes.h,v 1.17 2002/01/26 16:44:22 stevesk Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define RCSID(msg) \ -static const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } - -#include "config.h" - -#include <stdio.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> /* For O_NONBLOCK */ -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <pwd.h> -#include <grp.h> -#include <time.h> -#include <dirent.h> -#include <libintl.h> -#include <locale.h> - -#ifdef HAVE_LIMITS_H -#include <limits.h> /* For PATH_MAX */ -#endif - -#ifdef HAVE_GETOPT_H -#include <getopt.h> -#endif - -#ifdef HAVE_BSTRING_H -#include <bstring.h> -#endif - -#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \ - defined(GLOB_HAS_GL_MATCHC) -#include <glob.h> -#endif - -#ifdef HAVE_NETGROUP_H -#include <netgroup.h> -#endif - -#if defined(HAVE_NETDB_H) -#include <netdb.h> -#endif - -#ifdef HAVE_ENDIAN_H -#include <endian.h> -#endif - -#ifdef HAVE_TTYENT_H -#include <ttyent.h> -#endif - -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif - -#ifdef HAVE_MAILLOCK_H -#include <maillock.h> /* For _PATH_MAILDIR */ -#endif - -#include <unistd.h> /* For STDIN_FILENO, etc */ -#include <termios.h> /* Struct winsize */ - -/* - * *-*-nto-qnx needs these headers for strcasecmp and LASTLOG_FILE - * respectively - */ -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif - -#ifdef HAVE_LOGIN_H -#include <login.h> -#endif - -#ifdef HAVE_UCRED_H -#include <ucred.h> -#endif - -#ifdef HAVE_UTMP_H -#include <utmp.h> -#endif - -#ifdef HAVE_UTMPX_H -#ifdef HAVE_TV_IN_UTMPX -#include <sys/time.h> -#endif -#include <utmpx.h> -#endif - -#ifdef HAVE_LASTLOG_H -#include <lastlog.h> -#endif - -#ifdef HAVE_PATHS_H -#include <paths.h> /* For _PATH_XXX */ -#endif - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/wait.h> - -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> /* For timersub */ -#endif - -#include <sys/resource.h> -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#ifdef HAVE_SYS_BSDTTY_H -#include <sys/bsdtty.h> -#endif - -#include <sys/param.h> /* For MAXPATHLEN and roundup() */ -#ifdef HAVE_SYS_UN_H -#include <sys/un.h> /* For sockaddr_un */ -#endif - -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - -#ifdef HAVE_SYS_BITYPES_H -#include <sys/bitypes.h> /* For u_intXX_t */ -#endif - -#ifdef HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> /* For __P() */ -#endif - -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> /* For S_* constants and macros */ -#endif - -#ifdef HAVE_SYS_SYSMACROS_H -#include <sys/sysmacros.h> /* For MIN, MAX, etc */ -#endif - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> /* for MAP_ANONYMOUS */ -#endif - -#include <netinet/in_systm.h> /* For typedefs */ -#include <netinet/in.h> /* For IPv6 macros */ -#include <netinet/ip.h> /* For IPTOS macros */ -#include <netinet/tcp.h> -#include <arpa/inet.h> - -#ifdef HAVE_RPC_TYPES_H -#include <rpc/types.h> /* For INADDR_LOOPBACK */ -#endif - -#ifdef USE_PAM -#include <security/pam_appl.h> -#endif - -#ifdef HAVE_READPASSPHRASE_H -#include <readpassphrase.h> -#endif - -#ifdef HAVE_IA_H -#include <ia.h> -#endif - -#ifdef HAVE_TMPDIR_H -#include <tmpdir.h> -#endif - -#include <openssl/opensslv.h> /* For OPENSSL_VERSION_NUMBER */ - -#include "defines.h" - -#include "version.h" -#include "openbsd-compat.h" -#include "bsd-cygwin_util.h" - -#include "entropy.h" -#include "g11n.h" - -#ifdef __cplusplus -} -#endif - -#endif /* _INCLUDES_H */ diff --git a/usr/src/cmd/ssh/include/inet_ntoa.h b/usr/src/cmd/ssh/include/inet_ntoa.h deleted file mode 100644 index b491398f7f..0000000000 --- a/usr/src/cmd/ssh/include/inet_ntoa.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id: inet_ntoa.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _INET_NTOA_H -#define _INET_NTOA_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) -char *inet_ntoa(struct in_addr in); -#endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _INET_NTOA_H */ diff --git a/usr/src/cmd/ssh/include/inet_ntop.h b/usr/src/cmd/ssh/include/inet_ntop.h deleted file mode 100644 index 91005955f8..0000000000 --- a/usr/src/cmd/ssh/include/inet_ntop.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: inet_ntop.h,v 1.4 2001/08/09 00:56:53 mouring Exp $ */ - -#ifndef _INET_NTOP_H -#define _INET_NTOP_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#ifndef HAVE_INET_NTOP -const char * -inet_ntop(int af, const void *src, char *dst, size_t size); -#endif /* !HAVE_INET_NTOP */ - -#ifdef __cplusplus -} -#endif - -#endif /* _INET_NTOP_H */ diff --git a/usr/src/cmd/ssh/include/kex.h b/usr/src/cmd/ssh/include/kex.h deleted file mode 100644 index 30a6cdb4a5..0000000000 --- a/usr/src/cmd/ssh/include/kex.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $OpenBSD: kex.h,v 1.32 2002/09/09 14:54:14 markus Exp $ */ - -#ifndef _KEX_H -#define _KEX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <openssl/evp.h> -#include <openssl/hmac.h> -#include "buffer.h" -#include "cipher.h" -#include "key.h" - -#ifdef GSSAPI -#ifdef SUNW_GSSAPI -#include <gssapi/gssapi.h> -#include <gssapi/gssapi_ext.h> -#else -#ifdef GSS_KRB5 -#ifdef HEIMDAL -#include <gssapi.h> -#else -#include <gssapi_generic.h> -#endif /* HEIMDAL */ -#endif /* GSS_KRB5 */ -#endif /* SUNW_GSSAPI */ -#endif /* GSSAPI */ - -#define KEX_DH1 "diffie-hellman-group1-sha1" -#define KEX_DHGEX "diffie-hellman-group-exchange-sha1" - -enum kex_init_proposals { - PROPOSAL_KEX_ALGS, - PROPOSAL_SERVER_HOST_KEY_ALGS, - PROPOSAL_ENC_ALGS_CTOS, - PROPOSAL_ENC_ALGS_STOC, - PROPOSAL_MAC_ALGS_CTOS, - PROPOSAL_MAC_ALGS_STOC, - PROPOSAL_COMP_ALGS_CTOS, - PROPOSAL_COMP_ALGS_STOC, - PROPOSAL_LANG_CTOS, - PROPOSAL_LANG_STOC, - PROPOSAL_MAX -}; - -enum kex_modes { - MODE_IN, - MODE_OUT, - MODE_MAX -}; - -enum kex_exchange { - KEX_DH_GRP1_SHA1, - KEX_DH_GEX_SHA1, -#ifdef GSSAPI - KEX_GSS_GRP1_SHA1, -#endif /* GSSAPI */ - KEX_MAX -}; - - -#define KEX_INIT_SENT 0x0001 - -typedef struct Kex Kex; -typedef struct Mac Mac; -typedef struct Comp Comp; -typedef struct Enc Enc; -typedef struct Newkeys Newkeys; - -struct Enc { - char *name; - Cipher *cipher; - int enabled; - u_int key_len; - u_int block_size; - u_char *key; - u_char *iv; -}; -struct Mac { - char *name; - int enabled; - u_int mac_len; - u_char *key; - u_int key_len; - int type; - const EVP_MD *evp_md; - HMAC_CTX evp_ctx; -}; -struct Comp { - int type; - int enabled; - char *name; -}; -struct Newkeys { - Enc enc; - Mac mac; - Comp comp; -}; - -struct KexOptions { - int gss_deleg_creds; -}; - -struct Kex { - u_char *session_id; - u_int session_id_len; - Newkeys *newkeys[MODE_MAX]; - int we_need; - int server; - char *serverhost; - char *name; - int hostkey_type; - int kex_type; - Buffer my; - Buffer peer; - int initial_kex_done; - int done; - int flags; - char *client_version_string; - char *server_version_string; - struct KexOptions options; - int (*verify_host_key)(Key *); - int (*accept_host_key)(Key *); /* for GSS keyex */ - Key *(*load_host_key)(int); - int (*host_key_index)(Key *); - void (*kex[KEX_MAX])(Kex *); - void (*kex_hook)(Kex *, char **); /* for GSS keyex rekeying */ -#ifdef GSSAPI - gss_OID_set mechs; /* mechs in my proposal */ -#endif /* GSSAPI */ -}; - -typedef void (*Kex_hook_func)(Kex *, char **); /* for GSS-API rekeying */ - -Kex *kex_setup(const char *host, - char *proposal[PROPOSAL_MAX], - Kex_hook_func hook); -void kex_start(Kex *); -void kex_finish(Kex *); - -void kex_send_kexinit(Kex *); -void kex_input_kexinit(int, u_int32_t, void *); -void kex_derive_keys(Kex *, u_char *, BIGNUM *); - -Newkeys *kex_get_newkeys(int); - -void kexdh_client(Kex *); -void kexdh_server(Kex *); -void kexgex_client(Kex *); -void kexgex_server(Kex *); - -u_char * -kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, - BIGNUM *, BIGNUM *, BIGNUM *); -u_char * -kexgex_hash(char *, char *, char *, int, char *, int, u_char *, int, - int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *); - -#ifdef GSSAPI -void kexgss_client(Kex *); -void kexgss_server(Kex *); -#endif - -#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) -void dump_digest(char *, u_char *, int); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _KEX_H */ diff --git a/usr/src/cmd/ssh/include/key.h b/usr/src/cmd/ssh/include/key.h deleted file mode 100644 index 862b2d81d4..0000000000 --- a/usr/src/cmd/ssh/include/key.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _KEY_H -#define _KEY_H - -/* $OpenBSD: key.h,v 1.19 2002/03/18 17:23:31 markus Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#include <openssl/rsa.h> -#include <openssl/dsa.h> - -typedef struct Key Key; -enum types { - KEY_RSA1, - KEY_RSA, - KEY_DSA, - KEY_NULL, - KEY_UNSPEC -}; -enum fp_type { - SSH_FP_SHA1, - SSH_FP_MD5 -}; -enum fp_rep { - SSH_FP_HEX, - SSH_FP_BUBBLEBABBLE -}; - -/* key is stored in external hardware */ -#define KEY_FLAG_EXT 0x0001 - -struct Key { - int type; - int flags; - RSA *rsa; - DSA *dsa; -}; - -Key *key_new(int); -Key *key_new_private(int); -void key_free(Key *); -Key *key_demote(Key *); -int key_equal(const Key *, const Key *); -char *key_fingerprint(Key *, enum fp_type, enum fp_rep); -char *key_type(Key *); -int key_write(const Key *, FILE *); -int key_read(Key *, char **); -u_int key_size(Key *); - -Key *key_generate(int, u_int); -Key *key_from_private(Key *); -int key_type_from_name(char *); - -Key *key_from_blob(u_char *, int); -int key_to_blob(const Key *, u_char **, u_int *); -char *key_ssh_name(const Key *); -int key_names_valid2(const char *); - -int key_sign(Key *, u_char **, u_int *, u_char *, u_int); -int key_verify(Key *, u_char *, u_int, u_char *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _KEY_H */ diff --git a/usr/src/cmd/ssh/include/log.h b/usr/src/cmd/ssh/include/log.h deleted file mode 100644 index 34bc82f5e3..0000000000 --- a/usr/src/cmd/ssh/include/log.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* $OpenBSD: log.h,v 1.8 2002/07/19 15:43:33 markus Exp $ */ - -#ifndef _LOG_H -#define _LOG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* $OpenBSD: log.h,v 1.8 2002/07/19 15:43:33 markus Exp $ */ - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include <syslog.h> /* Needed for LOG_AUTHPRIV (if present) */ - -/* Supported syslog facilities and levels. */ -typedef enum { - SYSLOG_FACILITY_DAEMON, - SYSLOG_FACILITY_USER, - SYSLOG_FACILITY_AUTH, -#ifdef LOG_AUTHPRIV - SYSLOG_FACILITY_AUTHPRIV, -#endif - SYSLOG_FACILITY_LOCAL0, - SYSLOG_FACILITY_LOCAL1, - SYSLOG_FACILITY_LOCAL2, - SYSLOG_FACILITY_LOCAL3, - SYSLOG_FACILITY_LOCAL4, - SYSLOG_FACILITY_LOCAL5, - SYSLOG_FACILITY_LOCAL6, - SYSLOG_FACILITY_LOCAL7, - SYSLOG_FACILITY_NOT_SET = -1 -} SyslogFacility; - -typedef enum { - SYSLOG_LEVEL_QUIET, - SYSLOG_LEVEL_FATAL, - SYSLOG_LEVEL_ERROR, - SYSLOG_LEVEL_NOTICE, - SYSLOG_LEVEL_INFO, - SYSLOG_LEVEL_VERBOSE, - SYSLOG_LEVEL_DEBUG1, - SYSLOG_LEVEL_DEBUG2, - SYSLOG_LEVEL_DEBUG3, - SYSLOG_LEVEL_NOT_SET = -1 -} LogLevel; - -void log_init(char *, LogLevel, SyslogFacility, int); - -SyslogFacility log_facility_number(char *); -LogLevel log_level_number(char *); - -void set_log_txt_prefix(const char *); -void fatal(const char *, ...) __attribute__((format(printf, 1, 2))); -void error(const char *, ...) __attribute__((format(printf, 1, 2))); -void notice(const char *, ...) __attribute__((format(printf, 1, 2))); -void log(const char *, ...) __attribute__((format(printf, 1, 2))); -void verbose(const char *, ...) __attribute__((format(printf, 1, 2))); -void debug(const char *, ...) __attribute__((format(printf, 1, 2))); -void debug2(const char *, ...) __attribute__((format(printf, 1, 2))); -void debug3(const char *, ...) __attribute__((format(printf, 1, 2))); - -void fatal_cleanup(void); -void fatal_add_cleanup(void (*) (void *), void *); -void fatal_remove_cleanup(void (*) (void *), void *); -void fatal_remove_all_cleanups(void); - -void do_log(LogLevel, const char *, va_list); - -#ifdef __cplusplus -} -#endif - -#endif /* _LOG_H */ diff --git a/usr/src/cmd/ssh/include/loginrec.h b/usr/src/cmd/ssh/include/loginrec.h deleted file mode 100644 index 8086d96686..0000000000 --- a/usr/src/cmd/ssh/include/loginrec.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 2000 Andre Lucas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Markus Friedl. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * loginrec.h: platform-independent login recording and lastlog retrieval - */ - -#ifndef _LOGINREC_H -#define _LOGINREC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "includes.h" - -#include <sys/types.h> -#include <netinet/in.h> -#include <sys/socket.h> - -/* RCSID("$Id: loginrec.h,v 1.6 2001/05/08 20:33:06 mouring Exp $"); */ - -/** - ** you should use the login_* calls to work around platform dependencies - **/ - -/* - * login_netinfo structure - */ - -union login_netinfo { - struct sockaddr sa; - struct sockaddr_in sa_in; - struct sockaddr_storage sa_storage; -}; - -/* - * * logininfo structure * - */ -/* types - different to utmp.h 'type' macros */ -/* (though set to the same value as linux, openbsd and others...) */ -#define LTYPE_LOGIN 7 -#define LTYPE_LOGOUT 8 - -/* string lengths - set very long */ -#define LINFO_PROGSIZE 64 -#define LINFO_LINESIZE 64 -#define LINFO_NAMESIZE 64 -#define LINFO_HOSTSIZE 256 - -struct logininfo { - int progname_null; - char progname[LINFO_PROGSIZE]; /* name of program (for PAM) */ - short int type; /* type of login (LTYPE_*) */ - int pid; /* PID of login process */ - int uid; /* UID of this user */ - int line_null; - char line[LINFO_LINESIZE]; /* tty/pty name */ - char username[LINFO_NAMESIZE]; /* login username */ - char hostname[LINFO_HOSTSIZE]; /* remote hostname */ - /* 'exit_status' structure components */ - int exit; /* process exit status */ - int termination; /* process termination status */ - /* struct timeval (sys/time.h) isn't always available, if it isn't we'll - * use time_t's value as tv_sec and set tv_usec to 0 - */ - unsigned int tv_sec; - unsigned int tv_usec; - union login_netinfo hostaddr; /* caller's host address(es) */ -}; /* struct logininfo */ - -/* - * login recording functions - */ - -/** 'public' functions */ - -/* construct a new login entry */ -struct logininfo *login_alloc_entry(int pid, const char *username, - const char *hostname, const char *line, - const char *progname); -/* free a structure */ -void login_free_entry(struct logininfo *li); -/* fill out a pre-allocated structure with useful information */ -int login_init_entry(struct logininfo *li, int pid, const char *username, - const char *hostname, const char *line, - const char *progname); -/* place the current time in a logininfo struct */ -void login_set_current_time(struct logininfo *li); - -/* record the entry */ -int login_login (struct logininfo *li); -int login_logout(struct logininfo *li); -#ifdef LOGIN_NEEDS_UTMPX -int login_utmp_only(struct logininfo *li); -#endif - -/** End of public functions */ - -/* record the entry */ -int login_write (struct logininfo *li); -int login_log_entry(struct logininfo *li); - -/* set the network address based on network address type */ -void login_set_addr(struct logininfo *li, const struct sockaddr *sa, - const unsigned int sa_size); - -/* - * lastlog retrieval functions - */ -/* lastlog *entry* functions fill out a logininfo */ -struct logininfo *login_get_lastlog(struct logininfo *li, const int uid); -/* lastlog *time* functions return time_t equivalent (uint) */ -unsigned int login_get_lastlog_time(const int uid); - -/* produce various forms of the line filename */ -char *line_fullname(char *dst, const char *src, int dstsize); -char *line_stripname(char *dst, const char *src, int dstsize); -char *line_abbrevname(char *dst, const char *src, int dstsize); - -#ifdef __cplusplus -} -#endif - -#endif /* _LOGINREC_H */ diff --git a/usr/src/cmd/ssh/include/mac.h b/usr/src/cmd/ssh/include/mac.h deleted file mode 100644 index cc05d332ae..0000000000 --- a/usr/src/cmd/ssh/include/mac.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $OpenBSD: mac.h,v 1.3 2001/06/26 17:27:24 markus Exp $ */ - -#ifndef _MAC_H -#define _MAC_H - -#ifdef __cplusplus -extern "C" { -#endif - -int mac_valid(const char *); -int mac_setup(Mac *, char *); -int mac_init(Mac *); -u_char *mac_compute(Mac *, u_int32_t, u_char *, int); -void mac_clear(Mac *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MAC_H */ diff --git a/usr/src/cmd/ssh/include/match.h b/usr/src/cmd/ssh/include/match.h deleted file mode 100644 index 81729c33da..0000000000 --- a/usr/src/cmd/ssh/include/match.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $OpenBSD: match.h,v 1.12 2002/03/01 13:12:10 markus Exp $ */ - -#ifndef _MATCH_H -#define _MATCH_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -int match_pattern(const char *, const char *); -int match_pattern_list(const char *, const char *, u_int, int); -int match_hostname(const char *, const char *, u_int); -int match_host_and_ip(const char *, const char *, const char *); -int match_user(const char *, const char *, const char *, const char *); -char *match_list(const char *, const char *, u_int *); - -/* addrmatch.c */ -int addr_match_list(const char *, const char *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MATCH_H */ diff --git a/usr/src/cmd/ssh/include/misc.h b/usr/src/cmd/ssh/include/misc.h deleted file mode 100644 index c626301f84..0000000000 --- a/usr/src/cmd/ssh/include/misc.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _MISC_H -#define _MISC_H - -/* $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $ */ - -#ifdef __cplusplus -extern "C" { -#endif - -char *chop(char *); -char *strdelim(char **); -void set_nonblock(int); -void unset_nonblock(int); -void set_nodelay(int); -int a2port(const char *); -char *cleanhostname(char *); -char *hpdelim(char **); -char *colon(char *); -long convtime(const char *); -char *percent_expand(const char *, ...); -char *tohex(const void *, size_t); -void sanitise_stdfd(void); -int get_yes_no_flag(int *option, const char *arg, const char *filename, - int linenum, int active); -char *tolowercase(const char *s); - -struct passwd *pwcopy(struct passwd *); -void pwfree(struct passwd **); - -typedef struct arglist arglist; -struct arglist { - char **list; - int num; - int nalloc; -}; -void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3))); -void replacearg(arglist *, u_int, char *, ...) - __attribute__((format(printf, 3, 4))); -void freeargs(arglist *); - -/* wrapper for signal interface */ -typedef void (*mysig_t)(int); -mysig_t mysignal(int sig, mysig_t act); - -/* Functions to extract or store big-endian words of various sizes */ -u_int64_t get_u64(const void *) - __attribute__((__bounded__( __minbytes__, 1, 8))); -u_int32_t get_u32(const void *) - __attribute__((__bounded__( __minbytes__, 1, 4))); -u_int16_t get_u16(const void *) - __attribute__((__bounded__( __minbytes__, 1, 2))); -void put_u64(void *, u_int64_t) - __attribute__((__bounded__( __minbytes__, 1, 8))); -void put_u32(void *, u_int32_t) - __attribute__((__bounded__( __minbytes__, 1, 4))); -void put_u16(void *, u_int16_t) - __attribute__((__bounded__( __minbytes__, 1, 2))); - -#ifdef __cplusplus -} -#endif - -#endif /* _MISC_H */ diff --git a/usr/src/cmd/ssh/include/mktemp.h b/usr/src/cmd/ssh/include/mktemp.h deleted file mode 100644 index b93f2b5c10..0000000000 --- a/usr/src/cmd/ssh/include/mktemp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: mktemp.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _MKTEMP_H -#define _MKTEMP_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" -#ifndef HAVE_MKDTEMP -int mkstemps(char *path, int slen); -int mkstemp(char *path); -char *mkdtemp(char *path); -#endif /* !HAVE_MKDTEMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* _MKTEMP_H */ diff --git a/usr/src/cmd/ssh/include/mpaux.h b/usr/src/cmd/ssh/include/mpaux.h deleted file mode 100644 index 6577a9b05d..0000000000 --- a/usr/src/cmd/ssh/include/mpaux.h +++ /dev/null @@ -1,33 +0,0 @@ -/* $OpenBSD: mpaux.h,v 1.12 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _MPAUX_H -#define _MPAUX_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file contains various auxiliary functions related to multiple - * precision integers. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -void compute_session_id(u_char[16], u_char[8], BIGNUM *, BIGNUM *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MPAUX_H */ diff --git a/usr/src/cmd/ssh/include/msg.h b/usr/src/cmd/ssh/include/msg.h deleted file mode 100644 index c04f7d48b2..0000000000 --- a/usr/src/cmd/ssh/include/msg.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $OpenBSD: msg.h,v 1.1 2002/05/23 19:24:30 markus Exp $ */ -/* - * Copyright (c) 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MSG_H -#define _MSG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -void ssh_msg_send(int, u_char, Buffer *); -int ssh_msg_recv(int, Buffer *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MSG_H */ diff --git a/usr/src/cmd/ssh/include/myproposal.h b/usr/src/cmd/ssh/include/myproposal.h deleted file mode 100644 index dc0043e49a..0000000000 --- a/usr/src/cmd/ssh/include/myproposal.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */ - -#ifndef _MYPROPOSAL_H -#define _MYPROPOSAL_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1," \ - "diffie-hellman-group1-sha1" - -#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" - -/* - * Keep CBC modes in the back of the client default cipher list for backward - * compatibility but remove them from the server side because there are some - * potential security issues with those modes regarding SSH protocol version 2. - * Since the client is the one who picks the cipher from the list offered by the - * server the only way to force the client not to use CBC modes is not to - * advertise those at all. Note that we still support all such CBC modes in the - * server code, this is about the default server cipher list only. The list can - * be changed in the Ciphers option in the sshd_config(4) file. - * - * Note that the ordering of ciphers on the server side is not relevant but we - * must do it properly even here so that we can use the macro for the client - * list as well. - */ -#define KEX_DEFAULT_SERVER_ENCRYPT "aes128-ctr,aes192-ctr,aes256-ctr," \ - "arcfour128,arcfour256,arcfour" - -#define KEX_DEFAULT_CLIENT_ENCRYPT KEX_DEFAULT_SERVER_ENCRYPT \ - ",aes128-cbc,aes192-cbc,aes256-cbc," \ - "blowfish-cbc,3des-cbc" - -#define KEX_DEFAULT_MAC "hmac-md5,hmac-sha1,hmac-sha1-96," \ - "hmac-md5-96" - -#define KEX_DEFAULT_COMP "none,zlib" -#define KEX_DEFAULT_LANG "" - - -static char *my_srv_proposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, - KEX_DEFAULT_PK_ALG, - KEX_DEFAULT_SERVER_ENCRYPT, - KEX_DEFAULT_SERVER_ENCRYPT, - KEX_DEFAULT_MAC, - KEX_DEFAULT_MAC, - KEX_DEFAULT_COMP, - KEX_DEFAULT_COMP, - KEX_DEFAULT_LANG, - KEX_DEFAULT_LANG -}; - -static char *my_clnt_proposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, - KEX_DEFAULT_PK_ALG, - KEX_DEFAULT_CLIENT_ENCRYPT, - KEX_DEFAULT_CLIENT_ENCRYPT, - KEX_DEFAULT_MAC, - KEX_DEFAULT_MAC, - KEX_DEFAULT_COMP, - KEX_DEFAULT_COMP, - KEX_DEFAULT_LANG, - KEX_DEFAULT_LANG -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _MYPROPOSAL_H */ diff --git a/usr/src/cmd/ssh/include/openbsd-compat.h b/usr/src/cmd/ssh/include/openbsd-compat.h deleted file mode 100644 index aab8e36c62..0000000000 --- a/usr/src/cmd/ssh/include/openbsd-compat.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1999-2003 Damien Miller. All rights reserved. - * Copyright (c) 2003 Ben Lindstrom. All rights reserved. - * Copyright (c) 2002 Tim Rice. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _OPENBSD_COMPAT_H -#define _OPENBSD_COMPAT_H - -/* $Id: openbsd-compat.h,v 1.17 2002/09/12 00:33:02 djm Exp $ */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -/* OpenBSD function replacements */ -#include "bindresvport.h" -#include "getcwd.h" -#include "realpath.h" -#include "rresvport.h" -#include "strlcpy.h" -#include "strlcat.h" -#include "strmode.h" -#include "mktemp.h" -#include "dirname.h" -#include "base64.h" -#include "sigact.h" -#include "inet_ntoa.h" -#include "inet_ntop.h" -#include "setproctitle.h" -#include "getgrouplist.h" -#include "glob.h" -#include "readpassphrase.h" -#include "getopt.h" - -/* Home grown routines */ -#include "bsd-arc4random.h" -#include "bsd-getpeereid.h" -#include "bsd-misc.h" -#include "bsd-snprintf.h" -#include "bsd-waitpid.h" - -/* rfc2553 socket API replacements */ -#include "fake-getaddrinfo.h" -#include "fake-getnameinfo.h" -#include "fake-socket.h" - -/* Routines for a single OS platform */ -#include "bsd-cray.h" -#include "port-irix.h" -#include "port-aix.h" - -#ifndef HAVE_VASPRINTF -int vasprintf(char **, const char *, va_list); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _OPENBSD_COMPAT_H */ diff --git a/usr/src/cmd/ssh/include/packet.h b/usr/src/cmd/ssh/include/packet.h deleted file mode 100644 index 26c3f8843e..0000000000 --- a/usr/src/cmd/ssh/include/packet.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Interface for the packet protocol functions. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PACKET_H -#define _PACKET_H - -/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */ - -#ifdef __cplusplus -extern "C" { -#endif - - -#include <openssl/bn.h> -#include "kex.h" - -#ifdef ALTPRIVSEP -/* Monitor-side functions */ -void packet_set_server(void); -void packet_set_no_monitor(void); -void packet_set_monitor(int pip_fd); -int packet_is_server(void); -int packet_is_monitor(void); -void packet_set_packet(const void *buf, u_int len); -void packet_set_fds(int fd, int restore); -#endif /* ALTPRIVSEP */ - -void packet_set_connection(int, int); -void packet_set_nonblocking(void); -int packet_get_connection_in(void); -int packet_get_connection_out(void); -void packet_close(void); -void packet_set_encryption_key(const u_char *, u_int, int); -u_int packet_get_encryption_key(u_char *); -void packet_set_protocol_flags(u_int); -u_int packet_get_protocol_flags(void); -void packet_start_compression(int); -void packet_set_interactive(int); -int packet_is_interactive(void); - -void packet_start(u_char); -void packet_put_char(int ch); -void packet_put_int(u_int value); -void packet_put_bignum(BIGNUM * value); -void packet_put_bignum2(BIGNUM * value); -void packet_put_string(const void *buf, u_int len); -void packet_put_cstring(const char *str); -void packet_put_raw(const void *buf, u_int len); -void packet_send(void); - -void packet_put_utf8_string(const char *str, uint_t len); -void packet_put_utf8_cstring(const char *str); - -int packet_read(void); -void packet_read_expect(int type); -int packet_read_poll(void); -void packet_process_incoming(const char *buf, u_int len); -int packet_read_seqnr(u_int32_t *seqnr_p); -int packet_read_poll_seqnr(u_int32_t *seqnr_p); - -u_int packet_get_char(void); -u_int packet_get_int(void); -void packet_get_bignum(BIGNUM * value); -void packet_get_bignum2(BIGNUM * value); -void *packet_get_raw(u_int *length_ptr); -void *packet_get_string(u_int *length_ptr); -char *packet_get_utf8_string(uint_t *length_ptr); -void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); - -void set_newkeys(int mode); -void free_keys(Newkeys *keys); - -void packet_write_poll(void); -void packet_write_wait(void); -int packet_have_data_to_write(void); -int packet_not_very_much_data_to_write(void); - -int packet_connection_is_on_socket(void); -int packet_connection_is_ipv4(void); -int packet_remaining(void); -void packet_send_ignore(int); -void packet_add_padding(u_char); - -void tty_make_modes(int, struct termios *); -void tty_parse_modes(int, int *); - -extern int max_packet_size; -int packet_set_maxsize(int); -#define packet_get_maxsize() max_packet_size - -/* don't allow remaining bytes after the end of the message */ -#define packet_check_eom() \ -do { \ - int _len = packet_remaining(); \ - if (_len > 0) { \ - log("Packet integrity error (%d bytes remaining) at %s:%d", \ - _len ,__FILE__, __LINE__); \ - packet_disconnect("Packet integrity error."); \ - } \ -} while (0) - -int packet_need_rekeying(void); -void packet_set_rekey_limit(u_int32_t); - -/* see a comment attached to will_daemonize in packet.c for more information */ -#define NOT_DAEMONIZING 0 -#define DAEMONIZING_REQUESTED 1 -#define FIRST_NEWKEYS_PROCESSED 2 -#define SECOND_NEWKEYS_PROCESSED 3 - -#ifdef __cplusplus -} -#endif - -#endif /* _PACKET_H */ diff --git a/usr/src/cmd/ssh/include/pathnames.h b/usr/src/cmd/ssh/include/pathnames.h deleted file mode 100644 index 4c6638387d..0000000000 --- a/usr/src/cmd/ssh/include/pathnames.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */ - -#ifndef _PATHNAMES_H -#define _PATHNAMES_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#define ETCDIR "/etc" - -#ifndef SSHDIR -#define SSHDIR ETCDIR "/ssh" -#endif - -#ifndef _PATH_SSH_PIDDIR -#define _PATH_SSH_PIDDIR "/var/run" -#endif - -/* - * System-wide file containing host keys of known hosts. This file should be - * world-readable. - */ -#define _PATH_SSH_SYSTEM_HOSTFILE SSHDIR "/ssh_known_hosts" -/* backward compat for protocol 2 */ -#define _PATH_SSH_SYSTEM_HOSTFILE2 SSHDIR "/ssh_known_hosts2" - -/* - * Of these, ssh_host_key must be readable only by root, whereas ssh_config - * should be world-readable. - */ -#define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" -#define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" -#define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key" -#define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" -#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" -#define _PATH_DH_MODULI SSHDIR "/moduli" -/* Backwards compatibility */ -#define _PATH_DH_PRIMES SSHDIR "/primes" - -#ifndef _PATH_SSH_PROGRAM -#define _PATH_SSH_PROGRAM "/usr/bin/ssh" -#endif - -/* - * The process id of the daemon listening for connections is saved here to - * make it easier to kill the correct daemon when necessary. - */ -#define _PATH_SSH_DAEMON_PID_FILE _PATH_SSH_PIDDIR "/sshd.pid" - -/* - * The directory in user\'s home directory in which the files reside. The - * directory should be world-readable (though not all files are). - */ -#define _PATH_SSH_USER_DIR ".ssh" - -/* - * Per-user file containing host keys of known hosts. This file need not be - * readable by anyone except the user him/herself, though this does not - * contain anything particularly secret. - */ -#define _PATH_SSH_USER_HOSTFILE "~/.ssh/known_hosts" -/* backward compat for protocol 2 */ -#define _PATH_SSH_USER_HOSTFILE2 "~/.ssh/known_hosts2" - -/* - * Name of the default file containing client-side authentication key. This - * file should only be readable by the user him/herself. - */ -#define _PATH_SSH_CLIENT_IDENTITY ".ssh/identity" -#define _PATH_SSH_CLIENT_ID_DSA ".ssh/id_dsa" -#define _PATH_SSH_CLIENT_ID_RSA ".ssh/id_rsa" - -/* - * Configuration file in user\'s home directory. This file need not be - * readable by anyone but the user him/herself, but does not contain anything - * particularly secret. If the user\'s home directory resides on an NFS - * volume where root is mapped to nobody, this may need to be world-readable. - */ -#define _PATH_SSH_USER_CONFFILE ".ssh/config" - -/* - * File containing a list of those rsa keys that permit logging in as this - * user. This file need not be readable by anyone but the user him/herself, - * but does not contain anything particularly secret. If the user\'s home - * directory resides on an NFS volume where root is mapped to nobody, this - * may need to be world-readable. (This file is read by the daemon which is - * running as root.) - */ -#define _PATH_SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys" - -/* backward compat for protocol v2 */ -#define _PATH_SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2" - -/* - * Per-user and system-wide ssh "rc" files. These files are executed with - * /bin/sh before starting the shell or command if they exist. They will be - * passed "proto cookie" as arguments if X11 forwarding with spoofing is in - * use. xauth will be run if neither of these exists. - */ -#define _PATH_SSH_USER_RC ".ssh/rc" -#define _PATH_SSH_SYSTEM_RC SSHDIR "/sshrc" - -/* - * Ssh-only version of /etc/hosts.equiv. Additionally, the daemon may use - * ~/.rhosts and /etc/hosts.equiv if rhosts authentication is enabled. - */ -#define _PATH_SSH_HOSTS_EQUIV SSHDIR "/shosts.equiv" -#define _PATH_RHOSTS_EQUIV "/etc/hosts.equiv" - -/* - * /etc/default/login - */ -#define _PATH_DEFAULT_LOGIN "/etc/default/login" - -/* - * Default location of askpass - */ -#ifndef _PATH_SSH_ASKPASS_DEFAULT -#define _PATH_SSH_ASKPASS_DEFAULT "/usr/lib/ssh/ssh-askpass" -#endif - -/* Location of ssh-keysign for hostbased authentication */ -#ifndef _PATH_SSH_KEY_SIGN -#define _PATH_SSH_KEY_SIGN "/usr/lib/ssh/ssh-keysign" -#endif - -/* xauth for X11 forwarding */ -#ifndef _PATH_XAUTH -#define _PATH_XAUTH "/usr/openwin/bin/xauth" -#endif - -/* UNIX domain socket for X11 server; displaynum will replace %u */ -#ifndef _PATH_UNIX_X -#define _PATH_UNIX_X "/tmp/.X11-unix/X%u" -#endif - -/* for scp */ -#ifndef _PATH_CP -#define _PATH_CP "cp" -#endif - -/* for sftp */ -#ifndef _PATH_SFTP_SERVER -#define _PATH_SFTP_SERVER "/usr/lib/ssh/sftp-server" -#endif - -/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */ -#ifndef _PATH_PRIVSEP_CHROOT_DIR -#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty" -#endif - -#ifndef _PATH_LS -#define _PATH_LS "ls" -#endif - -/* path to login program */ -#ifndef LOGIN_PROGRAM -# ifdef LOGIN_PROGRAM_FALLBACK -# define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK -# else -# define LOGIN_PROGRAM "/usr/bin/login" -# endif -#endif /* LOGIN_PROGRAM */ - -/* Askpass program define */ -#ifndef ASKPASS_PROGRAM -#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass" -#endif /* ASKPASS_PROGRAM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _PATHNAMES_H */ diff --git a/usr/src/cmd/ssh/include/port-aix.h b/usr/src/cmd/ssh/include/port-aix.h deleted file mode 100644 index e14fb811b8..0000000000 --- a/usr/src/cmd/ssh/include/port-aix.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Copyright (c) 2001 Gert Doering. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _PORT_AIX_H -#define _PORT_AIX_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifdef _AIX -void aix_usrinfo(struct passwd *pw); -#endif /* _AIX */ - -#ifdef __cplusplus -} -#endif - -#endif /* _PORT_AIX_H */ diff --git a/usr/src/cmd/ssh/include/port-irix.h b/usr/src/cmd/ssh/include/port-irix.h deleted file mode 100644 index 79397e0674..0000000000 --- a/usr/src/cmd/ssh/include/port-irix.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * XXX - Add OpenSSH copyright - */ - -#ifndef _PORT_IRIX_H -#define _PORT_IRIX_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) - -void irix_setusercontext(struct passwd *pw); - -#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _PORT_IRIX_H */ diff --git a/usr/src/cmd/ssh/include/progressmeter.h b/usr/src/cmd/ssh/include/progressmeter.h deleted file mode 100644 index d8a3bc6737..0000000000 --- a/usr/src/cmd/ssh/include/progressmeter.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2002 Nils Nordman. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _PROGRESSMETER_H -#define _PROGRESSMETER_H - -/* $OpenBSD: progressmeter.h,v 1.2 2006/03/25 22:22:43 djm Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -void start_progress_meter(char *, off_t, off_t *); -void stop_progress_meter(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _PROGRESSMETER_H */ diff --git a/usr/src/cmd/ssh/include/proxy-io.h b/usr/src/cmd/ssh/include/proxy-io.h deleted file mode 100644 index e240118c8d..0000000000 --- a/usr/src/cmd/ssh/include/proxy-io.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PROXY_IO_H -#define _PROXY_IO_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Read/write loop for ssh proxies. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define BUFFER_SIZ 8192 - -int proxy_read_write_loop(int readfd, int writefd); - -#ifdef __cplusplus -} -#endif - -#endif /* _PROXY_IO_H */ diff --git a/usr/src/cmd/ssh/include/readconf.h b/usr/src/cmd/ssh/include/readconf.h deleted file mode 100644 index 1aceb9cb7c..0000000000 --- a/usr/src/cmd/ssh/include/readconf.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for reading the configuration file. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _READCONF_H -#define _READCONF_H - -/* $OpenBSD: readconf.h,v 1.43 2002/06/08 05:17:01 markus Exp $ */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "key.h" - -/* - * We accept only fixed amount of unknown options. Note that we must treat all - * options in different Host sections separately since we need to remember the - * line number. See IgnoreIfUnknown for more information. - */ -#define MAX_UNKNOWN_OPTIONS 64 - -/* Data structure for representing a forwarding request. */ - -typedef struct { - char *listen_host; /* Host (address) to listen on. */ - u_short listen_port; /* Port to forward. */ - char *connect_host; /* Host to connect. */ - u_short connect_port; /* Port to connect on connect_host. */ -} Forward; -/* Data structure for representing option data. */ - -/* For postponed processing of option keywords. */ -typedef struct { - char *keyword; /* option keyword name */ - char *filename; /* config file it was found in */ - int linenum; /* line number in the config file */ -} StoredOption; - -typedef struct { - int forward_agent; /* Forward authentication agent. */ - int forward_x11; /* Forward X11 display. */ - int forward_x11_trusted; /* Trust Forward X11 display. */ - char *xauth_location; /* Location for xauth program */ - int gateway_ports; /* Allow remote connects to forwarded ports. */ - int use_privileged_port; /* Don't use privileged port if false. */ - int rhosts_authentication; /* Try rhosts authentication. */ - int rhosts_rsa_authentication; /* Try rhosts with RSA - * authentication. */ - int rsa_authentication; /* Try RSA authentication. */ - int pubkey_authentication; /* Try ssh2 pubkey authentication. */ - int hostbased_authentication; /* ssh2's rhosts_rsa */ - int challenge_response_authentication; - int fallback_to_rsh; /* Use rsh if cannot connect with ssh. */ - int use_rsh; /* Always use rsh(don\'t try ssh). */ - /* Try S/Key or TIS, authentication. */ -#if defined(KRB4) || defined(KRB5) - int kerberos_authentication; /* Try Kerberos authentication. */ -#endif -#if defined(AFS) || defined(KRB5) - int kerberos_tgt_passing; /* Try Kerberos TGT passing. */ -#endif - -#ifdef GSSAPI - int gss_keyex; - int gss_authentication; - int gss_deleg_creds; -#ifdef GSI - int gss_globus_deleg_limited_proxy; -#endif /* GSI */ -#endif /* GSSAPI */ - -#ifdef AFS - int afs_token_passing; /* Try AFS token passing. */ -#endif - int password_authentication; /* Try password - * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ - char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ - int batch_mode; /* Batch mode: do not ask for passwords. */ - int check_host_ip; /* Also keep track of keys for IP address */ - int strict_host_key_checking; /* Strict host key checking. */ - int compression; /* Compress packets in both directions. */ - int compression_level; /* Compression level 1 (fast) to 9 - * (best). */ - int keepalives; /* Set SO_KEEPALIVE. */ - LogLevel log_level; /* Level for logging. */ - - int port; /* Port to connect. */ - int connection_attempts; /* Max attempts (seconds) before - * giving up */ - int connection_timeout; /* Max time (seconds) before - * aborting connection attempt */ - int number_of_password_prompts; /* Max number of password - * prompts. */ - int cipher; /* Cipher to use. */ - char *ciphers; /* SSH2 ciphers in order of preference. */ - char *macs; /* SSH2 macs in order of preference. */ - char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ - int protocol; /* Protocol in order of preference. */ - char *hostname; /* Real host to connect. */ - char *host_key_alias; /* hostname alias for .ssh/known_hosts */ - char *proxy_command; /* Proxy command for connecting the host. */ - char *user; /* User to log in as. */ - int escape_char; /* Escape character; -2 = none */ - - char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ - char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */ - char *system_hostfile2; - char *user_hostfile2; - char *preferred_authentications; - char *bind_address; /* local socket address for connection to sshd */ - char *smartcard_device; /* Smartcard reader device */ - int disable_banner; /* Disable display of banner */ - - /* - * Unknown options listed in IgnoreIfUnknown will not cause ssh to - * exit. So, we must store all unknown options here and can't process - * them before the command line options and all config files are read - * and IgnoreIfUnknown is properly set. - */ - char *ignore_if_unknown; - int unknown_opts_num; - StoredOption unknown_opts[MAX_UNKNOWN_OPTIONS]; - - int num_identity_files; /* Number of files for RSA/DSA identities. */ - char *identity_files[SSH_MAX_IDENTITY_FILES]; - Key *identity_keys[SSH_MAX_IDENTITY_FILES]; - - /* Local TCP/IP forward requests. */ - int num_local_forwards; - Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; - - /* Remote TCP/IP forward requests. */ - int num_remote_forwards; - Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; - int clear_forwardings; - - int64_t rekey_limit; - int no_host_authentication_for_localhost; - int server_alive_interval; - int server_alive_count_max; - - int hash_known_hosts; - int use_openssl_engine; -} Options; - - -void initialize_options(Options *); -void fill_default_options(Options *); -int read_config_file(const char *, const char *, Options *); -int parse_forward(int, Forward *, const char *); - -int -process_config_line(Options *, const char *, char *, const char *, int, int *); - -void add_local_forward(Options *, const Forward *); -void add_remote_forward(Options *, const Forward *); - -void process_unknown_options(Options *); - -#ifdef __cplusplus -} -#endif - -#endif /* _READCONF_H */ diff --git a/usr/src/cmd/ssh/include/readpass.h b/usr/src/cmd/ssh/include/readpass.h deleted file mode 100644 index 1917f08e30..0000000000 --- a/usr/src/cmd/ssh/include/readpass.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $OpenBSD: readpass.h,v 1.7 2002/03/26 15:58:46 markus Exp $ */ - -#ifndef _READPASS_H -#define _READPASS_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#define RP_ECHO 0x0001 -#define RP_ALLOW_STDIN 0x0002 -#define RP_ALLOW_EOF 0x0004 -#define RP_USE_ASKPASS 0x0008 - -char *read_passphrase(const char *, int); -int ask_permission(const char *, ...) - __attribute__((format(printf, 1, 2))); -int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *); - -#ifdef __cplusplus -} -#endif - -#endif /* _READPASS_H */ diff --git a/usr/src/cmd/ssh/include/readpassphrase.h b/usr/src/cmd/ssh/include/readpassphrase.h deleted file mode 100644 index 3dd7b367d0..0000000000 --- a/usr/src/cmd/ssh/include/readpassphrase.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD: readpassphrase.h,v 1.3 2002/06/28 12:32:22 millert Exp $ */ - -#ifndef _READPASSPHRASE_H -#define _READPASSPHRASE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifndef HAVE_READPASSPHRASE - -#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ -#define RPP_ECHO_ON 0x01 /* Leave echo on. */ -#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ -#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ -#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ -#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ -#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ - -char * readpassphrase(const char *, char *, size_t, int); - -#endif /* HAVE_READPASSPHRASE */ - -#ifdef __cplusplus -} -#endif - -#endif /* _READPASSPHRASE_H */ diff --git a/usr/src/cmd/ssh/include/realpath.h b/usr/src/cmd/ssh/include/realpath.h deleted file mode 100644 index 1bd00053ac..0000000000 --- a/usr/src/cmd/ssh/include/realpath.h +++ /dev/null @@ -1,24 +0,0 @@ -/* $Id: realpath.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _REALPATH_H -#define _REALPATH_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) - -char *realpath(const char *path, char *resolved); - -#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _REALPATH_H */ diff --git a/usr/src/cmd/ssh/include/rresvport.h b/usr/src/cmd/ssh/include/rresvport.h deleted file mode 100644 index 33c47d84cf..0000000000 --- a/usr/src/cmd/ssh/include/rresvport.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id: rresvport.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _RRESVPORT_H -#define _RRESVPORT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#ifndef HAVE_RRESVPORT_AF -int rresvport_af(int *alport, sa_family_t af); -#endif /* !HAVE_RRESVPORT_AF */ - -#ifdef __cplusplus -} -#endif - -#endif /* _RRESVPORT_H */ diff --git a/usr/src/cmd/ssh/include/rsa.h b/usr/src/cmd/ssh/include/rsa.h deleted file mode 100644 index f0fcc49ba0..0000000000 --- a/usr/src/cmd/ssh/include/rsa.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $OpenBSD: rsa.h,v 1.15 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _RSA_H -#define _RSA_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * RSA key generation, encryption and decryption. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include <openssl/bn.h> -#include <openssl/rsa.h> - -void rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); -int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); -void rsa_generate_additional_parameters(RSA *); - -#ifdef __cplusplus -} -#endif - -#endif /* _RSA_H */ diff --git a/usr/src/cmd/ssh/include/servconf.h b/usr/src/cmd/ssh/include/servconf.h deleted file mode 100644 index a66c6415cb..0000000000 --- a/usr/src/cmd/ssh/include/servconf.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Definitions for server configuration data and for the functions reading it. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -/* $OpenBSD: servconf.h,v 1.59 2002/07/30 17:03:55 markus Exp $ */ - -#ifndef _SERVCONF_H -#define _SERVCONF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAX_PORTS 256 /* Max # ports. */ - -#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ -#define MAX_DENY_USERS 256 /* Max # users on deny list. */ -#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ -#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ -#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ -#define MAX_HOSTKEYS 256 /* Max # hostkeys. */ - -/* permit_root_login */ -#define PERMIT_NOT_SET -1 -#define PERMIT_NO 0 -#define PERMIT_FORCED_ONLY 1 -#define PERMIT_NO_PASSWD 2 -#define PERMIT_YES 3 - -/* Magic name for internal sftp-server */ -#define INTERNAL_SFTP_NAME "internal-sftp" -#define _SSH_PAM_SERVICE_PREFIX "sshd" - -typedef struct { - u_int num_ports; - u_int ports_from_cmdline; - u_short ports[MAX_PORTS]; /* Port number to listen on. */ - char *listen_addr; /* Address on which the server listens. */ - struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ - char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */ - int num_host_key_files; /* Number of files for host keys. */ - char *pid_file; /* Where to put our pid */ - int server_key_bits;/* Size of the server key. */ - int login_grace_time; /* Disconnect if no auth in this time - * (sec). */ - int key_regeneration_time; /* Server key lifetime (seconds). */ - int permit_root_login; /* PERMIT_*, see above */ - int ignore_rhosts; /* Ignore .rhosts and .shosts. */ - int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts - * for RhostsRsaAuth */ - int print_motd; /* If true, print /etc/motd. */ - int print_lastlog; /* If true, print lastlog */ - int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ - int x11_display_offset; /* What DISPLAY number to start - * searching at */ - int x11_use_localhost; /* If true, use localhost for fake X11 server. */ - char *xauth_location; /* Location of xauth program */ - int strict_modes; /* If true, require string home dir modes. */ - int keepalives; /* If true, set SO_KEEPALIVE. */ - char *ciphers; /* Supported SSH2 ciphers. */ - char *macs; /* Supported SSH2 macs. */ - int protocol; /* Supported protocol versions. */ - int gateway_ports; /* If true, allow remote connects to forwarded ports. */ - SyslogFacility log_facility; /* Facility for system logging. */ - LogLevel log_level; /* Level for system logging. */ - int rhosts_authentication; /* If true, permit rhosts - * authentication. */ - int rhosts_rsa_authentication; /* If true, permit rhosts RSA - * authentication. */ - int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ - int hostbased_uses_name_from_packet_only; /* experimental */ - int rsa_authentication; /* If true, permit RSA authentication. */ - int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ -#ifdef GSSAPI - int gss_authentication; - int gss_keyex; - int gss_store_creds; - int gss_use_session_ccache; /* If true, delegated credentials are - * stored in a session specific cache */ - int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -#endif /* GSSAPI */ -#if defined(KRB4) || defined(KRB5) - int kerberos_authentication; /* If true, permit Kerberos - * authentication. */ - int kerberos_or_local_passwd; /* If true, permit kerberos - * and any other password - * authentication mechanism, - * such as SecurID or - * /etc/passwd */ - int kerberos_ticket_cleanup; /* If true, destroy ticket - * file on logout. */ -#endif -#if defined(AFS) || defined(KRB5) - int kerberos_tgt_passing; /* If true, permit Kerberos TGT - * passing. */ -#endif -#ifdef AFS - int afs_token_passing; /* If true, permit AFS token passing. */ -#endif - int password_authentication; /* If true, permit password - * authentication. */ - - int kbd_interactive_authentication; - int challenge_response_authentication; - int pam_authentication_via_kbd_int; - - int permit_empty_passwd; /* If false, do not permit empty - * passwords. */ - int permit_user_env; /* If true, read ~/.ssh/environment */ - int use_login; /* If true, login(1) is used */ - int compression; /* If true, compression is allowed */ - int allow_tcp_forwarding; - - u_int num_allow_users; - char *allow_users[MAX_ALLOW_USERS]; - u_int num_deny_users; - char *deny_users[MAX_DENY_USERS]; - u_int num_allow_groups; - char *allow_groups[MAX_ALLOW_GROUPS]; - u_int num_deny_groups; - char *deny_groups[MAX_DENY_GROUPS]; - - u_int num_subsystems; - char *subsystem_name[MAX_SUBSYSTEMS]; - char *subsystem_command[MAX_SUBSYSTEMS]; - char *subsystem_args[MAX_SUBSYSTEMS]; - - int max_startups_begin; - int max_startups_rate; - int max_startups; - char *banner; /* SSH-2 banner message */ - int verify_reverse_mapping; /* cross-check ip and dns */ - int client_alive_interval; /* - * poke the client this often to - * see if it's still there - */ - int client_alive_count_max; /* - * If the client is unresponsive - * for this many intervals above, - * disconnect the session - */ - - char *authorized_keys_file; /* File containing public keys */ - char *authorized_keys_file2; - - int max_auth_tries; - int max_auth_tries_log; - - int max_init_auth_tries; /* SUNW: /etc/default/login */ - int max_init_auth_tries_log; /* SUNW: /etc/default/login */ - - int lookup_client_hostnames; - int use_openssl_engine; - char *chroot_directory; - char *pre_userauth_hook; - char *pam_service_prefix; - char *pam_service_name; - -} ServerOptions; - -void initialize_server_options(ServerOptions *); -void fill_default_server_options(ServerOptions *); -int process_server_config_line(ServerOptions *, char *, const char *, int, - int *, const char *, const char *, const char *); -void load_server_config(const char *, Buffer *); -void parse_server_config(ServerOptions *, const char *, Buffer *, - const char *, const char *, const char *); -void parse_server_match_config(ServerOptions *, const char *, const char *, - const char *); -void copy_set_server_options(ServerOptions *, ServerOptions *, int); -int chroot_requested(char *chroot_directory); - -#ifdef __cplusplus -} -#endif - - -#endif /* _SERVCONF_H */ diff --git a/usr/src/cmd/ssh/include/serverloop.h b/usr/src/cmd/ssh/include/serverloop.h deleted file mode 100644 index ec5b34a6b2..0000000000 --- a/usr/src/cmd/ssh/include/serverloop.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $OpenBSD: serverloop.h,v 1.5 2001/06/27 02:12:53 markus Exp $ */ - -#ifndef _SERVERLOOP_H -#define _SERVERLOOP_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Performs the interactive session. This handles data transmission between - * the client and the program. Note that the notion of stdin, stdout, and - * stderr in this function is sort of reversed: this function writes to stdin - * (of the child program), and reads from stdout and stderr (of the child - * program). - */ - -void server_loop(pid_t, int, int, int); -void server_loop2(Authctxt *); - -#ifdef __cplusplus -} -#endif - -#endif /* _SERVERLOOP_H */ diff --git a/usr/src/cmd/ssh/include/session.h b/usr/src/cmd/ssh/include/session.h deleted file mode 100644 index 0d81189842..0000000000 --- a/usr/src/cmd/ssh/include/session.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SESSION_H -#define _SESSION_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* $OpenBSD: session.h,v 1.19 2002/06/30 21:59:45 deraadt Exp $ */ -#define TTYSZ 64 -typedef struct Session Session; -struct Session { - int used; - int self; - struct passwd *pw; - Authctxt *authctxt; - pid_t pid; - /* tty */ - char *term; - int ptyfd, ttyfd, ptymaster; - u_int row, col, xpixel, ypixel; - char tty[TTYSZ]; - /* last login */ - char hostname[MAXHOSTNAMELEN]; - time_t last_login_time; - /* X11 */ - u_int display_number; - char *display; - u_int screen; - char *auth_display; - char *auth_proto; - char *auth_data; - char *auth_file; /* xauth(1) authority file */ - int single_connection; - /* proto 2 */ - int chanid; - int is_subsystem; - char *command; - char **env; -}; - -void do_authenticated(Authctxt *); - -int session_open(Authctxt *, int); -int session_input_channel_req(Channel *, const char *); -void session_close_by_pid(pid_t, int); -void session_close_by_channel(int, void *); -void session_destroy_all(void (*)(Session *)); -void session_pty_cleanup2(void *); - -Session *session_new(void); -Session *session_by_tty(char *); -void session_close(Session *); -void do_setusercontext(struct passwd *); -void child_set_env(char ***envp, u_int *envsizep, const char *name, - const char *value); -void child_set_env_silent(char ***envp, u_int *envsizep, const char *name, - const char *value); - - -#ifdef __cplusplus -} -#endif - -#endif /* _SESSION_H */ diff --git a/usr/src/cmd/ssh/include/setproctitle.h b/usr/src/cmd/ssh/include/setproctitle.h deleted file mode 100644 index 9488be3cf7..0000000000 --- a/usr/src/cmd/ssh/include/setproctitle.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id: setproctitle.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _SETPROCTITLE_H -#define _SETPROCTITLE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" - -#ifndef HAVE_SETPROCTITLE -void setproctitle(const char *fmt, ...); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _SETPROCTITLE_H */ diff --git a/usr/src/cmd/ssh/include/sftp-client.h b/usr/src/cmd/ssh/include/sftp-client.h deleted file mode 100644 index 1927e3df16..0000000000 --- a/usr/src/cmd/ssh/include/sftp-client.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _SFTP_CLIENT_H -#define _SFTP_CLIENT_H - -/* $OpenBSD: sftp-client.h,v 1.14 2005/04/26 12:59:02 jmc Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Client side of SSH2 filexfer protocol */ - -typedef struct SFTP_DIRENT SFTP_DIRENT; - -struct SFTP_DIRENT { - char *filename; - char *longname; - Attrib a; -}; - -/* - * Initialise a SSH filexfer connection. Returns NULL on error or - * a pointer to a initialized sftp_conn struct on success. - */ -struct sftp_conn *do_init(int, int, u_int, u_int); - -u_int sftp_proto_version(struct sftp_conn *); - -/* Close file referred to by 'handle' */ -int do_close(struct sftp_conn *, char *, u_int); - -/* Read contents of 'path' to NULL-terminated array 'dir' */ -int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); - -/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ -void free_sftp_dirents(SFTP_DIRENT **); - -/* Delete file 'path' */ -int do_rm(struct sftp_conn *, char *); - -/* Create directory 'path' */ -int do_mkdir(struct sftp_conn *, char *, Attrib *); - -/* Remove directory 'path' */ -int do_rmdir(struct sftp_conn *, char *); - -/* Get file attributes of 'path' (follows symlinks) */ -Attrib *do_stat(struct sftp_conn *, char *, int); - -/* Get file attributes of 'path' (does not follow symlinks) */ -Attrib *do_lstat(struct sftp_conn *, char *, int); - -/* Get file attributes of open file 'handle' */ -Attrib *do_fstat(struct sftp_conn *, char *, u_int, int); - -/* Set file attributes of 'path' */ -int do_setstat(struct sftp_conn *, char *, Attrib *); - -/* Set file attributes of open file 'handle' */ -int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); - -/* Canonicalise 'path' - caller must free result */ -char *do_realpath(struct sftp_conn *, char *); - -/* Rename 'oldpath' to 'newpath' */ -int do_rename(struct sftp_conn *, char *, char *); - -/* Rename 'oldpath' to 'newpath' */ -int do_symlink(struct sftp_conn *, char *, char *); - -/* Return target of symlink 'path' - caller must free result */ -char *do_readlink(struct sftp_conn *, char *); - -/* XXX: add callbacks to do_download/do_upload so we can do progress meter */ - -/* - * Download 'remote_path' to 'local_path'. Preserve permissions and times - * if 'pflag' is set - */ -int do_download(struct sftp_conn *, char *, char *, int); - -/* - * Upload 'local_path' to 'remote_path'. Preserve permissions and times - * if 'pflag' is set - */ -int do_upload(struct sftp_conn *, char *, char *, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _SFTP_CLIENT_H */ diff --git a/usr/src/cmd/ssh/include/sftp-common.h b/usr/src/cmd/ssh/include/sftp-common.h deleted file mode 100644 index 86225bc175..0000000000 --- a/usr/src/cmd/ssh/include/sftp-common.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2001 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SFTP_COMMON_H -#define _SFTP_COMMON_H - -/* $OpenBSD: sftp-common.h,v 1.10 2006/08/03 03:34:42 deraadt Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Maximum packet that we are willing to send/accept */ -#define SFTP_MAX_MSG_LENGTH (256 * 1024) - -typedef struct Attrib Attrib; - -/* File attributes */ -struct Attrib { - u_int32_t flags; - u_int64_t size; - u_int32_t uid; - u_int32_t gid; - u_int32_t perm; - u_int32_t atime; - u_int32_t mtime; -}; - -void attrib_clear(Attrib *); -void stat_to_attrib(const struct stat *, Attrib *); -void attrib_to_stat(const Attrib *, struct stat *); -Attrib *decode_attrib(Buffer *); -void encode_attrib(Buffer *, const Attrib *); -char *ls_file(const char *, const struct stat *, int); - -const char *fx2txt(int); - -#ifdef __cplusplus -} -#endif - -#endif /* _SFTP_COMMON_H */ diff --git a/usr/src/cmd/ssh/include/sftp.h b/usr/src/cmd/ssh/include/sftp.h deleted file mode 100644 index e35cbdedf1..0000000000 --- a/usr/src/cmd/ssh/include/sftp.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $OpenBSD: sftp.h,v 1.4 2002/02/13 00:59:23 djm Exp $ */ - -/* - * draft-ietf-secsh-filexfer-01.txt - */ - -#ifndef _SFTP_H -#define _SFTP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* version */ -#define SSH2_FILEXFER_VERSION 3 - -/* client to server */ -#define SSH2_FXP_INIT 1 -#define SSH2_FXP_OPEN 3 -#define SSH2_FXP_CLOSE 4 -#define SSH2_FXP_READ 5 -#define SSH2_FXP_WRITE 6 -#define SSH2_FXP_LSTAT 7 -#define SSH2_FXP_STAT_VERSION_0 7 -#define SSH2_FXP_FSTAT 8 -#define SSH2_FXP_SETSTAT 9 -#define SSH2_FXP_FSETSTAT 10 -#define SSH2_FXP_OPENDIR 11 -#define SSH2_FXP_READDIR 12 -#define SSH2_FXP_REMOVE 13 -#define SSH2_FXP_MKDIR 14 -#define SSH2_FXP_RMDIR 15 -#define SSH2_FXP_REALPATH 16 -#define SSH2_FXP_STAT 17 -#define SSH2_FXP_RENAME 18 -#define SSH2_FXP_READLINK 19 -#define SSH2_FXP_SYMLINK 20 - -/* server to client */ -#define SSH2_FXP_VERSION 2 -#define SSH2_FXP_STATUS 101 -#define SSH2_FXP_HANDLE 102 -#define SSH2_FXP_DATA 103 -#define SSH2_FXP_NAME 104 -#define SSH2_FXP_ATTRS 105 - -#define SSH2_FXP_EXTENDED 200 -#define SSH2_FXP_EXTENDED_REPLY 201 - -/* attributes */ -#define SSH2_FILEXFER_ATTR_SIZE 0x00000001 -#define SSH2_FILEXFER_ATTR_UIDGID 0x00000002 -#define SSH2_FILEXFER_ATTR_PERMISSIONS 0x00000004 -#define SSH2_FILEXFER_ATTR_ACMODTIME 0x00000008 -#define SSH2_FILEXFER_ATTR_EXTENDED 0x80000000 - -/* portable open modes */ -#define SSH2_FXF_READ 0x00000001 -#define SSH2_FXF_WRITE 0x00000002 -#define SSH2_FXF_APPEND 0x00000004 -#define SSH2_FXF_CREAT 0x00000008 -#define SSH2_FXF_TRUNC 0x00000010 -#define SSH2_FXF_EXCL 0x00000020 - -/* status messages */ -#define SSH2_FX_OK 0 -#define SSH2_FX_EOF 1 -#define SSH2_FX_NO_SUCH_FILE 2 -#define SSH2_FX_PERMISSION_DENIED 3 -#define SSH2_FX_FAILURE 4 -#define SSH2_FX_BAD_MESSAGE 5 -#define SSH2_FX_NO_CONNECTION 6 -#define SSH2_FX_CONNECTION_LOST 7 -#define SSH2_FX_OP_UNSUPPORTED 8 -#define SSH2_FX_MAX 8 - -struct passwd; - -int sftp_server_main(int, char **, struct passwd *); - -#ifdef __cplusplus -} -#endif - -#endif /* _SFTP_H */ diff --git a/usr/src/cmd/ssh/include/sigact.h b/usr/src/cmd/ssh/include/sigact.h deleted file mode 100644 index fc5b3b6427..0000000000 --- a/usr/src/cmd/ssh/include/sigact.h +++ /dev/null @@ -1,99 +0,0 @@ -/* $OpenBSD: SigAction.h,v 1.2 1999/06/27 08:15:19 millert Exp $ */ - -#ifndef _SIGACT_H -#define _SIGACT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * - * and: Eric S. Raymond <esr@snark.thyrsus.com> * - ****************************************************************************/ - -/* - * $From: SigAction.h,v 1.5 1999/06/19 23:00:54 tom Exp $ - * - * This file exists to handle non-POSIX systems which don't have <unistd.h>, - * and usually no sigaction() nor <termios.h> - */ - -#if !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) - -#undef SIG_BLOCK -#define SIG_BLOCK 00 - -#undef SIG_UNBLOCK -#define SIG_UNBLOCK 01 - -#undef SIG_SETMASK -#define SIG_SETMASK 02 - -/* - * <bsd/signal.h> is in the Linux 1.2.8 + gcc 2.7.0 configuration, - * and is useful for testing this header file. - */ -#if HAVE_BSD_SIGNAL_H -# include <bsd/signal.h> -#endif - -struct sigaction -{ - struct sigvec sv; -}; - -typedef unsigned long sigset_t; - -#undef sa_mask -#define sa_mask sv.sv_mask -#undef sa_handler -#define sa_handler sv.sv_handler -#undef sa_flags -#define sa_flags sv.sv_flags - -int sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact); -int sigprocmask (int how, sigset_t *mask, sigset_t *omask); -int sigemptyset (sigset_t *mask); -int sigsuspend (sigset_t *mask); -int sigdelset (sigset_t *mask, int sig); -int sigaddset (sigset_t *mask, int sig); - -#endif /* !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SIGACT_H */ diff --git a/usr/src/cmd/ssh/include/ssh-dss.h b/usr/src/cmd/ssh/include/ssh-dss.h deleted file mode 100644 index 7f4e6d19fe..0000000000 --- a/usr/src/cmd/ssh/include/ssh-dss.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $OpenBSD: ssh-dss.h,v 1.6 2002/02/24 19:14:59 markus Exp $ */ - -#ifndef _SSH_DSS_H -#define _SSH_DSS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -int ssh_dss_sign(Key *, u_char **, u_int *, u_char *, u_int); -int ssh_dss_verify(Key *, u_char *, u_int, u_char *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSH_DSS_H */ diff --git a/usr/src/cmd/ssh/include/ssh-gss.h b/usr/src/cmd/ssh/include/ssh-gss.h deleted file mode 100644 index 6e35d9ed61..0000000000 --- a/usr/src/cmd/ssh/include/ssh-gss.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SSH_GSS_H -#define _SSH_GSS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef GSSAPI - -#include "kex.h" -#include "buffer.h" - -#ifdef SUNW_GSSAPI -#include <gssapi/gssapi.h> -#include <gssapi/gssapi_ext.h> -#else -#ifdef GSS_KRB5 -#ifndef HEIMDAL -#include <gssapi_generic.h> - -/* MIT Kerberos doesn't seem to define GSS_NT_HOSTBASED_SERVICE */ -#ifndef GSS_C_NT_HOSTBASED_SERVICE -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#endif /* GSS_C_NT_... */ -#endif /* !HEIMDAL */ -#endif /* GSS_KRB5 */ -#endif /* SUNW_GSSAPI */ - -/* draft-ietf-secsh-gsskeyex-03 */ -#define SSH2_MSG_KEXGSS_INIT 30 -#define SSH2_MSG_KEXGSS_CONTINUE 31 -#define SSH2_MSG_KEXGSS_COMPLETE 32 -#define SSH2_MSG_KEXGSS_HOSTKEY 33 -#define SSH2_MSG_KEXGSS_ERROR 34 -#define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60 -#define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61 -#define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63 -#define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64 -#define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65 -#define SSH2_MSG_USERAUTH_GSSAPI_MIC 66 - -#define KEX_GSS_SHA1 "gss-group1-sha1-" -#define SSH_GSS_HOSTBASED_SERVICE "host" - -#ifndef HAVE_GSS_STORE_CRED -typedef struct ssh_gssapi_cred_store ssh_gssapi_cred_store; /* server-only */ -#endif /* !HAVE_GSS_STORE_CRED */ - -typedef struct { - OM_uint32 major; - OM_uint32 minor; - int local; /* true on client, false on server */ - int established; - OM_uint32 flags; - gss_ctx_id_t context; - gss_OID desired_mech; /* client-side only */ - gss_OID actual_mech; - gss_name_t desired_name; /* targ on both */ - gss_name_t src_name; - gss_name_t dst_name; - gss_cred_id_t creds; /* server-side only */ - gss_cred_id_t deleg_creds; /* server-side only */ - int default_creds; /* server-side only */ -#ifndef HAVE_GSS_STORE_CRED - ssh_gssapi_cred_store *cred_store; /* server-side only */ -#endif /* !HAVE_GSS_STORE_CRED */ -} Gssctxt; - -/* Functions to get supported mech lists */ -void ssh_gssapi_server_mechs(gss_OID_set *mechs); -void ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs); - -/* Functions to get fix KEX proposals (needed for rekey cases) */ -void ssh_gssapi_modify_kex(Kex *kex, gss_OID_set mechs, char **proposal); -void ssh_gssapi_server_kex_hook(Kex *kex, char **proposal); -void ssh_gssapi_client_kex_hook(Kex *kex, char **proposal); - -/* Map an encoded mechanism keyex name to a mechanism OID */ -void ssh_gssapi_mech_oid_to_kexname(const gss_OID mech, char **kexname); -void ssh_gssapi_mech_oids_to_kexnames(const gss_OID_set mechs, - char **kexname_list); -/* dup oid? */ -void ssh_gssapi_oid_of_kexname(const char *kexname, gss_OID *mech); - -/* - * Unfortunately, the GSS-API is not generic enough for some things -- - * see gss-serv.c and ssh-gss.c - */ -int ssh_gssapi_is_spnego(gss_OID oid); -int ssh_gssapi_is_krb5(gss_OID oid); -int ssh_gssapi_is_gsi(gss_OID oid); -int ssh_gssapi_is_dh(gss_OID oid); - -/* GSS_Init/Accept_sec_context() and GSS_Acquire_cred() wrappers */ -/* client-only */ -OM_uint32 ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, - int deleg_creds, gss_buffer_t recv_tok, gss_buffer_t send_tok); -/* server-only */ -OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_t recv_tok, - gss_buffer_t send_tok); -/* server-only */ -OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx); - -/* MIC wrappers */ -OM_uint32 ssh_gssapi_get_mic(Gssctxt *ctx, gss_buffer_t buffer, - gss_buffer_t hash); -OM_uint32 ssh_gssapi_verify_mic(Gssctxt *ctx, gss_buffer_t buffer, - gss_buffer_t hash); - -/* Gssctxt functions */ -void ssh_gssapi_build_ctx(Gssctxt **ctx, int client, gss_OID mech); -void ssh_gssapi_delete_ctx(Gssctxt **ctx); -int ssh_gssapi_check_mech_oid(Gssctxt *ctx, void *data, size_t len); -void ssh_gssapi_error(Gssctxt *ctx, const char *where); -char *ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min); - -/* Server-side */ -int ssh_gssapi_userok(Gssctxt *ctx, char *name); -char *ssh_gssapi_localname(Gssctxt *ctx); - -/* Server-side, if PAM and gss_store_cred() are available, ... */ -struct Authctxt; /* needed to avoid conflicts between auth.h, sshconnect2.c */ -void ssh_gssapi_storecreds(Gssctxt *ctx, struct Authctxt *authctxt); - -/* ... else, if other interfaces are available for GSS-API cred storing */ -void ssh_gssapi_do_child(Gssctxt *ctx, char ***envp, uint_t *envsizep); -void ssh_gssapi_cleanup_creds(Gssctxt *ctx); - -/* Misc */ -int ssh_gssapi_import_name(Gssctxt *ctx, const char *server_host); -const char *ssh_gssapi_oid_to_name(gss_OID oid); -char *ssh_gssapi_oid_to_str(gss_OID oid); -gss_OID ssh_gssapi_dup_oid(gss_OID oid); -gss_OID ssh_gssapi_make_oid(size_t length, void *elements); -gss_OID ssh_gssapi_make_oid_ext(size_t length, void *elements, - int der_wrapped); -void *ssh_gssapi_der_wrap(size_t, size_t *length); -size_t ssh_gssapi_der_wrap_size(size_t, size_t *length); -void ssh_gssapi_release_oid(gss_OID *oid); -#endif /* GSSAPI */ - -#endif /* _SSH_GSS_H */ diff --git a/usr/src/cmd/ssh/include/ssh-rsa.h b/usr/src/cmd/ssh/include/ssh-rsa.h deleted file mode 100644 index 2d883fa774..0000000000 --- a/usr/src/cmd/ssh/include/ssh-rsa.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $OpenBSD: ssh-rsa.h,v 1.6 2002/02/24 19:14:59 markus Exp $ */ - -#ifndef _SSH_RSA_H -#define _SSH_RSA_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -int ssh_rsa_sign(Key *, u_char **, u_int *, u_char *, u_int); -int ssh_rsa_verify(Key *, u_char *, u_int, u_char *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSH_RSA_H */ diff --git a/usr/src/cmd/ssh/include/ssh.h b/usr/src/cmd/ssh/include/ssh.h deleted file mode 100644 index 746d2ff69b..0000000000 --- a/usr/src/cmd/ssh/include/ssh.h +++ /dev/null @@ -1,133 +0,0 @@ -/* $OpenBSD: ssh.h,v 1.71 2002/06/22 02:00:29 stevesk Exp $ */ - -#ifndef _SSH_H -#define _SSH_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <netinet/in.h> /* For struct sockaddr_in */ -#include <pwd.h> /* For struct pw */ -#include <stdarg.h> /* For va_list */ -#include <syslog.h> /* For LOG_AUTH and friends */ -#include <sys/socket.h> /* For struct sockaddr_storage */ -#include "fake-socket.h" /* For struct sockaddr_storage */ -#ifdef HAVE_SYS_SELECT_H -# include <sys/select.h> -#endif - -/* Cipher used for encrypting authentication files. */ -#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES - -/* Default port number. */ -#define SSH_DEFAULT_PORT 22 - -/* Maximum number of TCP/IP ports forwarded per direction. */ -#define SSH_MAX_FORWARDS_PER_DIRECTION 100 - -/* - * Maximum number of RSA authentication identity files that can be specified - * in configuration files or on the command line. - */ -#define SSH_MAX_IDENTITY_FILES 100 - -/* - * Major protocol version. Different version indicates major incompatibility - * that prevents communication. - * - * Minor protocol version. Different version indicates minor incompatibility - * that does not prevent interoperation. - */ -#define PROTOCOL_MAJOR_1 1 -#define PROTOCOL_MINOR_1 5 - -/* We support both SSH1 and SSH2 */ -#define PROTOCOL_MAJOR_2 2 -#define PROTOCOL_MINOR_2 0 - -/* - * Name for the service. The port named by this service overrides the - * default port if present. - */ -#define SSH_SERVICE_NAME "ssh" - -/* - * Name of the environment variable containing the process ID of the - * authentication agent. - */ -#define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID" - -/* - * Name of the environment variable containing the pathname of the - * authentication socket. - */ -#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK" - -/* - * Environment variable for overwriting the default location of askpass - */ -#define SSH_ASKPASS_ENV "SSH_ASKPASS" - -/* - * Force host key length and server key length to differ by at least this - * many bits. This is to make double encryption with rsaref work. - */ -#define SSH_KEY_BITS_RESERVED 128 - -/* - * Length of the session key in bytes. (Specified as 256 bits in the - * protocol.) - */ -#define SSH_SESSION_KEY_LENGTH 32 - -/* Name of Kerberos service for SSH to use. */ -#define KRB4_SERVICE_NAME "rcmd" - -/* Used to identify ``EscapeChar none'' */ -#define SSH_ESCAPECHAR_NONE -2 - -/* - * unprivileged user when UsePrivilegeSeparation=yes; - * sshd will change its privileges to this user and its - * primary group. - */ -#ifndef SSH_PRIVSEP_USER -#define SSH_PRIVSEP_USER "sshd" -#endif - -/* Minimum modulus size (n) for RSA keys. */ -#define SSH_RSA_MINIMUM_MODULUS_SIZE 768 - -/* Listen backlog for sshd, ssh-agent and forwarding sockets */ -#define SSH_LISTEN_BACKLOG 128 - -/* - * Do not display banner when in remote command mode only. Note that RFC 4254 - * uses "exec" as a mode name for the channel opened for the execution of the - * given command. - */ -#define SSH_NO_BANNER_IN_EXEC_MODE 2 - -#ifdef __cplusplus -} -#endif - -#endif /* _SSH_H */ diff --git a/usr/src/cmd/ssh/include/ssh1.h b/usr/src/cmd/ssh/include/ssh1.h deleted file mode 100644 index 8a6f84c594..0000000000 --- a/usr/src/cmd/ssh/include/ssh1.h +++ /dev/null @@ -1,105 +0,0 @@ -/* $OpenBSD: ssh1.h,v 1.3 2001/05/30 12:55:13 markus Exp $ */ - -#ifndef _SSH1_H -#define _SSH1_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* - * Definition of message types. New values can be added, but old values - * should not be removed or without careful consideration of the consequences - * for compatibility. The maximum value is 254; value 255 is reserved for - * future extension. - */ -/* Message name */ /* msg code */ /* arguments */ -#define SSH_MSG_NONE 0 /* no message */ -#define SSH_MSG_DISCONNECT 1 /* cause (string) */ -#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */ -#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */ -#define SSH_CMSG_USER 4 /* user (string) */ -#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */ -#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */ -#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */ -#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */ -#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */ -#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */ -#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */ -#define SSH_CMSG_EXEC_SHELL 12 /* */ -#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */ -#define SSH_SMSG_SUCCESS 14 /* */ -#define SSH_SMSG_FAILURE 15 /* */ -#define SSH_CMSG_STDIN_DATA 16 /* data (string) */ -#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */ -#define SSH_SMSG_STDERR_DATA 18 /* data (string) */ -#define SSH_CMSG_EOF 19 /* */ -#define SSH_SMSG_EXITSTATUS 20 /* status (int) */ -#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */ -#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */ -#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */ -#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */ -#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */ -/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */ -#define SSH_SMSG_X11_OPEN 27 /* channel (int) */ -#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */ -#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */ -#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */ -#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */ -#define SSH_MSG_IGNORE 32 /* string */ -#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */ -#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */ -#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */ -#define SSH_MSG_DEBUG 36 /* string */ -#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */ -#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */ -#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */ -#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */ -#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */ -#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */ -#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */ -#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */ -#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */ - -/* protocol version 1.5 overloads some version 1.3 message types */ -#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE -#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION - -/* - * Authentication methods. New types can be added, but old types should not - * be removed for compatibility. The maximum allowed value is 31. - */ -#define SSH_AUTH_RHOSTS 1 -#define SSH_AUTH_RSA 2 -#define SSH_AUTH_PASSWORD 3 -#define SSH_AUTH_RHOSTS_RSA 4 -#define SSH_AUTH_TIS 5 -#define SSH_AUTH_KERBEROS 6 -#define SSH_PASS_KERBEROS_TGT 7 - /* 8 to 15 are reserved */ -#define SSH_PASS_AFS_TOKEN 21 - -/* Protocol flags. These are bit masks. */ -#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */ -#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SSH1_H */ diff --git a/usr/src/cmd/ssh/include/ssh2.h b/usr/src/cmd/ssh/include/ssh2.h deleted file mode 100644 index 20782bb266..0000000000 --- a/usr/src/cmd/ssh/include/ssh2.h +++ /dev/null @@ -1,184 +0,0 @@ -/* $OpenBSD: ssh2.h,v 1.8 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _SSH2_H -#define _SSH2_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * draft-ietf-secsh-architecture-05.txt - * - * Transport layer protocol: - * - * 1-19 Transport layer generic (e.g. disconnect, ignore, debug, - * etc) - * 20-29 Algorithm negotiation - * 30-49 Key exchange method specific (numbers can be reused for - * different authentication methods) - * - * User authentication protocol: - * - * 50-59 User authentication generic - * 60-79 User authentication method specific (numbers can be reused - * for different authentication methods) - * - * Connection protocol: - * - * 80-89 Connection protocol generic - * 90-127 Channel related messages - * - * Reserved for client protocols: - * - * 128-191 Reserved - * - * Local extensions: - * - * 192-255 Local extensions - */ - -/* ranges */ - -#define SSH2_MSG_TRANSPORT_MIN 1 -#define SSH2_MSG_TRANSPORT_MAX 49 -#define SSH2_MSG_USERAUTH_MIN 50 -#define SSH2_MSG_USERAUTH_MAX 79 -#define SSH2_MSG_CONNECTION_MIN 80 -#define SSH2_MSG_CONNECTION_MAX 127 -#define SSH2_MSG_RESERVED_MIN 128 -#define SSH2_MSG_RESERVED_MAX 191 -#define SSH2_MSG_LOCAL_MIN 192 -#define SSH2_MSG_LOCAL_MAX 255 -#define SSH2_MSG_MIN 1 -#define SSH2_MSG_MAX 255 - -/* transport layer: generic */ - -#define SSH2_MSG_DISCONNECT 1 -#define SSH2_MSG_IGNORE 2 -#define SSH2_MSG_UNIMPLEMENTED 3 -#define SSH2_MSG_DEBUG 4 -#define SSH2_MSG_SERVICE_REQUEST 5 -#define SSH2_MSG_SERVICE_ACCEPT 6 - -/* transport layer: alg negotiation */ - -#define SSH2_MSG_KEXINIT 20 -#define SSH2_MSG_NEWKEYS 21 - -/* transport layer: kex specific messages, can be reused */ - -#define SSH2_MSG_KEXDH_INIT 30 -#define SSH2_MSG_KEXDH_REPLY 31 - -/* dh-group-exchange */ -#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 -#define SSH2_MSG_KEX_DH_GEX_GROUP 31 -#define SSH2_MSG_KEX_DH_GEX_INIT 32 -#define SSH2_MSG_KEX_DH_GEX_REPLY 33 -#define SSH2_MSG_KEX_DH_GEX_REQUEST 34 - -/* user authentication: generic */ - -#define SSH2_MSG_USERAUTH_REQUEST 50 -#define SSH2_MSG_USERAUTH_FAILURE 51 -#define SSH2_MSG_USERAUTH_SUCCESS 52 -#define SSH2_MSG_USERAUTH_BANNER 53 - -/* user authentication: method specific, can be reused */ - -#define SSH2_MSG_USERAUTH_PK_OK 60 -#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 -#define SSH2_MSG_USERAUTH_INFO_REQUEST 60 -#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 - -/* connection protocol: generic */ - -#define SSH2_MSG_GLOBAL_REQUEST 80 -#define SSH2_MSG_REQUEST_SUCCESS 81 -#define SSH2_MSG_REQUEST_FAILURE 82 - -/* channel related messages */ - -#define SSH2_MSG_CHANNEL_OPEN 90 -#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 -#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 -#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 -#define SSH2_MSG_CHANNEL_DATA 94 -#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 -#define SSH2_MSG_CHANNEL_EOF 96 -#define SSH2_MSG_CHANNEL_CLOSE 97 -#define SSH2_MSG_CHANNEL_REQUEST 98 -#define SSH2_MSG_CHANNEL_SUCCESS 99 -#define SSH2_MSG_CHANNEL_FAILURE 100 - -/* ALTPRIVSEP */ -#ifdef ALTPRIVSEP -#define SSH2_PRIV_MSG_ALTPRIVSEP 254 -#endif /* ALTPRIVSEP */ - -/* disconnect reason code */ - -#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 -#define SSH2_DISCONNECT_PROTOCOL_ERROR 2 -#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 -#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 -#define SSH2_DISCONNECT_RESERVED 4 -#define SSH2_DISCONNECT_MAC_ERROR 5 -#define SSH2_DISCONNECT_COMPRESSION_ERROR 6 -#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 -#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 -#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 -#define SSH2_DISCONNECT_CONNECTION_LOST 10 -#define SSH2_DISCONNECT_BY_APPLICATION 11 -#define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 -#define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 -#define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 -#define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 - -/* misc */ - -#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 -#define SSH2_OPEN_CONNECT_FAILED 2 -#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 -#define SSH2_OPEN_RESOURCE_SHORTAGE 4 - -#define SSH2_EXTENDED_DATA_STDERR 1 - -#ifdef __cplusplus -} -#endif - -#endif /* _SSH2_H */ diff --git a/usr/src/cmd/ssh/include/sshconnect.h b/usr/src/cmd/ssh/include/sshconnect.h deleted file mode 100644 index 74eaccfbbc..0000000000 --- a/usr/src/cmd/ssh/include/sshconnect.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $OpenBSD: sshconnect.h,v 1.17 2002/06/19 00:27:55 deraadt Exp $ */ - -#ifndef _SSHCONNECT_H -#define _SSHCONNECT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct Sensitive Sensitive; -struct Sensitive { - Key **keys; - int nkeys; - int external_keysign; -}; - -int -ssh_connect(const char *, struct sockaddr_storage *, ushort_t, int, int, - int, const char *); - -void -ssh_login(Sensitive *, const char *, struct sockaddr *, char *); - -int verify_host_key(char *, struct sockaddr *, Key *); -int accept_host_key(char *, struct sockaddr *, Key *); - -void ssh_kex(char *, struct sockaddr *); -void ssh_kex2(char *, struct sockaddr *); - -void ssh_userauth1(const char *, const char *, char *, Sensitive *); -void ssh_userauth2(const char *, const char *, char *, Sensitive *); - -void ssh_put_password(char *); - - -/* - * Macros to raise/lower permissions. - */ -#define PRIV_START do { \ - int save_errno = errno; \ - (void) seteuid(original_effective_uid); \ - errno = save_errno; \ -} while (0) - -#define PRIV_END do { \ - int save_errno = errno; \ - (void) seteuid(original_real_uid); \ - errno = save_errno; \ -} while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* _SSHCONNECT_H */ diff --git a/usr/src/cmd/ssh/include/sshlogin.h b/usr/src/cmd/ssh/include/sshlogin.h deleted file mode 100644 index e7d2ee7c89..0000000000 --- a/usr/src/cmd/ssh/include/sshlogin.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $OpenBSD: sshlogin.h,v 1.4 2002/08/29 15:57:25 stevesk Exp $ */ - -#ifndef _SSHLOGIN_H -#define _SSHLOGIN_H - -#ifdef __cplusplus -extern "C" { -#endif - -void -record_login(pid_t pid, const char *ttyname, const char *progname, - const char *user); -void -record_logout(pid_t pid, const char *ttyname, const char *progname, - const char *user); - -u_long -get_last_login_time(uid_t uid, const char *logname, char *buf, u_int bufsize); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSHLOGIN_H */ diff --git a/usr/src/cmd/ssh/include/sshpty.h b/usr/src/cmd/ssh/include/sshpty.h deleted file mode 100644 index f5dbf25640..0000000000 --- a/usr/src/cmd/ssh/include/sshpty.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $OpenBSD: sshpty.h,v 1.4 2002/03/04 17:27:39 stevesk Exp $ */ - -#ifndef _SSHPTY_H -#define _SSHPTY_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for allocating a pseudo-terminal and making it the controlling - * tty. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -int pty_allocate(int *, int *, char *, int); -void pty_release(const char *); -void pty_make_controlling_tty(int *, const char *); -void pty_change_window_size(int, int, int, int, int); -void pty_setowner(struct passwd *, const char *); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSHPTY_H */ diff --git a/usr/src/cmd/ssh/include/sshtty.h b/usr/src/cmd/ssh/include/sshtty.h deleted file mode 100644 index 584c63b6b9..0000000000 --- a/usr/src/cmd/ssh/include/sshtty.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenBSD: sshtty.h,v 1.2 2001/06/26 17:27:25 markus Exp $ */ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2001 Kevin Steves. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SSHTTY_H -#define _SSHTTY_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <termios.h> - -int in_raw_mode(void); -struct termios get_saved_tio(void); -void leave_raw_mode(void); -void enter_raw_mode(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSHTTY_H */ diff --git a/usr/src/cmd/ssh/include/strlcat.h b/usr/src/cmd/ssh/include/strlcat.h deleted file mode 100644 index b1b28cf33e..0000000000 --- a/usr/src/cmd/ssh/include/strlcat.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id: strlcat.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _STRLCAT_H -#define _STRLCAT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" -#ifndef HAVE_STRLCAT -#include <sys/types.h> -size_t strlcat(char *dst, const char *src, size_t siz); -#endif /* !HAVE_STRLCAT */ - -#ifdef __cplusplus -} -#endif - -#endif /* _STRLCAT_H */ diff --git a/usr/src/cmd/ssh/include/strlcpy.h b/usr/src/cmd/ssh/include/strlcpy.h deleted file mode 100644 index 6215c105f7..0000000000 --- a/usr/src/cmd/ssh/include/strlcpy.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id: strlcpy.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */ - -#ifndef _STRLCPY_H -#define _STRLCPY_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" -#ifndef HAVE_STRLCPY -#include <sys/types.h> -size_t strlcpy(char *dst, const char *src, size_t siz); -#endif /* !HAVE_STRLCPY */ - -#ifdef __cplusplus -} -#endif - -#endif /* _STRLCPY_H */ diff --git a/usr/src/cmd/ssh/include/strmode.h b/usr/src/cmd/ssh/include/strmode.h deleted file mode 100644 index cdbc4bd3c9..0000000000 --- a/usr/src/cmd/ssh/include/strmode.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: strmode.h,v 1.3 2001/06/09 02:22:17 mouring Exp $ */ - -#ifndef _STRMODE_H -#define _STRMODE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef HAVE_STRMODE - -void strmode(register mode_t mode, register char *p); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _STRMODE_H */ diff --git a/usr/src/cmd/ssh/include/sys-queue.h b/usr/src/cmd/ssh/include/sys-queue.h deleted file mode 100644 index c5d8e6a5b5..0000000000 --- a/usr/src/cmd/ssh/include/sys-queue.h +++ /dev/null @@ -1,595 +0,0 @@ -/* $OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $ */ -/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ - -#ifndef _SYS_QUEUE_H -#define _SYS_QUEUE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -/* - * Ignore all <sys/queue.h> since older platforms have broken/incomplete - * <sys/queue.h> that are too hard to work around. - */ -#undef SLIST_HEAD -#undef SLIST_HEAD_INITIALIZER -#undef SLIST_ENTRY -#undef SLIST_FIRST -#undef SLIST_END -#undef SLIST_EMPTY -#undef SLIST_NEXT -#undef SLIST_FOREACH -#undef SLIST_INIT -#undef SLIST_INSERT_AFTER -#undef SLIST_INSERT_HEAD -#undef SLIST_REMOVE_HEAD -#undef SLIST_REMOVE -#undef LIST_HEAD -#undef LIST_HEAD_INITIALIZER -#undef LIST_ENTRY -#undef LIST_FIRST -#undef LIST_END -#undef LIST_EMPTY -#undef LIST_NEXT -#undef LIST_FOREACH -#undef LIST_INIT -#undef LIST_INSERT_AFTER -#undef LIST_INSERT_BEFORE -#undef LIST_INSERT_HEAD -#undef LIST_REMOVE -#undef LIST_REPLACE -#undef SIMPLEQ_HEAD -#undef SIMPLEQ_HEAD_INITIALIZER -#undef SIMPLEQ_ENTRY -#undef SIMPLEQ_FIRST -#undef SIMPLEQ_END -#undef SIMPLEQ_EMPTY -#undef SIMPLEQ_NEXT -#undef SIMPLEQ_FOREACH -#undef SIMPLEQ_INIT -#undef SIMPLEQ_INSERT_HEAD -#undef SIMPLEQ_INSERT_TAIL -#undef SIMPLEQ_INSERT_AFTER -#undef SIMPLEQ_REMOVE_HEAD -#undef TAILQ_HEAD -#undef TAILQ_HEAD_INITIALIZER -#undef TAILQ_ENTRY -#undef TAILQ_FIRST -#undef TAILQ_END -#undef TAILQ_NEXT -#undef TAILQ_LAST -#undef TAILQ_PREV -#undef TAILQ_EMPTY -#undef TAILQ_FOREACH -#undef TAILQ_FOREACH_REVERSE -#undef TAILQ_INIT -#undef TAILQ_INSERT_HEAD -#undef TAILQ_INSERT_TAIL -#undef TAILQ_INSERT_AFTER -#undef TAILQ_INSERT_BEFORE -#undef TAILQ_REMOVE -#undef TAILQ_REPLACE -#undef CIRCLEQ_HEAD -#undef CIRCLEQ_HEAD_INITIALIZER -#undef CIRCLEQ_ENTRY -#undef CIRCLEQ_FIRST -#undef CIRCLEQ_LAST -#undef CIRCLEQ_END -#undef CIRCLEQ_NEXT -#undef CIRCLEQ_PREV -#undef CIRCLEQ_EMPTY -#undef CIRCLEQ_FOREACH -#undef CIRCLEQ_FOREACH_REVERSE -#undef CIRCLEQ_INIT -#undef CIRCLEQ_INSERT_AFTER -#undef CIRCLEQ_INSERT_BEFORE -#undef CIRCLEQ_INSERT_HEAD -#undef CIRCLEQ_INSERT_TAIL -#undef CIRCLEQ_REMOVE -#undef CIRCLEQ_REPLACE - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = (head)->slh_first; \ - while( curelm->field.sle_next != (elm) ) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - } \ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List access methods - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ - if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * tail queue access methods - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue access methods - */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ -} while (0) - -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ - (head).cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ - (head).cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ -} while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_QUEUE_H */ diff --git a/usr/src/cmd/ssh/include/sys-tree.h b/usr/src/cmd/ssh/include/sys-tree.h deleted file mode 100644 index fbd31a8f7c..0000000000 --- a/usr/src/cmd/ssh/include/sys-tree.h +++ /dev/null @@ -1,682 +0,0 @@ -/* $OpenBSD: tree.h,v 1.6 2002/06/11 22:09:52 provos Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SYS_TREE_H -#define _SYS_TREE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file defines data structures for different types of trees: - * splay trees and red-black trees. - * - * A splay tree is a self-organizing data structure. Every operation - * on the tree causes a splay to happen. The splay moves the requested - * node to the root of the tree and partly rebalances it. - * - * This has the benefit that request locality causes faster lookups as - * the requested nodes move to the top of the tree. On the other hand, - * every lookup causes memory writes. - * - * The Balance Theorem bounds the total access time for m operations - * and n inserts on an initially empty tree as O((m + n)lg n). The - * amortized cost for a sequence of m accesses to a splay tree is O(lg n); - * - * A red-black tree is a binary search tree with the node color as an - * extra attribute. It fulfills a set of conditions: - * - every search path from the root to a leaf consists of the - * same number of black nodes, - * - each red node (except for the root) has a black parent, - * - each leaf node is black. - * - * Every operation on a red-black tree is bounded as O(lg n). - * The maximum height of a red-black tree is 2lg (n+1). - */ - -#define SPLAY_HEAD(name, type) \ -struct name { \ - struct type *sph_root; /* root of the tree */ \ -} - -#define SPLAY_INITIALIZER(root) \ - { NULL } - -#define SPLAY_INIT(root) do { \ - (root)->sph_root = NULL; \ -} while (0) - -#define SPLAY_ENTRY(type) \ -struct { \ - struct type *spe_left; /* left element */ \ - struct type *spe_right; /* right element */ \ -} - -#define SPLAY_LEFT(elm, field) (elm)->field.spe_left -#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right -#define SPLAY_ROOT(head) (head)->sph_root -#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) - -/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (0) - -#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (0) - -#define SPLAY_LINKLEFT(head, tmp, field) do { \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ -} while (0) - -#define SPLAY_LINKRIGHT(head, tmp, field) do { \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ -} while (0) - -#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ - SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ -} while (0) - -/* Generates prototypes and inline functions */ - -#define SPLAY_PROTOTYPE(name, type, field, cmp) \ -void name##_SPLAY(struct name *, struct type *); \ -void name##_SPLAY_MINMAX(struct name *, int); \ -struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ -struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ - \ -/* Finds the node with the same key as elm */ \ -static __inline struct type * \ -name##_SPLAY_FIND(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) \ - return(NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) \ - return (head->sph_root); \ - return (NULL); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_NEXT(struct name *head, struct type *elm) \ -{ \ - name##_SPLAY(head, elm); \ - if (SPLAY_RIGHT(elm, field) != NULL) { \ - elm = SPLAY_RIGHT(elm, field); \ - while (SPLAY_LEFT(elm, field) != NULL) { \ - elm = SPLAY_LEFT(elm, field); \ - } \ - } else \ - elm = NULL; \ - return (elm); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_MIN_MAX(struct name *head, int val) \ -{ \ - name##_SPLAY_MINMAX(head, val); \ - return (SPLAY_ROOT(head)); \ -} - -/* Main splay operation. - * Moves node close to the key of elm to top - */ -#define SPLAY_GENERATE(name, type, field, cmp) \ -struct type * \ -name##_SPLAY_INSERT(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) { \ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ - } else { \ - int __comp; \ - name##_SPLAY(head, elm); \ - __comp = (cmp)(elm, (head)->sph_root); \ - if(__comp < 0) { \ - SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \ - SPLAY_LEFT((head)->sph_root, field) = NULL; \ - } else if (__comp > 0) { \ - SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ - SPLAY_LEFT(elm, field) = (head)->sph_root; \ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \ - } else \ - return ((head)->sph_root); \ - } \ - (head)->sph_root = (elm); \ - return (NULL); \ -} \ - \ -struct type * \ -name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *__tmp; \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) { \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ - } else { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ - name##_SPLAY(head, elm); \ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ - } \ - return (elm); \ - } \ - return (NULL); \ -} \ - \ -void \ -name##_SPLAY(struct name *head, struct type *elm) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - int __comp; \ -\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ - __left = __right = &__node; \ -\ - while ((__comp = (cmp)(elm, (head)->sph_root))) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) > 0){ \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} \ - \ -/* Splay with either the minimum or the maximum element \ - * Used to find minimum or maximum element in tree. \ - */ \ -void name##_SPLAY_MINMAX(struct name *head, int __comp) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ -\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ - __left = __right = &__node; \ -\ - while (1) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} - -#define SPLAY_NEGINF -1 -#define SPLAY_INF 1 - -#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) -#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) -#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) -#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) - -#define SPLAY_FOREACH(x, name, head) \ - for ((x) = SPLAY_MIN(name, head); \ - (x) != NULL; \ - (x) = SPLAY_NEXT(name, head, x)) - -/* Macros that define a red-back tree */ -#define RB_HEAD(name, type) \ -struct name { \ - struct type *rbh_root; /* root of the tree */ \ -} - -#define RB_INITIALIZER(root) \ - { NULL } - -#define RB_INIT(root) do { \ - (root)->rbh_root = NULL; \ -} while (0) - -#define RB_BLACK 0 -#define RB_RED 1 -#define RB_ENTRY(type) \ -struct { \ - struct type *rbe_left; /* left element */ \ - struct type *rbe_right; /* right element */ \ - struct type *rbe_parent; /* parent element */ \ - int rbe_color; /* node color */ \ -} - -#define RB_LEFT(elm, field) (elm)->field.rbe_left -#define RB_RIGHT(elm, field) (elm)->field.rbe_right -#define RB_PARENT(elm, field) (elm)->field.rbe_parent -#define RB_COLOR(elm, field) (elm)->field.rbe_color -#define RB_ROOT(head) (head)->rbh_root -#define RB_EMPTY(head) (RB_ROOT(head) == NULL) - -#define RB_SET(elm, parent, field) do { \ - RB_PARENT(elm, field) = parent; \ - RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ - RB_COLOR(elm, field) = RB_RED; \ -} while (0) - -#define RB_SET_BLACKRED(black, red, field) do { \ - RB_COLOR(black, field) = RB_BLACK; \ - RB_COLOR(red, field) = RB_RED; \ -} while (0) - -#ifndef RB_AUGMENT -#define RB_AUGMENT(x) -#endif - -#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ - (tmp) = RB_RIGHT(elm, field); \ - if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ - RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - RB_AUGMENT(RB_PARENT(elm, field)); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_LEFT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ -} while (0) - -#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ - (tmp) = RB_LEFT(elm, field); \ - if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ - RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - RB_AUGMENT(RB_PARENT(elm, field)); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_RIGHT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ -} while (0) - -/* Generates prototypes and inline functions */ -#define RB_PROTOTYPE(name, type, field, cmp) \ -void name##_RB_INSERT_COLOR(struct name *, struct type *); \ -void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ -struct type *name##_RB_REMOVE(struct name *, struct type *); \ -struct type *name##_RB_INSERT(struct name *, struct type *); \ -struct type *name##_RB_FIND(struct name *, struct type *); \ -struct type *name##_RB_NEXT(struct name *, struct type *); \ -struct type *name##_RB_MINMAX(struct name *, int); - -/* Main rb operation. - * Moves node close to the key of elm to top - */ -#define RB_GENERATE(name, type, field, cmp) \ -void \ -name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ -{ \ - struct type *parent, *gparent, *tmp; \ - while ((parent = RB_PARENT(elm, field)) && \ - RB_COLOR(parent, field) == RB_RED) { \ - gparent = RB_PARENT(parent, field); \ - if (parent == RB_LEFT(gparent, field)) { \ - tmp = RB_RIGHT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field);\ - elm = gparent; \ - continue; \ - } \ - if (RB_RIGHT(parent, field) == elm) { \ - RB_ROTATE_LEFT(head, parent, tmp, field);\ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_RIGHT(head, gparent, tmp, field); \ - } else { \ - tmp = RB_LEFT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field);\ - elm = gparent; \ - continue; \ - } \ - if (RB_LEFT(parent, field) == elm) { \ - RB_ROTATE_RIGHT(head, parent, tmp, field);\ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_LEFT(head, gparent, tmp, field); \ - } \ - } \ - RB_COLOR(head->rbh_root, field) = RB_BLACK; \ -} \ - \ -void \ -name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ -{ \ - struct type *tmp; \ - while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ - elm != RB_ROOT(head)) { \ - if (RB_LEFT(parent, field) == elm) { \ - tmp = RB_RIGHT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_LEFT(head, parent, tmp, field);\ - tmp = RB_RIGHT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ - struct type *oleft; \ - if ((oleft = RB_LEFT(tmp, field)))\ - RB_COLOR(oleft, field) = RB_BLACK;\ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_RIGHT(head, tmp, oleft, field);\ - tmp = RB_RIGHT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_RIGHT(tmp, field)) \ - RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ - RB_ROTATE_LEFT(head, parent, tmp, field);\ - elm = RB_ROOT(head); \ - break; \ - } \ - } else { \ - tmp = RB_LEFT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_RIGHT(head, parent, tmp, field);\ - tmp = RB_LEFT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ - struct type *oright; \ - if ((oright = RB_RIGHT(tmp, field)))\ - RB_COLOR(oright, field) = RB_BLACK;\ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_LEFT(head, tmp, oright, field);\ - tmp = RB_LEFT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_LEFT(tmp, field)) \ - RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ - RB_ROTATE_RIGHT(head, parent, tmp, field);\ - elm = RB_ROOT(head); \ - break; \ - } \ - } \ - } \ - if (elm) \ - RB_COLOR(elm, field) = RB_BLACK; \ -} \ - \ -struct type * \ -name##_RB_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *child, *parent, *old = elm; \ - int color; \ - if (RB_LEFT(elm, field) == NULL) \ - child = RB_RIGHT(elm, field); \ - else if (RB_RIGHT(elm, field) == NULL) \ - child = RB_LEFT(elm, field); \ - else { \ - struct type *left; \ - elm = RB_RIGHT(elm, field); \ - while ((left = RB_LEFT(elm, field))) \ - elm = left; \ - child = RB_RIGHT(elm, field); \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ - if (RB_PARENT(elm, field) == old) \ - parent = elm; \ - (elm)->field = (old)->field; \ - if (RB_PARENT(old, field)) { \ - if (RB_LEFT(RB_PARENT(old, field), field) == old)\ - RB_LEFT(RB_PARENT(old, field), field) = elm;\ - else \ - RB_RIGHT(RB_PARENT(old, field), field) = elm;\ - RB_AUGMENT(RB_PARENT(old, field)); \ - } else \ - RB_ROOT(head) = elm; \ - RB_PARENT(RB_LEFT(old, field), field) = elm; \ - if (RB_RIGHT(old, field)) \ - RB_PARENT(RB_RIGHT(old, field), field) = elm; \ - if (parent) { \ - left = parent; \ - do { \ - RB_AUGMENT(left); \ - } while ((left = RB_PARENT(left, field))); \ - } \ - goto color; \ - } \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ -color: \ - if (color == RB_BLACK) \ - name##_RB_REMOVE_COLOR(head, parent, child); \ - return (old); \ -} \ - \ -/* Inserts a node into the RB tree */ \ -struct type * \ -name##_RB_INSERT(struct name *head, struct type *elm) \ -{ \ - struct type *tmp; \ - struct type *parent = NULL; \ - int comp = 0; \ - tmp = RB_ROOT(head); \ - while (tmp) { \ - parent = tmp; \ - comp = (cmp)(elm, parent); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - RB_SET(elm, parent, field); \ - if (parent != NULL) { \ - if (comp < 0) \ - RB_LEFT(parent, field) = elm; \ - else \ - RB_RIGHT(parent, field) = elm; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = elm; \ - name##_RB_INSERT_COLOR(head, elm); \ - return (NULL); \ -} \ - \ -/* Finds the node with the same key as elm */ \ -struct type * \ -name##_RB_FIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (NULL); \ -} \ - \ -struct type * \ -name##_RB_NEXT(struct name *head, struct type *elm) \ -{ \ - if (RB_RIGHT(elm, field)) { \ - elm = RB_RIGHT(elm, field); \ - while (RB_LEFT(elm, field)) \ - elm = RB_LEFT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -struct type * \ -name##_RB_MINMAX(struct name *head, int val) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *parent = NULL; \ - while (tmp) { \ - parent = tmp; \ - if (val < 0) \ - tmp = RB_LEFT(tmp, field); \ - else \ - tmp = RB_RIGHT(tmp, field); \ - } \ - return (parent); \ -} - -#define RB_NEGINF -1 -#define RB_INF 1 - -#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) -#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) -#define RB_FIND(name, x, y) name##_RB_FIND(x, y) -#define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) -#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) -#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) - -#define RB_FOREACH(x, name, head) \ - for ((x) = RB_MIN(name, head); \ - (x) != NULL; \ - (x) = name##_RB_NEXT(head, x)) - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_TREE_H */ diff --git a/usr/src/cmd/ssh/include/tildexpand.h b/usr/src/cmd/ssh/include/tildexpand.h deleted file mode 100644 index 22e95b7779..0000000000 --- a/usr/src/cmd/ssh/include/tildexpand.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* $OpenBSD: tildexpand.h,v 1.4 2001/06/26 17:27:25 markus Exp $ */ - -#ifndef _TILDEXPAND_H -#define _TILDEXPAND_H - -#ifdef __cplusplus -extern "C" { -#endif - -char *tilde_expand_filename(const char *, uid_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _TILDEXPAND_H */ diff --git a/usr/src/cmd/ssh/include/ttymodes.h b/usr/src/cmd/ssh/include/ttymodes.h deleted file mode 100644 index d464e7f308..0000000000 --- a/usr/src/cmd/ssh/include/ttymodes.h +++ /dev/null @@ -1,190 +0,0 @@ -/* $OpenBSD: ttymodes.h,v 1.12 2002/03/04 17:27:39 stevesk Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * NOTE: This file MUST NOT have a header guard added!!! - * - * This header is included twice in ttymodes.c, which defines the TTYCHAR() - * and TTYMODE() macros, used below, twice, once prior to inclusion of this - * file in tty_make_modes() and once prior to inclusion of this file in - * tty_parse_modes(). - */ - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* - * SSH2 tty modes support by Kevin Steves. - * Copyright (c) 2001 Kevin Steves. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * SSH1: - * The tty mode description is a stream of bytes. The stream consists of - * opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0). - * Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer - * arguments. Opcodes 160-255 are not yet defined, and cause parsing to - * stop (they should only be used after any other data). - * - * SSH2: - * Differences between SSH1 and SSH2 terminal mode encoding include: - * 1. Encoded terminal modes are represented as a string, and a stream - * of bytes within that string. - * 2. Opcode arguments are uint32 (1-159); 160-255 remain undefined. - * 3. The values for TTY_OP_ISPEED and TTY_OP_OSPEED are different; - * 128 and 129 vs. 192 and 193 respectively. - * - * The client puts in the stream any modes it knows about, and the - * server ignores any modes it does not know about. This allows some degree - * of machine-independence, at least between systems that use a posix-like - * tty interface. The protocol can support other systems as well, but might - * require reimplementing as mode names would likely be different. - */ - -/* - * Some constants and prototypes are defined in packet.h; this file - * is only intended for including from ttymodes.c. - */ - -/* termios macro */ -/* name, op */ -TTYCHAR(VINTR, 1) -TTYCHAR(VQUIT, 2) -TTYCHAR(VERASE, 3) -#if defined(VKILL) -TTYCHAR(VKILL, 4) -#endif /* VKILL */ -TTYCHAR(VEOF, 5) -#if defined(VEOL) -TTYCHAR(VEOL, 6) -#endif /* VEOL */ -#ifdef VEOL2 -TTYCHAR(VEOL2, 7) -#endif /* VEOL2 */ -TTYCHAR(VSTART, 8) -TTYCHAR(VSTOP, 9) -#if defined(VSUSP) -TTYCHAR(VSUSP, 10) -#endif /* VSUSP */ -#if defined(VDSUSP) -TTYCHAR(VDSUSP, 11) -#endif /* VDSUSP */ -#if defined(VREPRINT) -TTYCHAR(VREPRINT, 12) -#endif /* VREPRINT */ -#if defined(VWERASE) -TTYCHAR(VWERASE, 13) -#endif /* VWERASE */ -#if defined(VLNEXT) -TTYCHAR(VLNEXT, 14) -#endif /* VLNEXT */ -#if defined(VFLUSH) -TTYCHAR(VFLUSH, 15) -#endif /* VFLUSH */ -#ifdef VSWTCH -TTYCHAR(VSWTCH, 16) -#endif /* VSWTCH */ -#if defined(VSTATUS) -TTYCHAR(VSTATUS, 17) -#endif /* VSTATUS */ -#ifdef VDISCARD -TTYCHAR(VDISCARD, 18) -#endif /* VDISCARD */ - -/* name, field, op */ -TTYMODE(IGNPAR, c_iflag, 30) -TTYMODE(PARMRK, c_iflag, 31) -TTYMODE(INPCK, c_iflag, 32) -TTYMODE(ISTRIP, c_iflag, 33) -TTYMODE(INLCR, c_iflag, 34) -TTYMODE(IGNCR, c_iflag, 35) -TTYMODE(ICRNL, c_iflag, 36) -#if defined(IUCLC) -TTYMODE(IUCLC, c_iflag, 37) -#endif -TTYMODE(IXON, c_iflag, 38) -TTYMODE(IXANY, c_iflag, 39) -TTYMODE(IXOFF, c_iflag, 40) -#ifdef IMAXBEL -TTYMODE(IMAXBEL,c_iflag, 41) -#endif /* IMAXBEL */ - -TTYMODE(ISIG, c_lflag, 50) -TTYMODE(ICANON, c_lflag, 51) -#ifdef XCASE -TTYMODE(XCASE, c_lflag, 52) -#endif -TTYMODE(ECHO, c_lflag, 53) -TTYMODE(ECHOE, c_lflag, 54) -TTYMODE(ECHOK, c_lflag, 55) -TTYMODE(ECHONL, c_lflag, 56) -TTYMODE(NOFLSH, c_lflag, 57) -TTYMODE(TOSTOP, c_lflag, 58) -#ifdef IEXTEN -TTYMODE(IEXTEN, c_lflag, 59) -#endif /* IEXTEN */ -#if defined(ECHOCTL) -TTYMODE(ECHOCTL,c_lflag, 60) -#endif /* ECHOCTL */ -#ifdef ECHOKE -TTYMODE(ECHOKE, c_lflag, 61) -#endif /* ECHOKE */ -#if defined(PENDIN) -TTYMODE(PENDIN, c_lflag, 62) -#endif /* PENDIN */ - -TTYMODE(OPOST, c_oflag, 70) -#if defined(OLCUC) -TTYMODE(OLCUC, c_oflag, 71) -#endif -#ifdef ONLCR -TTYMODE(ONLCR, c_oflag, 72) -#endif -#ifdef OCRNL -TTYMODE(OCRNL, c_oflag, 73) -#endif -#ifdef ONOCR -TTYMODE(ONOCR, c_oflag, 74) -#endif -#ifdef ONLRET -TTYMODE(ONLRET, c_oflag, 75) -#endif - -TTYMODE(CS7, c_cflag, 90) -TTYMODE(CS8, c_cflag, 91) -TTYMODE(PARENB, c_cflag, 92) -TTYMODE(PARODD, c_cflag, 93) diff --git a/usr/src/cmd/ssh/include/uidswap.h b/usr/src/cmd/ssh/include/uidswap.h deleted file mode 100644 index 5444f02d32..0000000000 --- a/usr/src/cmd/ssh/include/uidswap.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* $OpenBSD: uidswap.h,v 1.9 2001/06/26 17:27:25 markus Exp $ */ - -#ifndef _UIDSWAP_H -#define _UIDSWAP_H - -#ifdef __cplusplus -extern "C" { -#endif - -void temporarily_use_uid(struct passwd *); -void restore_uid(void); -void permanently_set_uid(struct passwd *, char *); - -#ifdef __cplusplus -} -#endif - -#endif /* _UIDSWAP_H */ diff --git a/usr/src/cmd/ssh/include/uuencode.h b/usr/src/cmd/ssh/include/uuencode.h deleted file mode 100644 index 89ba430779..0000000000 --- a/usr/src/cmd/ssh/include/uuencode.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $OpenBSD: uuencode.h,v 1.9 2002/02/25 16:33:27 markus Exp $ */ - -#ifndef _UUENCODE_H -#define _UUENCODE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -int uuencode(u_char *, u_int, char *, size_t); -int uudecode(const char *, u_char *, size_t); -void dump_base64(FILE *, u_char *, u_int); - -#ifdef __cplusplus -} -#endif - -#endif /* _UUENCODE_H */ diff --git a/usr/src/cmd/ssh/include/version.h b/usr/src/cmd/ssh/include/version.h deleted file mode 100644 index 7d641b6967..0000000000 --- a/usr/src/cmd/ssh/include/version.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* $OpenBSD: version.h,v 1.35 2002/10/01 13:24:50 markus Exp $ */ - -#ifndef _VERSION_H -#define _VERSION_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* #define SSH_VERSION "OpenSSH_3.5p1" */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _VERSION_H */ diff --git a/usr/src/cmd/ssh/include/xlist.h b/usr/src/cmd/ssh/include/xlist.h deleted file mode 100644 index a6675c246b..0000000000 --- a/usr/src/cmd/ssh/include/xlist.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _XLIST_H -#define _XLIST_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -char ** xsplit(char *list, char sep); -char * xjoin(char **alist, char sep); -void xfree_split_list(char **list); - -#ifdef __cplusplus -} -#endif - -#endif /* _XLIST_H */ diff --git a/usr/src/cmd/ssh/include/xmalloc.h b/usr/src/cmd/ssh/include/xmalloc.h deleted file mode 100644 index 6477737a4e..0000000000 --- a/usr/src/cmd/ssh/include/xmalloc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $OpenBSD: xmalloc.h,v 1.9 2002/06/19 00:27:55 deraadt Exp $ */ - -#ifndef _XMALLOC_H -#define _XMALLOC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Created: Mon Mar 20 22:09:17 1995 ylo - * - * Versions of malloc and friends that check their results, and never return - * failure (they call fatal if they encounter an error). - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -void *xmalloc(size_t); -void *xcalloc(size_t, size_t); -void *xrealloc(void *, size_t); -void xfree(void *); -char *xstrdup(const char *); - -#ifdef __cplusplus -} -#endif - -#endif /* _XMALLOC_H */ diff --git a/usr/src/cmd/ssh/include/xmmap.h b/usr/src/cmd/ssh/include/xmmap.h deleted file mode 100644 index 09723b4ecf..0000000000 --- a/usr/src/cmd/ssh/include/xmmap.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _XMMAP_H -#define _XMMAP_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -void *xmmap(size_t size); - -#ifdef __cplusplus -} -#endif - -#endif /* _XMMAP_H */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/Makefile b/usr/src/cmd/ssh/libopenbsd-compat/Makefile deleted file mode 100644 index 75acb9e97b..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (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 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# cmd/ssh/libssh/Makefile - -include $(SRC)/lib/Makefile.lib -include ../Makefile.ssh-common - -SUBDIRS= $(MACH) - -# Need to override the TEXT_DOMAIN here because we included a Makefile from -# usr/src/lib but this is a private library which is part of SUNW_OST_OSCMD -TEXT_DOMAIN= SUNW_OST_OSCMD - -POFILE=_messages.po - -all := TARGET= all -clean := TARGET= clean -clobber := TARGET= clobber -install := TARGET= install -lint := TARGET= lint -$(POFILE) := TARGET= $(POFILE) - -.KEEP_STATE: - -all clean clobber install lint $(POFILE): $(SUBDIRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include $(SRC)/lib/Makefile.targ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com b/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com deleted file mode 100644 index 0b8ad1622b..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com +++ /dev/null @@ -1,92 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/libopenbsd-compat/Makefile.com -# - -LIBRARY = libopenbsd-compat.a -VERS = .1 - -OBJECTS = \ - bsd-arc4random.o \ - bsd-cray.o \ - bsd-cygwin_util.o \ - bsd-getpeereid.o \ - bsd-misc.o \ - bsd-asprintf.o \ - bsd-snprintf.o \ - bsd-waitpid.o \ - fake-getaddrinfo.o \ - fake-getnameinfo.o \ - xmmap.o \ - base64.o \ - bindresvport.o \ - dirname.o \ - getcwd.o \ - getgrouplist.o \ - getopt.o \ - glob.o \ - inet_aton.o \ - inet_ntoa.o \ - inet_ntop.o \ - mktemp.o \ - readpassphrase.o \ - realpath.o \ - rresvport.o \ - setenv.o \ - setproctitle.o \ - sigact.o \ - strlcat.o \ - strlcpy.o \ - strmode.o \ - port-irix.o \ - port-aix.o - -include $(SRC)/lib/Makefile.lib - -BUILD.AR = $(RM) $@ ; $(AR) $(ARFLAGS) $@ $(AROBJS) - -SRCDIR = ../common -SRCS = $(OBJECTS:%.o=../common/%.c) - -LIBS = $(LIBRARY) $(LINTLIB) - -$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) - -POFILE_DIR = ../.. - -.KEEP_STATE: - -all: $(LIBS) - -# lint requires the (non-installed) lint library -lint: $(LINTLIB) .WAIT lintcheck - -include $(SRC)/lib/Makefile.targ - -objs/%.o: $(SRCDIR)/%.c - $(COMPILE.c) -o $@ $< - $(POST_PROCESS_O) - -include ../../Makefile.ssh-common -include ../../Makefile.msg.targ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/base64.c b/usr/src/cmd/ssh/libopenbsd-compat/common/base64.c deleted file mode 100644 index 62776ce4e0..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/base64.c +++ /dev/null @@ -1,319 +0,0 @@ -/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */ - -/* - * Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Portions Copyright (c) 1995 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. - * - * To the extent it has a right to do so, IBM grants an immunity from suit - * under its patents, if any, for the use, sale or manufacture of products to - * the extent that such products are used for performing Domain Name System - * dynamic updates in TCP/IP networks by means of the Software. No immunity is - * granted for any product per se or for any other function of any product. - * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <ctype.h> -#include <stdio.h> - -#include <stdlib.h> -#include <string.h> - -#include "base64.h" - -/* XXX abort illegal in library */ -#define Assert(Cond) if (!(Cond)) abort() - -static const char Base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char Pad64 = '='; - -/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) - The following encoding technique is taken from RFC 1521 by Borenstein - and Freed. It is reproduced here in a slightly edited form for - convenience. - - A 65-character subset of US-ASCII is used, enabling 6 bits to be - represented per printable character. (The extra 65th character, "=", - is used to signify a special processing function.) - - The encoding process represents 24-bit groups of input bits as output - strings of 4 encoded characters. Proceeding from left to right, a - 24-bit input group is formed by concatenating 3 8-bit input groups. - These 24 bits are then treated as 4 concatenated 6-bit groups, each - of which is translated into a single digit in the base64 alphabet. - - Each 6-bit group is used as an index into an array of 64 printable - characters. The character referenced by the index is placed in the - output string. - - Table 1: The Base64 Alphabet - - Value Encoding Value Encoding Value Encoding Value Encoding - 0 A 17 R 34 i 51 z - 1 B 18 S 35 j 52 0 - 2 C 19 T 36 k 53 1 - 3 D 20 U 37 l 54 2 - 4 E 21 V 38 m 55 3 - 5 F 22 W 39 n 56 4 - 6 G 23 X 40 o 57 5 - 7 H 24 Y 41 p 58 6 - 8 I 25 Z 42 q 59 7 - 9 J 26 a 43 r 60 8 - 10 K 27 b 44 s 61 9 - 11 L 28 c 45 t 62 + - 12 M 29 d 46 u 63 / - 13 N 30 e 47 v - 14 O 31 f 48 w (pad) = - 15 P 32 g 49 x - 16 Q 33 h 50 y - - Special processing is performed if fewer than 24 bits are available - at the end of the data being encoded. A full encoding quantum is - always completed at the end of a quantity. When fewer than 24 input - bits are available in an input group, zero bits are added (on the - right) to form an integral number of 6-bit groups. Padding at the - end of the data is performed using the '=' character. - - Since all base64 input is an integral number of octets, only the - ------------------------------------------------- - following cases can arise: - - (1) the final quantum of encoding input is an integral - multiple of 24 bits; here, the final unit of encoded - output will be an integral multiple of 4 characters - with no "=" padding, - (2) the final quantum of encoding input is exactly 8 bits; - here, the final unit of encoded output will be two - characters followed by two "=" padding characters, or - (3) the final quantum of encoding input is exactly 16 bits; - here, the final unit of encoded output will be three - characters followed by one "=" padding character. - */ - -int -b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) -{ - size_t datalength = 0; - u_char input[3]; - u_char output[4]; - int i; - - while (2 < srclength) { - input[0] = *src++; - input[1] = *src++; - input[2] = *src++; - srclength -= 3; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - output[3] = input[2] & 0x3f; - Assert(output[0] < 64); - Assert(output[1] < 64); - Assert(output[2] < 64); - Assert(output[3] < 64); - - if (datalength + 4 > targsize) - return (-1); - target[datalength++] = Base64[output[0]]; - target[datalength++] = Base64[output[1]]; - target[datalength++] = Base64[output[2]]; - target[datalength++] = Base64[output[3]]; - } - - /* Now we worry about padding. */ - if (0 != srclength) { - /* Get what's left. */ - input[0] = input[1] = input[2] = '\0'; - for (i = 0; i < srclength; i++) - input[i] = *src++; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - Assert(output[0] < 64); - Assert(output[1] < 64); - Assert(output[2] < 64); - - if (datalength + 4 > targsize) - return (-1); - target[datalength++] = Base64[output[0]]; - target[datalength++] = Base64[output[1]]; - if (srclength == 1) - target[datalength++] = Pad64; - else - target[datalength++] = Base64[output[2]]; - target[datalength++] = Pad64; - } - if (datalength >= targsize) - return (-1); - target[datalength] = '\0'; /* Returned value doesn't count \0. */ - return (datalength); -} - -/* skips all whitespace anywhere. - converts characters, four at a time, starting at (or after) - src from base - 64 numbers into three 8 bit bytes in the target area. - it returns the number of data bytes stored at the target, or -1 on error. - */ - -int -b64_pton(u_char const *src, u_char *target, size_t targsize) -{ - int tarindex, state, ch; - char *pos; - - state = 0; - tarindex = 0; - - while ((ch = *src++) != '\0') { - if (isspace(ch)) /* Skip whitespace anywhere. */ - continue; - - if (ch == Pad64) - break; - - pos = strchr(Base64, ch); - if (pos == 0) /* A non-base64 character. */ - return (-1); - - switch (state) { - case 0: - if (target) { - if (tarindex >= targsize) - return (-1); - target[tarindex] = (pos - Base64) << 2; - } - state = 1; - break; - case 1: - if (target) { - if (tarindex + 1 >= targsize) - return (-1); - target[tarindex] |= (pos - Base64) >> 4; - target[tarindex+1] = ((pos - Base64) & 0x0f) - << 4 ; - } - tarindex++; - state = 2; - break; - case 2: - if (target) { - if (tarindex + 1 >= targsize) - return (-1); - target[tarindex] |= (pos - Base64) >> 2; - target[tarindex+1] = ((pos - Base64) & 0x03) - << 6; - } - tarindex++; - state = 3; - break; - case 3: - if (target) { - if (tarindex >= targsize) - return (-1); - target[tarindex] |= (pos - Base64); - } - tarindex++; - state = 0; - break; - } - } - - /* - * We are done decoding Base-64 chars. Let's see if we ended - * on a byte boundary, and/or with erroneous trailing characters. - */ - - if (ch == Pad64) { /* We got a pad char. */ - ch = *src++; /* Skip it, get next. */ - switch (state) { - case 0: /* Invalid = in first position */ - case 1: /* Invalid = in second position */ - return (-1); - - case 2: /* Valid, means one byte of info */ - /* Skip any number of spaces. */ - for (; ch != '\0'; ch = *src++) - if (!isspace(ch)) - break; - /* Make sure there is another trailing = sign. */ - if (ch != Pad64) - return (-1); - ch = *src++; /* Skip the = */ - /* Fall through to "single trailing =" case. */ - /* FALLTHROUGH */ - - case 3: /* Valid, means two bytes of info */ - /* - * We know this char is an =. Is there anything but - * whitespace after it? - */ - for (; ch != '\0'; ch = *src++) - if (!isspace(ch)) - return (-1); - - /* - * Now make sure for cases 2 and 3 that the "extra" - * bits that slopped past the last full byte were - * zeros. If we don't check them, they become a - * subliminal channel. - */ - if (target && target[tarindex] != 0) - return (-1); - } - } else { - /* - * We ended by seeing the end of the string. Make sure we - * have no partial bytes lying around. - */ - if (state != 0) - return (-1); - } - - return (tarindex); -} - -#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bindresvport.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bindresvport.c deleted file mode 100644 index 8432233bb6..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bindresvport.c +++ /dev/null @@ -1,127 +0,0 @@ -/* This file has be modified from the original OpenBSD source */ - -/* - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user. - * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -#include "includes.h" - -#ifndef HAVE_BINDRESVPORT_SA - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: bindresvport.c,v 1.13 2000/01/26 03:43:21 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -/* - * Copyright (c) 1987 by Sun Microsystems, Inc. - * - * Portions Copyright(C) 1996, Jason Downs. All rights reserved. - */ - -#include "includes.h" - -#define STARTPORT 600 -#define ENDPORT (IPPORT_RESERVED - 1) -#define NPORTS (ENDPORT - STARTPORT + 1) - -/* - * Bind a socket to a privileged IP port - */ -int -bindresvport_sa(sd, sa) - int sd; - struct sockaddr *sa; -{ - int error, af; - struct sockaddr_storage myaddr; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - u_int16_t *portp; - u_int16_t port; - socklen_t salen; - int i; - - if (sa == NULL) { - memset(&myaddr, 0, sizeof(myaddr)); - sa = (struct sockaddr *)&myaddr; - - if (getsockname(sd, sa, &salen) == -1) - return -1; /* errno is correctly set */ - - af = sa->sa_family; - memset(&myaddr, 0, salen); - } else - af = sa->sa_family; - - if (af == AF_INET) { - /* LINTED */ - sin = (struct sockaddr_in *)sa; - salen = sizeof(struct sockaddr_in); - portp = &sin->sin_port; - } else if (af == AF_INET6) { - /* LINTED */ - sin6 = (struct sockaddr_in6 *)sa; - salen = sizeof(struct sockaddr_in6); - portp = &sin6->sin6_port; - } else { - errno = EPFNOSUPPORT; - return (-1); - } - sa->sa_family = af; - - port = ntohs(*portp); - if (port == 0) - port = (arc4random() % NPORTS) + STARTPORT; - - /* Avoid warning */ - error = -1; - - for(i = 0; i < NPORTS; i++) { - *portp = htons(port); - - error = bind(sd, sa, salen); - - /* Terminate on success */ - if (error == 0) - break; - - /* Terminate on errors, except "address already in use" */ - if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) - break; - - port++; - if (port > ENDPORT) - port = STARTPORT; - } - - return (error); -} - -#endif /* HAVE_BINDRESVPORT_SA */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-arc4random.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-arc4random.c deleted file mode 100644 index 3dac16f70a..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-arc4random.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 1999-2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#include "log.h" - -RCSID("$Id: bsd-arc4random.c,v 1.5 2002/05/08 22:57:18 tim Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef HAVE_ARC4RANDOM - -#include <openssl/rand.h> -#include <openssl/rc4.h> -#include <openssl/err.h> - -/* Size of key to use */ -#define SEED_SIZE 20 - -/* Number of bytes to reseed after */ -#define REKEY_BYTES (1 << 24) - -static int rc4_ready = 0; -static RC4_KEY rc4; - -unsigned int arc4random(void) -{ - unsigned int r = 0; - static int first_time = 1; - - if (rc4_ready <= 0) { - if (first_time) - seed_rng(); - first_time = 0; - arc4random_stir(); - } - - RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); - - rc4_ready -= sizeof(r); - - return(r); -} - -void arc4random_stir(void) -{ - unsigned char rand_buf[SEED_SIZE]; - - memset(&rc4, 0, sizeof(rc4)); - if (!RAND_bytes(rand_buf, sizeof(rand_buf))) - fatal("Couldn't obtain random bytes (error %ld)", - ERR_get_error()); - RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); - memset(rand_buf, 0, sizeof(rand_buf)); - - rc4_ready = REKEY_BYTES; -} -#endif /* !HAVE_ARC4RANDOM */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c deleted file mode 100644 index f06e7415de..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2004 Darren Tucker. - * - * Based originally on asprintf.c from OpenBSD: - * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#ifndef HAVE_VASPRINTF - -#include <errno.h> -#include <stdarg.h> -#include <stdlib.h> - -#ifndef VA_COPY -#ifdef HAVE_VA_COPY -#define VA_COPY(dest, src) va_copy(dest, src) -#else -#ifdef HAVE___VA_COPY -#define VA_COPY(dest, src) __va_copy(dest, src) -#else -#define VA_COPY(dest, src) (dest) = (src) -#endif -#endif -#endif - -#define INIT_SZ 128 - -int -vasprintf(char **str, const char *fmt, va_list ap) -{ - int ret = -1; - va_list ap2; - char *string, *newstr; - size_t len; - - VA_COPY(ap2, ap); - if ((string = malloc(INIT_SZ)) == NULL) - goto fail; - - ret = vsnprintf(string, INIT_SZ, fmt, ap2); - if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ - *str = string; - } else if (ret == INT_MAX || ret < 0) { /* Bad length */ - free(string); - goto fail; - } else { /* bigger than initial, realloc allowing for nul */ - len = (size_t)ret + 1; - if ((newstr = realloc(string, len)) == NULL) { - free(string); - goto fail; - } else { - va_end(ap2); - VA_COPY(ap2, ap); - ret = vsnprintf(newstr, len, fmt, ap2); - if (ret >= 0 && (size_t)ret < len) { - *str = newstr; - } else { /* failed with realloc'ed string, give up */ - free(newstr); - goto fail; - } - } - } - va_end(ap2); - return (ret); - -fail: - *str = NULL; - errno = ENOMEM; - va_end(ap2); - return (-1); -} -#endif - -#ifndef HAVE_ASPRINTF -int -asprintf(char **str, const char *fmt, ...) -{ - va_list ap; - int ret; - - *str = NULL; - va_start(ap, fmt); - ret = vasprintf(str, fmt, ap); - va_end(ap); - - return (ret); -} -#endif diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-cray.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-cray.c deleted file mode 100644 index dd3bd2cac5..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-cray.c +++ /dev/null @@ -1,802 +0,0 @@ -/* - * $Id: bsd-cray.c,v 1.8 2002/09/26 00:38:51 tim Exp $ - * - * bsd-cray.c - * - * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>) - * Significant portions provided by - * Wayne Schroeder, SDSC <schroeder@sdsc.edu> - * William Jones, UTexas <jones@tacc.utexas.edu> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Created: Apr 22 16.34:00 2002 wp - * - * This file contains functions required for proper execution - * on UNICOS systems. - * - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#ifdef _UNICOS - -#include <udb.h> -#include <tmpdir.h> -#include <unistd.h> -#include <sys/category.h> -#include <utmp.h> -#include <sys/jtab.h> -#include <signal.h> -#include <sys/priv.h> -#include <sys/secparm.h> -#include <sys/tfm.h> -#include <sys/usrv.h> -#include <sys/sysv.h> -#include <sys/sectab.h> -#include <sys/secstat.h> -#include <sys/stat.h> -#include <sys/session.h> -#include <stdlib.h> -#include <pwd.h> -#include <fcntl.h> -#include <errno.h> -#include <ia.h> -#include <urm.h> -#include "ssh.h" -#include "log.h" -#include "servconf.h" -#include "bsd-cray.h" - -#define MAXACID 80 - -extern ServerOptions options; - -char cray_tmpdir[TPATHSIZ+1]; /* job TMPDIR path */ - -struct sysv sysv; /* system security structure */ -struct usrv usrv; /* user security structure */ - -/* - * Functions. - */ -void cray_retain_utmp(struct utmp *, int); -void cray_delete_tmpdir(char *, int, uid_t); -void cray_init_job(struct passwd *); -void cray_set_tmpdir(struct utmp *); -void cray_login_failure(char *, int); -int cray_setup(uid_t, char *, const char *); -int cray_access_denied(char *); - -void -cray_login_failure(char *username, int errcode) -{ - struct udb *ueptr; /* UDB pointer for username */ - ia_failure_t fsent; /* ia_failure structure */ - ia_failure_ret_t fret; /* ia_failure return stuff */ - struct jtab jtab; /* job table structure */ - int jid = 0; /* job id */ - - if ((jid = getjtab(&jtab)) < 0) { - debug("cray_login_failure(): getjtab error"); - } - getsysudb(); - if ((ueptr = getudbnam(username)) == UDB_NULL) { - debug("cray_login_failure(): getudbname() returned NULL"); - } - endudb(); - fsent.revision = 0; - fsent.uname = username; - fsent.host = (char *)get_canonical_hostname(options.verify_reverse_mapping); - fsent.ttyn = "sshd"; - fsent.caller = IA_SSHD; - fsent.flags = IA_INTERACTIVE; - fsent.ueptr = ueptr; - fsent.jid = jid; - fsent.errcode = errcode; - fsent.pwdp = NULL; - fsent.exitcode = 0; /* dont exit in ia_failure() */ - - fret.revision = 0; - fret.normal = 0; - - /* - * Call ia_failure because of an login failure. - */ - ia_failure(&fsent,&fret); -} - -/* - * Cray access denied - */ -int -cray_access_denied(char *username) -{ - struct udb *ueptr; /* UDB pointer for username */ - int errcode; /* IA errorcode */ - - errcode = 0; - getsysudb(); - if ((ueptr = getudbnam(username)) == UDB_NULL) { - debug("cray_login_failure(): getudbname() returned NULL"); - } - endudb(); - if (ueptr && ueptr->ue_disabled) - errcode = IA_DISABLED; - if (errcode) - cray_login_failure(username, errcode); - return (errcode); -} - -int -cray_setup (uid_t uid, char *username, const char *command) -{ - extern struct udb *getudb(); - extern char *setlimits(); - - int err; /* error return */ - time_t system_time; /* current system clock */ - time_t expiration_time; /* password expiration time */ - int maxattempts; /* maximum no. of failed login attempts */ - int SecureSys; /* unicos security flag */ - int minslevel = 0; /* system minimum security level */ - int i, j; - int valid_acct = -1; /* flag for reading valid acct */ - char acct_name[MAXACID] = { "" }; /* used to read acct name */ - struct jtab jtab; /* Job table struct */ - struct udb ue; /* udb entry for logging-in user */ - struct udb *up; /* pointer to UDB entry */ - struct secstat secinfo; /* file security attributes */ - struct servprov init_info; /* used for sesscntl() call */ - int jid; /* job ID */ - int pid; /* process ID */ - char *sr; /* status return from setlimits() */ - char *ttyn = NULL; /* ttyname or command name*/ - char hostname[MAXHOSTNAMELEN]; - passwd_t pwdacm, - pwddialup, - pwdudb, - pwdwal, - pwddce; /* passwd stuff for ia_user */ - ia_user_ret_t uret; /* stuff returned from ia_user */ - ia_user_t usent; /* ia_user main structure */ - int ia_rcode; /* ia_user return code */ - ia_failure_t fsent; /* ia_failure structure */ - ia_failure_ret_t fret; /* ia_failure return stuff */ - ia_success_t ssent; /* ia_success structure */ - ia_success_ret_t sret; /* ia_success return stuff */ - int ia_mlsrcode; /* ia_mlsuser return code */ - int secstatrc; /* [f]secstat return code */ - - if (SecureSys = (int)sysconf(_SC_CRAY_SECURE_SYS)) { - getsysv(&sysv, sizeof(struct sysv)); - minslevel = sysv.sy_minlvl; - if (getusrv(&usrv) < 0) { - debug("getusrv() failed, errno = %d",errno); - exit(1); - } - } - hostname[0] = '\0'; - strncpy(hostname, - (char *)get_canonical_hostname(options.verify_reverse_mapping), - MAXHOSTNAMELEN); - /* - * Fetch user's UDB entry. - */ - getsysudb(); - if ((up = getudbnam(username)) == UDB_NULL) { - debug("cannot fetch user's UDB entry"); - exit(1); - } - - /* - * Prevent any possible fudging so perform a data - * safety check and compare the supplied uid against - * the udb's uid. - */ - if (up->ue_uid != uid) { - debug("IA uid missmatch"); - exit(1); - } - endudb(); - - if ((jid = getjtab (&jtab)) < 0) { - debug("getjtab"); - return -1; - } - pid = getpid(); - ttyn = ttyname(0); - if (SecureSys) { - if (ttyn) { - secstatrc = secstat(ttyn, &secinfo); - } else { - secstatrc = fsecstat(1, &secinfo); - } - if (secstatrc == 0) { - debug("[f]secstat() successful"); - } else { - debug("[f]secstat() error, rc = %d", secstatrc); - exit(1); - } - } - if ((ttyn == NULL) && ((char *)command != NULL)) - ttyn = (char *)command; - /* - * Initialize all structures to call ia_user - */ - usent.revision = 0; - usent.uname = username; - usent.host = hostname; - usent.ttyn = ttyn; - usent.caller = IA_SSHD; - usent.pswdlist = &pwdacm; - usent.ueptr = &ue; - usent.flags = IA_INTERACTIVE | IA_FFLAG; - pwdacm.atype = IA_SECURID; - pwdacm.pwdp = NULL; - pwdacm.next = &pwdudb; - - pwdudb.atype = IA_UDB; - pwdudb.pwdp = NULL; - pwdudb.next = &pwddce; - - pwddce.atype = IA_DCE; - pwddce.pwdp = NULL; - pwddce.next = &pwddialup; - - pwddialup.atype = IA_DIALUP; - pwddialup.pwdp = NULL; - /* pwddialup.next = &pwdwal; */ - pwddialup.next = NULL; - - pwdwal.atype = IA_WAL; - pwdwal.pwdp = NULL; - pwdwal.next = NULL; - - uret.revision = 0; - uret.pswd = NULL; - uret.normal = 0; - - ia_rcode = ia_user(&usent, &uret); - - switch (ia_rcode) { - /* - * These are acceptable return codes from ia_user() - */ - case IA_UDBWEEK: /* Password Expires in 1 week */ - expiration_time = ue.ue_pwage.time + ue.ue_pwage.maxage; - printf ("WARNING - your current password will expire %s\n", - ctime((const time_t *)&expiration_time)); - break; - case IA_UDBEXPIRED: - if (ttyname(0) != NULL) { - /* Force a password change */ - printf("Your password has expired; Choose a new one.\n"); - execl("/bin/passwd", "passwd", username, 0); - exit(9); - } - - break; - case IA_NORMAL: /* Normal Return Code */ - break; - case IA_BACKDOOR: - strcpy(ue.ue_name, "root"); - strcpy(ue.ue_passwd, ""); - strcpy(ue.ue_dir, "/"); - strcpy(ue.ue_shell, "/bin/sh"); - strcpy(ue.ue_age, ""); - strcpy(ue.ue_comment, ""); - strcpy(ue.ue_loghost, ""); - strcpy(ue.ue_logline, ""); - ue.ue_uid=-1; - ue.ue_nice[UDBRC_INTER]=0; - for (i=0;i<MAXVIDS;i++) - ue.ue_gids[i]=0; - ue.ue_logfails=0; - ue.ue_minlvl=minslevel; - ue.ue_maxlvl=minslevel; - ue.ue_deflvl=minslevel; - ue.ue_defcomps=0; - ue.ue_comparts=0; - ue.ue_permits=0; - ue.ue_trap=0; - ue.ue_disabled=0; - ue.ue_logtime=0; - break; - case IA_CONSOLE: /* Superuser not from Console */ - case IA_TRUSTED: /* Trusted user */ - if (options.permit_root_login > PERMIT_NO) - break; /* Accept root login */ - default: - /* - * These are failed return codes from ia_user() - */ - switch (ia_rcode) - { - case IA_BADAUTH: - printf ("Bad authorization, access denied.\n"); - break; - case IA_DIALUPERR: - break; - case IA_DISABLED: - printf ("Your login has been disabled. Contact the system "); - printf ("administrator for assistance.\n"); - break; - case IA_GETSYSV: - printf ("getsysv() failed - errno = %d\n", errno); - break; - case IA_LOCALHOST: - break; - case IA_MAXLOGS: - printf ("Maximum number of failed login attempts exceeded.\n"); - printf ("Access denied.\n"); - break; - case IA_NOPASS: - break; - case IA_PUBLIC: - break; - case IA_SECURIDERR: - break; - case IA_CONSOLE: - break; - case IA_TRUSTED: - break; - case IA_UDBERR: - break; - case IA_UDBPWDNULL: - /* - * NULL password not allowed on MLS systems - */ - if (SecureSys) { - printf("NULL Password not allowed on MLS systems.\n"); - } - break; - case IA_UNKNOWN: - break; - case IA_UNKNOWNYP: - break; - case IA_WALERR: - break; - default: - /* nothing special */ - ; - } /* 2. switch (ia_rcode) */ - /* - * Authentication failed. - */ - printf("sshd: Login incorrect, (0%o)\n", - ia_rcode-IA_ERRORCODE); - - /* - * Initialize structure for ia_failure - * which will exit. - */ - fsent.revision = 0; - fsent.uname = username; - fsent.host = hostname; - fsent.ttyn = ttyn; - fsent.caller = IA_SSHD; - fsent.flags = IA_INTERACTIVE; - fsent.ueptr = &ue; - fsent.jid = jid; - fsent.errcode = ia_rcode; - fsent.pwdp = uret.pswd; - fsent.exitcode = 1; - - fret.revision = 0; - fret.normal = 0; - - /* - * Call ia_failure because of an IA failure. - * There is no return because ia_failure exits. - */ - - ia_failure(&fsent,&fret); - - exit(1); - } /* 1. switch (ia_rcode) */ - ia_mlsrcode = IA_NORMAL; - if (SecureSys) { - debug("calling ia_mlsuser()"); - ia_mlsrcode = ia_mlsuser (&ue, &secinfo, &usrv, NULL, 0); - } - if (ia_mlsrcode != IA_NORMAL) { - printf("sshd: Login incorrect, (0%o)\n", - ia_mlsrcode-IA_ERRORCODE); - /* - * Initialize structure for ia_failure - * which will exit. - */ - fsent.revision = 0; - fsent.uname = username; - fsent.host = hostname; - fsent.ttyn = ttyn; - fsent.caller = IA_SSHD; - fsent.flags = IA_INTERACTIVE; - fsent.ueptr = &ue; - fsent.jid = jid; - fsent.errcode = ia_mlsrcode; - fsent.pwdp = uret.pswd; - fsent.exitcode = 1; - fret.revision = 0; - fret.normal = 0; - - /* - * Call ia_failure because of an IA failure. - * There is no return because ia_failure exits. - */ - ia_failure(&fsent,&fret); - exit(1); - } - - /* Provide login status information */ - if (options.print_lastlog && ue.ue_logtime != 0) { - printf("Last successful login was : %.*s ", - 19, (char *)ctime(&ue.ue_logtime)); - - if (*ue.ue_loghost != '\0') - printf("from %.*s\n", sizeof(ue.ue_loghost), ue.ue_loghost); - - else printf("on %.*s\n", sizeof(ue.ue_logline), ue.ue_logline); - - if ( SecureSys && (ue.ue_logfails != 0)) - printf(" followed by %d failed attempts\n", ue.ue_logfails); - } - - - /* - * Call ia_success to process successful I/A. - */ - ssent.revision = 0; - ssent.uname = username; - ssent.host = hostname; - ssent.ttyn = ttyn; - ssent.caller = IA_SSHD; - ssent.flags = IA_INTERACTIVE; - ssent.ueptr = &ue; - ssent.jid = jid; - ssent.errcode = ia_rcode; - ssent.us = NULL; - ssent.time = 1; /* Set ue_logtime */ - - sret.revision = 0; - sret.normal = 0; - - ia_success(&ssent,&sret); - - /* - * Query for account, iff > 1 valid acid & askacid permbit - */ - if (((ue.ue_permbits & PERMBITS_ACCTID) || - (ue.ue_acids[0] >= 0) && (ue.ue_acids[1] >= 0)) && - ue.ue_permbits & PERMBITS_ASKACID) { - if (ttyname(0) != NULL) { - debug("cray_setup: ttyname true case, %.100s", ttyname); - while (valid_acct == -1) { - printf("Account (? for available accounts)" - " [%s]: ", acid2nam(ue.ue_acids[0])); - gets(acct_name); - switch (acct_name[0]) { - case EOF: - exit(0); - break; - case '\0': - valid_acct = ue.ue_acids[0]; - strcpy(acct_name, acid2nam(valid_acct)); - break; - case '?': - /* Print the list 3 wide */ - for (i = 0, j = 0; i < MAXVIDS; i++) { - if (ue.ue_acids[i] == -1) { - printf("\n"); - break; - } - if (++j == 4) { - j = 1; - printf("\n"); - } - printf(" %s", - acid2nam(ue.ue_acids[i])); - } - if (ue.ue_permbits & PERMBITS_ACCTID) - printf("\"acctid\" permbit also allows" - " you to select any valid " - "account name.\n"); - printf("\n"); - break; - default: - if ((valid_acct = nam2acid(acct_name)) == -1) printf("Account id not found for" - " account name \"%s\"\n\n", - acct_name); - break; - } - /* - * If an account was given, search the user's - * acids array to verify they can use this account. - */ - if ((valid_acct != -1) && - !(ue.ue_permbits & PERMBITS_ACCTID)) { - for (i = 0; i < MAXVIDS; i++) { - if (ue.ue_acids[i] == -1) - break; - if (valid_acct == ue.ue_acids[i]) - break; - } - if (i == MAXVIDS || - ue.ue_acids[i] == -1) { - fprintf(stderr, "Cannot set" - " account name to " - "\"%s\", permission " - "denied\n\n", acct_name); - valid_acct = -1; - } - } - } - } else { - /* - * The client isn't connected to a terminal and can't - * respond to an acid prompt. Use default acid. - */ - debug("cray_setup: ttyname false case, %.100s", ttyname); - valid_acct = ue.ue_acids[0]; - } - } else { - /* - * The user doesn't have the askacid permbit set or - * only has one valid account to use. - */ - valid_acct = ue.ue_acids[0]; - } - if (acctid(0, valid_acct) < 0) { - printf ("Bad account id: %d\n", valid_acct); - exit(1); - } - -/* set up shares and quotas */ -/* Now set shares, quotas, limits, including CPU time for the (interactive) - * job and process, and set up permissions (for chown etc), etc. - */ - if (setshares(ue.ue_uid, valid_acct, printf, 0, 0)) { - printf("Unable to give %d shares to <%s>(%d/%d)\n", ue.ue_shares, ue.ue_name, ue.ue_uid, valid_acct); - exit(1); - } - - sr = setlimits(username, C_PROC, pid, UDBRC_INTER); - if (sr != NULL) { - debug("%.200s", sr); - exit(1); - } - sr = setlimits(username, C_JOB, jid, UDBRC_INTER); - if (sr != NULL) { - debug("%.200s", sr); - exit(1); - } - /* - * Place the service provider information into - * the session table (Unicos) or job table (Unicos/mk). - * There exist double defines for the job/session table in - * unicos/mk (jtab.h) so no need for a compile time switch. - */ - bzero((char *)&init_info, sizeof(struct servprov)); - init_info.s_sessinit.si_id = URM_SPT_LOGIN; - init_info.s_sessinit.si_pid = getpid(); - init_info.s_sessinit.si_sid = jid; - init_info.s_routing.seqno = 0; - init_info.s_routing.iadrs = 0; - sesscntl(0, S_SETSERVPO, (int)&init_info); - - /* - * Set user and controlling tty security attributes. - */ - if (SecureSys) { - if (setusrv(&usrv) == -1) { - debug("setusrv() failed, errno = %d",errno); - exit(1); - } - } - - return(0); -} - -/* - * The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk - * can have pal privileges that sshd can inherit which - * could allow a user to su to root with out a password. - * This subroutine clears all privileges. - */ -void -drop_cray_privs() -{ -#if defined(_SC_CRAY_PRIV_SU) - priv_proc_t* privstate; - int result; - extern int priv_set_proc(); - extern priv_proc_t* priv_init_proc(); - - /* - * If ether of theses two flags are not set - * then don't allow this version of ssh to run. - */ - if (!sysconf(_SC_CRAY_PRIV_SU)) - fatal("Not PRIV_SU system."); - if (!sysconf(_SC_CRAY_POSIX_PRIV)) - fatal("Not POSIX_PRIV."); - - debug("Setting MLS labels.");; - - if (sysconf(_SC_CRAY_SECURE_MAC)) { - usrv.sv_minlvl = SYSLOW; - usrv.sv_actlvl = SYSHIGH; - usrv.sv_maxlvl = SYSHIGH; - } else { - usrv.sv_minlvl = sysv.sy_minlvl; - usrv.sv_actlvl = sysv.sy_minlvl; - usrv.sv_maxlvl = sysv.sy_maxlvl; - } - usrv.sv_actcmp = 0; - usrv.sv_valcmp = sysv.sy_valcmp; - - usrv.sv_intcat = TFM_SYSTEM; - usrv.sv_valcat |= (TFM_SYSTEM | TFM_SYSFILE); - - if (setusrv(&usrv) < 0) - fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__, - strerror(errno)); - - if ((privstate = priv_init_proc()) != NULL) { - result = priv_set_proc(privstate); - if (result != 0 ) - fatal("%s(%d): priv_set_proc(): %s", - __FILE__, __LINE__, strerror(errno)); - priv_free_proc(privstate); - } - debug ("Privileges should be cleared..."); -#else - /* XXX: do this differently */ -# error Cray systems must be run with _SC_CRAY_PRIV_SU on! -#endif -} - - -/* - * Retain utmp/wtmp information - used by cray accounting. - */ -void -cray_retain_utmp(struct utmp *ut, int pid) -{ - int fd; - struct utmp utmp; - - if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) { - while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) { - if (pid == utmp.ut_pid) { - ut->ut_jid = utmp.ut_jid; - strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath)); - strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host)); - strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name)); - break; - } - } - close(fd); - } - else - fatal("Unable to open utmp file"); -} - -/* - * tmpdir support. - */ - -/* - * find and delete jobs tmpdir. - */ -void -cray_delete_tmpdir(char *login, int jid, uid_t uid) -{ - int child; - static char jtmp[TPATHSIZ]; - struct stat statbuf; - int c; - int wstat; - - for (c = 'a'; c <= 'z'; c++) { - snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); - if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid) - break; - } - - if (c > 'z') - return; - - if ((child = fork()) == 0) { - execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL); - fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed"); - } - - while (waitpid(child, &wstat, 0) == -1 && errno == EINTR) - ; -} - -/* - * Remove tmpdir on job termination. - */ -void -cray_job_termination_handler(int sig) -{ - int jid; - char *login = NULL; - struct jtab jtab; - - debug("received signal %d",sig); - - if ((jid = waitjob(&jtab)) == -1 || - (login = uid2nam(jtab.j_uid)) == NULL) - return; - - cray_delete_tmpdir(login, jid, jtab.j_uid); -} - -/* - * Set job id and create tmpdir directory. - */ -void -cray_init_job(struct passwd *pw) -{ - int jid; - int c; - - jid = setjob(pw->pw_uid, WJSIGNAL); - if (jid < 0) - fatal("System call setjob failure"); - - for (c = 'a'; c <= 'z'; c++) { - snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); - if (mkdir(cray_tmpdir, JTMPMODE) != 0) - continue; - if (chown(cray_tmpdir, pw->pw_uid, pw->pw_gid) != 0) { - rmdir(cray_tmpdir); - continue; - } - break; - } - - if (c > 'z') - cray_tmpdir[0] = '\0'; -} - -void -cray_set_tmpdir(struct utmp *ut) -{ - int jid; - struct jtab jbuf; - - if ((jid = getjtab(&jbuf)) < 0) - return; - - /* - * Set jid and tmpdir in utmp record. - */ - ut->ut_jid = jid; - strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ); -} -#endif diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-cygwin_util.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-cygwin_util.c deleted file mode 100644 index 5e31351628..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-cygwin_util.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * cygwin_util.c - * - * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Created: Sat Sep 02 12:17:00 2000 cv - * - * This file contains functions for forcing opened file descriptors to - * binary mode on Windows systems. - */ - -#include "includes.h" - -RCSID("$Id: bsd-cygwin_util.c,v 1.8 2002/04/15 22:00:52 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef HAVE_CYGWIN - -#include <fcntl.h> -#include <stdlib.h> -#include <sys/utsname.h> -#include <sys/vfs.h> -#include <windows.h> -#define is_winnt (GetVersion() < 0x80000000) - -#define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec")) -#define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea")) - -#if defined(open) && open == binary_open -# undef open -#endif -#if defined(pipe) && open == binary_pipe -# undef pipe -#endif - -int binary_open(const char *filename, int flags, ...) -{ - va_list ap; - mode_t mode; - - va_start(ap, flags); - mode = va_arg(ap, mode_t); - va_end(ap); - return open(filename, flags | O_BINARY, mode); -} - -int binary_pipe(int fd[2]) -{ - int ret = pipe(fd); - - if (!ret) { - setmode (fd[0], O_BINARY); - setmode (fd[1], O_BINARY); - } - return ret; -} - -int check_nt_auth(int pwd_authenticated, struct passwd *pw) -{ - /* - * The only authentication which is able to change the user - * context on NT systems is the password authentication. So - * we deny all requsts for changing the user context if another - * authentication method is used. - * - * This doesn't apply to Cygwin versions >= 1.3.2 anymore which - * uses the undocumented NtCreateToken() call to create a user - * token if the process has the appropriate privileges and if - * CYGWIN ntsec setting is on. - */ - static int has_create_token = -1; - - if (pw == NULL) - return 0; - if (is_winnt) { - if (has_create_token < 0) { - struct utsname uts; - int major_high = 0, major_low = 0, minor = 0; - char *cygwin = getenv("CYGWIN"); - - has_create_token = 0; - if (ntsec_on(cygwin) && !uname(&uts)) { - sscanf(uts.release, "%d.%d.%d", - &major_high, &major_low, &minor); - if (major_high > 1 || - (major_high == 1 && (major_low > 3 || - (major_low == 3 && minor >= 2)))) - has_create_token = 1; - } - } - if (has_create_token < 1 && - !pwd_authenticated && geteuid() != pw->pw_uid) - return 0; - } - return 1; -} - -int check_ntsec(const char *filename) -{ - char *cygwin; - int allow_ntea = 0; - int allow_ntsec = 0; - struct statfs fsstat; - - /* Windows 95/98/ME don't support file system security at all. */ - if (!is_winnt) - return 0; - - /* Evaluate current CYGWIN settings. */ - cygwin = getenv("CYGWIN"); - allow_ntea = ntea_on(cygwin); - allow_ntsec = ntsec_on(cygwin); - - /* - * `ntea' is an emulation of POSIX attributes. It doesn't support - * real file level security as ntsec on NTFS file systems does - * but it supports FAT filesystems. `ntea' is minimum requirement - * for security checks. - */ - if (allow_ntea) - return 1; - - /* - * Retrieve file system flags. In Cygwin, file system flags are - * copied to f_type which has no meaning in Win32 itself. - */ - if (statfs(filename, &fsstat)) - return 1; - - /* - * Only file systems supporting ACLs are able to set permissions. - * `ntsec' is the setting in Cygwin which switches using of NTFS - * ACLs to support POSIX permissions on files. - */ - if (fsstat.f_type & FS_PERSISTENT_ACLS) - return allow_ntsec; - - return 0; -} - -void register_9x_service(void) -{ - HINSTANCE kerneldll; - DWORD (*RegisterServiceProcess)(DWORD, DWORD); - - /* The service register mechanism in 9x/Me is pretty different from - * NT/2K/XP. In NT/2K/XP we're using a special service starter - * application to register and control sshd as service. This method - * doesn't play nicely with 9x/Me. For that reason we register here - * as service when running under 9x/Me. This function is only called - * by the child sshd when it's going to daemonize. - */ - if (is_winnt) - return; - if (! (kerneldll = LoadLibrary("KERNEL32.DLL"))) - return; - if (! (RegisterServiceProcess = (DWORD (*)(DWORD, DWORD)) - GetProcAddress(kerneldll, "RegisterServiceProcess"))) - return; - RegisterServiceProcess(0, 1); -} - -#endif /* HAVE_CYGWIN */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-getpeereid.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-getpeereid.c deleted file mode 100644 index 85e68ca6bf..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-getpeereid.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2002 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -RCSID("$Id: bsd-getpeereid.c,v 1.1 2002/09/12 00:33:02 djm Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#if !defined(HAVE_GETPEEREID) - -#if defined(SO_PEERCRED) -int -getpeereid(int s, uid_t *euid, gid_t *gid) -{ - struct ucred cred; - size_t len = sizeof(cred); - - if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0) - return (-1); - *euid = cred.uid; - *gid = cred.gid; - - return (0); -} -#elif defined(HAVE_GETPEERUCRED) -int -getpeereid(int s, uid_t *euid, gid_t *gid) -{ - ucred_t *ucred = NULL; - - if (getpeerucred(s, &ucred) == -1) - return (-1); - if ((*euid = ucred_geteuid(ucred)) == (uid_t)-1) - return (-1); - if ((*gid = ucred_getrgid(ucred)) == (gid_t)-1) - return (-1); - - ucred_free(ucred); - - return (0); -} -#else -int -getpeereid(int s, uid_t *euid, gid_t *gid) -{ - *euid = geteuid(); - *gid = getgid(); - - return (0); -} -#endif /* defined(SO_PEERCRED) */ - -#endif /* !defined(HAVE_GETPEEREID) */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-misc.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-misc.c deleted file mode 100644 index a7b9cbf052..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-misc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 1999-2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -RCSID("$Id: bsd-misc.c,v 1.10 2002/07/08 21:09:41 mouring Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -char *get_progname(char *argv0) -{ -#ifdef HAVE___PROGNAME - extern char *__progname; - - return __progname; -#else - char *p; - - if (argv0 == NULL) - return "unknown"; /* XXX */ - p = strrchr(argv0, '/'); - if (p == NULL) - p = argv0; - else - p++; - return p; -#endif -} - -#ifndef HAVE_SETLOGIN -int setlogin(const char *name) -{ - return(0); -} -#endif /* !HAVE_SETLOGIN */ - -#ifndef HAVE_INNETGR -int innetgr(const char *netgroup, const char *host, - const char *user, const char *domain) -{ - return(0); -} -#endif /* HAVE_INNETGR */ - -#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) -int seteuid(uid_t euid) -{ - return(setreuid(-1,euid)); -} -#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ - -#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) -int setegid(uid_t egid) -{ - return(setresgid(-1,egid,-1)); -} -#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ - -#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) -const char *strerror(int e) -{ - extern int sys_nerr; - extern char *sys_errlist[]; - - if ((e >= 0) && (e < sys_nerr)) - return(sys_errlist[e]); - else - return("unlisted error"); -} -#endif - -#ifndef HAVE_UTIMES -int utimes(char *filename, struct timeval *tvp) -{ - struct utimbuf ub; - - ub.actime = tvp[0].tv_sec; - ub.modtime = tvp[1].tv_sec; - - return(utime(filename, &ub)); -} -#endif - -#ifndef HAVE_TRUNCATE -int truncate (const char *path, off_t length) -{ - int fd, ret, saverrno; - - fd = open(path, O_WRONLY); - if (fd < 0) - return -1; - - ret = ftruncate(fd, length); - saverrno = errno; - (void) close (fd); - if (ret == -1) - errno = saverrno; - return(ret); -} -#endif /* HAVE_TRUNCATE */ - -#if !defined(HAVE_SETGROUPS) && defined(SETGROUPS_NOOP) -/* - * Cygwin setgroups should be a noop. - */ -int -setgroups(size_t size, const gid_t *list) -{ - return 0; -} -#endif - diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-snprintf.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-snprintf.c deleted file mode 100644 index 12148fd6c2..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-snprintf.c +++ /dev/null @@ -1,746 +0,0 @@ -/************************************************************** - * Original: - * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. - * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... - * - * snprintf() is used instead of sprintf() as it does limit checks - * for string length. This covers a nasty loophole. - * - * The other functions are there to prevent NULL pointers from - * causing nast effects. - * - * More Recently: - * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 - * This was ugly. It is still ugly. I opted out of floating point - * numbers, but the formatter understands just about everything - * from the normal C string format, at least as far as I can tell from - * the Solaris 2.5 printf(3S) man page. - * - * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 - * Ok, added some minimal floating point support, which means this - * probably requires libm on most operating systems. Don't yet - * support the exponent (e,E) and sigfig (g,G). Also, fmtint() - * was pretty badly broken, it just wasn't being exercised in ways - * which showed it, so that's been fixed. Also, formated the code - * to mutt conventions, and removed dead code left over from the - * original. Also, there is now a builtin-test, just compile with: - * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm - * and run snprintf for results. - * - * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i - * The PGP code was using unsigned hexadecimal formats. - * Unfortunately, unsigned formats simply didn't work. - * - * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 - * The original code assumed that both snprintf() and vsnprintf() were - * missing. Some systems only have snprintf() but not vsnprintf(), so - * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. - * - * Ben Lindstrom <mouring@eviladmin.org> 09/27/00 for OpenSSH - * Welcome to the world of %lld and %qd support. With other - * long long support. This is needed for sftp-server to work - * right. - * - * Ben Lindstrom <mouring@eviladmin.org> 02/12/01 for OpenSSH - * Removed all hint of VARARGS stuff and banished it to the void, - * and did a bit of KNF style work to make things a bit more - * acceptable. Consider stealing from mutt or enlightenment. - **************************************************************/ - -#include "includes.h" - -RCSID("$Id: bsd-snprintf.c,v 1.5 2001/02/25 23:20:41 mouring Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */ -# undef HAVE_SNPRINTF -# undef HAVE_VSNPRINTF -#endif - -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) - -static void -dopr(char *buffer, size_t maxlen, const char *format, va_list args); - -static void -fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, - int min, int max); - -static void -fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, - int min, int max, int flags); - -static void -fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, - int min, int max, int flags); - -static void -dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); - -/* - * dopr(): poor man's version of doprintf - */ - -/* format read states */ -#define DP_S_DEFAULT 0 -#define DP_S_FLAGS 1 -#define DP_S_MIN 2 -#define DP_S_DOT 3 -#define DP_S_MAX 4 -#define DP_S_MOD 5 -#define DP_S_CONV 6 -#define DP_S_DONE 7 - -/* format flags - Bits */ -#define DP_F_MINUS (1 << 0) -#define DP_F_PLUS (1 << 1) -#define DP_F_SPACE (1 << 2) -#define DP_F_NUM (1 << 3) -#define DP_F_ZERO (1 << 4) -#define DP_F_UP (1 << 5) -#define DP_F_UNSIGNED (1 << 6) - -/* Conversion Flags */ -#define DP_C_SHORT 1 -#define DP_C_LONG 2 -#define DP_C_LDOUBLE 3 -#define DP_C_LONG_LONG 4 - -#define char_to_int(p) (p - '0') -#define abs_val(p) (p < 0 ? -p : p) - - -static void -dopr(char *buffer, size_t maxlen, const char *format, va_list args) -{ - char *strvalue; - char ch; - long value; - long double fvalue; - int min = 0; - int max = -1; - int state = DP_S_DEFAULT; - int flags = 0; - int cflags = 0; - size_t currlen = 0; - - ch = *format++; - - while (state != DP_S_DONE) { - if ((ch == '\0') || (currlen >= maxlen)) - state = DP_S_DONE; - - switch(state) { - case DP_S_DEFAULT: - if (ch == '%') - state = DP_S_FLAGS; - else - dopr_outch(buffer, &currlen, maxlen, ch); - ch = *format++; - break; - case DP_S_FLAGS: - switch (ch) { - case '-': - flags |= DP_F_MINUS; - ch = *format++; - break; - case '+': - flags |= DP_F_PLUS; - ch = *format++; - break; - case ' ': - flags |= DP_F_SPACE; - ch = *format++; - break; - case '#': - flags |= DP_F_NUM; - ch = *format++; - break; - case '0': - flags |= DP_F_ZERO; - ch = *format++; - break; - default: - state = DP_S_MIN; - break; - } - break; - case DP_S_MIN: - if (isdigit((unsigned char)ch)) { - min = 10*min + char_to_int (ch); - ch = *format++; - } else if (ch == '*') { - min = va_arg (args, int); - ch = *format++; - state = DP_S_DOT; - } else - state = DP_S_DOT; - break; - case DP_S_DOT: - if (ch == '.') { - state = DP_S_MAX; - ch = *format++; - } else - state = DP_S_MOD; - break; - case DP_S_MAX: - if (isdigit((unsigned char)ch)) { - if (max < 0) - max = 0; - max = 10*max + char_to_int(ch); - ch = *format++; - } else if (ch == '*') { - max = va_arg (args, int); - ch = *format++; - state = DP_S_MOD; - } else - state = DP_S_MOD; - break; - case DP_S_MOD: - switch (ch) { - case 'h': - cflags = DP_C_SHORT; - ch = *format++; - break; - case 'l': - cflags = DP_C_LONG; - ch = *format++; - if (ch == 'l') { - cflags = DP_C_LONG_LONG; - ch = *format++; - } - break; - case 'q': - cflags = DP_C_LONG_LONG; - ch = *format++; - break; - case 'L': - cflags = DP_C_LDOUBLE; - ch = *format++; - break; - default: - break; - } - state = DP_S_CONV; - break; - case DP_S_CONV: - switch (ch) { - case 'd': - case 'i': - if (cflags == DP_C_SHORT) - value = va_arg(args, int); - else if (cflags == DP_C_LONG) - value = va_arg(args, long int); - else if (cflags == DP_C_LONG_LONG) - value = va_arg (args, long long); - else - value = va_arg (args, int); - fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'o': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg(args, unsigned int); - else if (cflags == DP_C_LONG) - value = va_arg(args, unsigned long int); - else if (cflags == DP_C_LONG_LONG) - value = va_arg(args, unsigned long long); - else - value = va_arg(args, unsigned int); - fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags); - break; - case 'u': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg(args, unsigned int); - else if (cflags == DP_C_LONG) - value = va_arg(args, unsigned long int); - else if (cflags == DP_C_LONG_LONG) - value = va_arg(args, unsigned long long); - else - value = va_arg(args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'X': - flags |= DP_F_UP; - case 'x': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg(args, unsigned int); - else if (cflags == DP_C_LONG) - value = va_arg(args, unsigned long int); - else if (cflags == DP_C_LONG_LONG) - value = va_arg(args, unsigned long long); - else - value = va_arg(args, unsigned int); - fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags); - break; - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, long double); - else - fvalue = va_arg(args, double); - /* um, floating point? */ - fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); - break; - case 'E': - flags |= DP_F_UP; - case 'e': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, long double); - else - fvalue = va_arg(args, double); - break; - case 'G': - flags |= DP_F_UP; - case 'g': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, long double); - else - fvalue = va_arg(args, double); - break; - case 'c': - dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); - break; - case 's': - strvalue = va_arg(args, char *); - if (max < 0) - max = maxlen; /* ie, no max */ - fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max); - break; - case 'p': - strvalue = va_arg(args, void *); - fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); - break; - case 'n': - if (cflags == DP_C_SHORT) { - short int *num; - num = va_arg(args, short int *); - *num = currlen; - } else if (cflags == DP_C_LONG) { - long int *num; - num = va_arg(args, long int *); - *num = currlen; - } else if (cflags == DP_C_LONG_LONG) { - long long *num; - num = va_arg(args, long long *); - *num = currlen; - } else { - int *num; - num = va_arg(args, int *); - *num = currlen; - } - break; - case '%': - dopr_outch(buffer, &currlen, maxlen, ch); - break; - case 'w': /* not supported yet, treat as next char */ - ch = *format++; - break; - default: /* Unknown, skip */ - break; - } - ch = *format++; - state = DP_S_DEFAULT; - flags = cflags = min = 0; - max = -1; - break; - case DP_S_DONE: - break; - default: /* hmm? */ - break; /* some picky compilers need this */ - } - } - if (currlen < maxlen - 1) - buffer[currlen] = '\0'; - else - buffer[maxlen - 1] = '\0'; -} - -static void -fmtstr(char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max) -{ - int padlen, strln; /* amount to pad */ - int cnt = 0; - - if (value == 0) - value = "<NULL>"; - - for (strln = 0; value[strln]; ++strln); /* strlen */ - padlen = min - strln; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justify */ - - while ((padlen > 0) && (cnt < max)) { - dopr_outch(buffer, currlen, maxlen, ' '); - --padlen; - ++cnt; - } - while (*value && (cnt < max)) { - dopr_outch(buffer, currlen, maxlen, *value++); - ++cnt; - } - while ((padlen < 0) && (cnt < max)) { - dopr_outch(buffer, currlen, maxlen, ' '); - ++padlen; - ++cnt; - } -} - -/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ - -static void -fmtint(char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags) -{ - unsigned long uvalue; - char convert[20]; - int signvalue = 0; - int place = 0; - int spadlen = 0; /* amount to space pad */ - int zpadlen = 0; /* amount to zero pad */ - int caps = 0; - - if (max < 0) - max = 0; - - uvalue = value; - - if (!(flags & DP_F_UNSIGNED)) { - if (value < 0) { - signvalue = '-'; - uvalue = -value; - } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else if (flags & DP_F_SPACE) - signvalue = ' '; - } - - if (flags & DP_F_UP) - caps = 1; /* Should characters be upper case? */ - - do { - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base]; - uvalue = (uvalue / (unsigned)base ); - } while (uvalue && (place < 20)); - if (place == 20) - place--; - convert[place] = 0; - - zpadlen = max - place; - spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); - if (zpadlen < 0) - zpadlen = 0; - if (spadlen < 0) - spadlen = 0; - if (flags & DP_F_ZERO) { - zpadlen = MAX(zpadlen, spadlen); - spadlen = 0; - } - if (flags & DP_F_MINUS) - spadlen = -spadlen; /* Left Justifty */ - - - /* Spaces */ - while (spadlen > 0) { - dopr_outch(buffer, currlen, maxlen, ' '); - --spadlen; - } - - /* Sign */ - if (signvalue) - dopr_outch(buffer, currlen, maxlen, signvalue); - - /* Zeros */ - if (zpadlen > 0) { - while (zpadlen > 0) { - dopr_outch(buffer, currlen, maxlen, '0'); - --zpadlen; - } - } - - /* Digits */ - while (place > 0) - dopr_outch(buffer, currlen, maxlen, convert[--place]); - - /* Left Justified spaces */ - while (spadlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++spadlen; - } -} - -static long double -pow10(int exp) -{ - long double result = 1; - - while (exp) { - result *= 10; - exp--; - } - - return result; -} - -static long -round(long double value) -{ - long intpart = value; - - value -= intpart; - if (value >= 0.5) - intpart++; - - return intpart; -} - -static void -fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, - int min, int max, int flags) -{ - char iconvert[20]; - char fconvert[20]; - int signvalue = 0; - int iplace = 0; - int fplace = 0; - int padlen = 0; /* amount to pad */ - int zpadlen = 0; - int caps = 0; - long intpart; - long fracpart; - long double ufvalue; - - /* - * AIX manpage says the default is 0, but Solaris says the default - * is 6, and sprintf on AIX defaults to 6 - */ - if (max < 0) - max = 6; - - ufvalue = abs_val(fvalue); - - if (fvalue < 0) - signvalue = '-'; - else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else if (flags & DP_F_SPACE) - signvalue = ' '; - - intpart = ufvalue; - - /* - * Sorry, we only support 9 digits past the decimal because of our - * conversion method - */ - if (max > 9) - max = 9; - - /* We "cheat" by converting the fractional part to integer by - * multiplying by a factor of 10 - */ - fracpart = round((pow10 (max)) * (ufvalue - intpart)); - - if (fracpart >= pow10 (max)) { - intpart++; - fracpart -= pow10 (max); - } - - /* Convert integer part */ - do { - iconvert[iplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; - intpart = (intpart / 10); - } while(intpart && (iplace < 20)); - if (iplace == 20) - iplace--; - iconvert[iplace] = 0; - - /* Convert fractional part */ - do { - fconvert[fplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; - fracpart = (fracpart / 10); - } while(fracpart && (fplace < 20)); - if (fplace == 20) - fplace--; - fconvert[fplace] = 0; - - /* -1 for decimal point, another -1 if we are printing a sign */ - padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); - zpadlen = max - fplace; - if (zpadlen < 0) - zpadlen = 0; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justifty */ - - if ((flags & DP_F_ZERO) && (padlen > 0)) { - if (signvalue) { - dopr_outch(buffer, currlen, maxlen, signvalue); - --padlen; - signvalue = 0; - } - while (padlen > 0) { - dopr_outch(buffer, currlen, maxlen, '0'); - --padlen; - } - } - while (padlen > 0) { - dopr_outch(buffer, currlen, maxlen, ' '); - --padlen; - } - if (signvalue) - dopr_outch(buffer, currlen, maxlen, signvalue); - - while (iplace > 0) - dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - dopr_outch(buffer, currlen, maxlen, '.'); - - while (fplace > 0) - dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); - - while (zpadlen > 0) { - dopr_outch(buffer, currlen, maxlen, '0'); - --zpadlen; - } - - while (padlen < 0) { - dopr_outch(buffer, currlen, maxlen, ' '); - ++padlen; - } -} - -static void -dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) -{ - if (*currlen < maxlen) - buffer[(*currlen)++] = c; -} -#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ - -#ifndef HAVE_VSNPRINTF -int -vsnprintf(char *str, size_t count, const char *fmt, va_list args) -{ - str[0] = 0; - dopr(str, count, fmt, args); - - return(strlen(str)); -} -#endif /* !HAVE_VSNPRINTF */ - -#ifndef HAVE_SNPRINTF -int -snprintf(char *str,size_t count,const char *fmt,...) -{ - va_list ap; - - va_start(ap, fmt); - (void) vsnprintf(str, count, fmt, ap); - va_end(ap); - - return(strlen(str)); -} - -#ifdef TEST_SNPRINTF -int -main(void) -{ -#define LONG_STRING 1024 - char buf1[LONG_STRING]; - char buf2[LONG_STRING]; - char *fp_fmt[] = { - "%-1.5f", - "%1.5f", - "%123.9f", - "%10.5f", - "% 10.5f", - "%+22.9f", - "%+4.9f", - "%01.3f", - "%4f", - "%3.1f", - "%3.2f", - NULL - }; - double fp_nums[] = { - -1.5, - 134.21, - 91340.2, - 341.1234, - 0203.9, - 0.96, - 0.996, - 0.9996, - 1.996, - 4.136, - 0 - }; - char *int_fmt[] = { - "%-1.5d", - "%1.5d", - "%123.9d", - "%5.5d", - "%10.5d", - "% 10.5d", - "%+22.33d", - "%01.3d", - "%4d", - "%lld", - "%qd", - NULL - }; - long long int_nums[] = { -1, 134, 91340, 341, 0203, 0, 9999999 }; - int x, y; - int fail = 0; - int num = 0; - - printf("Testing snprintf format codes against system sprintf...\n"); - - for (x = 0; fp_fmt[x] != NULL ; x++) { - for (y = 0; fp_nums[y] != 0 ; y++) { - snprintf(buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); - sprintf (buf2, fp_fmt[x], fp_nums[y]); - if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\t" - "snprintf = %s\n\tsprintf = %s\n", - fp_fmt[x], buf1, buf2); - fail++; - } - num++; - } - } - for (x = 0; int_fmt[x] != NULL ; x++) { - for (y = 0; int_nums[y] != 0 ; y++) { - snprintf(buf1, sizeof (buf1), int_fmt[x], int_nums[y]); - sprintf(buf2, int_fmt[x], int_nums[y]); - if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\t" - "snprintf = %s\n\tsprintf = %s\n", - int_fmt[x], buf1, buf2); - fail++; - } - num++; - } - } - printf("%d tests failed out of %d.\n", fail, num); - return(0); -} -#endif /* SNPRINTF_TEST */ - -#endif /* !HAVE_SNPRINTF */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-waitpid.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-waitpid.c deleted file mode 100644 index 8b221309a0..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-waitpid.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -RCSID("$Id: bsd-waitpid.c,v 1.3 2001/03/26 05:35:34 mouring Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef HAVE_WAITPID -#include <errno.h> -#include <sys/wait.h> -#include "bsd-waitpid.h" - -pid_t -waitpid(int pid, int *stat_loc, int options) -{ - union wait statusp; - pid_t wait_pid; - - if (pid <= 0) { - if (pid != -1) { - errno = EINVAL; - return -1; - } - pid = 0; /* wait4() wants pid=0 for indiscriminate wait. */ - } - wait_pid = wait4(pid, &statusp, options, NULL); - if (stat_loc) - *stat_loc = (int) statusp.w_status; - - return wait_pid; -} - -#endif /* !HAVE_WAITPID */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/dirname.c b/usr/src/cmd/ssh/libopenbsd-compat/common/dirname.c deleted file mode 100644 index b6dcff6f36..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/dirname.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $OpenBSD: dirname.c,v 1.7 2002/05/24 21:22:37 deraadt Exp $ */ - -/* - * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#ifndef HAVE_DIRNAME - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: dirname.c,v 1.7 2002/05/24 21:22:37 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <errno.h> -#include <string.h> -#include <sys/param.h> - -char * -dirname(path) - const char *path; -{ - static char bname[MAXPATHLEN]; - register const char *endp; - - /* Empty or NULL string gets treated as "." */ - if (path == NULL || *path == '\0') { - (void)strlcpy(bname, ".", sizeof bname); - return(bname); - } - - /* Strip trailing slashes */ - endp = path + strlen(path) - 1; - while (endp > path && *endp == '/') - endp--; - - /* Find the start of the dir */ - while (endp > path && *endp != '/') - endp--; - - /* Either the dir is "/" or there are no slashes */ - if (endp == path) { - (void)strlcpy(bname, *endp == '/' ? "/" : ".", sizeof bname); - return(bname); - } else { - do { - endp--; - } while (endp > path && *endp == '/'); - } - - if (endp - path + 2 > sizeof(bname)) { - errno = ENAMETOOLONG; - return(NULL); - } - strlcpy(bname, path, endp - path + 2); - return(bname); -} -#endif - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/fake-getaddrinfo.c b/usr/src/cmd/ssh/libopenbsd-compat/common/fake-getaddrinfo.c deleted file mode 100644 index ede2fa014a..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/fake-getaddrinfo.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * fake library for ssh - * - * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror(). - * These funtions are defined in rfc2133. - * - * But these functions are not implemented correctly. The minimum subset - * is implemented for ssh use only. For exapmle, this routine assumes - * that ai_family is AF_INET. Don't use it for another purpose. - */ - -#include "includes.h" -#include "ssh.h" - -RCSID("$Id: fake-getaddrinfo.c,v 1.2 2001/02/09 01:55:36 djm Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef HAVE_GAI_STRERROR -char *gai_strerror(int ecode) -{ - switch (ecode) { - case EAI_NODATA: - return "no address associated with hostname."; - case EAI_MEMORY: - return "memory allocation failure."; - default: - return "unknown error."; - } -} -#endif /* !HAVE_GAI_STRERROR */ - -#ifndef HAVE_FREEADDRINFO -void freeaddrinfo(struct addrinfo *ai) -{ - struct addrinfo *next; - - do { - next = ai->ai_next; - free(ai); - } while (NULL != (ai = next)); -} -#endif /* !HAVE_FREEADDRINFO */ - -#ifndef HAVE_GETADDRINFO -static struct addrinfo *malloc_ai(int port, u_long addr) -{ - struct addrinfo *ai; - - ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); - if (ai == NULL) - return(NULL); - - memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); - - ai->ai_addr = (struct sockaddr *)(ai + 1); - /* XXX -- ssh doesn't use sa_len */ - ai->ai_addrlen = sizeof(struct sockaddr_in); - ai->ai_addr->sa_family = ai->ai_family = AF_INET; - - ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; - ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; - - return(ai); -} - -int getaddrinfo(const char *hostname, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) -{ - struct addrinfo *cur, *prev = NULL; - struct hostent *hp; - struct in_addr in; - int i, port; - - if (servname) - port = htons(atoi(servname)); - else - port = 0; - - if (hints && hints->ai_flags & AI_PASSIVE) { - if (NULL != (*res = malloc_ai(port, htonl(0x00000000)))) - return 0; - else - return EAI_MEMORY; - } - - if (!hostname) { - if (NULL != (*res = malloc_ai(port, htonl(0x7f000001)))) - return 0; - else - return EAI_MEMORY; - } - - if (inet_aton(hostname, &in)) { - if (NULL != (*res = malloc_ai(port, in.s_addr))) - return 0; - else - return EAI_MEMORY; - } - - hp = gethostbyname(hostname); - if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { - for (i = 0; hp->h_addr_list[i]; i++) { - cur = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr); - if (cur == NULL) { - if (*res) - freeaddrinfo(*res); - return EAI_MEMORY; - } - - if (prev) - prev->ai_next = cur; - else - *res = cur; - - prev = cur; - } - return 0; - } - - return EAI_NODATA; -} -#endif /* !HAVE_GETADDRINFO */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/fake-getnameinfo.c b/usr/src/cmd/ssh/libopenbsd-compat/common/fake-getnameinfo.c deleted file mode 100644 index 60cef5cc2d..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/fake-getnameinfo.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * fake library for ssh - * - * This file includes getnameinfo(). - * These funtions are defined in rfc2133. - * - * But these functions are not implemented correctly. The minimum subset - * is implemented for ssh use only. For exapmle, this routine assumes - * that ai_family is AF_INET. Don't use it for another purpose. - */ - -#include "includes.h" -#include "ssh.h" - -RCSID("$Id: fake-getnameinfo.c,v 1.2 2001/02/09 01:55:36 djm Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef HAVE_GETNAMEINFO -int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, - size_t hostlen, char *serv, size_t servlen, int flags) -{ - struct sockaddr_in *sin = (struct sockaddr_in *)sa; - struct hostent *hp; - char tmpserv[16]; - - if (serv) { - snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); - if (strlen(tmpserv) >= servlen) - return EAI_MEMORY; - else - strcpy(serv, tmpserv); - } - - if (host) { - if (flags & NI_NUMERICHOST) { - if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen) - return EAI_MEMORY; - - strcpy(host, inet_ntoa(sin->sin_addr)); - return 0; - } else { - hp = gethostbyaddr((char *)&sin->sin_addr, - sizeof(struct in_addr), AF_INET); - if (hp == NULL) - return EAI_NODATA; - - if (strlen(hp->h_name) >= hostlen) - return EAI_MEMORY; - - strcpy(host, hp->h_name); - return 0; - } - } - return 0; -} -#endif /* !HAVE_GETNAMEINFO */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/getcwd.c b/usr/src/cmd/ssh/libopenbsd-compat/common/getcwd.c deleted file mode 100644 index 35027a0e7b..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/getcwd.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 1989, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#if !defined(HAVE_GETCWD) - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getcwd.c,v 1.6 2000/07/19 15:25:13 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <errno.h> -#include <dirent.h> -#include <sys/dir.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "includes.h" - -#define ISDOT(dp) \ - (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ - (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) - -char * -getcwd(char *pt,size_t size) -{ - register struct dirent *dp; - register DIR *dir = NULL; - register dev_t dev; - register ino_t ino; - register int first; - register char *bpt, *bup; - struct stat s; - dev_t root_dev; - ino_t root_ino; - size_t ptsize, upsize; - int save_errno; - char *ept, *eup, *up; - - /* - * If no buffer specified by the user, allocate one as necessary. - * If a buffer is specified, the size has to be non-zero. The path - * is built from the end of the buffer backwards. - */ - if (pt) { - ptsize = 0; - if (!size) { - errno = EINVAL; - return (NULL); - } - ept = pt + size; - } else { - if ((pt = malloc(ptsize = 1024 - 4)) == NULL) - return (NULL); - ept = pt + ptsize; - } - bpt = ept - 1; - *bpt = '\0'; - - /* - * Allocate bytes (1024 - malloc space) for the string of "../"'s. - * Should always be enough (it's 340 levels). If it's not, allocate - * as necessary. Special * case the first stat, it's ".", not "..". - */ - if ((up = malloc(upsize = 1024 - 4)) == NULL) - goto err; - eup = up + MAXPATHLEN; - bup = up; - up[0] = '.'; - up[1] = '\0'; - - /* Save root values, so know when to stop. */ - if (stat("/", &s)) - goto err; - root_dev = s.st_dev; - root_ino = s.st_ino; - - errno = 0; /* XXX readdir has no error return. */ - - for (first = 1;; first = 0) { - /* Stat the current level. */ - if (lstat(up, &s)) - goto err; - - /* Save current node values. */ - ino = s.st_ino; - dev = s.st_dev; - - /* Check for reaching root. */ - if (root_dev == dev && root_ino == ino) { - *--bpt = '/'; - /* - * It's unclear that it's a requirement to copy the - * path to the beginning of the buffer, but it's always - * been that way and stuff would probably break. - */ - memmove(pt, bpt, ept - bpt); - free(up); - return (pt); - } - - /* - * Build pointer to the parent directory, allocating memory - * as necessary. Max length is 3 for "../", the largest - * possible component name, plus a trailing NULL. - */ - if (bup + 3 + MAXNAMLEN + 1 >= eup) { - char *nup; - - if ((nup = realloc(up, upsize *= 2)) == NULL) - goto err; - up = nup; - bup = up; - eup = up + upsize; - } - *bup++ = '.'; - *bup++ = '.'; - *bup = '\0'; - - /* Open and stat parent directory. - * RACE?? - replaced fstat(dirfd(dir), &s) w/ lstat(up,&s) - */ - if (!(dir = opendir(up)) || lstat(up,&s)) - goto err; - - /* Add trailing slash for next directory. */ - *bup++ = '/'; - - /* - * If it's a mount point, have to stat each element because - * the inode number in the directory is for the entry in the - * parent directory, not the inode number of the mounted file. - */ - save_errno = 0; - if (s.st_dev == dev) { - for (;;) { - if (!(dp = readdir(dir))) - goto notfound; - if (dp->d_fileno == ino) - break; - } - } else - for (;;) { - if (!(dp = readdir(dir))) - goto notfound; - if (ISDOT(dp)) - continue; - memmove(bup, dp->d_name, dp->d_namlen + 1); - - /* Save the first error for later. */ - if (lstat(up, &s)) { - if (!save_errno) - save_errno = errno; - errno = 0; - continue; - } - if (s.st_dev == dev && s.st_ino == ino) - break; - } - - /* - * Check for length of the current name, preceding slash, - * leading slash. - */ - if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) { - size_t len, off; - char *npt; - - if (!ptsize) { - errno = ERANGE; - goto err; - } - off = bpt - pt; - len = ept - bpt; - if ((npt = realloc(pt, ptsize *= 2)) == NULL) - goto err; - pt = npt; - bpt = pt + off; - ept = pt + ptsize; - memmove(ept - len, bpt, len); - bpt = ept - len; - } - if (!first) - *--bpt = '/'; - bpt -= dp->d_namlen; - memmove(bpt, dp->d_name, dp->d_namlen); - (void)closedir(dir); - - /* Truncate any file name. */ - *bup = '\0'; - } - -notfound: - /* - * If readdir set errno, use it, not any saved error; otherwise, - * didn't find the current directory in its parent directory, set - * errno to ENOENT. - */ - if (!errno) - errno = save_errno ? save_errno : ENOENT; - /* FALLTHROUGH */ -err: - if (ptsize) - free(pt); - if (up) - free(up); - if (dir) - (void)closedir(dir); - return (NULL); -} - -#endif /* !defined(HAVE_GETCWD) */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/getgrouplist.c b/usr/src/cmd/ssh/libopenbsd-compat/common/getgrouplist.c deleted file mode 100644 index bdd4c3a153..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/getgrouplist.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#ifndef HAVE_GETGROUPLIST - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getgrouplist.c,v 1.7 1997/08/19 19:13:27 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -/* - * get credential - */ -#include <sys/types.h> -#include <string.h> -#include <grp.h> - -int -getgrouplist(uname, agroup, groups, grpcnt) - const char *uname; - gid_t agroup; - register gid_t *groups; - int *grpcnt; -{ - register struct group *grp; - register int i, ngroups; - int ret, maxgroups; - int bail; - - ret = 0; - ngroups = 0; - maxgroups = *grpcnt; - - /* - * install primary group - */ - if (ngroups >= maxgroups) { - *grpcnt = ngroups; - return (-1); - } - groups[ngroups++] = agroup; - - /* - * Scan the group file to find additional groups. - */ - setgrent(); - while ((grp = getgrent())) { - if (grp->gr_gid == agroup) - continue; - for (bail = 0, i = 0; bail == 0 && i < ngroups; i++) - if (groups[i] == grp->gr_gid) - bail = 1; - if (bail) - continue; - for (i = 0; grp->gr_mem[i]; i++) { - if (!strcmp(grp->gr_mem[i], uname)) { - if (ngroups >= maxgroups) { - ret = -1; - goto out; - } - groups[ngroups++] = grp->gr_gid; - break; - } - } - } -out: - endgrent(); - *grpcnt = ngroups; - return (ret); -} - -#endif /* HAVE_GETGROUPLIST */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/getopt.c b/usr/src/cmd/ssh/libopenbsd-compat/common/getopt.c deleted file mode 100644 index f69487950f..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/getopt.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" -#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: getopt.c,v 1.2 1996/08/19 08:33:32 tholo Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int BSDopterr = 1, /* if error message should be printed */ - BSDoptind = 1, /* index into parent argv vector */ - BSDoptopt, /* character checked for validity */ - BSDoptreset; /* reset getopt */ -char *BSDoptarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" - -/* - * getopt -- - * Parse argc/argv argument vector. - */ -int -BSDgetopt(nargc, nargv, ostr) - int nargc; - char * const *nargv; - const char *ostr; -{ - extern char *__progname; - static char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - - if (BSDoptreset || !*place) { /* update scanning pointer */ - BSDoptreset = 0; - if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') { - place = EMSG; - return (-1); - } - if (place[1] && *++place == '-') { /* found "--" */ - ++BSDoptind; - place = EMSG; - return (-1); - } - } /* option letter okay? */ - if ((BSDoptopt = (int)*place++) == (int)':' || - !(oli = strchr(ostr, BSDoptopt))) { - /* - * if the user didn't specify '-' as an option, - * assume it means -1. - */ - if (BSDoptopt == (int)'-') - return (-1); - if (!*place) - ++BSDoptind; - if (BSDopterr && *ostr != ':') - (void) fprintf(stderr, - gettext("%s: illegal option -- %c\n"), __progname, - BSDoptopt); - return (BADCH); - } - if (*++oli != ':') { /* don't need argument */ - BSDoptarg = NULL; - if (!*place) - ++BSDoptind; - } else { /* need an argument */ - if (*place) /* no white space */ - BSDoptarg = place; - else if (nargc <= ++BSDoptind) { /* no arg */ - place = EMSG; - if (*ostr == ':') - return (BADARG); - if (BSDopterr) - (void) fprintf(stderr, - "%s: option requires an argument -- %c\n", - __progname, BSDoptopt); - return (BADCH); - /* white space */ - } else - BSDoptarg = nargv[BSDoptind]; - - place = EMSG; - ++BSDoptind; - } - return (BSDoptopt); /* dump back option letter */ -} - -#endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/glob.c b/usr/src/cmd/ssh/libopenbsd-compat/common/glob.c deleted file mode 100644 index 2688cccaee..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/glob.c +++ /dev/null @@ -1,933 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Guido van Rossum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" -#include <ctype.h> - -#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ - !defined(GLOB_HAS_GL_MATCHC) - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; -#else -static char rcsid[] = "$OpenBSD: glob.c,v 1.20 2002/06/14 21:34:58 todd Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -/* - * glob(3) -- a superset of the one defined in POSIX 1003.2. - * - * The [!...] convention to negate a range is supported (SysV, Posix, ksh). - * - * Optional extra services, controlled by flags not defined by POSIX: - * - * GLOB_QUOTE: - * Escaping convention: \ inhibits any special meaning the following - * character might have (except \ at end of string is retained). - * GLOB_MAGCHAR: - * Set in gl_flags if pattern contained a globbing character. - * GLOB_NOMAGIC: - * Same as GLOB_NOCHECK, but it will only append pattern if it did - * not contain any magic characters. [Used in csh style globbing] - * GLOB_ALTDIRFUNC: - * Use alternately specified directory access functions. - * GLOB_TILDE: - * expand ~user/foo to the /home/dir/of/user/foo - * GLOB_BRACE: - * expand {1,2}{a,b} to 1a 1b 2a 2b - * gl_matchc: - * Number of matches in the current invocation of glob. - */ - - -#define DOLLAR '$' -#define DOT '.' -#define EOS '\0' -#define LBRACKET '[' -#define NOT '!' -#define QUESTION '?' -#define QUOTE '\\' -#define RANGE '-' -#define RBRACKET ']' -#define SEP '/' -#define STAR '*' -#undef TILDE /* Some platforms may already define it */ -#define TILDE '~' -#define UNDERSCORE '_' -#define LBRACE '{' -#define RBRACE '}' -#define SLASH '/' -#define COMMA ',' - -#ifndef DEBUG - -#define M_QUOTE 0x8000 -#define M_PROTECT 0x4000 -#define M_MASK 0xffff -#define M_ASCII 0x00ff - -typedef u_short Char; - -#else - -#define M_QUOTE 0x80 -#define M_PROTECT 0x40 -#define M_MASK 0xff -#define M_ASCII 0x7f - -typedef char Char; - -#endif - - -#define CHAR(c) ((Char)((c)&M_ASCII)) -#define META(c) ((Char)((c)|M_QUOTE)) -#define M_ALL META('*') -#define M_END META(']') -#define M_NOT META('!') -#define M_ONE META('?') -#define M_RNG META('-') -#define M_SET META('[') -#define ismeta(c) (((c)&M_QUOTE) != 0) - - -#define GLOB_LIMIT_MALLOC 65536 -#define GLOB_LIMIT_STAT 128 -#define GLOB_LIMIT_READDIR 16384 - -#define GLOB_INDEX_MALLOC 0 -#define GLOB_INDEX_STAT 1 -#define GLOB_INDEX_READDIR 2 - -static int compare(const void *, const void *); -static int g_Ctoc(const Char *, char *, u_int); -static int g_lstat(Char *, struct stat *, glob_t *); -static DIR *g_opendir(Char *, glob_t *); -static Char *g_strchr(Char *, int); -static int g_stat(Char *, struct stat *, glob_t *); -static int glob0(const Char *, glob_t *, size_t *); -static int glob1(Char *, Char *, glob_t *, size_t *); -static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, - glob_t *, size_t *); -static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, - Char *, Char *, glob_t *, size_t *); -static int globextend(const Char *, glob_t *, size_t *); -static const Char * - globtilde(const Char *, Char *, size_t, glob_t *); -static int globexp1(const Char *, glob_t *, size_t *); -static int globexp2(const Char *, const Char *, glob_t *, int *, - size_t *); -static int match(Char *, Char *, Char *); -#ifdef DEBUG -static void qprintf(const char *, Char *); -#endif - -int -glob(pattern, flags, errfunc, pglob) - const char *pattern; - int flags, (*errfunc)(const char *, int); - glob_t *pglob; -{ - const u_char *patnext; - int c; - Char *bufnext, *bufend, patbuf[MAXPATHLEN]; - /* 0 = malloc(), 1 = stat(), 2 = readdir() */ - static size_t limit[] = { 0, 0, 0 }; - - patnext = (u_char *) pattern; - if (!(flags & GLOB_APPEND)) { - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - if (!(flags & GLOB_DOOFFS)) - pglob->gl_offs = 0; - } - pglob->gl_flags = flags & ~GLOB_MAGCHAR; - pglob->gl_errfunc = errfunc; - pglob->gl_matchc = 0; - - bufnext = patbuf; - bufend = bufnext + MAXPATHLEN - 1; - if (flags & GLOB_NOESCAPE) - while (bufnext < bufend && (c = *patnext++) != EOS) - *bufnext++ = c; - else { - /* Protect the quoted characters. */ - while (bufnext < bufend && (c = *patnext++) != EOS) - if (c == QUOTE) { - if ((c = *patnext++) == EOS) { - c = QUOTE; - --patnext; - } - *bufnext++ = c | M_PROTECT; - } else - *bufnext++ = c; - } - *bufnext = EOS; - - if (flags & GLOB_BRACE) - return globexp1(patbuf, pglob, limit); - else - return glob0(patbuf, pglob, limit); -} - -/* - * Expand recursively a glob {} pattern. When there is no more expansion - * invoke the standard globbing routine to glob the rest of the magic - * characters - */ -static int -globexp1(pattern, pglob, limit) - const Char *pattern; - glob_t *pglob; - size_t *limit; -{ - const Char* ptr = pattern; - int rv; - - /* Protect a single {}, for find(1), like csh */ - if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) - return glob0(pattern, pglob, limit); - - while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) - if (!globexp2(ptr, pattern, pglob, &rv, limit)) - return rv; - - return glob0(pattern, pglob, limit); -} - - -/* - * Recursive brace globbing helper. Tries to expand a single brace. - * If it succeeds then it invokes globexp1 with the new pattern. - * If it fails then it tries to glob the rest of the pattern and returns. - */ -static int -globexp2(ptr, pattern, pglob, rv, limit) - const Char *ptr, *pattern; - glob_t *pglob; - int *rv; - size_t *limit; -{ - int i; - Char *lm, *ls; - const Char *pe, *pm, *pl; - Char patbuf[MAXPATHLEN]; - - /* copy part up to the brace */ - for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) - ; - *lm = EOS; - ls = lm; - - /* Find the balanced brace */ - for (i = 0, pe = ++ptr; *pe; pe++) - if (*pe == LBRACKET) { - /* Ignore everything between [] */ - for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) - ; - if (*pe == EOS) { - /* - * We could not find a matching RBRACKET. - * Ignore and just look for RBRACE - */ - pe = pm; - } - } else if (*pe == LBRACE) - i++; - else if (*pe == RBRACE) { - if (i == 0) - break; - i--; - } - - /* Non matching braces; just glob the pattern */ - if (i != 0 || *pe == EOS) { - *rv = glob0(patbuf, pglob, limit); - return 0; - } - - for (i = 0, pl = pm = ptr; pm <= pe; pm++) { - switch (*pm) { - case LBRACKET: - /* Ignore everything between [] */ - for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) - ; - if (*pm == EOS) { - /* - * We could not find a matching RBRACKET. - * Ignore and just look for RBRACE - */ - pm = pl; - } - break; - - case LBRACE: - i++; - break; - - case RBRACE: - if (i) { - i--; - break; - } - /* FALLTHROUGH */ - case COMMA: - if (i && *pm == COMMA) - break; - else { - /* Append the current string */ - for (lm = ls; (pl < pm); *lm++ = *pl++) - ; - - /* - * Append the rest of the pattern after the - * closing brace - */ - for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) - ; - - /* Expand the current pattern */ -#ifdef DEBUG - qprintf("globexp2:", patbuf); -#endif - *rv = globexp1(patbuf, pglob, limit); - - /* move after the comma, to the next string */ - pl = pm + 1; - } - break; - - default: - break; - } - } - *rv = 0; - return 0; -} - - - -/* - * expand tilde from the passwd file. - */ -static const Char * -globtilde(pattern, patbuf, patbuf_len, pglob) - const Char *pattern; - Char *patbuf; - size_t patbuf_len; - glob_t *pglob; -{ - struct passwd *pwd; - char *h; - const Char *p; - Char *b, *eb; - - if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) - return pattern; - - /* Copy up to the end of the string or / */ - eb = &patbuf[patbuf_len - 1]; - for (p = pattern + 1, h = (char *) patbuf; - h < (char *)eb && *p && *p != SLASH; *h++ = *p++) - ; - - *h = EOS; - -#if 0 - if (h == (char *)eb) - return what; -#endif - - if (((char *) patbuf)[0] == EOS) { - /* - * handle a plain ~ or ~/ by expanding $HOME - * first and then trying the password file - */ -#if 0 - if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { -#endif - if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) { - if ((pwd = getpwuid(getuid())) == NULL) - return pattern; - else - h = pwd->pw_dir; - } - } else { - /* - * Expand a ~user - */ - if ((pwd = getpwnam((char*) patbuf)) == NULL) - return pattern; - else - h = pwd->pw_dir; - } - - /* Copy the home directory */ - for (b = patbuf; b < eb && *h; *b++ = *h++) - ; - - /* Append the rest of the pattern */ - while (b < eb && (*b++ = *p++) != EOS) - ; - *b = EOS; - - return patbuf; -} - - -/* - * The main glob() routine: compiles the pattern (optionally processing - * quotes), calls glob1() to do the real pattern matching, and finally - * sorts the list (unless unsorted operation is requested). Returns 0 - * if things went well, nonzero if errors occurred. It is not an error - * to find no matches. - */ -static int -glob0(pattern, pglob, limit) - const Char *pattern; - glob_t *pglob; - size_t *limit; -{ - const Char *qpatnext; - int c, err, oldpathc; - Char *bufnext, patbuf[MAXPATHLEN]; - - qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); - oldpathc = pglob->gl_pathc; - bufnext = patbuf; - - /* We don't need to check for buffer overflow any more. */ - while ((c = *qpatnext++) != EOS) { - switch (c) { - case LBRACKET: - c = *qpatnext; - if (c == NOT) - ++qpatnext; - if (*qpatnext == EOS || - g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { - *bufnext++ = LBRACKET; - if (c == NOT) - --qpatnext; - break; - } - *bufnext++ = M_SET; - if (c == NOT) - *bufnext++ = M_NOT; - c = *qpatnext++; - do { - *bufnext++ = CHAR(c); - if (*qpatnext == RANGE && - (c = qpatnext[1]) != RBRACKET) { - *bufnext++ = M_RNG; - *bufnext++ = CHAR(c); - qpatnext += 2; - } - } while ((c = *qpatnext++) != RBRACKET); - pglob->gl_flags |= GLOB_MAGCHAR; - *bufnext++ = M_END; - break; - case QUESTION: - pglob->gl_flags |= GLOB_MAGCHAR; - *bufnext++ = M_ONE; - break; - case STAR: - pglob->gl_flags |= GLOB_MAGCHAR; - /* collapse adjacent stars to one, - * to avoid exponential behavior - */ - if (bufnext == patbuf || bufnext[-1] != M_ALL) - *bufnext++ = M_ALL; - break; - default: - *bufnext++ = CHAR(c); - break; - } - } - *bufnext = EOS; -#ifdef DEBUG - qprintf("glob0:", patbuf); -#endif - - if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limit)) != 0) - return(err); - - /* - * If there was no match we are going to append the pattern - * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified - * and the pattern did not contain any magic characters - * GLOB_NOMAGIC is there just for compatibility with csh. - */ - if (pglob->gl_pathc == oldpathc) { - if ((pglob->gl_flags & GLOB_NOCHECK) || - ((pglob->gl_flags & GLOB_NOMAGIC) && - !(pglob->gl_flags & GLOB_MAGCHAR))) - return(globextend(pattern, pglob, limit)); - else - return(GLOB_NOMATCH); - } - if (!(pglob->gl_flags & GLOB_NOSORT)) - qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, - pglob->gl_pathc - oldpathc, sizeof(char *), compare); - return(0); -} - -static int -compare(p, q) - const void *p, *q; -{ - return(strcmp(*(char **)p, *(char **)q)); -} - -static int -glob1(pattern, pattern_last, pglob, limit) - Char *pattern, *pattern_last; - glob_t *pglob; - size_t *limit; -{ - Char pathbuf[MAXPATHLEN]; - - /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ - if (*pattern == EOS) - return(0); - return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, - pathbuf, pathbuf+MAXPATHLEN-1, - pattern, pattern_last, pglob, limit)); -} - -/* - * The functions glob2 and glob3 are mutually recursive; there is one level - * of recursion for each segment in the pattern that contains one or more - * meta characters. - */ -static int -glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern, - pattern_last, pglob, limit) - Char *pathbuf, *pathbuf_last, *pathend, *pathend_last; - Char *pattern, *pattern_last; - glob_t *pglob; - size_t *limit; -{ - struct stat sb; - Char *p, *q; - int anymeta; - - /* - * Loop over pattern segments until end of pattern or until - * segment with meta character found. - */ - for (anymeta = 0;;) { - if (*pattern == EOS) { /* End of pattern? */ - *pathend = EOS; - if (g_lstat(pathbuf, &sb, pglob)) - return(0); - - if ((pglob->gl_flags & GLOB_LIMIT) && - limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) { - errno = 0; - *pathend++ = SEP; - *pathend = EOS; - return GLOB_NOSPACE; - } - - if (((pglob->gl_flags & GLOB_MARK) && - pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || - (S_ISLNK(sb.st_mode) && - (g_stat(pathbuf, &sb, pglob) == 0) && - S_ISDIR(sb.st_mode)))) { - if (pathend+1 > pathend_last) - return (1); - *pathend++ = SEP; - *pathend = EOS; - } - ++pglob->gl_matchc; - return(globextend(pathbuf, pglob, limit)); - } - - /* Find end of next segment, copy tentatively to pathend. */ - q = pathend; - p = pattern; - while (*p != EOS && *p != SEP) { - if (ismeta(*p)) - anymeta = 1; - if (q+1 > pathend_last) - return (1); - *q++ = *p++; - } - - if (!anymeta) { /* No expansion, do next segment. */ - pathend = q; - pattern = p; - while (*pattern == SEP) { - if (pathend+1 > pathend_last) - return (1); - *pathend++ = *pattern++; - } - } else - /* Need expansion, recurse. */ - return(glob3(pathbuf, pathbuf_last, pathend, - pathend_last, pattern, pattern_last, - p, pattern_last, pglob, limit)); - } - /* NOTREACHED */ -} - -static int -glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, - restpattern, restpattern_last, pglob, limit) - Char *pathbuf, *pathbuf_last, *pathend, *pathend_last; - Char *pattern, *pattern_last, *restpattern, *restpattern_last; - glob_t *pglob; - size_t *limit; -{ - register struct dirent *dp; - DIR *dirp; - int err; - char buf[MAXPATHLEN]; - - /* - * The readdirfunc declaration can't be prototyped, because it is - * assigned, below, to two functions which are prototyped in glob.h - * and dirent.h as taking pointers to differently typed opaque - * structures. - */ - struct dirent *(*readdirfunc)(); - - if (pathend > pathend_last) - return (1); - *pathend = EOS; - errno = 0; - - if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { - /* TODO: don't call for ENOENT or ENOTDIR? */ - if (pglob->gl_errfunc) { - if (g_Ctoc(pathbuf, buf, sizeof(buf))) - return(GLOB_ABORTED); - if (pglob->gl_errfunc(buf, errno) || - pglob->gl_flags & GLOB_ERR) - return(GLOB_ABORTED); - } - return(0); - } - - err = 0; - - /* Search directory for matching names. */ - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - readdirfunc = pglob->gl_readdir; - else - readdirfunc = readdir; - while ((dp = (*readdirfunc)(dirp))) { - register u_char *sc; - register Char *dc; - - if ((pglob->gl_flags & GLOB_LIMIT) && - limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) { - errno = 0; - *pathend++ = SEP; - *pathend = EOS; - return GLOB_NOSPACE; - } - - /* Initial DOT must be matched literally. */ - if (dp->d_name[0] == DOT && *pattern != DOT) - continue; - dc = pathend; - sc = (u_char *) dp->d_name; - while (dc < pathend_last && (*dc++ = *sc++) != EOS) - ; - if (dc >= pathend_last) { - *dc = EOS; - err = 1; - break; - } - - if (!match(pathend, pattern, restpattern)) { - *pathend = EOS; - continue; - } - err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, - restpattern, restpattern_last, pglob, limit); - if (err) - break; - } - - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - (*pglob->gl_closedir)(dirp); - else - closedir(dirp); - return(err); -} - - -/* - * Extend the gl_pathv member of a glob_t structure to accommodate a new item, - * add the new item, and update gl_pathc. - * - * This assumes the BSD realloc, which only copies the block when its size - * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic - * behavior. - * - * Return 0 if new item added, error code if memory couldn't be allocated. - * - * Invariant of the glob_t structure: - * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and - * gl_pathv points to (gl_offs + gl_pathc + 1) items. - */ -static int -globextend(path, pglob, limit) - const Char *path; - glob_t *pglob; - size_t *limit; -{ - register char **pathv; - register int i; - u_int newsize, len; - char *copy; - const Char *p; - - newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); - pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : - malloc(newsize); - if (pathv == NULL) { - if (pglob->gl_pathv) { - free(pglob->gl_pathv); - pglob->gl_pathv = NULL; - } - return(GLOB_NOSPACE); - } - - if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { - /* first time around -- clear initial gl_offs items */ - pathv += pglob->gl_offs; - for (i = pglob->gl_offs; --i >= 0; ) - *--pathv = NULL; - } - pglob->gl_pathv = pathv; - - for (p = path; *p++;) - ; - len = (size_t)(p - path); - limit[GLOB_INDEX_MALLOC] += len; - if ((copy = malloc(len)) != NULL) { - if (g_Ctoc(path, copy, len)) { - free(copy); - return(GLOB_NOSPACE); - } - pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; - } - pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; - if ((pglob->gl_flags & GLOB_LIMIT) && - (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) { - errno = 0; - return GLOB_NOSPACE; - } - - return(copy == NULL ? GLOB_NOSPACE : 0); -} - - -/* - * pattern matching function for filenames. Each occurrence of the * - * pattern causes a recursion level. - */ -static int -match(name, pat, patend) - register Char *name, *pat, *patend; -{ - int ok, negate_range; - Char c, k; - - while (pat < patend) { - c = *pat++; - switch (c & M_MASK) { - case M_ALL: - if (pat == patend) - return(1); - do - if (match(name, pat, patend)) - return(1); - while (*name++ != EOS) - ; - return(0); - case M_ONE: - if (*name++ == EOS) - return(0); - break; - case M_SET: - ok = 0; - if ((k = *name++) == EOS) - return(0); - if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) - ++pat; - while (((c = *pat++) & M_MASK) != M_END) - if ((*pat & M_MASK) == M_RNG) { - if (c <= k && k <= pat[1]) - ok = 1; - pat += 2; - } else if (c == k) - ok = 1; - if (ok == negate_range) - return(0); - break; - default: - if (*name++ != c) - return(0); - break; - } - } - return(*name == EOS); -} - -/* Free allocated data belonging to a glob_t structure. */ -void -globfree(pglob) - glob_t *pglob; -{ - register int i; - register char **pp; - - if (pglob->gl_pathv != NULL) { - pp = pglob->gl_pathv + pglob->gl_offs; - for (i = pglob->gl_pathc; i--; ++pp) - if (*pp) - free(*pp); - free(pglob->gl_pathv); - pglob->gl_pathv = NULL; - } -} - -static DIR * -g_opendir(str, pglob) - register Char *str; - glob_t *pglob; -{ - char buf[MAXPATHLEN]; - - if (!*str) - strlcpy(buf, ".", sizeof buf); - else { - if (g_Ctoc(str, buf, sizeof(buf))) - return(NULL); - } - - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - return((*pglob->gl_opendir)(buf)); - - return(opendir(buf)); -} - -static int -g_lstat(fn, sb, pglob) - register Char *fn; - struct stat *sb; - glob_t *pglob; -{ - char buf[MAXPATHLEN]; - - if (g_Ctoc(fn, buf, sizeof(buf))) - return(-1); - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - return((*pglob->gl_lstat)(buf, sb)); - return(lstat(buf, sb)); -} - -static int -g_stat(fn, sb, pglob) - register Char *fn; - struct stat *sb; - glob_t *pglob; -{ - char buf[MAXPATHLEN]; - - if (g_Ctoc(fn, buf, sizeof(buf))) - return(-1); - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - return((*pglob->gl_stat)(buf, sb)); - return(stat(buf, sb)); -} - -static Char * -g_strchr(str, ch) - Char *str; - int ch; -{ - do { - if (*str == ch) - return (str); - } while (*str++); - return (NULL); -} - -static int -g_Ctoc(str, buf, len) - register const Char *str; - char *buf; - u_int len; -{ - - while (len--) { - if ((*buf++ = *str++) == EOS) - return (0); - } - return (1); -} - -#ifdef DEBUG -static void -qprintf(str, s) - const char *str; - register Char *s; -{ - register Char *p; - - (void)printf("%s:\n", str); - for (p = s; *p; p++) - (void)printf("%c", CHAR(*p)); - (void)printf("\n"); - for (p = s; *p; p++) - (void)printf("%c", *p & M_PROTECT ? '"' : ' '); - (void)printf("\n"); - for (p = s; *p; p++) - (void)printf("%c", ismeta(*p) ? '_' : ' '); - (void)printf("\n"); -} -#endif - -#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || - !defined(GLOB_HAS_GL_MATCHC) */ - - diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/inet_aton.c b/usr/src/cmd/ssh/libopenbsd-compat/common/inet_aton.c deleted file mode 100644 index d98afff30d..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/inet_aton.c +++ /dev/null @@ -1,195 +0,0 @@ -/* $OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $ */ - -/* - * ++Copyright++ 1983, 1990, 1993 - * - - * Copyright (c) 1983, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - - * --Copyright-- - */ - -#include "includes.h" - -#if !defined(HAVE_INET_ATON) - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $"; -#else -static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <ctype.h> - -#if 0 -/* - * Ascii internet address interpretation routine. - * The value returned is in network order. - */ -in_addr_t -inet_addr(cp) - register const char *cp; -{ - struct in_addr val; - - if (inet_aton(cp, &val)) - return (val.s_addr); - return (INADDR_NONE); -} -#endif - -/* - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - */ -int -inet_aton(const char *cp, struct in_addr *addr) -{ - register u_int32_t val; - register int base, n; - register char c; - unsigned int parts[4]; - register unsigned int *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, isdigit=decimal. - */ - if (!isdigit(c)) - return (0); - val = 0; base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') - base = 16, c = *++cp; - else - base = 8; - } - for (;;) { - if (isascii(c) && isdigit(c)) { - val = (val * base) + (c - '0'); - c = *++cp; - } else if (base == 16 && isascii(c) && isxdigit(c)) { - val = (val << 4) | - (c + 10 - (islower(c) ? 'a' : 'A')); - c = *++cp; - } else - break; - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) - return (0); - *pp++ = val; - c = *++cp; - } else - break; - } - /* - * Check for trailing characters. - */ - if (c != '\0' && (!isascii(c) || !isspace(c))) - return (0); - /* - * Concoct the address according to - * the number of parts specified. - */ - n = pp - parts + 1; - switch (n) { - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if ((val > 0xffffff) || (parts[0] > 0xff)) - return (0); - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - if (addr) - addr->s_addr = htonl(val); - return (1); -} - -#endif /* !defined(HAVE_INET_ATON) */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/inet_ntoa.c b/usr/src/cmd/ssh/libopenbsd-compat/common/inet_ntoa.c deleted file mode 100644 index e788c83ea0..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/inet_ntoa.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.3 2002/06/27 10:14:01 itojun Exp $"; -#endif /* LIBC_SCCS and not lint */ - -/* - * Convert network-format internet address - * to base 256 d.d.d.d representation. - */ -#include <sys/types.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <stdio.h> -#include "inet_ntoa.h" - -char *inet_ntoa(struct in_addr in) -{ - static char b[18]; - register char *p; - - p = (char *)∈ -#define UC(b) (((int)b)&0xff) - (void)snprintf(b, sizeof(b), - "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); - return (b); -} - -#endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/inet_ntop.c b/usr/src/cmd/ssh/libopenbsd-compat/common/inet_ntop.c deleted file mode 100644 index ed1acbfb1e..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/inet_ntop.c +++ /dev/null @@ -1,232 +0,0 @@ -/* $OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $ */ - -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include "includes.h" - -#ifndef HAVE_INET_NTOP - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $"; -#else -static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include "fake-socket.h" -#include <netinet/in.h> -#include <arpa/inet.h> -#ifndef HAVE_CYGWIN -#include <arpa/nameser.h> -#endif -#include <string.h> -#include <errno.h> -#include <stdio.h> - -#ifndef IN6ADDRSZ -#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ -#endif - -#ifndef INT16SZ -#define INT16SZ 2 /* for systems without 16-bit ints */ -#endif - -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ - -static const char *inet_ntop4(const u_char *src, char *dst, size_t size); -static const char *inet_ntop6(const u_char *src, char *dst, size_t size); - -/* char * - * inet_ntop(af, src, dst, size) - * convert a network format address to presentation format. - * return: - * pointer to presentation format address (`dst'), or NULL (see errno). - * author: - * Paul Vixie, 1996. - */ -const char * -inet_ntop(af, src, dst, size) - int af; - const void *src; - char *dst; - size_t size; -{ - switch (af) { - case AF_INET: - return (inet_ntop4(src, dst, size)); - case AF_INET6: - return (inet_ntop6(src, dst, size)); - default: - errno = EAFNOSUPPORT; - return (NULL); - } - /* NOTREACHED */ -} - -/* const char * - * inet_ntop4(src, dst, size) - * format an IPv4 address, more or less like inet_ntoa() - * return: - * `dst' (as a const) - * notes: - * (1) uses no statics - * (2) takes a u_char* not an in_addr as input - * author: - * Paul Vixie, 1996. - */ -static const char * -inet_ntop4(src, dst, size) - const u_char *src; - char *dst; - size_t size; -{ - static const char fmt[] = "%u.%u.%u.%u"; - char tmp[sizeof "255.255.255.255"]; - int l; - - l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); - if (l <= 0 || l >= size) { - errno = ENOSPC; - return (NULL); - } - strlcpy(dst, tmp, size); - return (dst); -} - -/* const char * - * inet_ntop6(src, dst, size) - * convert IPv6 binary address into presentation (printable) format - * author: - * Paul Vixie, 1996. - */ -static const char * -inet_ntop6(src, dst, size) - const u_char *src; - char *dst; - size_t size; -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; - char *tp, *ep; - struct { int base, len; } best, cur; - u_int words[IN6ADDRSZ / INT16SZ]; - int i; - int advance; - - /* - * Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof words); - for (i = 0; i < IN6ADDRSZ; i++) - words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); - best.base = -1; - cur.base = -1; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { - if (words[i] == 0) { - if (cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } else { - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - } - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - } - if (best.base != -1 && best.len < 2) - best.base = -1; - - /* - * Format the result. - */ - tp = tmp; - ep = tmp + sizeof(tmp); - for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { - /* Are we inside the best run of 0x00's? */ - if (best.base != -1 && i >= best.base && - i < (best.base + best.len)) { - if (i == best.base) { - if (tp + 1 >= ep) - return (NULL); - *tp++ = ':'; - } - continue; - } - /* Are we following an initial run of 0x00s or any real hex? */ - if (i != 0) { - if (tp + 1 >= ep) - return (NULL); - *tp++ = ':'; - } - /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { - if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) - return (NULL); - tp += strlen(tp); - break; - } - advance = snprintf(tp, ep - tp, "%x", words[i]); - if (advance <= 0 || advance >= ep - tp) - return (NULL); - tp += advance; - } - /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { - if (tp + 1 >= ep) - return (NULL); - *tp++ = ':'; - } - if (tp + 1 >= ep) - return (NULL); - *tp++ = '\0'; - - /* - * Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) { - errno = ENOSPC; - return (NULL); - } - strlcpy(dst, tmp, size); - return (dst); -} - -#endif /* !HAVE_INET_NTOP */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/llib-lopenbsd-compat b/usr/src/cmd/ssh/libopenbsd-compat/common/llib-lopenbsd-compat deleted file mode 100644 index 3c5912997f..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/llib-lopenbsd-compat +++ /dev/null @@ -1,83 +0,0 @@ -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -/* - * 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 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <includes.h> -#include <atomicio.h> -#include <base64.h> -#include <bindresvport.h> -#include <bsd-arc4random.h> -#include <bsd-cray.h> -#include <bsd-cygwin_util.h> -#include <bsd-getpeereid.h> -#include <bsd-misc.h> -#include <bsd-snprintf.h> -#include <bsd-waitpid.h> -#include <config.h> -#include <crc32.h> -#include <deattack.h> -#include <defines.h> -#include <dirname.h> -#include <dispatch.h> -#include <entropy.h> -#include <fake-gai-errnos.h> -#include <fake-getaddrinfo.h> -#include <fake-getnameinfo.h> -#include <fake-socket.h> -#include <getcwd.h> -#include <getgrouplist.h> -#include <getopt.h> -#include <getput.h> -#include <glob.h> -#include <groupaccess.h> -#include <inet_ntoa.h> -#include <inet_ntop.h> -#include <log.h> -#include <match.h> -#include <misc.h> -#include <mktemp.h> -#include <openbsd-compat.h> -#include <pathnames.h> -#include <port-aix.h> -#include <port-irix.h> -#include <proxy-io.h> -#include <readpass.h> -#include <readpassphrase.h> -#include <realpath.h> -#include <rresvport.h> -#include <rsa.h> -#include <setproctitle.h> -#include <sigact.h> -#include <strlcat.h> -#include <strlcpy.h> -#include <strmode.h> -#include <sys-queue.h> -#include <sys-tree.h> -#include <tildexpand.h> -#include <uuencode.h> -#include <version.h> -#include <xmalloc.h> -#include <xmmap.h> diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/mktemp.c b/usr/src/cmd/ssh/libopenbsd-compat/common/mktemp.c deleted file mode 100644 index c6b18d22d4..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/mktemp.c +++ /dev/null @@ -1,186 +0,0 @@ -/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ -/* Changes: Removed mktemp */ - -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#ifndef HAVE_MKDTEMP - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: mktemp.c,v 1.16 2002/05/27 18:20:45 millert Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#ifdef HAVE_CYGWIN -#define open binary_open -extern int binary_open(); -#endif - -static int _gettemp(char *, int *, int, int); - -int -mkstemps(path, slen) - char *path; - int slen; -{ - int fd; - - return (_gettemp(path, &fd, 0, slen) ? fd : -1); -} - -int -mkstemp(path) - char *path; -{ - int fd; - - return (_gettemp(path, &fd, 0, 0) ? fd : -1); -} - -char * -mkdtemp(path) - char *path; -{ - return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); -} - -static int -_gettemp(path, doopen, domkdir, slen) - char *path; - register int *doopen; - int domkdir; - int slen; -{ - register char *start, *trv, *suffp; - struct stat sbuf; - int rval; - pid_t pid; - - if (doopen && domkdir) { - errno = EINVAL; - return(0); - } - - for (trv = path; *trv; ++trv) - ; - trv -= slen; - suffp = trv; - --trv; - if (trv < path) { - errno = EINVAL; - return (0); - } - pid = getpid(); - while (trv >= path && *trv == 'X' && pid != 0) { - *trv-- = (pid % 10) + '0'; - pid /= 10; - } - while (trv >= path && *trv == 'X') { - char c; - - pid = (arc4random() & 0xffff) % (26+26); - if (pid < 26) - c = pid + 'A'; - else - c = (pid - 26) + 'a'; - *trv-- = c; - } - start = trv + 1; - - /* - * check the target directory; if you have six X's and it - * doesn't exist this runs for a *very* long time. - */ - if (doopen || domkdir) { - for (;; --trv) { - if (trv <= path) - break; - if (*trv == '/') { - *trv = '\0'; - rval = stat(path, &sbuf); - *trv = '/'; - if (rval != 0) - return(0); - if (!S_ISDIR(sbuf.st_mode)) { - errno = ENOTDIR; - return(0); - } - break; - } - } - } - - for (;;) { - if (doopen) { - if ((*doopen = - open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) - return(1); - if (errno != EEXIST) - return(0); - } else if (domkdir) { - if (mkdir(path, 0700) == 0) - return(1); - if (errno != EEXIST) - return(0); - } else if (lstat(path, &sbuf)) - return(errno == ENOENT ? 1 : 0); - - /* tricky little algorithm for backward compatibility */ - for (trv = start;;) { - if (!*trv) - return (0); - if (*trv == 'Z') { - if (trv == suffp) - return (0); - *trv++ = 'a'; - } else { - if (isdigit(*trv)) - *trv = 'a'; - else if (*trv == 'z') /* inc from z to A */ - *trv = 'A'; - else { - if (trv == suffp) - return (0); - ++*trv; - } - break; - } - } - } - /*NOTREACHED*/ -} - -#endif /* !HAVE_MKDTEMP */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/port-aix.c b/usr/src/cmd/ssh/libopenbsd-compat/common/port-aix.c deleted file mode 100644 index 4b83f53c07..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/port-aix.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Copyright (c) 2001 Gert Doering. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "includes.h" - -#ifdef _AIX - -#include <uinfo.h> -#include <../xmalloc.h> - -/* - * AIX has a "usrinfo" area where logname and other stuff is stored - - * a few applications actually use this and die if it's not set - * - * NOTE: TTY= should be set, but since no one uses it and it's hard to - * acquire due to privsep code. We will just drop support. - */ -void -aix_usrinfo(struct passwd *pw) -{ - u_int i; - char *cp; - - cp = xmalloc(16 + 2 * strlen(pw->pw_name)); - i = sprintf(cp, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, 0, - pw->pw_name, 0); - if (usrinfo(SETUINFO, cp, i) == -1) - fatal("Couldn't set usrinfo: %s", strerror(errno)); - debug3("AIX/UsrInfo: set len %d", i); - xfree(cp); -} - -#endif /* _AIX */ - - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/port-irix.c b/usr/src/cmd/ssh/libopenbsd-compat/common/port-irix.c deleted file mode 100644 index 5f839043c0..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/port-irix.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "includes.h" - -#if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) - -#ifdef WITH_IRIX_PROJECT -#include <proj.h> -#endif /* WITH_IRIX_PROJECT */ -#ifdef WITH_IRIX_JOBS -#include <sys/resource.h> -#endif -#ifdef WITH_IRIX_AUDIT -#include <sat.h> -#endif /* WITH_IRIX_AUDIT */ - -void -irix_setusercontext(struct passwd *pw) -{ -#ifdef WITH_IRIX_PROJECT - prid_t projid; -#endif /* WITH_IRIX_PROJECT */ -#ifdef WITH_IRIX_JOBS - jid_t jid = 0; -#else -# ifdef WITH_IRIX_ARRAY - int jid = 0; -# endif /* WITH_IRIX_ARRAY */ -#endif /* WITH_IRIX_JOBS */ - -#ifdef WITH_IRIX_JOBS - jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive"); - if (jid == -1) - fatal("Failed to create job container: %.100s", - strerror(errno)); -#endif /* WITH_IRIX_JOBS */ -#ifdef WITH_IRIX_ARRAY - /* initialize array session */ - if (jid == 0 && newarraysess() != 0) - fatal("Failed to set up new array session: %.100s", - strerror(errno)); -#endif /* WITH_IRIX_ARRAY */ -#ifdef WITH_IRIX_PROJECT - /* initialize irix project info */ - if ((projid = getdfltprojuser(pw->pw_name)) == -1) { - debug("Failed to get project id, using projid 0"); - projid = 0; - } - if (setprid(projid)) - fatal("Failed to initialize project %d for %s: %.100s", - (int)projid, pw->pw_name, strerror(errno)); -#endif /* WITH_IRIX_PROJECT */ -#ifdef WITH_IRIX_AUDIT - if (sysconf(_SC_AUDIT)) { - debug("Setting sat id to %d", (int) pw->pw_uid); - if (satsetid(pw->pw_uid)) - debug("error setting satid: %.100s", strerror(errno)); - } -#endif /* WITH_IRIX_AUDIT */ -} - - -#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/readpassphrase.c b/usr/src/cmd/ssh/libopenbsd-compat/common/readpassphrase.c deleted file mode 100644 index 67ed2caff7..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/readpassphrase.c +++ /dev/null @@ -1,192 +0,0 @@ -/* $OpenBSD: readpassphrase.c,v 1.14 2002/06/28 01:43:58 millert Exp $ */ - -/* - * Copyright (c) 2000-2002 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.14 2002/06/28 01:43:58 millert Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include "includes.h" - -#ifndef HAVE_READPASSPHRASE - -#include <termios.h> -#include <readpassphrase.h> - -#ifdef TCSASOFT -# define _T_FLUSH (TCSAFLUSH|TCSASOFT) -#else -# define _T_FLUSH (TCSAFLUSH) -#endif - -/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */ -#if !defined(_POSIX_VDISABLE) && defined(VDISABLE) -# define _POSIX_VDISABLE VDISABLE -#endif - -static volatile sig_atomic_t signo; - -static void handler(int); - -char * -readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) -{ - ssize_t nr; - int input, output, save_errno; - char ch, *p, *end; - struct termios term, oterm; - struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; - struct sigaction savetstp, savettin, savettou, savepipe; - - /* I suppose we could alloc on demand in this case (XXX). */ - if (bufsiz == 0) { - errno = EINVAL; - return(NULL); - } - -restart: - signo = 0; - /* - * Read and write to /dev/tty if available. If not, read from - * stdin and write to stderr unless a tty is required. - */ - if ((flags & RPP_STDIN) || - (input = output = open(_PATH_TTY, O_RDWR)) == -1) { - if (flags & RPP_REQUIRE_TTY) { - errno = ENOTTY; - return(NULL); - } - input = STDIN_FILENO; - output = STDERR_FILENO; - } - - /* - * Catch signals that would otherwise cause the user to end - * up with echo turned off in the shell. Don't worry about - * things like SIGXCPU and SIGVTALRM for now. - */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; /* don't restart system calls */ - sa.sa_handler = handler; - (void)sigaction(SIGALRM, &sa, &savealrm); - (void)sigaction(SIGHUP, &sa, &savehup); - (void)sigaction(SIGINT, &sa, &saveint); - (void)sigaction(SIGPIPE, &sa, &savepipe); - (void)sigaction(SIGQUIT, &sa, &savequit); - (void)sigaction(SIGTERM, &sa, &saveterm); - (void)sigaction(SIGTSTP, &sa, &savetstp); - (void)sigaction(SIGTTIN, &sa, &savettin); - (void)sigaction(SIGTTOU, &sa, &savettou); - - /* Turn off echo if possible. */ - if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { - memcpy(&term, &oterm, sizeof(term)); - if (!(flags & RPP_ECHO_ON)) - term.c_lflag &= ~(ECHO | ECHONL); -#ifdef VSTATUS - if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) - term.c_cc[VSTATUS] = _POSIX_VDISABLE; -#endif - (void)tcsetattr(input, _T_FLUSH, &term); - } else { - memset(&term, 0, sizeof(term)); - term.c_lflag |= ECHO; - memset(&oterm, 0, sizeof(oterm)); - oterm.c_lflag |= ECHO; - } - - if (!(flags & RPP_STDIN)) - (void)write(output, prompt, strlen(prompt)); - end = buf + bufsiz - 1; - for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { - if (p < end) { - if ((flags & RPP_SEVENBIT)) - ch &= 0x7f; - if (isalpha(ch)) { - if ((flags & RPP_FORCELOWER)) - ch = tolower(ch); - if ((flags & RPP_FORCEUPPER)) - ch = toupper(ch); - } - *p++ = ch; - } - } - *p = '\0'; - save_errno = errno; - if (!(term.c_lflag & ECHO)) - (void)write(output, "\n", 1); - - /* Restore old terminal settings and signals. */ - if (memcmp(&term, &oterm, sizeof(term)) != 0) - (void)tcsetattr(input, _T_FLUSH, &oterm); - (void)sigaction(SIGALRM, &savealrm, NULL); - (void)sigaction(SIGHUP, &savehup, NULL); - (void)sigaction(SIGINT, &saveint, NULL); - (void)sigaction(SIGQUIT, &savequit, NULL); - (void)sigaction(SIGPIPE, &savepipe, NULL); - (void)sigaction(SIGTERM, &saveterm, NULL); - (void)sigaction(SIGTSTP, &savetstp, NULL); - (void)sigaction(SIGTTIN, &savettin, NULL); - if (input != STDIN_FILENO) - (void)close(input); - - /* - * If we were interrupted by a signal, resend it to ourselves - * now that we have restored the signal handlers. - */ - if (signo) { - kill(getpid(), signo); - switch (signo) { - case SIGTSTP: - case SIGTTIN: - case SIGTTOU: - goto restart; - } - } - - errno = save_errno; - return(nr == -1 ? NULL : buf); -} - -#if 0 -char * -getpass(const char *prompt) -{ - static char buf[_PASSWORD_LEN + 1]; - - return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); -} -#endif - -static void handler(int s) -{ - signo = s; -} -#endif /* HAVE_READPASSPHRASE */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/realpath.c b/usr/src/cmd/ssh/libopenbsd-compat/common/realpath.c deleted file mode 100644 index e962264a50..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/realpath.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: realpath.c,v 1.7 2002/05/24 21:22:37 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * MAXSYMLINKS - */ -#ifndef MAXSYMLINKS -#define MAXSYMLINKS 5 -#endif - -/* - * char *realpath(const char *path, char resolved_path[MAXPATHLEN]); - * - * Find the real name of path, by removing all ".", ".." and symlink - * components. Returns (resolved) on success, or (NULL) on failure, - * in which case the path which caused trouble is left in (resolved). - */ -char * -realpath(const char *path, char *resolved) -{ - struct stat sb; - int fd, n, rootd, serrno = 0; - char *p, *q, wbuf[MAXPATHLEN], start[MAXPATHLEN]; - int symlinks = 0; - - /* Save the starting point. */ - getcwd(start,MAXPATHLEN); - if ((fd = open(".", O_RDONLY)) < 0) { - (void)strlcpy(resolved, ".", MAXPATHLEN); - return (NULL); - } - close(fd); - - /* Convert "." -> "" to optimize away a needless lstat() and chdir() */ - if (path[0] == '.' && path[1] == '\0') - path = ""; - - /* - * Find the dirname and basename from the path to be resolved. - * Change directory to the dirname component. - * lstat the basename part. - * if it is a symlink, read in the value and loop. - * if it is a directory, then change to that directory. - * get the current directory name and append the basename. - */ - strlcpy(resolved, path, MAXPATHLEN); -loop: - q = strrchr(resolved, '/'); - if (q != NULL) { - p = q + 1; - if (q == resolved) - q = "/"; - else { - do { - --q; - } while (q > resolved && *q == '/'); - q[1] = '\0'; - q = resolved; - } - if (chdir(q) < 0) - goto err1; - } else - p = resolved; - - /* Deal with the last component. */ - if (*p != '\0' && lstat(p, &sb) == 0) { - if (S_ISLNK(sb.st_mode)) { - if (++symlinks > MAXSYMLINKS) { - serrno = ELOOP; - goto err1; - } - n = readlink(p, resolved, MAXPATHLEN-1); - if (n < 0) - goto err1; - resolved[n] = '\0'; - goto loop; - } - if (S_ISDIR(sb.st_mode)) { - if (chdir(p) < 0) - goto err1; - p = ""; - } - } - - /* - * Save the last component name and get the full pathname of - * the current directory. - */ - (void)strlcpy(wbuf, p, sizeof wbuf); - if (getcwd(resolved, MAXPATHLEN) == 0) - goto err1; - - /* - * Join the two strings together, ensuring that the right thing - * happens if the last component is empty, or the dirname is root. - */ - if (resolved[0] == '/' && resolved[1] == '\0') - rootd = 1; - else - rootd = 0; - - if (*wbuf) { - if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { - serrno = ENAMETOOLONG; - goto err1; - } - if (rootd == 0) - (void)strcat(resolved, "/"); - (void)strcat(resolved, wbuf); - } - - /* Go back to where we came from. */ - if (chdir(start) < 0) { - serrno = errno; - goto err2; - } - return (resolved); - -err1: chdir(start); -err2: errno = serrno; - return (NULL); -} -#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/rresvport.c b/usr/src/cmd/ssh/libopenbsd-compat/common/rresvport.c deleted file mode 100644 index bfb9a0a51c..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/rresvport.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. - * Copyright (c) 1983, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * This product includes software developed by Theo de Raadt. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#ifndef HAVE_RRESVPORT_AF - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: rresvport.c,v 1.5 2000/01/26 03:43:20 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include "includes.h" - -#if 0 -int -rresvport(alport) - int *alport; -{ - return rresvport_af(alport, AF_INET); -} -#endif - -int -rresvport_af(int *alport, sa_family_t af) -{ - struct sockaddr_storage ss; - struct sockaddr *sa; - u_int16_t *portp; - int s; - socklen_t salen; - - memset(&ss, '\0', sizeof ss); - sa = (struct sockaddr *)&ss; - - switch (af) { - case AF_INET: - salen = sizeof(struct sockaddr_in); - portp = &((struct sockaddr_in *)sa)->sin_port; - break; - case AF_INET6: - salen = sizeof(struct sockaddr_in6); - portp = &((struct sockaddr_in6 *)sa)->sin6_port; - break; - default: - errno = EPFNOSUPPORT; - return (-1); - } - sa->sa_family = af; - - s = socket(af, SOCK_STREAM, 0); - if (s < 0) - return (-1); - - *portp = htons(*alport); - if (*alport < IPPORT_RESERVED - 1) { - if (bind(s, sa, salen) >= 0) - return (s); - if (errno != EADDRINUSE) { - (void)close(s); - return (-1); - } - } - - *portp = 0; - sa->sa_family = af; - if (bindresvport_sa(s, sa) == -1) { - (void)close(s); - return (-1); - } - *alport = ntohs(*portp); - return (s); -} - -#endif /* HAVE_RRESVPORT_AF */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/setenv.c b/usr/src/cmd/ssh/libopenbsd-compat/common/setenv.c deleted file mode 100644 index ed5b9525ce..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/setenv.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" -#ifndef HAVE_SETENV - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: setenv.c,v 1.4 2001/07/09 06:57:45 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <stdlib.h> -#include <string.h> - -/* - * __findenv -- - * Returns pointer to value associated with name, if any, else NULL. - * Sets offset to be the offset of the name/value combination in the - * environmental array, for use by setenv(3) and unsetenv(3). - * Explicitly removes '=' in argument name. - * - * This routine *should* be a static; don't use it. - */ -char * -__findenv(name, offset) - register const char *name; - int *offset; -{ - extern char **environ; - register int len, i; - register const char *np; - register char **p, *cp; - - if (name == NULL || environ == NULL) - return (NULL); - for (np = name; *np && *np != '='; ++np) - ; - len = np - name; - for (p = environ; (cp = *p) != NULL; ++p) { - for (np = name, i = len; i && *cp; i--) - if (*cp++ != *np++) - break; - if (i == 0 && *cp++ == '=') { - *offset = p - environ; - return (cp); - } - } - return (NULL); -} - -/* - * setenv -- - * Set the value of the environmental variable "name" to be - * "value". If rewrite is set, replace any current value. - */ -int -setenv(name, value, rewrite) - register const char *name; - register const char *value; - int rewrite; -{ - extern char **environ; - static int alloced; /* if allocated space before */ - register char *C; - int l_value, offset; - char *__findenv(); - - if (*value == '=') /* no `=' in value */ - ++value; - l_value = strlen(value); - if ((C = __findenv(name, &offset))) { /* find if already exists */ - if (!rewrite) - return (0); - if (strlen(C) >= l_value) { /* old larger; copy over */ - while ((*C++ = *value++)) - ; - return (0); - } - } else { /* create new slot */ - register int cnt; - register char **P; - - for (P = environ, cnt = 0; *P; ++P, ++cnt); - if (alloced) { /* just increase size */ - P = (char **)realloc((void *)environ, - (size_t)(sizeof(char *) * (cnt + 2))); - if (!P) - return (-1); - environ = P; - } - else { /* get new space */ - alloced = 1; /* copy old entries into it */ - P = (char **)malloc((size_t)(sizeof(char *) * - (cnt + 2))); - if (!P) - return (-1); - memmove(P, environ, cnt * sizeof(char *)); - environ = P; - } - environ[cnt + 1] = NULL; - offset = cnt; - } - for (C = (char *)name; *C && *C != '='; ++C); /* no `=' in name */ - if (!(environ[offset] = /* name + `=' + value */ - malloc((size_t)((int)(C - name) + l_value + 2)))) - return (-1); - /* LINTED */ - for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) - ; - for (*C++ = '='; (*C++ = *value++); ) - ; - return (0); -} - -/* - * unsetenv(name) -- - * Delete environmental variable "name". - */ -void -unsetenv(name) - const char *name; -{ - extern char **environ; - register char **P; - int offset; - char *__findenv(); - - while (__findenv(name, &offset)) /* if set multiple times */ - for (P = &environ[offset];; ++P) - /* LINTED */ - if (!(*P = *(P + 1))) - break; -} - -#endif /* HAVE_SETENV */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/setproctitle.c b/usr/src/cmd/ssh/libopenbsd-compat/common/setproctitle.c deleted file mode 100644 index 4163f0cfec..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/setproctitle.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Modified for OpenSSH by Kevin Steves - * October 2000 - */ - -/* - * Copyright (c) 1994, 1995 Christopher G. Demetriou - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou - * for the NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: setproctitle.c,v 1.8 2001/11/06 19:21:40 art Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include "includes.h" - -#ifndef HAVE_SETPROCTITLE - -#define SPT_NONE 0 -#define SPT_PSTAT 1 - -#ifndef SPT_TYPE -#define SPT_TYPE SPT_NONE -#endif - -#if SPT_TYPE == SPT_PSTAT -#include <sys/param.h> -#include <sys/pstat.h> -#endif /* SPT_TYPE == SPT_PSTAT */ - -#define MAX_PROCTITLE 2048 - -extern char *__progname; - -/* - * Set Process Title (SPT) defines. Modeled after sendmail's - * SPT type definition strategy. - * - * SPT_TYPE: - * - * SPT_NONE: Don't set the process title. Default. - * SPT_PSTAT: Use pstat(PSTAT_SETCMD). HP-UX specific. - */ - -void -setproctitle(const char *fmt, ...) -{ -#if SPT_TYPE != SPT_NONE - va_list ap; - - char buf[MAX_PROCTITLE]; - size_t used; - -#if SPT_TYPE == SPT_PSTAT - union pstun pst; -#endif /* SPT_TYPE == SPT_PSTAT */ - - va_start(ap, fmt); - if (fmt != NULL) { - used = snprintf(buf, MAX_PROCTITLE, "%s: ", __progname); - if (used >= MAX_PROCTITLE) - used = MAX_PROCTITLE - 1; - (void)vsnprintf(buf + used, MAX_PROCTITLE - used, fmt, ap); - } else - (void)snprintf(buf, MAX_PROCTITLE, "%s", __progname); - va_end(ap); - used = strlen(buf); - -#if SPT_TYPE == SPT_PSTAT - pst.pst_command = buf; - pstat(PSTAT_SETCMD, pst, used, 0, 0); -#endif /* SPT_TYPE == SPT_PSTAT */ - -#endif /* SPT_TYPE != SPT_NONE */ -} -#endif /* HAVE_SETPROCTITLE */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/sigact.c b/usr/src/cmd/ssh/libopenbsd-compat/common/sigact.c deleted file mode 100644 index 5d89f8bb37..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/sigact.c +++ /dev/null @@ -1,104 +0,0 @@ -/* $OpenBSD: sigaction.c,v 1.3 1999/06/27 08:14:21 millert Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * - * and: Eric S. Raymond <esr@snark.thyrsus.com> * - ****************************************************************************/ - -#include "includes.h" -#include <signal.h> -#include "sigact.h" - -/* This file provides sigaction() emulation using sigvec() */ -/* Use only if this is non POSIX system */ - -#if !HAVE_SIGACTION && HAVE_SIGVEC - -int -sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact) -{ - return sigvec(sig, &(sigact->sv), &(osigact->sv)); -} - -int -sigemptyset (sigset_t * mask) -{ - *mask = 0; - return 0; -} - -int -sigprocmask (int mode, sigset_t * mask, sigset_t * omask) -{ - sigset_t current = sigsetmask(0); - - if (omask) *omask = current; - - if (mode==SIG_BLOCK) - current |= *mask; - else if (mode==SIG_UNBLOCK) - current &= ~*mask; - else if (mode==SIG_SETMASK) - current = *mask; - - sigsetmask(current); - return 0; -} - -int -sigsuspend (sigset_t * mask) -{ - return sigpause(*mask); -} - -int -sigdelset (sigset_t * mask, int sig) -{ - *mask &= ~sigmask(sig); - return 0; -} - -int -sigaddset (sigset_t * mask, int sig) -{ - *mask |= sigmask(sig); - return 0; -} - -int -sigismember (sigset_t * mask, int sig) -{ - return (*mask & sigmask(sig)) != 0; -} - -#endif - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/strlcat.c b/usr/src/cmd/ssh/libopenbsd-compat/common/strlcat.c deleted file mode 100644 index 8143a627d0..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/strlcat.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#ifndef HAVE_STRLCAT - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <string.h> -#include "strlcat.h" - -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - */ -size_t -strlcat(dst, src, siz) - char *dst; - const char *src; - size_t siz; -{ - register char *d = dst; - register const char *s = src; - register size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - -#endif /* !HAVE_STRLCAT */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/strlcpy.c b/usr/src/cmd/ssh/libopenbsd-compat/common/strlcpy.c deleted file mode 100644 index fb87445cd2..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/strlcpy.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#ifndef HAVE_STRLCPY - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <string.h> -#include "strlcpy.h" - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -strlcpy(dst, src, siz) - char *dst; - const char *src; - size_t siz; -{ - register char *d = dst; - register const char *s = src; - register size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -#endif /* !HAVE_STRLCPY */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/strmode.c b/usr/src/cmd/ssh/libopenbsd-compat/common/strmode.c deleted file mode 100644 index 2a52c22d19..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/strmode.c +++ /dev/null @@ -1,158 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" -#ifndef HAVE_STRMODE - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strmode.c,v 1.3 1997/06/13 13:57:20 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <string.h> - -void -strmode(register mode_t mode, register char *p) -{ - /* print type */ - switch (mode & S_IFMT) { - case S_IFDIR: /* directory */ - *p++ = 'd'; - break; - case S_IFCHR: /* character special */ - *p++ = 'c'; - break; - case S_IFBLK: /* block special */ - *p++ = 'b'; - break; - case S_IFREG: /* regular */ - *p++ = '-'; - break; - case S_IFLNK: /* symbolic link */ - *p++ = 'l'; - break; -#ifdef S_IFSOCK - case S_IFSOCK: /* socket */ - *p++ = 's'; - break; -#endif -#ifdef S_IFIFO - case S_IFIFO: /* fifo */ - *p++ = 'p'; - break; -#endif -#ifdef S_IFWHT - case S_IFWHT: /* whiteout */ - *p++ = 'w'; - break; -#endif - default: /* unknown */ - *p++ = '?'; - break; - } - /* usr */ - if (mode & S_IRUSR) - *p++ = 'r'; - else - *p++ = '-'; - if (mode & S_IWUSR) - *p++ = 'w'; - else - *p++ = '-'; - switch (mode & (S_IXUSR | S_ISUID)) { - case 0: - *p++ = '-'; - break; - case S_IXUSR: - *p++ = 'x'; - break; - case S_ISUID: - *p++ = 'S'; - break; - case S_IXUSR | S_ISUID: - *p++ = 's'; - break; - } - /* group */ - if (mode & S_IRGRP) - *p++ = 'r'; - else - *p++ = '-'; - if (mode & S_IWGRP) - *p++ = 'w'; - else - *p++ = '-'; - switch (mode & (S_IXGRP | S_ISGID)) { - case 0: - *p++ = '-'; - break; - case S_IXGRP: - *p++ = 'x'; - break; - case S_ISGID: - *p++ = 'S'; - break; - case S_IXGRP | S_ISGID: - *p++ = 's'; - break; - } - /* other */ - if (mode & S_IROTH) - *p++ = 'r'; - else - *p++ = '-'; - if (mode & S_IWOTH) - *p++ = 'w'; - else - *p++ = '-'; - switch (mode & (S_IXOTH | S_ISVTX)) { - case 0: - *p++ = '-'; - break; - case S_IXOTH: - *p++ = 'x'; - break; - case S_ISVTX: - *p++ = 'T'; - break; - case S_IXOTH | S_ISVTX: - *p++ = 't'; - break; - } - *p++ = ' '; /* will be a '+' if ACL's implemented */ - *p = '\0'; -} -#endif - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/xmmap.c b/usr/src/cmd/ssh/libopenbsd-compat/common/xmmap.c deleted file mode 100644 index 9548d47e0d..0000000000 --- a/usr/src/cmd/ssh/libopenbsd-compat/common/xmmap.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#include "log.h" - -void *xmmap(size_t size) -{ - void *address; - -#ifdef HAVE_MMAP -# ifdef MAP_ANON - address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, - -1, 0); -# else - address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, - open("/dev/zero", O_RDWR), 0); -# endif - -#define MM_SWAP_TEMPLATE "/var/run/sshd.mm.XXXXXXXX" - if (address == MAP_FAILED) { - char tmpname[sizeof(MM_SWAP_TEMPLATE)] = MM_SWAP_TEMPLATE; - int tmpfd; - - tmpfd = mkstemp(tmpname); - if (tmpfd == -1) - fatal("mkstemp(\"%s\"): %s", - MM_SWAP_TEMPLATE, strerror(errno)); - unlink(tmpname); - ftruncate(tmpfd, size); - address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, - tmpfd, 0); - close(tmpfd); - } - - return (address); -#else - fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported", - __func__); -#endif /* HAVE_MMAP */ - -} - - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/libssh/Makefile b/usr/src/cmd/ssh/libssh/Makefile deleted file mode 100644 index dfc3be5088..0000000000 --- a/usr/src/cmd/ssh/libssh/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (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 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# cmd/ssh/libssh/Makefile - -include $(SRC)/lib/Makefile.lib -include ../Makefile.ssh-common - -SUBDIRS= $(MACH) -# Need to override the TEXT_DOMAIN here because we included a Makefile from -# usr/src/lib but this is a private library which is part of SUNW_OST_OSCMD -TEXT_DOMAIN= SUNW_OST_OSCMD - -POFILE=_messages.po - -all := TARGET= all -clean := TARGET= clean -clobber := TARGET= clobber -install := TARGET= install -lint := TARGET= lint -$(POFILE) := TARGET= $(POFILE) - -.KEEP_STATE: - -all clean clobber install lint $(POFILE): $(SUBDIRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include $(SRC)/lib/Makefile.targ diff --git a/usr/src/cmd/ssh/libssh/Makefile.com b/usr/src/cmd/ssh/libssh/Makefile.com deleted file mode 100644 index 569afe7207..0000000000 --- a/usr/src/cmd/ssh/libssh/Makefile.com +++ /dev/null @@ -1,116 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = libssh.a -VERS = .1 - -OBJECTS = \ - addrmatch.o \ - atomicio.o \ - authfd.o \ - authfile.o \ - bufaux.o \ - buffer.o \ - canohost.o \ - channels.o \ - cipher.o \ - cipher-ctr.o \ - compat.o \ - compress.o \ - crc32.o \ - deattack.o \ - dh.o \ - dispatch.o \ - engine.o \ - entropy.o \ - fatal.o \ - g11n.o \ - hostfile.o \ - key.o \ - kex.o \ - kexdh.o \ - kexdhc.o \ - kexdhs.o \ - kexgex.o \ - kexgexc.o \ - kexgexs.o \ - kexgssc.o \ - kexgsss.o \ - log.o \ - mac.o \ - match.o \ - misc.o \ - mpaux.o \ - msg.o \ - nchan.o \ - packet.o \ - progressmeter.o \ - proxy-io.o \ - radix.o \ - readconf.o \ - readpass.o \ - rsa.o \ - sftp-common.o \ - ssh-dss.o \ - ssh-gss.o \ - ssh-rsa.o \ - tildexpand.o \ - ttymodes.o \ - uidswap.o \ - uuencode.o \ - xlist.o \ - xmalloc.o - -include $(SRC)/lib/Makefile.lib - -BUILD.AR = $(RM) $@ ; $(AR) $(ARFLAGS) $@ $(AROBJS) - -SRCDIR = ../common -SRCS = $(OBJECTS:%.o=../common/%.c) - -LIBS = $(LIBRARY) $(LINTLIB) - -# Define LDLIBS conditionally for lintcheck, rather than in general, since -# we're building an archive library which itself links to nothing, we just -# want lint to know about these libraries. -lintcheck := LDLIBS += -lcrypto -lz -lsocket -lnsl -lc -$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) - -POFILE_DIR = ../.. - -.KEEP_STATE: - -all: $(LIBS) - -# lint requires the (not installed) lint library -lint: $(LINTLIB) .WAIT lintcheck - -include $(SRC)/lib/Makefile.targ - -objs/%.o: $(SRCDIR)/%.c - $(COMPILE.c) -o $@ $< - $(POST_PROCESS_O) - -include ../../Makefile.ssh-common -include ../../Makefile.msg.targ diff --git a/usr/src/cmd/ssh/libssh/common/addrmatch.c b/usr/src/cmd/ssh/libssh/common/addrmatch.c deleted file mode 100644 index 91aa1e7ac7..0000000000 --- a/usr/src/cmd/ssh/libssh/common/addrmatch.c +++ /dev/null @@ -1,426 +0,0 @@ -/* $OpenBSD: addrmatch.c,v 1.4 2008/12/10 03:55:20 stevesk Exp $ */ - -/* - * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <netdb.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> - -#include "match.h" -#include "log.h" -#include "xmalloc.h" - -struct xaddr { - sa_family_t af; - union { - struct in_addr v4; - struct in6_addr v6; - u_int8_t addr8[16]; - u_int32_t addr32[4]; - } xa; /* 128-bit address */ - u_int32_t scope_id; /* iface scope id for v6 */ -#define v4 xa.v4 -#define v6 xa.v6 -#define addr8 xa.addr8 -#define addr32 xa.addr32 -}; - -static int -addr_unicast_masklen(int af) -{ - switch (af) { - case AF_INET: - return 32; - case AF_INET6: - return 128; - default: - return -1; - } -} - -static inline int -masklen_valid(int af, u_int masklen) -{ - switch (af) { - case AF_INET: - return masklen <= 32 ? 0 : -1; - case AF_INET6: - return masklen <= 128 ? 0 : -1; - default: - return -1; - } -} - -/* - * Convert struct sockaddr to struct xaddr - * Returns 0 on success, -1 on failure. - */ -static int -addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) -{ - /* LINTED E_BAD_PTR_CAST_ALIGN */ - struct sockaddr_in *in4 = (struct sockaddr_in *)sa; - /* LINTED E_BAD_PTR_CAST_ALIGN */ - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; - - memset(xa, '\0', sizeof(*xa)); - - switch (sa->sa_family) { - case AF_INET: - if (slen < sizeof(*in4)) - return -1; - xa->af = AF_INET; - memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4)); - break; - case AF_INET6: - if (slen < sizeof(*in6)) - return -1; - xa->af = AF_INET6; - memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); -#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID - xa->scope_id = in6->sin6_scope_id; -#endif - break; - default: - return -1; - } - - return 0; -} - -/* - * Calculate a netmask of length 'l' for address family 'af' and - * store it in 'n'. - * Returns 0 on success, -1 on failure. - */ -static int -addr_netmask(int af, u_int l, struct xaddr *n) -{ - int i; - - if (masklen_valid(af, l) != 0 || n == NULL) - return -1; - - memset(n, '\0', sizeof(*n)); - switch (af) { - case AF_INET: - n->af = AF_INET; - n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); - return 0; - case AF_INET6: - n->af = AF_INET6; - for (i = 0; i < 4 && l >= 32; i++, l -= 32) - n->addr32[i] = 0xffffffffU; - if (i < 4 && l != 0) - n->addr32[i] = htonl((0xffffffff << (32 - l)) & - 0xffffffff); - return 0; - default: - return -1; - } -} - -/* - * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'. - * Returns 0 on success, -1 on failure. - */ -static int -addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) -{ - int i; - - if (dst == NULL || a == NULL || b == NULL || a->af != b->af) - return -1; - - memcpy(dst, a, sizeof(*dst)); - switch (a->af) { - case AF_INET: - dst->v4.s_addr &= b->v4.s_addr; - return 0; - case AF_INET6: - dst->scope_id = a->scope_id; - for (i = 0; i < 4; i++) - dst->addr32[i] &= b->addr32[i]; - return 0; - default: - return -1; - } -} - -/* - * Compare addresses 'a' and 'b' - * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b) - */ -static int -addr_cmp(const struct xaddr *a, const struct xaddr *b) -{ - int i; - - if (a->af != b->af) - return a->af == AF_INET6 ? 1 : -1; - - switch (a->af) { - case AF_INET: - if (a->v4.s_addr == b->v4.s_addr) - return 0; - return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1; - case AF_INET6: - for (i = 0; i < 16; i++) - if (a->addr8[i] - b->addr8[i] != 0) - return a->addr8[i] > b->addr8[i] ? 1 : -1; - if (a->scope_id == b->scope_id) - return 0; - return a->scope_id > b->scope_id ? 1 : -1; - default: - return -1; - } -} - -/* - * Parse string address 'p' into 'n' - * Returns 0 on success, -1 on failure. - */ -static int -addr_pton(const char *p, struct xaddr *n) -{ - struct addrinfo hints, *ai; - - memset(&hints, '\0', sizeof(hints)); - hints.ai_flags = AI_NUMERICHOST; - - if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) - return -1; - - if (ai == NULL || ai->ai_addr == NULL) - return -1; - - if (n != NULL && - addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) { - freeaddrinfo(ai); - return -1; - } - - freeaddrinfo(ai); - return 0; -} - -/* - * Perform bitwise negation of address - * Returns 0 on success, -1 on failure. - */ -static int -addr_invert(struct xaddr *n) -{ - int i; - - if (n == NULL) - return (-1); - - switch (n->af) { - case AF_INET: - n->v4.s_addr = ~n->v4.s_addr; - return (0); - case AF_INET6: - for (i = 0; i < 4; i++) - n->addr32[i] = ~n->addr32[i]; - return (0); - default: - return (-1); - } -} - -/* - * Calculate a netmask of length 'l' for address family 'af' and - * store it in 'n'. - * Returns 0 on success, -1 on failure. - */ -static int -addr_hostmask(int af, u_int l, struct xaddr *n) -{ - if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) - return (-1); - return (0); -} - -/* - * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::) - * Returns 0 on if address is all-zeros, -1 if not all zeros or on failure. - */ -static int -addr_is_all0s(const struct xaddr *a) -{ - int i; - - switch (a->af) { - case AF_INET: - return (a->v4.s_addr == 0 ? 0 : -1); - case AF_INET6:; - for (i = 0; i < 4; i++) - if (a->addr32[i] != 0) - return (-1); - return (0); - default: - return (-1); - } -} - -/* - * Test whether host portion of address 'a', as determined by 'masklen' - * is all zeros. - * Returns 0 on if host portion of address is all-zeros, - * -1 if not all zeros or on failure. - */ -static int -addr_host_is_all0s(const struct xaddr *a, u_int masklen) -{ - struct xaddr tmp_addr, tmp_mask, tmp_result; - - memcpy(&tmp_addr, a, sizeof(tmp_addr)); - if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) - return (-1); - if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1) - return (-1); - return (addr_is_all0s(&tmp_result)); -} - -/* - * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z). - * Return -1 on parse error, -2 on inconsistency or 0 on success. - */ -static int -addr_pton_cidr(const char *p, struct xaddr *n, u_int *l) -{ - struct xaddr tmp; - long unsigned int masklen = 999; - char addrbuf[64], *mp, *cp; - - /* Don't modify argument */ - if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) > sizeof(addrbuf)) - return -1; - - if ((mp = strchr(addrbuf, '/')) != NULL) { - *mp = '\0'; - mp++; - masklen = strtoul(mp, &cp, 10); - if (*mp == '\0' || *cp != '\0' || masklen > 128) - return -1; - } - - if (addr_pton(addrbuf, &tmp) == -1) - return -1; - - if (mp == NULL) - masklen = addr_unicast_masklen(tmp.af); - if (masklen_valid(tmp.af, masklen) == -1) - return -2; - if (addr_host_is_all0s(&tmp, masklen) != 0) - return -2; - - if (n != NULL) - memcpy(n, &tmp, sizeof(*n)); - if (l != NULL) - *l = masklen; - - return 0; -} - -static int -addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen) -{ - struct xaddr tmp_mask, tmp_result; - - if (host->af != net->af) - return -1; - - if (addr_netmask(host->af, masklen, &tmp_mask) == -1) - return -1; - if (addr_and(&tmp_result, host, &tmp_mask) == -1) - return -1; - return addr_cmp(&tmp_result, net); -} - -/* - * Match "addr" against list pattern list "_list", which may contain a - * mix of CIDR addresses and old-school wildcards. - * - * If addr is NULL, then no matching is performed, but _list is parsed - * and checked for well-formedness. - * - * Returns 1 on match found (never returned when addr == NULL). - * Returns 0 on if no match found, or no errors found when addr == NULL. - * Returns -1 on negated match found (never returned when addr == NULL). - * Returns -2 on invalid list entry. - */ -int -addr_match_list(const char *addr, const char *_list) -{ - char *list, *cp, *o; - struct xaddr try_addr, match_addr; - u_int masklen, neg; - int ret = 0, r; - - if (addr != NULL && addr_pton(addr, &try_addr) != 0) { - debug2("%s: couldn't parse address %.100s", __func__, addr); - return 0; - } - if ((o = list = strdup(_list)) == NULL) - return -1; - while ((cp = strsep(&list, ",")) != NULL) { - neg = *cp == '!'; - if (neg) - cp++; - if (*cp == '\0') { - ret = -2; - break; - } - /* Prefer CIDR address matching */ - r = addr_pton_cidr(cp, &match_addr, &masklen); - if (r == -2) { - error("Inconsistent mask length for " - "network \"%.100s\"", cp); - ret = -2; - break; - } else if (r == 0) { - if (addr != NULL && addr_netmatch(&try_addr, - &match_addr, masklen) == 0) { - foundit: - if (neg) { - ret = -1; - break; - } - ret = 1; - } - continue; - } else { - /* If CIDR parse failed, try wildcard string match */ - if (addr != NULL && match_pattern(addr, cp) == 1) - goto foundit; - } - } - xfree(o); - - return ret; -} diff --git a/usr/src/cmd/ssh/libssh/common/atomicio.c b/usr/src/cmd/ssh/libssh/common/atomicio.c deleted file mode 100644 index f4a7945702..0000000000 --- a/usr/src/cmd/ssh/libssh/common/atomicio.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2006 Damien Miller. All rights reserved. - * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. - * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "atomicio.h" - -/* - * ensure all of data on socket comes through. f==read || f==write - */ -ssize_t -atomicio(f, fd, _s, n) - ssize_t (*f) (); - int fd; - void *_s; - size_t n; -{ - char *s = _s; - ssize_t res, pos = 0; - - while (n > pos) { - res = (f) (fd, s + pos, n - pos); - switch (res) { - case -1: -#ifdef EWOULDBLOCK - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) -#else - if (errno == EINTR || errno == EAGAIN) -#endif - continue; - /* FALLTHROUGH */ - case 0: - return (res); - default: - pos += res; - } - } - return (pos); -} - -/* - * ensure all of data on socket comes through. f==readv || f==writev - */ -size_t -atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, - const struct iovec *_iov, int iovcnt) -{ - size_t pos = 0, rem; - ssize_t res; - struct iovec iov_array[IOV_MAX], *iov = iov_array; - - if (iovcnt > IOV_MAX) { - errno = EINVAL; - return 0; - } - /* Make a copy of the iov array because we may modify it below */ - memcpy(iov, _iov, iovcnt * sizeof(*_iov)); - - for (; iovcnt > 0 && iov[0].iov_len > 0;) { - res = (f) (fd, iov, iovcnt); - switch (res) { - case -1: - if (errno == EINTR || errno == EAGAIN) - continue; - return 0; - case 0: - errno = EPIPE; - return pos; - default: - rem = (size_t)res; - pos += rem; - /* skip completed iov entries */ - while (iovcnt > 0 && rem >= iov[0].iov_len) { - rem -= iov[0].iov_len; - iov++; - iovcnt--; - } - /* This shouldn't happen... */ - if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) { - errno = EFAULT; - return 0; - } - if (iovcnt == 0) - break; - /* update pointer in partially complete iov */ - iov[0].iov_base = ((char *)iov[0].iov_base) + rem; - iov[0].iov_len -= rem; - } - } - return pos; -} diff --git a/usr/src/cmd/ssh/libssh/common/authfd.c b/usr/src/cmd/ssh/libssh/common/authfd.c deleted file mode 100644 index 43fbfbeb3c..0000000000 --- a/usr/src/cmd/ssh/libssh/common/authfd.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for connecting the local authentication agent. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * SSH2 implementation, - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: authfd.c,v 1.57 2002/09/11 18:27:26 stevesk Exp $"); - -#include <openssl/evp.h> - -#include "ssh.h" -#include "rsa.h" -#include "buffer.h" -#include "bufaux.h" -#include "xmalloc.h" -#include "getput.h" -#include "key.h" -#include "authfd.h" -#include "cipher.h" -#include "kex.h" -#include "compat.h" -#include "log.h" -#include "atomicio.h" - -static int agent_present = 0; - -/* helper */ -int decode_reply(int type); - -/* macro to check for "agent failure" message */ -#define agent_failed(x) \ - ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \ - (x == SSH2_AGENT_FAILURE)) - -int -ssh_agent_present(void) -{ - int authfd; - - if (agent_present) - return 1; - if ((authfd = ssh_get_authentication_socket()) == -1) - return 0; - else { - ssh_close_authentication_socket(authfd); - return 1; - } -} - -/* Returns the number of the authentication fd, or -1 if there is none. */ - -int -ssh_get_authentication_socket(void) -{ - const char *authsocket; - int sock; - struct sockaddr_un sunaddr; - - authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); - if (!authsocket) - return -1; - - sunaddr.sun_family = AF_UNIX; - strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return -1; - - /* close on exec */ - if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { - close(sock); - return -1; - } - if (connect(sock, (struct sockaddr *) &sunaddr, sizeof sunaddr) < 0) { - close(sock); - return -1; - } - agent_present = 1; - return sock; -} - -static int -ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) -{ - int l, len; - char buf[1024]; - - /* Get the length of the message, and format it in the buffer. */ - len = buffer_len(request); - PUT_32BIT(buf, len); - - /* Send the length and then the packet to the agent. */ - if (atomicio(write, auth->fd, buf, 4) != 4 || - atomicio(write, auth->fd, buffer_ptr(request), - buffer_len(request)) != buffer_len(request)) { - error("Error writing to authentication socket."); - return 0; - } - /* - * Wait for response from the agent. First read the length of the - * response packet. - */ - len = 4; - while (len > 0) { - l = read(auth->fd, buf + 4 - len, len); - if (l == -1 && (errno == EAGAIN || errno == EINTR)) - continue; - if (l <= 0) { - error("Error reading response length from authentication socket."); - return 0; - } - len -= l; - } - - /* Extract the length, and check it for sanity. */ - len = GET_32BIT(buf); - if (len > 256 * 1024) - fatal("Authentication response too long: %d", len); - - /* Read the rest of the response in to the buffer. */ - buffer_clear(reply); - while (len > 0) { - l = len; - if (l > sizeof(buf)) - l = sizeof(buf); - l = read(auth->fd, buf, l); - if (l == -1 && (errno == EAGAIN || errno == EINTR)) - continue; - if (l <= 0) { - error("Error reading response from authentication socket."); - return 0; - } - buffer_append(reply, buf, l); - len -= l; - } - return 1; -} - -/* - * Closes the agent socket if it should be closed (depends on how it was - * obtained). The argument must have been returned by - * ssh_get_authentication_socket(). - */ - -void -ssh_close_authentication_socket(int sock) -{ - if (getenv(SSH_AUTHSOCKET_ENV_NAME)) - close(sock); -} - -/* - * Opens and connects a private socket for communication with the - * authentication agent. Returns the file descriptor (which must be - * shut down and closed by the caller when no longer needed). - * Returns NULL if an error occurred and the connection could not be - * opened. - */ - -AuthenticationConnection * -ssh_get_authentication_connection(void) -{ - AuthenticationConnection *auth; - int sock; - - sock = ssh_get_authentication_socket(); - - /* - * Fail if we couldn't obtain a connection. This happens if we - * exited due to a timeout. - */ - if (sock < 0) - return NULL; - - auth = xmalloc(sizeof(*auth)); - auth->fd = sock; - buffer_init(&auth->identities); - auth->howmany = 0; - - return auth; -} - -/* - * Closes the connection to the authentication agent and frees any associated - * memory. - */ - -void -ssh_close_authentication_connection(AuthenticationConnection *auth) -{ - buffer_free(&auth->identities); - close(auth->fd); - xfree(auth); -} - -/* Lock/unlock agent */ -int -ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password) -{ - int type; - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK); - buffer_put_cstring(&msg, password); - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); -} - -/* - * Returns the first authentication identity held by the agent. - */ - -int -ssh_get_num_identities(AuthenticationConnection *auth, int version) -{ - int type, code1 = 0, code2 = 0; - Buffer request; - - switch (version) { - case 1: - code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; - code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; - break; - case 2: - code1 = SSH2_AGENTC_REQUEST_IDENTITIES; - code2 = SSH2_AGENT_IDENTITIES_ANSWER; - break; - default: - return 0; - } - - /* - * Send a message to the agent requesting for a list of the - * identities it can represent. - */ - buffer_init(&request); - buffer_put_char(&request, code1); - - buffer_clear(&auth->identities); - if (ssh_request_reply(auth, &request, &auth->identities) == 0) { - buffer_free(&request); - return 0; - } - buffer_free(&request); - - /* Get message type, and verify that we got a proper answer. */ - type = buffer_get_char(&auth->identities); - if (agent_failed(type)) { - return 0; - } else if (type != code2) { - fatal("Bad authentication reply message type: %d", type); - } - - /* Get the number of entries in the response and check it for sanity. */ - auth->howmany = buffer_get_int(&auth->identities); - if (auth->howmany > 1024) - fatal("Too many identities in authentication reply: %d", - auth->howmany); - - return auth->howmany; -} - -Key * -ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) -{ - /* get number of identities and return the first entry (if any). */ - if (ssh_get_num_identities(auth, version) > 0) - return ssh_get_next_identity(auth, comment, version); - return NULL; -} - -Key * -ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) -{ - u_int bits; - u_char *blob; - u_int blen; - Key *key = NULL; - - /* Return failure if no more entries. */ - if (auth->howmany <= 0) - return NULL; - - /* - * Get the next entry from the packet. These will abort with a fatal - * error if the packet is too short or contains corrupt data. - */ - switch (version) { - case 1: - key = key_new(KEY_RSA1); - bits = buffer_get_int(&auth->identities); - buffer_get_bignum(&auth->identities, key->rsa->e); - buffer_get_bignum(&auth->identities, key->rsa->n); - *comment = buffer_get_string(&auth->identities, NULL); - if (bits != BN_num_bits(key->rsa->n)) - log("Warning: identity keysize mismatch: actual %d, announced %u", - BN_num_bits(key->rsa->n), bits); - break; - case 2: - blob = buffer_get_string(&auth->identities, &blen); - *comment = buffer_get_string(&auth->identities, NULL); - key = key_from_blob(blob, blen); - xfree(blob); - break; - default: - return NULL; - break; - } - /* Decrement the number of remaining entries. */ - auth->howmany--; - return key; -} - -/* - * Generates a random challenge, sends it to the agent, and waits for - * response from the agent. Returns true (non-zero) if the agent gave the - * correct answer, zero otherwise. Response type selects the style of - * response desired, with 0 corresponding to protocol version 1.0 (no longer - * supported) and 1 corresponding to protocol version 1.1. - */ - -int -ssh_decrypt_challenge(AuthenticationConnection *auth, - Key* key, BIGNUM *challenge, - u_char session_id[16], - u_int response_type, - u_char response[16]) -{ - Buffer buffer; - int success = 0; - int i; - int type; - - if (key->type != KEY_RSA1) - return 0; - if (response_type == 0) { - log("Compatibility with ssh protocol version 1.0 no longer supported."); - return 0; - } - buffer_init(&buffer); - buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); - buffer_put_int(&buffer, BN_num_bits(key->rsa->n)); - buffer_put_bignum(&buffer, key->rsa->e); - buffer_put_bignum(&buffer, key->rsa->n); - buffer_put_bignum(&buffer, challenge); - buffer_append(&buffer, session_id, 16); - buffer_put_int(&buffer, response_type); - - if (ssh_request_reply(auth, &buffer, &buffer) == 0) { - buffer_free(&buffer); - return 0; - } - type = buffer_get_char(&buffer); - - if (agent_failed(type)) { - log("Agent admitted failure to authenticate using the key."); - } else if (type != SSH_AGENT_RSA_RESPONSE) { - fatal("Bad authentication response: %d", type); - } else { - success = 1; - /* - * Get the response from the packet. This will abort with a - * fatal error if the packet is corrupt. - */ - for (i = 0; i < 16; i++) - response[i] = buffer_get_char(&buffer); - } - buffer_free(&buffer); - return success; -} - -/* ask agent to sign data, returns -1 on error, 0 on success */ -int -ssh_agent_sign(AuthenticationConnection *auth, - Key *key, - u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - Buffer msg; - u_char *blob; - u_int blen; - int type, flags = 0; - int ret = -1; - - if (key_to_blob(key, &blob, &blen) == 0) - return -1; - - if (datafellows & SSH_BUG_SIGBLOB) - flags = SSH_AGENT_OLD_SIGNATURE; - - buffer_init(&msg); - buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); - buffer_put_string(&msg, blob, blen); - buffer_put_string(&msg, data, datalen); - buffer_put_int(&msg, flags); - xfree(blob); - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return -1; - } - type = buffer_get_char(&msg); - if (agent_failed(type)) { - log("Agent admitted failure to sign using the key."); - } else if (type != SSH2_AGENT_SIGN_RESPONSE) { - fatal("Bad authentication response: %d", type); - } else { - ret = 0; - *sigp = buffer_get_string(&msg, lenp); - } - buffer_free(&msg); - return ret; -} - -/* Encode key for a message to the agent. */ - -static void -ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) -{ - buffer_put_int(b, BN_num_bits(key->n)); - buffer_put_bignum(b, key->n); - buffer_put_bignum(b, key->e); - buffer_put_bignum(b, key->d); - /* To keep within the protocol: p < q for ssh. in SSL p > q */ - buffer_put_bignum(b, key->iqmp); /* ssh key->u */ - buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ - buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ - buffer_put_cstring(b, comment); -} - -static void -ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) -{ - buffer_put_cstring(b, key_ssh_name(key)); - switch (key->type) { - case KEY_RSA: - buffer_put_bignum2(b, key->rsa->n); - buffer_put_bignum2(b, key->rsa->e); - buffer_put_bignum2(b, key->rsa->d); - buffer_put_bignum2(b, key->rsa->iqmp); - buffer_put_bignum2(b, key->rsa->p); - buffer_put_bignum2(b, key->rsa->q); - break; - case KEY_DSA: - buffer_put_bignum2(b, key->dsa->p); - buffer_put_bignum2(b, key->dsa->q); - buffer_put_bignum2(b, key->dsa->g); - buffer_put_bignum2(b, key->dsa->pub_key); - buffer_put_bignum2(b, key->dsa->priv_key); - break; - } - buffer_put_cstring(b, comment); -} - -/* - * Adds an identity to the authentication server. This call is not meant to - * be used by normal applications. - */ - -int -ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, - const char *comment, u_int life) -{ - Buffer msg; - int type, constrained = (life != 0); - - buffer_init(&msg); - - switch (key->type) { - case KEY_RSA1: - type = constrained ? - SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : - SSH_AGENTC_ADD_RSA_IDENTITY; - buffer_put_char(&msg, type); - ssh_encode_identity_rsa1(&msg, key->rsa, comment); - break; - case KEY_RSA: - case KEY_DSA: - type = constrained ? - SSH2_AGENTC_ADD_ID_CONSTRAINED : - SSH2_AGENTC_ADD_IDENTITY; - buffer_put_char(&msg, type); - ssh_encode_identity_ssh2(&msg, key, comment); - break; - default: - buffer_free(&msg); - return 0; - break; - } - if (constrained) { - if (life != 0) { - buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); - buffer_put_int(&msg, life); - } - } - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); -} - -int -ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) -{ - return ssh_add_identity_constrained(auth, key, comment, 0); -} - -/* - * Removes an identity from the authentication server. This call is not - * meant to be used by normal applications. - */ - -int -ssh_remove_identity(AuthenticationConnection *auth, Key *key) -{ - Buffer msg; - int type; - u_char *blob; - u_int blen; - - buffer_init(&msg); - - if (key->type == KEY_RSA1) { - buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); - buffer_put_int(&msg, BN_num_bits(key->rsa->n)); - buffer_put_bignum(&msg, key->rsa->e); - buffer_put_bignum(&msg, key->rsa->n); - } else if (key->type == KEY_DSA || key->type == KEY_RSA) { - key_to_blob(key, &blob, &blen); - buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); - buffer_put_string(&msg, blob, blen); - xfree(blob); - } else { - buffer_free(&msg); - return 0; - } - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); -} - - -/* - * Removes all identities from the agent. This call is not meant to be used - * by normal applications. - */ - -int -ssh_remove_all_identities(AuthenticationConnection *auth, int version) -{ - Buffer msg; - int type; - int code = (version==1) ? - SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : - SSH2_AGENTC_REMOVE_ALL_IDENTITIES; - - buffer_init(&msg); - buffer_put_char(&msg, code); - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); -} - -int -decode_reply(int type) -{ - switch (type) { - case SSH_AGENT_FAILURE: - case SSH_COM_AGENT2_FAILURE: - case SSH2_AGENT_FAILURE: - log("SSH_AGENT_FAILURE"); - return 0; - case SSH_AGENT_SUCCESS: - return 1; - default: - fatal("Bad response from authentication agent: %d", type); - } - /* NOTREACHED */ - return 0; -} diff --git a/usr/src/cmd/ssh/libssh/common/authfile.c b/usr/src/cmd/ssh/libssh/common/authfile.c deleted file mode 100644 index 29076f390f..0000000000 --- a/usr/src/cmd/ssh/libssh/common/authfile.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file contains functions for reading and writing identity files, and - * for reading the passphrase from the user. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: authfile.c,v 1.50 2002/06/24 14:55:38 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/err.h> -#include <openssl/evp.h> -#include <openssl/pem.h> - -#include "cipher.h" -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "ssh.h" -#include "log.h" -#include "authfile.h" -#include "rsa.h" - -/* Version identification string for SSH v1 identity files. */ -static const char authfile_id_string[] = - "SSH PRIVATE KEY FILE FORMAT 1.1\n"; - -/* - * Saves the authentication (private) key in a file, encrypting it with - * passphrase. The identification of the file (lowest 64 bits of n) will - * precede the key to provide identification of the key without needing a - * passphrase. - */ - -static int -key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, - const char *comment) -{ - Buffer buffer, encrypted; - u_char buf[100], *cp; - int fd, i, cipher_num; - CipherContext ciphercontext; - Cipher *cipher; - u_int32_t rand; - - /* - * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting - * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. - */ - cipher_num = (strcmp(passphrase, "") == 0) ? - SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER; - if ((cipher = cipher_by_number(cipher_num)) == NULL) - fatal("save_private_key_rsa: bad cipher"); - - /* This buffer is used to built the secret part of the private key. */ - buffer_init(&buffer); - - /* Put checkbytes for checking passphrase validity. */ - rand = arc4random(); - buf[0] = rand & 0xff; - buf[1] = (rand >> 8) & 0xff; - buf[2] = buf[0]; - buf[3] = buf[1]; - buffer_append(&buffer, buf, 4); - - /* - * Store the private key (n and e will not be stored because they - * will be stored in plain text, and storing them also in encrypted - * format would just give known plaintext). - */ - buffer_put_bignum(&buffer, key->rsa->d); - buffer_put_bignum(&buffer, key->rsa->iqmp); - buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */ - buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */ - - /* Pad the part to be encrypted until its size is a multiple of 8. */ - while (buffer_len(&buffer) % 8 != 0) - buffer_put_char(&buffer, 0); - - /* This buffer will be used to contain the data in the file. */ - buffer_init(&encrypted); - - /* First store keyfile id string. */ - for (i = 0; authfile_id_string[i]; i++) - buffer_put_char(&encrypted, authfile_id_string[i]); - buffer_put_char(&encrypted, 0); - - /* Store cipher type. */ - buffer_put_char(&encrypted, cipher_num); - buffer_put_int(&encrypted, 0); /* For future extension */ - - /* Store public key. This will be in plain text. */ - buffer_put_int(&encrypted, BN_num_bits(key->rsa->n)); - buffer_put_bignum(&encrypted, key->rsa->n); - buffer_put_bignum(&encrypted, key->rsa->e); - buffer_put_cstring(&encrypted, comment); - - /* Allocate space for the private part of the key in the buffer. */ - cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - - cipher_set_key_string(&ciphercontext, cipher, passphrase, - CIPHER_ENCRYPT); - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer)); - cipher_cleanup(&ciphercontext); - memset(&ciphercontext, 0, sizeof(ciphercontext)); - - /* Destroy temporary data. */ - memset(buf, 0, sizeof(buf)); - buffer_free(&buffer); - - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) { - error("open %s failed: %s.", filename, strerror(errno)); - return 0; - } - if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) != - buffer_len(&encrypted)) { - error("write to key file %s failed: %s", filename, - strerror(errno)); - buffer_free(&encrypted); - close(fd); - unlink(filename); - return 0; - } - close(fd); - buffer_free(&encrypted); - return 1; -} - -/* save SSH v2 key in OpenSSL PEM format */ -static int -key_save_private_pem(Key *key, const char *filename, const char *_passphrase, - const char *comment) -{ - FILE *fp; - int fd; - int success = 0; - int len = strlen(_passphrase); - u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; - const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; - - if (len > 0 && len <= 4) { - error("passphrase too short: have %d bytes, need > 4", len); - return 0; - } - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) { - error("open %s failed: %s.", filename, strerror(errno)); - return 0; - } - fp = fdopen(fd, "w"); - if (fp == NULL ) { - error("fdopen %s failed: %s.", filename, strerror(errno)); - close(fd); - return 0; - } - switch (key->type) { - case KEY_DSA: - success = PEM_write_DSAPrivateKey(fp, key->dsa, - cipher, passphrase, len, NULL, NULL); - break; - case KEY_RSA: - success = PEM_write_RSAPrivateKey(fp, key->rsa, - cipher, passphrase, len, NULL, NULL); - break; - } - fclose(fp); - return success; -} - -int -key_save_private(Key *key, const char *filename, const char *passphrase, - const char *comment) -{ - switch (key->type) { - case KEY_RSA1: - return key_save_private_rsa1(key, filename, passphrase, - comment); - break; - case KEY_DSA: - case KEY_RSA: - return key_save_private_pem(key, filename, passphrase, - comment); - break; - default: - break; - } - error("key_save_private: cannot save key type %d", key->type); - return 0; -} - -/* - * Loads the public part of the ssh v1 key file. Returns NULL if an error was - * encountered (the file does not exist or is not readable), and the key - * otherwise. - */ - -static Key * -key_load_public_rsa1(int fd, const char *filename, char **commentp) -{ - Buffer buffer; - Key *pub; - char *cp; - int i; - off_t len; - - len = lseek(fd, (off_t) 0, SEEK_END); - lseek(fd, (off_t) 0, SEEK_SET); - - buffer_init(&buffer); - cp = buffer_append_space(&buffer, len); - - if (read(fd, cp, (size_t) len) != (size_t) len) { - debug("Read from key file %.200s failed: %.100s", filename, - strerror(errno)); - buffer_free(&buffer); - return NULL; - } - - /* Check that it is at least big enough to contain the ID string. */ - if (len < sizeof(authfile_id_string)) { - debug3("Not a RSA1 key file %.200s.", filename); - buffer_free(&buffer); - return NULL; - } - /* - * Make sure it begins with the id string. Consume the id string - * from the buffer. - */ - for (i = 0; i < sizeof(authfile_id_string); i++) - if (buffer_get_char(&buffer) != authfile_id_string[i]) { - debug3("Not a RSA1 key file %.200s.", filename); - buffer_free(&buffer); - return NULL; - } - /* Skip cipher type and reserved data. */ - (void) buffer_get_char(&buffer); /* cipher type */ - (void) buffer_get_int(&buffer); /* reserved */ - - /* Read the public key from the buffer. */ - (void) buffer_get_int(&buffer); - pub = key_new(KEY_RSA1); - buffer_get_bignum(&buffer, pub->rsa->n); - buffer_get_bignum(&buffer, pub->rsa->e); - if (commentp) - *commentp = buffer_get_string(&buffer, NULL); - /* The encrypted private part is not parsed by this function. */ - - buffer_free(&buffer); - return pub; -} - -/* load public key from private-key file, works only for SSH v1 */ -Key * -key_load_public_type(int type, const char *filename, char **commentp) -{ - Key *pub; - int fd; - - if (type == KEY_RSA1) { - fd = open(filename, O_RDONLY); - if (fd < 0) - return NULL; - pub = key_load_public_rsa1(fd, filename, commentp); - close(fd); - return pub; - } - return NULL; -} - -/* - * Loads the private key from the file. Returns 0 if an error is encountered - * (file does not exist or is not readable, or passphrase is bad). This - * initializes the private key. - * Assumes we are called under uid of the owner of the file. - */ - -static Key * -key_load_private_rsa1(int fd, const char *filename, const char *passphrase, - char **commentp) -{ - int i, check1, check2, cipher_type; - off_t len; - Buffer buffer, decrypted; - u_char *cp; - CipherContext ciphercontext; - Cipher *cipher; - Key *prv = NULL; - - len = lseek(fd, (off_t) 0, SEEK_END); - lseek(fd, (off_t) 0, SEEK_SET); - - buffer_init(&buffer); - cp = buffer_append_space(&buffer, len); - - if (read(fd, cp, (size_t) len) != (size_t) len) { - debug("Read from key file %.200s failed: %.100s", filename, - strerror(errno)); - buffer_free(&buffer); - close(fd); - return NULL; - } - - /* Check that it is at least big enough to contain the ID string. */ - if (len < sizeof(authfile_id_string)) { - debug3("Not a RSA1 key file %.200s.", filename); - buffer_free(&buffer); - close(fd); - return NULL; - } - /* - * Make sure it begins with the id string. Consume the id string - * from the buffer. - */ - for (i = 0; i < sizeof(authfile_id_string); i++) - if (buffer_get_char(&buffer) != authfile_id_string[i]) { - debug3("Not a RSA1 key file %.200s.", filename); - buffer_free(&buffer); - close(fd); - return NULL; - } - - /* Read cipher type. */ - cipher_type = buffer_get_char(&buffer); - (void) buffer_get_int(&buffer); /* Reserved data. */ - - /* Read the public key from the buffer. */ - (void) buffer_get_int(&buffer); - prv = key_new_private(KEY_RSA1); - - buffer_get_bignum(&buffer, prv->rsa->n); - buffer_get_bignum(&buffer, prv->rsa->e); - if (commentp) - *commentp = buffer_get_string(&buffer, NULL); - else - xfree(buffer_get_string(&buffer, NULL)); - - /* Check that it is a supported cipher. */ - cipher = cipher_by_number(cipher_type); - if (cipher == NULL) { - debug("Unsupported cipher %d used in key file %.200s.", - cipher_type, filename); - buffer_free(&buffer); - goto fail; - } - /* Initialize space for decrypted data. */ - buffer_init(&decrypted); - cp = buffer_append_space(&decrypted, buffer_len(&buffer)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ - cipher_set_key_string(&ciphercontext, cipher, passphrase, - CIPHER_DECRYPT); - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer)); - cipher_cleanup(&ciphercontext); - memset(&ciphercontext, 0, sizeof(ciphercontext)); - buffer_free(&buffer); - - check1 = buffer_get_char(&decrypted); - check2 = buffer_get_char(&decrypted); - if (check1 != buffer_get_char(&decrypted) || - check2 != buffer_get_char(&decrypted)) { - if (strcmp(passphrase, "") != 0) - debug("Bad passphrase supplied for key file %.200s.", - filename); - /* Bad passphrase. */ - buffer_free(&decrypted); - goto fail; - } - /* Read the rest of the private key. */ - buffer_get_bignum(&decrypted, prv->rsa->d); - buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */ - /* in SSL and SSH v1 p and q are exchanged */ - buffer_get_bignum(&decrypted, prv->rsa->q); /* p */ - buffer_get_bignum(&decrypted, prv->rsa->p); /* q */ - - /* calculate p-1 and q-1 */ - rsa_generate_additional_parameters(prv->rsa); - - buffer_free(&decrypted); - close(fd); - return prv; - -fail: - if (commentp) - xfree(*commentp); - close(fd); - key_free(prv); - return NULL; -} - -Key * -key_load_private_pem(int fd, int type, const char *passphrase, - char **commentp) -{ - FILE *fp; - EVP_PKEY *pk = NULL; - Key *prv = NULL; - char *name = "<no key>"; - - fp = fdopen(fd, "r"); - if (fp == NULL) { - error("fdopen failed: %s", strerror(errno)); - close(fd); - return NULL; - } - pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); - if (pk == NULL) { - debug("PEM_read_PrivateKey failed"); - (void)ERR_get_error(); - } else if (pk->type == EVP_PKEY_RSA && - (type == KEY_UNSPEC||type==KEY_RSA)) { - prv = key_new(KEY_UNSPEC); - prv->rsa = EVP_PKEY_get1_RSA(pk); - prv->type = KEY_RSA; - name = "rsa w/o comment"; -#ifdef DEBUG_PK - RSA_print_fp(stderr, prv->rsa, 8); -#endif - } else if (pk->type == EVP_PKEY_DSA && - (type == KEY_UNSPEC||type==KEY_DSA)) { - prv = key_new(KEY_UNSPEC); - prv->dsa = EVP_PKEY_get1_DSA(pk); - prv->type = KEY_DSA; - name = "dsa w/o comment"; -#ifdef DEBUG_PK - DSA_print_fp(stderr, prv->dsa, 8); -#endif - } else { - error("PEM_read_PrivateKey: mismatch or " - "unknown EVP_PKEY save_type %d", pk->save_type); - } - fclose(fp); - if (pk != NULL) - EVP_PKEY_free(pk); - if (prv != NULL && commentp) - *commentp = xstrdup(name); - debug("read PEM private key done: type %s", - prv ? key_type(prv) : "<unknown>"); - return prv; -} - -static int -key_perm_ok(int fd, const char *filename) -{ - struct stat st; - - if (fstat(fd, &st) < 0) - return 0; - /* - * if a key owned by the user is accessed, then we check the - * permissions of the file. if the key owned by a different user, - * then we don't care. - */ -#ifdef HAVE_CYGWIN - if (check_ntsec(filename)) -#endif - if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("Permissions 0%3.3o for '%s' are too open.", - (int)(st.st_mode & 0777), filename); - error("It is recommended that your private key files are NOT accessible by others."); - error("This private key will be ignored."); - return 0; - } - return 1; -} - -Key * -key_load_private_type(int type, const char *filename, const char *passphrase, - char **commentp) -{ - int fd; - - fd = open(filename, O_RDONLY); - if (fd < 0) - return NULL; - if (!key_perm_ok(fd, filename)) { - error("bad permissions: ignore key: %s", filename); - close(fd); - return NULL; - } - switch (type) { - case KEY_RSA1: - return key_load_private_rsa1(fd, filename, passphrase, - commentp); - /* closes fd */ - break; - case KEY_DSA: - case KEY_RSA: - case KEY_UNSPEC: - return key_load_private_pem(fd, type, passphrase, commentp); - /* closes fd */ - break; - default: - close(fd); - break; - } - return NULL; -} - -Key * -key_load_private(const char *filename, const char *passphrase, - char **commentp) -{ - Key *pub, *prv; - int fd; - - fd = open(filename, O_RDONLY); - if (fd < 0) - return NULL; - if (!key_perm_ok(fd, filename)) { - error("bad permissions: ignore key: %s", filename); - close(fd); - return NULL; - } - pub = key_load_public_rsa1(fd, filename, commentp); - lseek(fd, (off_t) 0, SEEK_SET); /* rewind */ - if (pub == NULL) { - /* closes fd */ - prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL); - /* use the filename as a comment for PEM */ - if (commentp && prv) - *commentp = xstrdup(filename); - } else { - /* it's a SSH v1 key if the public key part is readable */ - key_free(pub); - /* closes fd */ - prv = key_load_private_rsa1(fd, filename, passphrase, NULL); - } - return prv; -} - -static int -key_try_load_public(Key *k, const char *filename, char **commentp) -{ - FILE *f; - char line[4096]; - char *cp; - - f = fopen(filename, "r"); - if (f != NULL) { - while (fgets(line, sizeof(line), f)) { - line[sizeof(line)-1] = '\0'; - cp = line; - switch (*cp) { - case '#': - case '\n': - case '\0': - continue; - } - /* Skip leading whitespace. */ - for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) - ; - if (*cp) { - if (key_read(k, &cp) == 1) { - if (commentp) - *commentp=xstrdup(filename); - fclose(f); - return 1; - } - } - } - fclose(f); - } - return 0; -} - -/* load public key from ssh v1 private or any pubkey file */ -Key * -key_load_public(const char *filename, char **commentp) -{ - Key *pub; - char file[MAXPATHLEN]; - - pub = key_load_public_type(KEY_RSA1, filename, commentp); - if (pub != NULL) - return pub; - pub = key_new(KEY_UNSPEC); - if (key_try_load_public(pub, filename, commentp) == 1) - return pub; - if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && - (strlcat(file, ".pub", sizeof file) < sizeof(file)) && - (key_try_load_public(pub, file, commentp) == 1)) - return pub; - key_free(pub); - return NULL; -} diff --git a/usr/src/cmd/ssh/libssh/common/bufaux.c b/usr/src/cmd/ssh/libssh/common/bufaux.c deleted file mode 100644 index 0a94ba9054..0000000000 --- a/usr/src/cmd/ssh/libssh/common/bufaux.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Auxiliary functions for storing and retrieving various data types to/from - * Buffers. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * SSH2 packet format added by Markus Friedl - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $"); - -#include <langinfo.h> -#include <openssl/bn.h> -#include "bufaux.h" -#include "xmalloc.h" -#include "getput.h" -#include "log.h" -#include "g11n.h" - -/* - * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed - * by (bits+7)/8 bytes of binary data, msb first. - */ -int -buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) -{ - int bits = BN_num_bits(value); - int bin_size = (bits + 7) / 8; - u_char *buf = xmalloc(bin_size); - int oi; - char msg[2]; - - /* Get the value of in binary */ - oi = BN_bn2bin(value, buf); - if (oi != bin_size) { - error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d", - oi, bin_size); - xfree(buf); - return (-1); - } - - /* Store the number of bits in the buffer in two bytes, msb first. */ - PUT_16BIT(msg, bits); - buffer_append(buffer, msg, 2); - /* Store the binary data. */ - buffer_append(buffer, (char *)buf, oi); - - memset(buf, 0, bin_size); - xfree(buf); - - return (0); -} - -void -buffer_put_bignum(Buffer *buffer, const BIGNUM *value) -{ - if (buffer_put_bignum_ret(buffer, value) == -1) - fatal("buffer_put_bignum: buffer error"); -} - -/* - * Retrieves an BIGNUM from the buffer. - */ -int -buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) -{ - u_int bits, bytes; - u_char buf[2], *bin; - - /* Get the number for bits. */ - if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { - error("buffer_get_bignum_ret: invalid length"); - return (-1); - } - bits = GET_16BIT(buf); - /* Compute the number of binary bytes that follow. */ - bytes = (bits + 7) / 8; - if (bytes > 8 * 1024) { - error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes); - return (-1); - } - if (buffer_len(buffer) < bytes) { - error("buffer_get_bignum_ret: input buffer too small"); - return (-1); - } - bin = buffer_ptr(buffer); - BN_bin2bn(bin, bytes, value); - if (buffer_consume_ret(buffer, bytes) == -1) { - error("buffer_get_bignum_ret: buffer_consume failed"); - return (-1); - } - return (0); -} - -void -buffer_get_bignum(Buffer *buffer, BIGNUM *value) -{ - if (buffer_get_bignum_ret(buffer, value) == -1) - fatal("buffer_get_bignum: buffer error"); -} - -/* - * Stores an BIGNUM in the buffer in SSH2 format. - */ -int -buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) -{ - u_int bytes; - u_char *buf; - int oi; - u_int hasnohigh = 0; - - if (BN_is_zero(value)) { - buffer_put_int(buffer, 0); - return 0; - } - if (value->neg) { - error("buffer_put_bignum2_ret: negative numbers not supported"); - return (-1); - } - bytes = BN_num_bytes(value) + 1; /* extra padding byte */ - if (bytes < 2) { - error("buffer_put_bignum2_ret: BN too small"); - return (-1); - } - buf = xmalloc(bytes); - buf[0] = 0x00; - /* Get the value of in binary */ - oi = BN_bn2bin(value, buf+1); - if (oi < 0 || (u_int)oi != bytes - 1) { - error("buffer_put_bignum2_ret: BN_bn2bin() failed: " - "oi %d != bin_size %d", oi, bytes); - xfree(buf); - return (-1); - } - hasnohigh = (buf[1] & 0x80) ? 0 : 1; - buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); - memset(buf, 0, bytes); - xfree(buf); - return (0); -} - -void -buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) -{ - if (buffer_put_bignum2_ret(buffer, value) == -1) - fatal("buffer_put_bignum2: buffer error"); -} - -/* XXX does not handle negative BNs */ -int -buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) -{ - u_int len; - u_char *bin; - - if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { - error("buffer_get_bignum2_ret: invalid bignum"); - return (-1); - } - - if (len > 0 && (bin[0] & 0x80)) { - error("buffer_get_bignum2_ret: negative numbers not supported"); - xfree(bin); - return (-1); - } - if (len > 8 * 1024) { - error("buffer_get_bignum2_ret: cannot handle BN of size %d", len); - xfree(bin); - return (-1); - } - BN_bin2bn(bin, len, value); - xfree(bin); - return (0); -} - -void -buffer_get_bignum2(Buffer *buffer, BIGNUM *value) -{ - if (buffer_get_bignum2_ret(buffer, value) == -1) - fatal("buffer_get_bignum2: buffer error"); -} - -/* - * Returns integers from the buffer (msb first). - */ - -int -buffer_get_short_ret(u_short *ret, Buffer *buffer) -{ - u_char buf[2]; - - if (buffer_get_ret(buffer, (char *) buf, 2) == -1) - return (-1); - *ret = GET_16BIT(buf); - return (0); -} - -u_short -buffer_get_short(Buffer *buffer) -{ - u_short ret; - - if (buffer_get_short_ret(&ret, buffer) == -1) - fatal("buffer_get_short: buffer error"); - - return (ret); -} - -int -buffer_get_int_ret(u_int *ret, Buffer *buffer) -{ - u_char buf[4]; - - if (buffer_get_ret(buffer, (char *) buf, 4) == -1) - return (-1); - *ret = GET_32BIT(buf); - return (0); -} - -u_int -buffer_get_int(Buffer *buffer) -{ - u_int ret; - - if (buffer_get_int_ret(&ret, buffer) == -1) - fatal("buffer_get_int: buffer error"); - - return (ret); -} - -#ifdef HAVE_U_INT64_T -int -buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) -{ - u_char buf[8]; - - if (buffer_get_ret(buffer, (char *) buf, 8) == -1) - return (-1); - *ret = GET_64BIT(buf); - return (0); -} - -u_int64_t -buffer_get_int64(Buffer *buffer) -{ - u_int64_t ret; - - if (buffer_get_int64_ret(&ret, buffer) == -1) - fatal("buffer_get_int: buffer error"); - - return (ret); -} -#endif - -/* - * Stores integers in the buffer, msb first. - */ -void -buffer_put_short(Buffer *buffer, u_short value) -{ - char buf[2]; - - PUT_16BIT(buf, value); - buffer_append(buffer, buf, 2); -} - -void -buffer_put_int(Buffer *buffer, u_int value) -{ - char buf[4]; - - PUT_32BIT(buf, value); - buffer_append(buffer, buf, 4); -} - -#ifdef HAVE_U_INT64_T -void -buffer_put_int64(Buffer *buffer, u_int64_t value) -{ - char buf[8]; - - PUT_64BIT(buf, value); - buffer_append(buffer, buf, 8); -} -#endif - -/* - * Returns an arbitrary binary string from the buffer. The string cannot - * be longer than 256k. The returned value points to memory allocated - * with xmalloc; it is the responsibility of the calling function to free - * the data. If length_ptr is non-NULL, the length of the returned data - * will be stored there. A null character will be automatically appended - * to the returned string, and is not counted in length. - */ -void * -buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) -{ - u_char *value; - u_int len; - - /* Get the length. */ - len = buffer_get_int(buffer); - if (len > 256 * 1024) { - error("buffer_get_string_ret: bad string length %u", len); - return (NULL); - } - /* Allocate space for the string. Add one byte for a null character. */ - value = xmalloc(len + 1); - /* Get the string. */ - if (buffer_get_ret(buffer, value, len) == -1) { - error("buffer_get_string_ret: buffer_get failed"); - xfree(value); - return (NULL); - } - /* Append a null character to make processing easier. */ - value[len] = 0; - /* Optionally return the length of the string. */ - if (length_ptr) - *length_ptr = len; - return (value); -} - -void * -buffer_get_string(Buffer *buffer, u_int *length_ptr) -{ - void *ret; - - if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) - fatal("buffer_get_string: buffer error"); - return (ret); -} - -char * -buffer_get_utf8_string(Buffer *buffer, uint_t *length_ptr) -{ - char *value, *converted, *estr; - uint_t len; - - if ((value = buffer_get_string(buffer, &len)) == NULL) - return (value); - - converted = g11n_convert_from_utf8(value, &len, &estr); - if (converted == NULL) { - if (estr != NULL) - error("invalid UTF-8 sequence: %s", estr); - converted = value; - } else { - xfree(value); - } - - if (length_ptr != NULL) - *length_ptr = len; - - return (converted); -} - -/* - * Stores and arbitrary binary string in the buffer. - */ -void -buffer_put_string(Buffer *buffer, const void *buf, u_int len) -{ - buffer_put_int(buffer, len); - buffer_append(buffer, buf, len); -} -void -buffer_put_cstring(Buffer *buffer, const char *s) -{ - if (s == NULL) - fatal("buffer_put_cstring: s == NULL"); - buffer_put_string(buffer, s, strlen(s)); -} - -/* - * UTF-8 versions of the above. - */ -void -buffer_put_utf8_string(Buffer *buffer, const char *s, uint_t len) -{ - char *converted, *estr; - uint_t nlen = len; - - converted = g11n_convert_to_utf8(s, &nlen, 0, &estr); - if (converted == NULL) { - if (estr != NULL) - error("Can't convert to UTF-8: %s", estr); - converted = (char *)s; - } - - buffer_put_string(buffer, converted, nlen); - - if (converted != s) - xfree(converted); -} - -void -buffer_put_utf8_cstring(Buffer *buffer, const char *s) -{ - buffer_put_utf8_string(buffer, s, strlen(s)); -} - -/* - * Returns a character from the buffer (0 - 255). - */ -int -buffer_get_char_ret(char *ret, Buffer *buffer) -{ - if (buffer_get_ret(buffer, ret, 1) == -1) { - error("buffer_get_char_ret: buffer_get_ret failed"); - return (-1); - } - return (0); -} - -int -buffer_get_char(Buffer *buffer) -{ - char ch; - - if (buffer_get_char_ret(&ch, buffer) == -1) - fatal("buffer_get_char: buffer error"); - return (u_char) ch; -} - -/* - * Stores a character in the buffer. - */ -void -buffer_put_char(Buffer *buffer, int value) -{ - char ch = value; - - buffer_append(buffer, &ch, 1); -} diff --git a/usr/src/cmd/ssh/libssh/common/buffer.c b/usr/src/cmd/ssh/libssh/common/buffer.c deleted file mode 100644 index 2ec761b7ad..0000000000 --- a/usr/src/cmd/ssh/libssh/common/buffer.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for manipulating fifo buffers (that can grow if needed). - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */ - -#include "includes.h" - -#include "xmalloc.h" -#include "buffer.h" -#include "log.h" - -#define BUFFER_MAX_CHUNK 0x100000 -#define BUFFER_MAX_LEN 0xa00000 -#define BUFFER_ALLOCSZ 0x008000 - -/* Initializes the buffer structure. */ - -void -buffer_init(Buffer *buffer) -{ - const u_int len = 4096; - - buffer->alloc = 0; - buffer->buf = xmalloc(len); - buffer->alloc = len; - buffer->offset = 0; - buffer->end = 0; -} - -/* Frees any memory used for the buffer. */ - -void -buffer_free(Buffer *buffer) -{ - if (buffer->alloc > 0) { - memset(buffer->buf, 0, buffer->alloc); - buffer->alloc = 0; - xfree(buffer->buf); - } -} - -/* - * Clears any data from the buffer, making it empty. This does not actually - * zero the memory. - */ - -void -buffer_clear(Buffer *buffer) -{ - buffer->offset = 0; - buffer->end = 0; -} - -/* Appends data to the buffer, expanding it if necessary. */ - -void -buffer_append(Buffer *buffer, const void *data, u_int len) -{ - void *p; - p = buffer_append_space(buffer, len); - memcpy(p, data, len); -} - -static int -buffer_compact(Buffer *buffer) -{ - /* - * If the buffer is quite empty, but all data is at the end, move the - * data to the beginning. - */ - if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) { - memmove(buffer->buf, buffer->buf + buffer->offset, - buffer->end - buffer->offset); - buffer->end -= buffer->offset; - buffer->offset = 0; - return (1); - } - return (0); -} - -/* - * Appends space to the buffer, expanding the buffer if necessary. This does - * not actually copy the data into the buffer, but instead returns a pointer - * to the allocated region. - */ - -void * -buffer_append_space(Buffer *buffer, u_int len) -{ - u_int newlen; - void *p; - - if (len > BUFFER_MAX_CHUNK) - fatal("buffer_append_space: len %u not supported", len); - - /* If the buffer is empty, start using it from the beginning. */ - if (buffer->offset == buffer->end) { - buffer->offset = 0; - buffer->end = 0; - } -restart: - /* If there is enough space to store all data, store it now. */ - if (buffer->end + len < buffer->alloc) { - p = buffer->buf + buffer->end; - buffer->end += len; - return p; - } - - /* Compact data back to the start of the buffer if necessary */ - if (buffer_compact(buffer)) - goto restart; - - /* Increase the size of the buffer and retry. */ - newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); - if (newlen > BUFFER_MAX_LEN) - fatal("buffer_append_space: alloc %u not supported", - newlen); - buffer->buf = xrealloc(buffer->buf, newlen); - buffer->alloc = newlen; - goto restart; - /* NOTREACHED */ -} - -/* - * Check whether an allocation of 'len' will fit in the buffer - * This must follow the same math as buffer_append_space - */ -int -buffer_check_alloc(Buffer *buffer, u_int len) -{ - if (buffer->offset == buffer->end) { - buffer->offset = 0; - buffer->end = 0; - } - restart: - if (buffer->end + len < buffer->alloc) - return (1); - if (buffer_compact(buffer)) - goto restart; - if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN) - return (1); - return (0); -} - -/* Returns the number of bytes of data in the buffer. */ - -u_int -buffer_len(Buffer *buffer) -{ - return buffer->end - buffer->offset; -} - -/* Gets data from the beginning of the buffer. */ - -int -buffer_get_ret(Buffer *buffer, void *buf, u_int len) -{ - if (len > buffer->end - buffer->offset) { - error("buffer_get_ret: trying to get more bytes %d than in buffer %d", - len, buffer->end - buffer->offset); - return (-1); - } - memcpy(buf, buffer->buf + buffer->offset, len); - buffer->offset += len; - return (0); -} - -void -buffer_get(Buffer *buffer, void *buf, u_int len) -{ - if (buffer_get_ret(buffer, buf, len) == -1) - fatal("buffer_get: buffer error"); -} - -/* Consumes the given number of bytes from the beginning of the buffer. */ - -int -buffer_consume_ret(Buffer *buffer, u_int bytes) -{ - if (bytes > buffer->end - buffer->offset) { - error("buffer_consume_ret: trying to get more bytes than in buffer"); - return (-1); - } - buffer->offset += bytes; - return (0); -} - -void -buffer_consume(Buffer *buffer, u_int bytes) -{ - if (buffer_consume_ret(buffer, bytes) == -1) - fatal("buffer_consume: buffer error"); -} - -/* Consumes the given number of bytes from the end of the buffer. */ - -int -buffer_consume_end_ret(Buffer *buffer, u_int bytes) -{ - if (bytes > buffer->end - buffer->offset) - return (-1); - buffer->end -= bytes; - return (0); -} - -void -buffer_consume_end(Buffer *buffer, u_int bytes) -{ - if (buffer_consume_end_ret(buffer, bytes) == -1) - fatal("buffer_consume_end: trying to get more bytes than in buffer"); -} - -/* Returns a pointer to the first used byte in the buffer. */ - -void * -buffer_ptr(Buffer *buffer) -{ - return buffer->buf + buffer->offset; -} - -/* Dumps the contents of the buffer to stderr. */ -void -buffer_dump(Buffer *buffer) -{ - u_int i; - u_char *ucp = buffer->buf; - - for (i = buffer->offset; i < buffer->end; i++) { - fprintf(stderr, "%02x", ucp[i]); - if ((i-buffer->offset)%16==15) - fprintf(stderr, "\n"); - else if ((i-buffer->offset)%2==1) - fprintf(stderr, " "); - } - - if (buffer->offset == buffer->end) { - /* explicitly state when the buffer is empty */ - fprintf(stderr, "<EMPTY BUFFER>\n"); - } else { - /* print the terminal '\n' if it wasn't already printed */ - if ((i - buffer->offset) % 16 != 0) - fprintf(stderr, "\n"); - } - /* - * We want an extra empty line after the packet dump for better - * readability. - */ - fprintf(stderr, "\n"); -} diff --git a/usr/src/cmd/ssh/libssh/common/canohost.c b/usr/src/cmd/ssh/libssh/common/canohost.c deleted file mode 100644 index 2d427b9e8d..0000000000 --- a/usr/src/cmd/ssh/libssh/common/canohost.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for returning the canonical host name of the remote site. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * Copyright 2012 Nexenta Systems, Inc. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: canohost.c,v 1.34 2002/09/23 20:46:27 stevesk Exp $"); - -#include "packet.h" -#include "xmalloc.h" -#include "log.h" -#include "canohost.h" - -static const char *inet_ntop_native(int af, const void *src, - char *dst, size_t size); - - -/* - * Return the canonical name of the host at the other end of the socket. The - * caller should free the returned string with xfree. - */ - -static char * -get_remote_hostname(int socket, int verify_reverse_mapping) -{ - struct sockaddr_storage from; - int i, res; - socklen_t fromlen; - struct addrinfo hints, *ai, *aitop; - char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; - - /* Get IP address of client. */ - fromlen = sizeof(from); - memset(&from, 0, sizeof(from)); - if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) { - debug("getpeername failed: %.100s", strerror(errno)); - fatal_cleanup(); - } - - if ((res = getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), - NULL, 0, NI_NUMERICHOST)) != 0) - fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed: %d", res); - -#ifdef IPV4_IN_IPV6 - if (from.ss_family == AF_INET6) { - struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from; - - (void) inet_ntop_native(from.ss_family, - from6->sin6_addr.s6_addr, - ntop, sizeof(ntop)); - } -#endif /* IPV4_IN_IPV6 */ - - if (!verify_reverse_mapping) - return xstrdup(ntop); - - debug3("Trying to reverse map address %.100s.", ntop); - /* Map the IP address to a host name. */ - if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), - NULL, 0, NI_NAMEREQD) != 0) { - /* Host name not found. Use ip address. */ -#if 0 - log("Could not reverse map address %.100s.", ntop); -#endif - return xstrdup(ntop); - } - - /* Got host name. */ - name[sizeof(name) - 1] = '\0'; - /* - * Convert it to all lowercase (which is expected by the rest - * of this software). - */ - for (i = 0; name[i]; i++) - if (isupper(name[i])) - name[i] = tolower(name[i]); - - /* - * Map it back to an IP address and check that the given - * address actually is an address of this host. This is - * necessary because anyone with access to a name server can - * define arbitrary names for an IP address. Mapping from - * name to IP address can be trusted better (but can still be - * fooled if the intruder has access to the name server of - * the domain). - */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = from.ss_family; - hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { - log("reverse mapping checking getaddrinfo for %.700s " - "failed - POSSIBLE BREAKIN ATTEMPT!", name); - return xstrdup(ntop); - } - /* Look for the address from the list of addresses. */ - for (ai = aitop; ai; ai = ai->ai_next) { - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, - sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && - (strcmp(ntop, ntop2) == 0)) - break; - } - freeaddrinfo(aitop); - /* If we reached the end of the list, the address was not there. */ - if (!ai) { - /* Address not found for the host name. */ - log("Address %.100s maps to %.600s, but this does not " - "map back to the address - POSSIBLE BREAKIN ATTEMPT!", - ntop, name); - return xstrdup(ntop); - } - return xstrdup(name); -} - -/* - * Return the canonical name of the host in the other side of the current - * connection. The host name is cached, so it is efficient to call this - * several times. - */ - -const char * -get_canonical_hostname(int verify_reverse_mapping) -{ - static char *canonical_host_name = NULL; - static int verify_reverse_mapping_done = 0; - - /* Check if we have previously retrieved name with same option. */ - if (canonical_host_name != NULL) { - if (verify_reverse_mapping_done != verify_reverse_mapping) - xfree(canonical_host_name); - else - return canonical_host_name; - } - - /* Get the real hostname if socket; otherwise return UNKNOWN. */ - if (packet_connection_is_on_socket()) - canonical_host_name = get_remote_hostname( - packet_get_connection_in(), verify_reverse_mapping); - else - canonical_host_name = xstrdup("UNKNOWN"); - - verify_reverse_mapping_done = verify_reverse_mapping; - return canonical_host_name; -} - -/* - * Returns the remote IP-address of socket as a string. The returned - * string must be freed. - */ -char * -get_socket_address(int socket, int remote, int flags) -{ - struct sockaddr_storage addr; - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; - socklen_t addrlen; - char ntop[NI_MAXHOST]; - const char *result; - char abuf[INET6_ADDRSTRLEN]; - - /* Get IP address of client. */ - addrlen = sizeof (addr); - memset(&addr, 0, sizeof (addr)); - - if (remote) { - if (getpeername(socket, (struct sockaddr *)&addr, &addrlen) - < 0) { - debug("get_socket_ipaddr: getpeername failed: %.100s", - strerror(errno)); - return (NULL); - } - } else { - if (getsockname(socket, (struct sockaddr *)&addr, &addrlen) - < 0) { - debug("get_socket_ipaddr: getsockname failed: %.100s", - strerror(errno)); - return (NULL); - } - } - - /* Get the address in ascii. */ - if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof (ntop), - NULL, 0, flags) != 0) { - error("get_socket_ipaddr: getnameinfo %d failed", flags); - return (NULL); - } - - if (addr.ss_family == AF_INET) { - return (xstrdup(ntop)); - } - - result = inet_ntop_native(addr.ss_family, - addr6->sin6_addr.s6_addr, abuf, sizeof (abuf)); - - return (xstrdup(result)); -} -#if 0 -static char * -get_socket_address(int socket, int remote, int flags) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - char ntop[NI_MAXHOST]; - - /* Get IP address of client. */ - addrlen = sizeof(addr); - memset(&addr, 0, sizeof(addr)); - - if (remote) { - if (getpeername(socket, (struct sockaddr *)&addr, &addrlen) - < 0) - return NULL; - } else { - if (getsockname(socket, (struct sockaddr *)&addr, &addrlen) - < 0) - return NULL; - } - /* Get the address in ascii. */ - if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), - NULL, 0, flags) != 0) { - error("get_socket_ipaddr: getnameinfo %d failed", flags); - return NULL; - } - return xstrdup(ntop); -} -#endif - -char * -get_peer_ipaddr(int socket) -{ - char *p; - - if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL) - return p; - return xstrdup("UNKNOWN"); -} - -char * -get_local_ipaddr(int socket) -{ - char *p; - - if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL) - return p; - return xstrdup("UNKNOWN"); -} - -char * -get_local_name(int socket) -{ - return get_socket_address(socket, 0, NI_NAMEREQD); -} - -/* - * Returns the IP-address of the remote host as a string. The returned - * string must not be freed. - */ - -const char * -get_remote_ipaddr(void) -{ - static char *canonical_host_ip = NULL; - - /* Check whether we have cached the ipaddr. */ - if (canonical_host_ip == NULL) { - if (packet_connection_is_on_socket()) { - canonical_host_ip = - get_peer_ipaddr(packet_get_connection_in()); - if (canonical_host_ip == NULL) - fatal_cleanup(); - } else { - /* If not on socket, return UNKNOWN. */ - canonical_host_ip = xstrdup("UNKNOWN"); - } - } - return canonical_host_ip; -} - -const char * -get_remote_name_or_ip(u_int utmp_len, int verify_reverse_mapping) -{ - static const char *remote = ""; - if (utmp_len > 0) - remote = get_canonical_hostname(verify_reverse_mapping); - if (utmp_len == 0 || strlen(remote) > utmp_len) - remote = get_remote_ipaddr(); - return remote; -} - -/* Returns the local/remote port for the socket. */ - -static int -get_sock_port(int sock, int local) -{ - struct sockaddr_storage from; - socklen_t fromlen; - char strport[NI_MAXSERV]; - - /* Get IP address of client. */ - fromlen = sizeof(from); - memset(&from, 0, sizeof(from)); - if (local) { - if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) { - error("getsockname failed: %.100s", strerror(errno)); - return 0; - } - } else { - if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) { - debug("getpeername failed: %.100s", strerror(errno)); - fatal_cleanup(); - } - } - /* Return port number. */ - if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, - strport, sizeof(strport), NI_NUMERICSERV) != 0) - fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed"); - return atoi(strport); -} - -/* Returns remote/local port number for the current connection. */ - -static int -get_port(int local) -{ - /* - * If the connection is not a socket, return 65535. This is - * intentionally chosen to be an unprivileged port number. - */ - if (!packet_connection_is_on_socket()) - return 65535; - - /* Get socket and return the port number. */ - return get_sock_port(packet_get_connection_in(), local); -} - -int -get_peer_port(int sock) -{ - return get_sock_port(sock, 0); -} - -int -get_remote_port(void) -{ - return get_port(0); -} - -int -get_local_port(void) -{ - return get_port(1); -} - -/* - * Taken from inetd.c - * This is a wrapper function for inet_ntop(). In case the af is AF_INET6 - * and the address pointed by src is a IPv4-mapped IPv6 address, it - * returns printable IPv4 address, not IPv4-mapped IPv6 address. In other cases - * it behaves just like inet_ntop(). - */ -static const char * -inet_ntop_native(int af, const void *src, char *dst, size_t size) -{ - struct in_addr src4; - const char *result; - - if (af == AF_INET6) { - if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) { - IN6_V4MAPPED_TO_INADDR((struct in6_addr *)src, &src4); - result = inet_ntop(AF_INET, &src4, dst, size); - } else { - result = inet_ntop(AF_INET6, src, dst, size); - } - } else { - result = inet_ntop(af, src, dst, size); - } - - return (result); -} diff --git a/usr/src/cmd/ssh/libssh/common/channels.c b/usr/src/cmd/ssh/libssh/common/channels.c deleted file mode 100644 index 7133758b73..0000000000 --- a/usr/src/cmd/ssh/libssh/common/channels.c +++ /dev/null @@ -1,3035 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file contains functions for generic socket connection forwarding. - * There is also code for initiating connection forwarding for X11 connections, - * arbitrary tcp/ip connections, and the authentication agent connection. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * SSH2 support added by Markus Friedl. - * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. - * Copyright (c) 1999 Dug Song. All rights reserved. - * Copyright (c) 1999 Theo de Raadt. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.183 2002/09/17 07:47:02 itojun Exp $"); - -#include "ssh.h" -#include "ssh1.h" -#include "ssh2.h" -#include "packet.h" -#include "xmalloc.h" -#include "log.h" -#include "misc.h" -#include "channels.h" -#include "compat.h" -#include "canohost.h" -#include "key.h" -#include "authfd.h" -#include "pathnames.h" -#include "bufaux.h" - - -/* -- channel core */ - -/* - * Pointer to an array containing all allocated channels. The array is - * dynamically extended as needed. - */ -static Channel **channels = NULL; - -/* - * Size of the channel array. All slots of the array must always be - * initialized (at least the type field); unused slots set to NULL - */ -static int channels_alloc = 0; - -/* - * Maximum file descriptor value used in any of the channels. This is - * updated in channel_new. - */ -static int channel_max_fd = 0; - - -/* -- tcp forwarding */ - -/* - * Data structure for storing which hosts are permitted for forward requests. - * The local sides of any remote forwards are stored in this array to prevent - * a corrupt remote server from accessing arbitrary TCP/IP ports on our local - * network (which might be behind a firewall). - */ -typedef struct { - char *host_to_connect; /* Connect to 'host'. */ - u_short port_to_connect; /* Connect to 'port'. */ - u_short listen_port; /* Remote side should listen port number. */ -} ForwardPermission; - -/* List of all permitted host/port pairs to connect. */ -static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION]; - -/* Number of permitted host/port pairs in the array. */ -static int num_permitted_opens = 0; -/* - * If this is true, all opens are permitted. This is the case on the server - * on which we have to trust the client anyway, and the user could do - * anything after logging in anyway. - */ -static int all_opens_permitted = 0; - - -/* -- X11 forwarding */ - -/* Maximum number of fake X11 displays to try. */ -#define MAX_DISPLAYS 1000 - -/* Saved X11 authentication protocol name. */ -static char *x11_saved_proto = NULL; - -/* Saved X11 authentication data. This is the real data. */ -static char *x11_saved_data = NULL; -static u_int x11_saved_data_len = 0; - -/* - * Fake X11 authentication data. This is what the server will be sending us; - * we should replace any occurrences of this by the real data. - */ -static u_char *x11_fake_data = NULL; -static u_int x11_fake_data_len; - - -/* -- agent forwarding */ - -#define NUM_SOCKS 10 - -/* AF_UNSPEC or AF_INET or AF_INET6 */ -static int IPv4or6 = AF_UNSPEC; - -/* helper */ -static void port_open_helper(Channel *c, char *rtype); - -/* -- channel core */ - -Channel * -channel_lookup(int id) -{ - Channel *c; - - if (id < 0 || id >= channels_alloc) { - log("channel_lookup: %d: bad id", id); - return NULL; - } - c = channels[id]; - if (c == NULL) { - log("channel_lookup: %d: bad id: channel free", id); - return NULL; - } - return c; -} - -/* - * Register filedescriptors for a channel, used when allocating a channel or - * when the channel consumer/producer is ready, e.g. shell exec'd - */ - -static void -channel_register_fds(Channel *c, int rfd, int wfd, int efd, - int extusage, int nonblock) -{ - /* Update the maximum file descriptor value. */ - channel_max_fd = MAX(channel_max_fd, rfd); - channel_max_fd = MAX(channel_max_fd, wfd); - channel_max_fd = MAX(channel_max_fd, efd); - - /* XXX set close-on-exec -markus */ - - c->rfd = rfd; - c->wfd = wfd; - c->sock = (rfd == wfd) ? rfd : -1; - c->efd = efd; - c->extended_usage = extusage; - - /* XXX ugly hack: nonblock is only set by the server */ - if (nonblock && isatty(c->rfd)) { - debug("channel %d: rfd %d isatty", c->self, c->rfd); - c->isatty = 1; - if (!isatty(c->wfd)) { - error("channel %d: wfd %d is not a tty?", - c->self, c->wfd); - } - } else { - c->isatty = 0; - } - c->wfd_isatty = isatty(c->wfd); - - /* enable nonblocking mode */ - if (nonblock) { - if (rfd != -1) - set_nonblock(rfd); - if (wfd != -1) - set_nonblock(wfd); - if (efd != -1) - set_nonblock(efd); - } -} - -/* - * Allocate a new channel object and set its type and socket. This will cause - * remote_name to be freed. - */ - -Channel * -channel_new(char *ctype, int type, int rfd, int wfd, int efd, - u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) -{ - int i, found; - Channel *c; - - /* Do initial allocation if this is the first call. */ - if (channels_alloc == 0) { - channels_alloc = 10; - channels = xmalloc(channels_alloc * sizeof(Channel *)); - for (i = 0; i < channels_alloc; i++) - channels[i] = NULL; - fatal_add_cleanup((void (*) (void *)) channel_free_all, NULL); - } - /* Try to find a free slot where to put the new channel. */ - for (found = -1, i = 0; i < channels_alloc; i++) - if (channels[i] == NULL) { - /* Found a free slot. */ - found = i; - break; - } - if (found == -1) { - /* There are no free slots. Take last+1 slot and expand the array. */ - found = channels_alloc; - if (channels_alloc > 10000) - fatal("channel_new: internal error: channels_alloc %d " - "too big.", channels_alloc); - channels = xrealloc(channels, - (channels_alloc + 10) * sizeof(Channel *)); - channels_alloc += 10; - debug2("channel: expanding %d", channels_alloc); - for (i = found; i < channels_alloc; i++) - channels[i] = NULL; - } - /* Initialize and return new channel. */ - c = channels[found] = xmalloc(sizeof(Channel)); - memset(c, 0, sizeof(Channel)); - buffer_init(&c->input); - buffer_init(&c->output); - buffer_init(&c->extended); - c->ostate = CHAN_OUTPUT_OPEN; - c->istate = CHAN_INPUT_OPEN; - c->flags = 0; - channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); - c->self = found; - c->type = type; - c->ctype = ctype; - c->local_window = window; - c->local_window_max = window; - c->local_consumed = 0; - c->local_maxpacket = maxpack; - c->remote_id = -1; - c->remote_name = remote_name; - c->remote_window = 0; - c->remote_maxpacket = 0; - c->force_drain = 0; - c->single_connection = 0; - c->detach_user = NULL; - c->confirm = NULL; - c->input_filter = NULL; - c->delayed = 1; /* prevent call to channel_post handler */ - debug("channel %d: new [%s]", found, remote_name); - return c; -} - -static int -channel_find_maxfd(void) -{ - int i, max = 0; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c != NULL) { - max = MAX(max, c->rfd); - max = MAX(max, c->wfd); - max = MAX(max, c->efd); - } - } - return max; -} - -int -channel_close_fd(int *fdp) -{ - int ret = 0, fd = *fdp; - - if (fd != -1) { - ret = close(fd); - *fdp = -1; - if (fd == channel_max_fd) - channel_max_fd = channel_find_maxfd(); - } - return ret; -} - -/* Close all channel fd/socket. */ - -static void -channel_close_fds(Channel *c) -{ - debug3("channel_close_fds: channel %d: r %d w %d e %d", - c->self, c->rfd, c->wfd, c->efd); - - channel_close_fd(&c->sock); - channel_close_fd(&c->rfd); - channel_close_fd(&c->wfd); - channel_close_fd(&c->efd); -} - -/* Free the channel and close its fd/socket. */ - -void -channel_free(Channel *c) -{ - char *s; - int i, n; - - for (n = 0, i = 0; i < channels_alloc; i++) - if (channels[i]) - n++; - debug("channel_free: channel %d: %s, nchannels %d", c->self, - c->remote_name ? c->remote_name : "???", n); - - s = channel_open_message(); - debug3("channel_free: status: %s", s); - xfree(s); - - if (c->sock != -1) - shutdown(c->sock, SHUT_RDWR); - channel_close_fds(c); - buffer_free(&c->input); - buffer_free(&c->output); - buffer_free(&c->extended); - if (c->remote_name) { - xfree(c->remote_name); - c->remote_name = NULL; - } - channels[c->self] = NULL; - xfree(c); -} - -void -channel_free_all(void) -{ - int i; - - for (i = 0; i < channels_alloc; i++) - if (channels[i] != NULL) - channel_free(channels[i]); -} - -/* - * Closes the sockets/fds of all channels. This is used to close extra file - * descriptors after a fork. - */ - -void -channel_close_all(void) -{ - int i; - - for (i = 0; i < channels_alloc; i++) - if (channels[i] != NULL) - channel_close_fds(channels[i]); -} - -/* - * Stop listening to channels. - */ - -void -channel_stop_listening(void) -{ - int i; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c != NULL) { - switch (c->type) { - case SSH_CHANNEL_AUTH_SOCKET: - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_X11_LISTENER: - channel_close_fd(&c->sock); - channel_free(c); - break; - } - } - } -} - -/* - * Returns true if no channel has too much buffered data, and false if one or - * more channel is overfull. - */ - -int -channel_not_very_much_buffered_data(void) -{ - u_int i; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c != NULL && c->type == SSH_CHANNEL_OPEN) { -#if 0 - if (!compat20 && - buffer_len(&c->input) > packet_get_maxsize()) { - debug("channel %d: big input buffer %d", - c->self, buffer_len(&c->input)); - return 0; - } -#endif - if (buffer_len(&c->output) > packet_get_maxsize()) { - debug("channel %d: big output buffer %d > %d", - c->self, buffer_len(&c->output), - packet_get_maxsize()); - return 0; - } - } - } - return 1; -} - -/* Returns true if any channel is still open. */ - -int -channel_still_open(void) -{ - int i; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c == NULL) - continue; - switch (c->type) { - case SSH_CHANNEL_X11_LISTENER: - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_CLOSED: - case SSH_CHANNEL_AUTH_SOCKET: - case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_CONNECTING: - case SSH_CHANNEL_ZOMBIE: - continue; - case SSH_CHANNEL_LARVAL: - if (!compat20) - fatal("cannot happen: SSH_CHANNEL_LARVAL"); - continue; - case SSH_CHANNEL_OPENING: - case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_X11_OPEN: - return 1; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - if (!compat13) - fatal("cannot happen: OUT_DRAIN"); - return 1; - default: - fatal("channel_still_open: bad channel type %d", c->type); - /* NOTREACHED */ - } - } - return 0; -} - -/* Returns the id of an open channel suitable for keepaliving */ - -int -channel_find_open(void) -{ - int i; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c == NULL) - continue; - switch (c->type) { - case SSH_CHANNEL_CLOSED: - case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_X11_LISTENER: - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_OPENING: - case SSH_CHANNEL_CONNECTING: - case SSH_CHANNEL_ZOMBIE: - continue; - case SSH_CHANNEL_LARVAL: - case SSH_CHANNEL_AUTH_SOCKET: - case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_X11_OPEN: - return i; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - if (!compat13) - fatal("cannot happen: OUT_DRAIN"); - return i; - default: - fatal("channel_find_open: bad channel type %d", c->type); - /* NOTREACHED */ - } - } - return -1; -} - - -/* - * Returns a message describing the currently open forwarded connections, - * suitable for sending to the client. The message contains crlf pairs for - * newlines. - */ - -char * -channel_open_message(void) -{ - Buffer buffer; - Channel *c; - char buf[1024], *cp; - int i; - - buffer_init(&buffer); - snprintf(buf, sizeof buf, "The following connections are open:\r\n"); - buffer_append(&buffer, buf, strlen(buf)); - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c == NULL) - continue; - switch (c->type) { - case SSH_CHANNEL_X11_LISTENER: - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_CLOSED: - case SSH_CHANNEL_AUTH_SOCKET: - case SSH_CHANNEL_ZOMBIE: - continue; - case SSH_CHANNEL_LARVAL: - case SSH_CHANNEL_OPENING: - case SSH_CHANNEL_CONNECTING: - case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_X11_OPEN: - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n", - c->self, c->remote_name, - c->type, c->remote_id, - c->istate, buffer_len(&c->input), - c->ostate, buffer_len(&c->output), - c->rfd, c->wfd); - buffer_append(&buffer, buf, strlen(buf)); - continue; - default: - fatal("channel_open_message: bad channel type %d", c->type); - /* NOTREACHED */ - } - } - buffer_append(&buffer, "\0", 1); - cp = xstrdup(buffer_ptr(&buffer)); - buffer_free(&buffer); - return cp; -} - -void -channel_send_open(int id) -{ - Channel *c = channel_lookup(id); - - if (c == NULL) { - log("channel_send_open: %d: bad id", id); - return; - } - debug("send channel open %d", id); - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring(c->ctype); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - packet_send(); -} - -void -channel_request_start(int local_id, char *service, int wantconfirm) -{ - Channel *c = channel_lookup(local_id); - - debug("channel request %d: %s", local_id, service); - if (c == NULL) { - log("channel_request_start: %d: unknown channel id", local_id); - return; - } - packet_start(SSH2_MSG_CHANNEL_REQUEST); - packet_put_int(c->remote_id); - packet_put_cstring(service); - packet_put_char(wantconfirm); -} -void -channel_register_confirm(int id, channel_callback_fn *fn) -{ - Channel *c = channel_lookup(id); - - if (c == NULL) { - log("channel_register_comfirm: %d: bad id", id); - return; - } - c->confirm = fn; -} -void -channel_register_cleanup(int id, channel_callback_fn *fn) -{ - Channel *c = channel_lookup(id); - - if (c == NULL) { - log("channel_register_cleanup: %d: bad id", id); - return; - } - c->detach_user = fn; -} -void -channel_cancel_cleanup(int id) -{ - Channel *c = channel_lookup(id); - - if (c == NULL) { - log("channel_cancel_cleanup: %d: bad id", id); - return; - } - c->detach_user = NULL; -} -void -channel_register_filter(int id, channel_filter_fn *fn) -{ - Channel *c = channel_lookup(id); - - if (c == NULL) { - log("channel_register_filter: %d: bad id", id); - return; - } - c->input_filter = fn; -} - -void -channel_set_fds(int id, int rfd, int wfd, int efd, - int extusage, int nonblock, u_int window_max) -{ - Channel *c = channel_lookup(id); - - if (c == NULL || c->type != SSH_CHANNEL_LARVAL) - fatal("channel_activate for non-larval channel %d.", id); - channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); - c->type = SSH_CHANNEL_OPEN; - c->local_window = c->local_window_max = window_max; - packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); - packet_put_int(c->remote_id); - packet_put_int(c->local_window); - packet_send(); -} - -void -channel_set_wait_for_exit(int id, int wait_for_exit) -{ - Channel *c = channel_lookup(id); - - if (c == NULL || c->type != SSH_CHANNEL_OPEN) - fatal("channel_set_wait_for_exit for non-open channel %d.", id); - - debug3("channel_set_wait_for_exit %d, %d (type: %d)", id, wait_for_exit, c->type); - c->wait_for_exit = wait_for_exit; -} - -/* - * 'channel_pre*' are called just before select() to add any bits relevant to - * channels in the select bitmasks. - */ -/* - * 'channel_post*': perform any appropriate operations for channels which - * have events pending. - */ -typedef void chan_fn(Channel *c, fd_set * readset, fd_set * writeset); -chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE]; -chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE]; - -static void -channel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset) -{ - FD_SET(c->sock, readset); -} - -static void -channel_pre_connecting(Channel *c, fd_set * readset, fd_set * writeset) -{ - debug3("channel %d: waiting for connection", c->self); - FD_SET(c->sock, writeset); -} - -static void -channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset) -{ - if (buffer_len(&c->input) < packet_get_maxsize()) - FD_SET(c->sock, readset); - if (buffer_len(&c->output) > 0) - FD_SET(c->sock, writeset); -} - -static void -channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) -{ - u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); - - if (c->istate == CHAN_INPUT_OPEN && - limit > 0 && - buffer_len(&c->input) < limit && - buffer_check_alloc(&c->input, CHAN_RBUF)) - FD_SET(c->rfd, readset); - if (c->ostate == CHAN_OUTPUT_OPEN || - c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - if (buffer_len(&c->output) > 0) { - FD_SET(c->wfd, writeset); - } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) - debug2("channel %d: obuf_empty delayed efd %d/(%d)", - c->self, c->efd, buffer_len(&c->extended)); - else - chan_obuf_empty(c); - } - } - /** XXX check close conditions, too */ - if (compat20 && c->efd != -1) { - if (c->extended_usage == CHAN_EXTENDED_WRITE && - buffer_len(&c->extended) > 0) - FD_SET(c->efd, writeset); - else if (!(c->flags & CHAN_EOF_SENT) && - c->extended_usage == CHAN_EXTENDED_READ && - buffer_len(&c->extended) < c->remote_window) - FD_SET(c->efd, readset); - } -} - -static void -channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset) -{ - if (buffer_len(&c->input) == 0) { - packet_start(SSH_MSG_CHANNEL_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - c->type = SSH_CHANNEL_CLOSED; - debug("channel %d: closing after input drain.", c->self); - } -} - -static void -channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset) -{ - if (buffer_len(&c->output) == 0) - chan_mark_dead(c); - else - FD_SET(c->sock, writeset); -} - -/* - * This is a special state for X11 authentication spoofing. An opened X11 - * connection (when authentication spoofing is being done) remains in this - * state until the first packet has been completely read. The authentication - * data in that packet is then substituted by the real data if it matches the - * fake data, and the channel is put into normal mode. - * XXX All this happens at the client side. - * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok - */ -static int -x11_open_helper(Buffer *b) -{ - u_char *ucp; - u_int proto_len, data_len; - - /* Check if the fixed size part of the packet is in buffer. */ - if (buffer_len(b) < 12) - return 0; - - /* Parse the lengths of variable-length fields. */ - ucp = buffer_ptr(b); - if (ucp[0] == 0x42) { /* Byte order MSB first. */ - proto_len = 256 * ucp[6] + ucp[7]; - data_len = 256 * ucp[8] + ucp[9]; - } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */ - proto_len = ucp[6] + 256 * ucp[7]; - data_len = ucp[8] + 256 * ucp[9]; - } else { - debug("Initial X11 packet contains bad byte order byte: 0x%x", - ucp[0]); - return -1; - } - - /* Check if the whole packet is in buffer. */ - if (buffer_len(b) < - 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) - return 0; - - /* Check if authentication protocol matches. */ - if (proto_len != strlen(x11_saved_proto) || - memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { - debug("X11 connection uses different authentication protocol."); - return -1; - } - /* Check if authentication data matches our fake data. */ - if (data_len != x11_fake_data_len || - memcmp(ucp + 12 + ((proto_len + 3) & ~3), - x11_fake_data, x11_fake_data_len) != 0) { - debug("X11 auth data does not match fake data."); - return -1; - } - /* Check fake data length */ - if (x11_fake_data_len != x11_saved_data_len) { - error("X11 fake_data_len %d != saved_data_len %d", - x11_fake_data_len, x11_saved_data_len); - return -1; - } - /* - * Received authentication protocol and data match - * our fake data. Substitute the fake data with real - * data. - */ - memcpy(ucp + 12 + ((proto_len + 3) & ~3), - x11_saved_data, x11_saved_data_len); - return 1; -} - -static void -channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset) -{ - int ret = x11_open_helper(&c->output); - - if (ret == 1) { - /* Start normal processing for the channel. */ - c->type = SSH_CHANNEL_OPEN; - channel_pre_open_13(c, readset, writeset); - } else if (ret == -1) { - /* - * We have received an X11 connection that has bad - * authentication information. - */ - log("X11 connection rejected because of wrong authentication."); - buffer_clear(&c->input); - buffer_clear(&c->output); - channel_close_fd(&c->sock); - c->sock = -1; - c->type = SSH_CHANNEL_CLOSED; - packet_start(SSH_MSG_CHANNEL_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - } -} - -static void -channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset) -{ - int ret = x11_open_helper(&c->output); - - /* c->force_drain = 1; */ - - if (ret == 1) { - c->type = SSH_CHANNEL_OPEN; - channel_pre_open(c, readset, writeset); - } else if (ret == -1) { - log("X11 connection rejected because of wrong authentication."); - debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); - chan_read_failed(c); - buffer_clear(&c->input); - chan_ibuf_empty(c); - buffer_clear(&c->output); - /* for proto v1, the peer will send an IEOF */ - if (compat20) - chan_write_failed(c); - else - c->type = SSH_CHANNEL_OPEN; - debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); - } -} - -/* try to decode a socks4 header */ -static int -channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset) -{ - char *p, *host; - int len, have, i, found; - char username[256]; - struct { - u_int8_t version; - u_int8_t command; - u_int16_t dest_port; - struct in_addr dest_addr; - } s4_req, s4_rsp; - - debug2("channel %d: decode socks4", c->self); - - have = buffer_len(&c->input); - len = sizeof(s4_req); - if (have < len) - return 0; - p = buffer_ptr(&c->input); - for (found = 0, i = len; i < have; i++) { - if (p[i] == '\0') { - found = 1; - break; - } - if (i > 1024) { - /* the peer is probably sending garbage */ - debug("channel %d: decode socks4: too long", - c->self); - return -1; - } - } - if (!found) - return 0; - buffer_get(&c->input, (char *)&s4_req.version, 1); - buffer_get(&c->input, (char *)&s4_req.command, 1); - buffer_get(&c->input, (char *)&s4_req.dest_port, 2); - buffer_get(&c->input, (char *)&s4_req.dest_addr, 4); - have = buffer_len(&c->input); - p = buffer_ptr(&c->input); - len = strlen(p); - debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); - if (len > have) - fatal("channel %d: decode socks4: len %d > have %d", - c->self, len, have); - strlcpy(username, p, sizeof(username)); - buffer_consume(&c->input, len); - buffer_consume(&c->input, 1); /* trailing '\0' */ - - host = inet_ntoa(s4_req.dest_addr); - strlcpy(c->path, host, sizeof(c->path)); - c->host_port = ntohs(s4_req.dest_port); - - debug("channel %d: dynamic request: socks4 host %s port %u command %u", - c->self, host, c->host_port, s4_req.command); - - if (s4_req.command != 1) { - debug("channel %d: cannot handle: socks4 cn %d", - c->self, s4_req.command); - return -1; - } - s4_rsp.version = 0; /* vn: 0 for reply */ - s4_rsp.command = 90; /* cd: req granted */ - s4_rsp.dest_port = 0; /* ignored */ - s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ - buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp)); - return 1; -} - -/* try to decode a socks5 header */ -#define SSH_SOCKS5_AUTHDONE 0x1000 -#define SSH_SOCKS5_NOAUTH 0x00 -#define SSH_SOCKS5_IPV4 0x01 -#define SSH_SOCKS5_DOMAIN 0x03 -#define SSH_SOCKS5_IPV6 0x04 -#define SSH_SOCKS5_CONNECT 0x01 -#define SSH_SOCKS5_SUCCESS 0x00 - -/* ARGSUSED */ -static int -channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) -{ - struct { - u_int8_t version; - u_int8_t command; - u_int8_t reserved; - u_int8_t atyp; - } s5_req, s5_rsp; - u_int16_t dest_port; - u_char *p, dest_addr[255+1]; - u_int have, need, i, found, nmethods, addrlen; - struct in_addr bnd_addr; - int af; - - debug2("channel %d: decode socks5", c->self); - p = buffer_ptr(&c->input); - if (p[0] != 0x05) - return -1; - have = buffer_len(&c->input); - if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { - /* format: ver | nmethods | methods */ - if (have < 2) - return 0; - nmethods = p[1]; - if (have < nmethods + 2) - return 0; - /* look for method: "NO AUTHENTICATION REQUIRED" */ - for (found = 0, i = 2 ; i < nmethods + 2; i++) { - if (p[i] == SSH_SOCKS5_NOAUTH) { - found = 1; - break; - } - } - if (!found) { - error("channel %d: socks5 authentication methods not implemented", - c->self); - error("channel %d: forwarding failed: " - "SSH_SOCKS5_NOAUTH method not found", c->self); - return -1; - } - buffer_consume(&c->input, nmethods + 2); - buffer_put_char(&c->output, 0x05); /* version */ - buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */ - FD_SET(c->sock, writeset); - c->flags |= SSH_SOCKS5_AUTHDONE; - debug2("channel %d: socks5 auth done", c->self); - return 0; /* need more */ - } - debug2("channel %d: socks5 post auth", c->self); - if (have < sizeof(s5_req)+1) - return 0; /* need more */ - memcpy(&s5_req, p, sizeof(s5_req)); - if (s5_req.version != 0x05 || - s5_req.command != SSH_SOCKS5_CONNECT || - s5_req.reserved != 0x00) { - error("channel %d: forwarding failed: " - "only socks5 connect is supported", c->self); - return -1; - } - switch (s5_req.atyp){ - case SSH_SOCKS5_IPV4: - addrlen = 4; - af = AF_INET; - break; - case SSH_SOCKS5_DOMAIN: - addrlen = p[sizeof(s5_req)]; - af = -1; - break; - case SSH_SOCKS5_IPV6: - addrlen = 16; - af = AF_INET6; - break; - default: - error("channel %d: forwarding failed: " - "bad socks5 atyp %d", c->self, s5_req.atyp); - return -1; - } - need = sizeof(s5_req) + addrlen + 2; - if (s5_req.atyp == SSH_SOCKS5_DOMAIN) - need++; - if (have < need) - return 0; - buffer_consume(&c->input, sizeof(s5_req)); - if (s5_req.atyp == SSH_SOCKS5_DOMAIN) - buffer_consume(&c->input, 1); /* host string length */ - buffer_get(&c->input, (char *)&dest_addr, addrlen); - buffer_get(&c->input, (char *)&dest_port, 2); - dest_addr[addrlen] = '\0'; - if (s5_req.atyp == SSH_SOCKS5_DOMAIN) - strlcpy(c->path, (char *)dest_addr, sizeof(c->path)); - else if (inet_ntop(af, dest_addr, c->path, sizeof(c->path)) == NULL) - return -1; - c->host_port = ntohs(dest_port); - - debug2("channel %d: dynamic request: socks5 host %s port %u command %u", - c->self, c->path, c->host_port, s5_req.command); - - s5_rsp.version = 0x05; - s5_rsp.command = SSH_SOCKS5_SUCCESS; - s5_rsp.reserved = 0; /* ignored */ - s5_rsp.atyp = SSH_SOCKS5_IPV4; - bzero(&bnd_addr, sizeof(bnd_addr)); - bnd_addr.s_addr = htonl(INADDR_ANY); - dest_port = 0; /* ignored */ - - buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp)); - buffer_append(&c->output, &bnd_addr, sizeof(struct in_addr)); - buffer_append(&c->output, &dest_port, sizeof(dest_port)); - return 1; -} - -/* dynamic port forwarding */ -static void -channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) -{ - u_char *p; - int have, ret; - - have = buffer_len(&c->input); - debug2("channel %d: pre_dynamic: have %d", c->self, have); - /* buffer_dump(&c->input); */ - /* check if the fixed size part of the packet is in buffer. */ - if (have < 3) { - /* need more */ - FD_SET(c->sock, readset); - return; - } - /* try to guess the protocol */ - p = buffer_ptr(&c->input); - switch (p[0]) { - case 0x04: - ret = channel_decode_socks4(c, readset, writeset); - break; - case 0x05: - ret = channel_decode_socks5(c, readset, writeset); - break; - default: - error("channel %d: forwarding failed: unknown socks " - "version 0x%02X", c->self, p[0]); - ret = -1; - break; - } - if (ret < 0) { - chan_mark_dead(c); - } else if (ret == 0) { - debug2("channel %d: pre_dynamic: need more", c->self); - /* need more */ - FD_SET(c->sock, readset); - } else { - /* switch to the next state */ - c->type = SSH_CHANNEL_OPENING; - port_open_helper(c, "direct-tcpip"); - } -} - -/* This is our fake X11 server socket. */ -static void -channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) -{ - Channel *nc; - struct sockaddr addr; - int newsock; - socklen_t addrlen; - char buf[16384], *remote_ipaddr; - int remote_port; - - if (FD_ISSET(c->sock, readset)) { - debug("X11 connection requested."); - addrlen = sizeof(addr); - newsock = accept(c->sock, &addr, &addrlen); - if (c->single_connection) { - debug("single_connection: closing X11 listener."); - channel_close_fd(&c->sock); - chan_mark_dead(c); - } - if (newsock < 0) { - error("accept: %.100s", strerror(errno)); - return; - } - set_nodelay(newsock); - remote_ipaddr = get_peer_ipaddr(newsock); - remote_port = get_peer_port(newsock); - snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", - remote_ipaddr, remote_port); - - nc = channel_new("accepted x11 socket", - SSH_CHANNEL_OPENING, newsock, newsock, -1, - c->local_window_max, c->local_maxpacket, - 0, xstrdup(buf), 1); - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring("x11"); - packet_put_int(nc->self); - packet_put_int(nc->local_window_max); - packet_put_int(nc->local_maxpacket); - /* originator ipaddr and port */ - packet_put_cstring(remote_ipaddr); - if (datafellows & SSH_BUG_X11FWD) { - debug("ssh2 x11 bug compat mode"); - } else { - packet_put_int(remote_port); - } - packet_send(); - } else { - packet_start(SSH_SMSG_X11_OPEN); - packet_put_int(nc->self); - if (packet_get_protocol_flags() & - SSH_PROTOFLAG_HOST_IN_FWD_OPEN) - packet_put_cstring(buf); - packet_send(); - } - xfree(remote_ipaddr); - } -} - -static void -port_open_helper(Channel *c, char *rtype) -{ - int direct; - char buf[1024]; - char *remote_ipaddr = get_peer_ipaddr(c->sock); - u_short remote_port = get_peer_port(c->sock); - - direct = (strcmp(rtype, "direct-tcpip") == 0); - - snprintf(buf, sizeof buf, - "%s: listening port %d for %.100s port %d, " - "connect from %.200s port %d", - rtype, c->listening_port, c->path, c->host_port, - remote_ipaddr, remote_port); - - xfree(c->remote_name); - c->remote_name = xstrdup(buf); - - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring(rtype); - packet_put_int(c->self); - packet_put_int(c->local_window_max); - packet_put_int(c->local_maxpacket); - if (direct) { - /* target host, port */ - packet_put_cstring(c->path); - packet_put_int(c->host_port); - } else { - /* listen address, port */ - packet_put_cstring(c->path); - packet_put_int(c->listening_port); - } - /* originator host and port */ - packet_put_cstring(remote_ipaddr); - packet_put_int(remote_port); - packet_send(); - } else { - packet_start(SSH_MSG_PORT_OPEN); - packet_put_int(c->self); - packet_put_cstring(c->path); - packet_put_int(c->host_port); - if (packet_get_protocol_flags() & - SSH_PROTOFLAG_HOST_IN_FWD_OPEN) - packet_put_cstring(c->remote_name); - packet_send(); - } - xfree(remote_ipaddr); -} - -/* - * This socket is listening for connections to a forwarded TCP/IP port. - */ -static void -channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) -{ - Channel *nc; - struct sockaddr addr; - int newsock, nextstate; - socklen_t addrlen; - char *rtype; - - if (FD_ISSET(c->sock, readset)) { - debug("Connection to port %d forwarding " - "to %.100s port %d requested.", - c->listening_port, c->path, c->host_port); - - if (c->type == SSH_CHANNEL_RPORT_LISTENER) { - nextstate = SSH_CHANNEL_OPENING; - rtype = "forwarded-tcpip"; - } else { - if (c->host_port == 0) { - nextstate = SSH_CHANNEL_DYNAMIC; - rtype = "dynamic-tcpip"; - } else { - nextstate = SSH_CHANNEL_OPENING; - rtype = "direct-tcpip"; - } - } - - addrlen = sizeof(addr); - newsock = accept(c->sock, &addr, &addrlen); - if (newsock < 0) { - error("accept: %.100s", strerror(errno)); - return; - } - set_nodelay(newsock); - nc = channel_new(rtype, - nextstate, newsock, newsock, -1, - c->local_window_max, c->local_maxpacket, - 0, xstrdup(rtype), 1); - nc->listening_port = c->listening_port; - nc->host_port = c->host_port; - strlcpy(nc->path, c->path, sizeof(nc->path)); - - if (nextstate != SSH_CHANNEL_DYNAMIC) - port_open_helper(nc, rtype); - } -} - -/* - * This is the authentication agent socket listening for connections from - * clients. - */ -static void -channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) -{ - Channel *nc; - char *name; - int newsock; - struct sockaddr addr; - socklen_t addrlen; - - if (FD_ISSET(c->sock, readset)) { - addrlen = sizeof(addr); - newsock = accept(c->sock, &addr, &addrlen); - if (newsock < 0) { - error("accept from auth socket: %.100s", strerror(errno)); - return; - } - name = xstrdup("accepted auth socket"); - nc = channel_new("accepted auth socket", - SSH_CHANNEL_OPENING, newsock, newsock, -1, - c->local_window_max, c->local_maxpacket, - 0, name, 1); - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring("auth-agent@openssh.com"); - packet_put_int(nc->self); - packet_put_int(c->local_window_max); - packet_put_int(c->local_maxpacket); - } else { - packet_start(SSH_SMSG_AGENT_OPEN); - packet_put_int(nc->self); - } - packet_send(); - } -} - -static void -channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset) -{ - int err = 0; - socklen_t sz = sizeof(err); - - if (FD_ISSET(c->sock, writeset)) { - if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { - err = errno; - error("getsockopt SO_ERROR failed"); - } - if (err == 0) { - debug("channel %d: connected", c->self); - c->type = SSH_CHANNEL_OPEN; - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - } else { - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - } - } else { - debug("channel %d: not connected: %s", - c->self, strerror(err)); - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(c->remote_id); - packet_put_int(SSH2_OPEN_CONNECT_FAILED); - if (!(datafellows & SSH_BUG_OPENFAILURE)) { - packet_put_utf8_cstring(strerror(err)); - packet_put_cstring(""); - } - } else { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(c->remote_id); - } - chan_mark_dead(c); - } - packet_send(); - } -} - -static int -channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) -{ - char buf[CHAN_RBUF]; - int len; - - if (c->rfd != -1 && - FD_ISSET(c->rfd, readset)) { - len = read(c->rfd, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) - return 1; - if (len <= 0) { - debug("channel %d: read<=0 rfd %d len %d", - c->self, c->rfd, len); - if (c->type != SSH_CHANNEL_OPEN) { - debug("channel %d: not open", c->self); - chan_mark_dead(c); - return -1; - } else if (compat13) { - buffer_clear(&c->output); - c->type = SSH_CHANNEL_INPUT_DRAINING; - debug("channel %d: input draining.", c->self); - } else { - chan_read_failed(c); - } - return -1; - } - if (c->input_filter != NULL) { - if (c->input_filter(c, buf, len) == -1) { - debug("channel %d: filter stops", c->self); - chan_read_failed(c); - } - } else { - buffer_append(&c->input, buf, len); - } - } - return 1; -} -static int -channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) -{ - struct termios tio; - u_char *data; - u_int dlen; - int len; - - /* Send buffered output data to the socket. */ - if (c->wfd != -1 && - FD_ISSET(c->wfd, writeset) && - buffer_len(&c->output) > 0) { - data = buffer_ptr(&c->output); - dlen = buffer_len(&c->output); -#ifdef _AIX - /* XXX: Later AIX versions can't push as much data to tty */ - if (compat20 && c->wfd_isatty && dlen > 8*1024) - dlen = 8*1024; -#endif - len = write(c->wfd, data, dlen); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) - return 1; - if (len <= 0) { - if (c->type != SSH_CHANNEL_OPEN) { - debug("channel %d: not open", c->self); - chan_mark_dead(c); - return -1; - } else if (compat13) { - buffer_clear(&c->output); - debug("channel %d: input draining.", c->self); - c->type = SSH_CHANNEL_INPUT_DRAINING; - } else { - chan_write_failed(c); - } - return -1; - } - if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') { - if (tcgetattr(c->wfd, &tio) == 0 && - !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { - /* - * Simulate echo to reduce the impact of - * traffic analysis. We need to match the - * size of a SSH2_MSG_CHANNEL_DATA message - * (4 byte channel id + data) - */ - packet_send_ignore(4 + len); - packet_send(); - } - } - buffer_consume(&c->output, len); - if (compat20 && len > 0) { - c->local_consumed += len; - } - } - return 1; -} -static int -channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) -{ - char buf[CHAN_RBUF]; - int len; - -/** XXX handle drain efd, too */ - if (c->efd != -1) { - if (c->extended_usage == CHAN_EXTENDED_WRITE && - FD_ISSET(c->efd, writeset) && - buffer_len(&c->extended) > 0) { - len = write(c->efd, buffer_ptr(&c->extended), - buffer_len(&c->extended)); - debug2("channel %d: written %d to efd %d", - c->self, len, c->efd); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) - return 1; - if (len <= 0) { - debug2("channel %d: closing write-efd %d", - c->self, c->efd); - channel_close_fd(&c->efd); - } else { - buffer_consume(&c->extended, len); - c->local_consumed += len; - } - } else if (c->extended_usage == CHAN_EXTENDED_READ && - FD_ISSET(c->efd, readset)) { - len = read(c->efd, buf, sizeof(buf)); - debug2("channel %d: read %d from efd %d", - c->self, len, c->efd); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) - return 1; - if (len <= 0) { - debug2("channel %d: closing read-efd %d", - c->self, c->efd); - channel_close_fd(&c->efd); - } else { - buffer_append(&c->extended, buf, len); - } - } - } - return 1; -} -static int -channel_check_window(Channel *c) -{ - if (c->type == SSH_CHANNEL_OPEN && - !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && - c->local_window < c->local_window_max/2 && - c->local_consumed > 0) { - packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); - packet_put_int(c->remote_id); - packet_put_int(c->local_consumed); - packet_send(); - debug2("channel %d: window %d sent adjust %d", - c->self, c->local_window, - c->local_consumed); - c->local_window += c->local_consumed; - c->local_consumed = 0; - } - return 1; -} - -static void -channel_post_open(Channel *c, fd_set * readset, fd_set * writeset) -{ - channel_handle_rfd(c, readset, writeset); - channel_handle_wfd(c, readset, writeset); - if (!compat20) - return; - channel_handle_efd(c, readset, writeset); - channel_check_window(c); -} - -static void -channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset) -{ - int len; - - /* Send buffered output data to the socket. */ - if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) { - len = write(c->sock, buffer_ptr(&c->output), - buffer_len(&c->output)); - if (len <= 0) - buffer_clear(&c->output); - else - buffer_consume(&c->output, len); - } -} - -static void -channel_handler_init_20(void) -{ - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; - channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; - channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; - channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; - channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; -} - -static void -channel_handler_init_13(void) -{ - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13; - channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining; - channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; - channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; - channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; - channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; - channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; - channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; -} - -static void -channel_handler_init_15(void) -{ - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; - channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; - channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - - channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; - channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; - channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; -} - -static void -channel_handler_init(void) -{ - int i; - - for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { - channel_pre[i] = NULL; - channel_post[i] = NULL; - } - if (compat20) - channel_handler_init_20(); - else if (compat13) - channel_handler_init_13(); - else - channel_handler_init_15(); -} - -/* gc dead channels */ -static void -channel_garbage_collect(Channel *c) -{ - if (c == NULL) - return; - if (c->detach_user != NULL) { - if (!chan_is_dead(c, 0)) - return; - debug("channel %d: gc: notify user", c->self); - c->detach_user(c->self, NULL); - /* if we still have a callback */ - if (c->detach_user != NULL) - return; - debug("channel %d: gc: user detached", c->self); - } - if (!c->wait_for_exit && !chan_is_dead(c, 1)) - return; - debug("channel %d: garbage collecting", c->self); - channel_free(c); -} - -static void -channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) -{ - static int did_init = 0; - int i, oalloc; - Channel *c; - - if (!did_init) { - channel_handler_init(); - did_init = 1; - } - for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { - c = channels[i]; - if (c == NULL) - continue; - if (c->delayed) { - if (ftab == channel_pre) - c->delayed = 0; - else - continue; - } - if (ftab[c->type] != NULL) - (*ftab[c->type])(c, readset, writeset); - channel_garbage_collect(c); - } -} - -/* - * Allocate/update select bitmasks and add any bits relevant to channels in - * select bitmasks. - */ -void -channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, - int *nallocp, int rekeying) -{ - int n; - u_int sz; - - n = MAX(*maxfdp, channel_max_fd); - - sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); - /* perhaps check sz < nalloc/2 and shrink? */ - if (*readsetp == NULL || sz > *nallocp) { - *readsetp = xrealloc(*readsetp, sz); - *writesetp = xrealloc(*writesetp, sz); - *nallocp = sz; - } - *maxfdp = n; - memset(*readsetp, 0, sz); - memset(*writesetp, 0, sz); - - if (!rekeying) - channel_handler(channel_pre, *readsetp, *writesetp); -} - -/* - * After select, perform any appropriate operations for channels which have - * events pending. - */ -void -channel_after_select(fd_set * readset, fd_set * writeset) -{ - channel_handler(channel_post, readset, writeset); -} - - -/* If there is data to send to the connection, enqueue some of it now. */ - -void -channel_output_poll(void) -{ - Channel *c; - int i; - u_int len; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c == NULL) - continue; - - /* - * We are only interested in channels that can have buffered - * incoming data. - */ - if (compat13) { - if (c->type != SSH_CHANNEL_OPEN && - c->type != SSH_CHANNEL_INPUT_DRAINING) - continue; - } else { - if (c->type != SSH_CHANNEL_OPEN) - continue; - } - if (compat20 && - (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { - /* XXX is this true? */ - debug3("channel %d: will not send data after close", c->self); - continue; - } - - /* Get the amount of buffered data for this channel. */ - if ((c->istate == CHAN_INPUT_OPEN || - c->istate == CHAN_INPUT_WAIT_DRAIN) && - (len = buffer_len(&c->input)) > 0) { - /* - * Send some data for the other side over the secure - * connection. - */ - if (compat20) { - if (len > c->remote_window) - len = c->remote_window; - if (len > c->remote_maxpacket) - len = c->remote_maxpacket; - } else { - if (packet_is_interactive()) { - if (len > 1024) - len = 512; - } else { - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()/2) - len = packet_get_maxsize()/2; - } - } - if (len > 0) { - packet_start(compat20 ? - SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); - packet_put_int(c->remote_id); - packet_put_string(buffer_ptr(&c->input), len); - packet_send(); - buffer_consume(&c->input, len); - c->remote_window -= len; - } - } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { - if (compat13) - fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); - /* - * input-buffer is empty and read-socket shutdown: - * tell peer, that we will not send more data: send IEOF. - * hack for extended data: delay EOF if EFD still in use. - */ - if (CHANNEL_EFD_INPUT_ACTIVE(c)) - debug2("channel %d: ibuf_empty delayed efd %d/(%d)", - c->self, c->efd, buffer_len(&c->extended)); - else - chan_ibuf_empty(c); - } - /* Send extended data, i.e. stderr */ - if (compat20 && - !(c->flags & CHAN_EOF_SENT) && - c->remote_window > 0 && - (len = buffer_len(&c->extended)) > 0 && - c->extended_usage == CHAN_EXTENDED_READ) { - debug2("channel %d: rwin %u elen %u euse %d", - c->self, c->remote_window, buffer_len(&c->extended), - c->extended_usage); - if (len > c->remote_window) - len = c->remote_window; - if (len > c->remote_maxpacket) - len = c->remote_maxpacket; - packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA); - packet_put_int(c->remote_id); - packet_put_int(SSH2_EXTENDED_DATA_STDERR); - packet_put_string(buffer_ptr(&c->extended), len); - packet_send(); - buffer_consume(&c->extended, len); - c->remote_window -= len; - debug2("channel %d: sent ext data %d", c->self, len); - } - } -} - - -/* -- protocol input */ - -void -channel_input_data(int type, u_int32_t seq, void *ctxt) -{ - int id; - char *data; - u_int data_len; - Channel *c; - - /* Get the channel number and verify it. */ - id = packet_get_int(); - c = channel_lookup(id); - if (c == NULL) - packet_disconnect("Received data for nonexistent channel %d.", id); - - /* Ignore any data for non-open channels (might happen on close) */ - if (c->type != SSH_CHANNEL_OPEN && - c->type != SSH_CHANNEL_X11_OPEN) - return; - - /* same for protocol 1.5 if output end is no longer open */ - if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) - return; - - /* Get the data. */ - data = packet_get_string(&data_len); - - if (compat20) { - if (data_len > c->local_maxpacket) { - log("channel %d: rcvd big packet %d, maxpack %d", - c->self, data_len, c->local_maxpacket); - } - if (data_len > c->local_window) { - log("channel %d: rcvd too much data %d, win %d", - c->self, data_len, c->local_window); - xfree(data); - return; - } - c->local_window -= data_len; - } - packet_check_eom(); - buffer_append(&c->output, data, data_len); - xfree(data); -} - -void -channel_input_extended_data(int type, u_int32_t seq, void *ctxt) -{ - int id; - char *data; - u_int data_len, tcode; - Channel *c; - - /* Get the channel number and verify it. */ - id = packet_get_int(); - c = channel_lookup(id); - - if (c == NULL) - packet_disconnect("Received extended_data for bad channel %d.", id); - if (c->type != SSH_CHANNEL_OPEN) { - log("channel %d: ext data for non open", id); - return; - } - if (c->flags & CHAN_EOF_RCVD) { - if (datafellows & SSH_BUG_EXTEOF) - debug("channel %d: accepting ext data after eof", id); - else - packet_disconnect("Received extended_data after EOF " - "on channel %d.", id); - } - tcode = packet_get_int(); - if (c->efd == -1 || - c->extended_usage != CHAN_EXTENDED_WRITE || - tcode != SSH2_EXTENDED_DATA_STDERR) { - log("channel %d: bad ext data", c->self); - return; - } - data = packet_get_string(&data_len); - packet_check_eom(); - if (data_len > c->local_window) { - log("channel %d: rcvd too much extended_data %d, win %d", - c->self, data_len, c->local_window); - xfree(data); - return; - } - debug2("channel %d: rcvd ext data %d", c->self, data_len); - c->local_window -= data_len; - buffer_append(&c->extended, data, data_len); - xfree(data); -} - -void -channel_input_ieof(int type, u_int32_t seq, void *ctxt) -{ - int id; - Channel *c; - - id = packet_get_int(); - packet_check_eom(); - c = channel_lookup(id); - if (c == NULL) - packet_disconnect("Received ieof for nonexistent channel %d.", id); - chan_rcvd_ieof(c); - - /* XXX force input close */ - if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { - debug("channel %d: FORCE input drain", c->self); - c->istate = CHAN_INPUT_WAIT_DRAIN; - if (buffer_len(&c->input) == 0) - chan_ibuf_empty(c); - } - -} - -void -channel_input_close(int type, u_int32_t seq, void *ctxt) -{ - int id; - Channel *c; - - id = packet_get_int(); - packet_check_eom(); - c = channel_lookup(id); - if (c == NULL) - packet_disconnect("Received close for nonexistent channel %d.", id); - - /* - * Send a confirmation that we have closed the channel and no more - * data is coming for it. - */ - packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION); - packet_put_int(c->remote_id); - packet_send(); - - /* - * If the channel is in closed state, we have sent a close request, - * and the other side will eventually respond with a confirmation. - * Thus, we cannot free the channel here, because then there would be - * no-one to receive the confirmation. The channel gets freed when - * the confirmation arrives. - */ - if (c->type != SSH_CHANNEL_CLOSED) { - /* - * Not a closed channel - mark it as draining, which will - * cause it to be freed later. - */ - buffer_clear(&c->input); - c->type = SSH_CHANNEL_OUTPUT_DRAINING; - } -} - -/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ -void -channel_input_oclose(int type, u_int32_t seq, void *ctxt) -{ - int id = packet_get_int(); - Channel *c = channel_lookup(id); - - packet_check_eom(); - if (c == NULL) - packet_disconnect("Received oclose for nonexistent channel %d.", id); - chan_rcvd_oclose(c); -} - -void -channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt) -{ - int id = packet_get_int(); - Channel *c = channel_lookup(id); - - packet_check_eom(); - if (c == NULL) - packet_disconnect("Received close confirmation for " - "out-of-range channel %d.", id); - if (c->type != SSH_CHANNEL_CLOSED) - packet_disconnect("Received close confirmation for " - "non-closed channel %d (type %d).", id, c->type); - channel_free(c); -} - -void -channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) -{ - int id, remote_id; - Channel *c; - - id = packet_get_int(); - c = channel_lookup(id); - - if (c==NULL || c->type != SSH_CHANNEL_OPENING) - packet_disconnect("Received open confirmation for " - "non-opening channel %d.", id); - remote_id = packet_get_int(); - /* Record the remote channel number and mark that the channel is now open. */ - c->remote_id = remote_id; - c->type = SSH_CHANNEL_OPEN; - - if (compat20) { - c->remote_window = packet_get_int(); - c->remote_maxpacket = packet_get_int(); - if (c->confirm) { - debug2("callback start"); - c->confirm(c->self, NULL); - debug2("callback done"); - } - debug("channel %d: open confirm rwindow %u rmax %u", c->self, - c->remote_window, c->remote_maxpacket); - } - packet_check_eom(); -} - -static char * -reason2txt(int reason) -{ - switch (reason) { - case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED: - return "administratively prohibited"; - case SSH2_OPEN_CONNECT_FAILED: - return "connect failed"; - case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE: - return "unknown channel type"; - case SSH2_OPEN_RESOURCE_SHORTAGE: - return "resource shortage"; - } - return "unknown reason"; -} - -void -channel_input_open_failure(int type, u_int32_t seq, void *ctxt) -{ - int id, reason; - char *msg = NULL, *lang = NULL; - Channel *c; - - id = packet_get_int(); - c = channel_lookup(id); - - if (c==NULL || c->type != SSH_CHANNEL_OPENING) - packet_disconnect("Received open failure for " - "non-opening channel %d.", id); - if (compat20) { - reason = packet_get_int(); - if (!(datafellows & SSH_BUG_OPENFAILURE)) { - msg = packet_get_string(NULL); - lang = packet_get_string(NULL); - } - log("channel %d: open failed: %s%s%s", id, - reason2txt(reason), msg ? ": ": "", msg ? msg : ""); - if (msg != NULL) - xfree(msg); - if (lang != NULL) - xfree(lang); - } - packet_check_eom(); - /* Free the channel. This will also close the socket. */ - channel_free(c); -} - -void -channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) -{ - Channel *c; - int id; - u_int adjust; - - if (!compat20) - return; - - /* Get the channel number and verify it. */ - id = packet_get_int(); - c = channel_lookup(id); - - if (c == NULL || c->type != SSH_CHANNEL_OPEN) { - log("Received window adjust for " - "non-open channel %d.", id); - return; - } - adjust = packet_get_int(); - packet_check_eom(); - debug2("channel %d: rcvd adjust %u", id, adjust); - c->remote_window += adjust; -} - -void -channel_input_port_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - u_short host_port; - char *host, *originator_string; - int remote_id, sock = -1; - - remote_id = packet_get_int(); - host = packet_get_string(NULL); - host_port = packet_get_int(); - - if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) { - originator_string = packet_get_string(NULL); - } else { - originator_string = xstrdup("unknown (remote did not supply name)"); - } - packet_check_eom(); - sock = channel_connect_to(host, host_port); - if (sock != -1) { - c = channel_new("connected socket", - SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0, - originator_string, 1); - c->remote_id = remote_id; - } - if (c == NULL) { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_id); - packet_send(); - } - xfree(host); -} - - -/* -- tcp forwarding */ - -void -channel_set_af(int af) -{ - IPv4or6 = af; -} - -static int -channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports) -{ - Channel *c; - int sock, r, is_client, on = 1, wildcard = 0, success = 0; - struct addrinfo hints, *ai, *aitop; - const char *host, *addr; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; - - host = (type == SSH_CHANNEL_RPORT_LISTENER) ? - listen_addr : host_to_connect; - is_client = (type == SSH_CHANNEL_PORT_LISTENER); - - if (host == NULL) { - error("No forward host name."); - return 0; - } - if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) { - error("Forward host name too long."); - return 0; - } - - /* - * Determine whether or not a port forward listens to loopback, - * specified address or wildcard. On the client, a specified bind - * address will always override gateway_ports. On the server, a - * gateway_ports of 1 (``yes'') will override the client's - * specification and force a wildcard bind, whereas a value of 2 - * (``clientspecified'') will bind to whatever address the client - * asked for. - * - * Special-case listen_addrs are: - * - * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR - * "" (empty string), "*" -> wildcard v4/v6 - * "localhost" -> loopback v4/v6 - */ - addr = NULL; - if (listen_addr == NULL) { - /* No address specified: default to gateway_ports setting */ - if (gateway_ports) - wildcard = 1; - } else if (gateway_ports || is_client) { - if (((datafellows & SSH_OLD_FORWARD_ADDR) && - strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || - *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || - (!is_client && gateway_ports == 1)) - wildcard = 1; - else if (strcmp(listen_addr, "localhost") != 0) - addr = listen_addr; - } - - debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", - type, wildcard, (addr == NULL) ? "NULL" : addr); - - /* - * getaddrinfo returns a loopback address if the hostname is - * set to NULL and hints.ai_flags is not AI_PASSIVE - */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_flags = wildcard ? AI_PASSIVE : 0; - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", listen_port); - if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { - if (addr == NULL) { - /* This really shouldn't happen */ - packet_disconnect("getaddrinfo: fatal error: %s", - gai_strerror(r)); - } else { - error("channel_setup_fwd_listener: " - "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); - } - return 0; - } - - for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) - continue; - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), - strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("channel_setup_fwd_listener: getnameinfo failed"); - continue; - } - /* Create a port to listen for the host. */ - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) { - /* this is no error since kernel may not support ipv6 */ - verbose("socket: %.100s", strerror(errno)); - continue; - } - /* - * Set socket options. - * Allow local port reuse in TIME_WAIT. - */ - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, - sizeof(on)) == -1) - error("setsockopt SO_REUSEADDR: %s", strerror(errno)); - - debug("Local forwarding listening on %s port %s.", ntop, strport); - - /* Bind the socket to the address. */ - if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - /* address can be in use ipv6 address is already bound */ - if (!ai->ai_next) - error("bind: %.100s", strerror(errno)); - else - verbose("bind: %.100s", strerror(errno)); - - close(sock); - continue; - } - /* Start listening for connections on the socket. */ - if (listen(sock, 5) < 0) { - error("listen: %.100s", strerror(errno)); - close(sock); - continue; - } - /* Allocate a channel number for the socket. */ - c = channel_new("port listener", type, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, - 0, xstrdup("port listener"), 1); - strlcpy(c->path, host, sizeof(c->path)); - c->host_port = port_to_connect; - c->listening_port = listen_port; - success = 1; - } - if (success == 0) - error("channel_setup_fwd_listener: cannot listen to port: %d", - listen_port); - freeaddrinfo(aitop); - return success; -} - -int -channel_cancel_rport_listener(const char *host, u_short port) -{ - u_int i; - int found = 0; - - for (i = 0; i < channels_alloc; i++) { - Channel *c = channels[i]; - - if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && - strncmp(c->path, host, sizeof(c->path)) == 0 && - c->listening_port == port) { - debug2("%s: close channel %d", __func__, i); - channel_free(c); - found = 1; - } - } - - return (found); -} - -/* protocol local port fwd, used by ssh (and sshd in v1) */ -int -channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports) -{ - return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, - listen_host, listen_port, host_to_connect, port_to_connect, - gateway_ports); -} - -/* protocol v2 remote port fwd, used by sshd */ -int -channel_setup_remote_fwd_listener(const char *listen_address, - u_short listen_port, int gateway_ports) -{ - return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, - listen_address, listen_port, NULL, 0, gateway_ports); -} - -/* - * Initiate forwarding of connections to port "port" on remote host through - * the secure channel to host:port from local side. - */ - -int -channel_request_remote_forwarding(const char *listen_host, u_short listen_port, - const char *host_to_connect, u_short port_to_connect) -{ - int type, success = 0; - - /* Record locally that connection to this host/port is permitted. */ - if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) - fatal("channel_request_remote_forwarding: too many forwards"); - - if (listen_host != NULL && - strlen(listen_host) > SSH_CHANNEL_PATH_LEN - 1) { - error("Binding address too long."); - return -1; - } - - /* Send the forward request to the remote side. */ - if (compat20) { - const char *address_to_bind; - if (listen_host == NULL) { - if (datafellows & SSH_BUG_RFWD_ADDR) - address_to_bind = "127.0.0.1"; - else - address_to_bind = "localhost"; - } else if (*listen_host == '\0' || - strcmp(listen_host, "*") == 0) { - if (datafellows & SSH_BUG_RFWD_ADDR) - address_to_bind = "0.0.0.0"; - else - address_to_bind = ""; - } else - address_to_bind = listen_host; - - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("tcpip-forward"); - packet_put_char(1); /* boolean: want reply */ - packet_put_cstring(address_to_bind); - packet_put_int(listen_port); - packet_send(); - packet_write_wait(); - /* Assume that server accepts the request */ - success = 1; - } else { - packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); - packet_put_int(listen_port); - packet_put_cstring(host_to_connect); - packet_put_int(port_to_connect); - packet_send(); - packet_write_wait(); - - /* Wait for response from the remote side. */ - type = packet_read(); - switch (type) { - case SSH_SMSG_SUCCESS: - success = 1; - break; - case SSH_SMSG_FAILURE: - log("Warning: Server denied remote port forwarding."); - break; - default: - /* Unknown packet */ - packet_disconnect("Protocol error for port forward request:" - "received packet type %d.", type); - } - } - if (success) { - permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); - permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; - permitted_opens[num_permitted_opens].listen_port = listen_port; - num_permitted_opens++; - } - return (success ? 0 : -1); -} - -/* - * Request cancellation of remote forwarding of connection host:port from - * local side. - */ -void -channel_request_rforward_cancel(const char *host, u_short port) -{ - int i; - - if (!compat20) - return; - - for (i = 0; i < num_permitted_opens; i++) { - if (permitted_opens[i].host_to_connect != NULL && - permitted_opens[i].listen_port == port) - break; - } - if (i >= num_permitted_opens) { - debug("%s: requested forward not found", __func__); - return; - } - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("cancel-tcpip-forward"); - packet_put_char(0); - packet_put_cstring(host == NULL ? "" : host); - packet_put_int(port); - packet_send(); - - permitted_opens[i].listen_port = 0; - permitted_opens[i].port_to_connect = 0; - xfree(permitted_opens[i].host_to_connect); - permitted_opens[i].host_to_connect = NULL; -} - -/* - * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates - * listening for the port, and sends back a success reply (or disconnect - * message if there was an error). This never returns if there was an error. - */ - -void -channel_input_port_forward_request(int is_root, int gateway_ports) -{ - u_short port, host_port; - char *hostname; - - /* Get arguments from the packet. */ - port = packet_get_int(); - hostname = packet_get_string(NULL); - host_port = packet_get_int(); - -#ifndef HAVE_CYGWIN - /* - * Check that an unprivileged user is not trying to forward a - * privileged port. - */ - if (port < IPPORT_RESERVED && !is_root) - packet_disconnect("Requested forwarding of port %d but user is not root.", - port); -#endif - /* Initiate forwarding */ - channel_setup_local_fwd_listener(NULL, port, hostname, - host_port, gateway_ports); - - /* Free the argument string. */ - xfree(hostname); -} - -/* - * Permits opening to any host/port if permitted_opens[] is empty. This is - * usually called by the server, because the user could connect to any port - * anyway, and the server has no way to know but to trust the client anyway. - */ -void -channel_permit_all_opens(void) -{ - if (num_permitted_opens == 0) - all_opens_permitted = 1; -} - -void -channel_add_permitted_opens(char *host, int port) -{ - if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) - fatal("channel_add_permitted_opens: too many forwards"); - debug("allow port forwarding to host %s port %d", host, port); - - permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); - permitted_opens[num_permitted_opens].port_to_connect = port; - num_permitted_opens++; - - all_opens_permitted = 0; -} - -void -channel_clear_permitted_opens(void) -{ - int i; - - for (i = 0; i < num_permitted_opens; i++) - xfree(permitted_opens[i].host_to_connect); - num_permitted_opens = 0; -} - - -/* return socket to remote host, port */ -static int -connect_to(const char *host, u_short port) -{ - struct addrinfo hints, *ai, *aitop; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; - int gaierr; - int sock = -1; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", port); - if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { - error("connect_to %.100s: unknown host (%s)", host, - gai_strerror(gaierr)); - return -1; - } - for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) - continue; - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), - strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("connect_to: getnameinfo failed"); - continue; - } - sock = socket(ai->ai_family, SOCK_STREAM, 0); - if (sock < 0) { - error("socket: %.100s", strerror(errno)); - continue; - } - if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) - fatal("connect_to: F_SETFL: %s", strerror(errno)); - if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && - errno != EINPROGRESS) { - error("connect_to %.100s port %s: %.100s", ntop, strport, - strerror(errno)); - close(sock); - continue; /* fail -- try next */ - } - break; /* success */ - - } - freeaddrinfo(aitop); - if (!ai) { - error("connect_to %.100s port %d: failed.", host, port); - return -1; - } - /* success */ - set_nodelay(sock); - return sock; -} - -int -channel_connect_by_listen_address(u_short listen_port) -{ - int i; - - for (i = 0; i < num_permitted_opens; i++) - if (permitted_opens[i].listen_port == listen_port) - return connect_to( - permitted_opens[i].host_to_connect, - permitted_opens[i].port_to_connect); - error("WARNING: Server requests forwarding for unknown listen_port %d", - listen_port); - return -1; -} - -/* Check if connecting to that port is permitted and connect. */ -int -channel_connect_to(const char *host, u_short port) -{ - int i, permit; - - permit = all_opens_permitted; - if (!permit) { - for (i = 0; i < num_permitted_opens; i++) - if (permitted_opens[i].port_to_connect == port && - strcmp(permitted_opens[i].host_to_connect, host) == 0) - permit = 1; - - } - if (!permit) { - log("Received request to connect to host %.100s port %d, " - "but the request was denied.", host, port); - return -1; - } - return connect_to(host, port); -} - -/* -- X11 forwarding */ - -/* - * Creates an internet domain socket for listening for X11 connections. - * Returns 0 and a suitable display number for the DISPLAY variable - * stored in display_numberp , or -1 if an error occurs. - */ -int -x11_create_display_inet(int x11_display_offset, int x11_use_localhost, - int single_connection, u_int *display_numberp) -{ - Channel *nc = NULL; - int display_number, sock; - u_short port; - struct addrinfo hints, *ai, *aitop; - char strport[NI_MAXSERV]; - int gaierr, n, num_socks = 0, socks[NUM_SOCKS]; - - for (display_number = x11_display_offset; - display_number < MAX_DISPLAYS; - display_number++) { - port = 6000 + display_number; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", port); - if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { - error("getaddrinfo: %.100s", gai_strerror(gaierr)); - return -1; - } - for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) - continue; - sock = socket(ai->ai_family, SOCK_STREAM, 0); - if (sock < 0) { - if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) { - error("socket: %.100s", strerror(errno)); - freeaddrinfo(aitop); - for (n = 0; n < num_socks; n++) - close(socks[n]); - return -1; - } else { - debug("x11_create_display_inet: Socket family %d not supported", - ai->ai_family); - continue; - } - } -#ifdef IPV6_V6ONLY - if (ai->ai_family == AF_INET6) { - int on = 1; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) - error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno)); - } -#endif - if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - /* - * If bind() fails with EADDRNOTAVAIL, we - * should not break immediately but rather - * try the next address available. - */ - if (errno == EADDRNOTAVAIL) { - close(sock); - continue; - } - - debug("bind port %d: %.100s; skipping this port", port, - strerror(errno)); - close(sock); - - for (n = 0; n < num_socks; n++) { - close(socks[n]); - } - num_socks = 0; - break; - } - socks[num_socks++] = sock; -#ifndef DONT_TRY_OTHER_AF - if (num_socks == NUM_SOCKS) - break; -#else - if (x11_use_localhost) { - if (num_socks == NUM_SOCKS) - break; - } else { - break; - } -#endif - } - freeaddrinfo(aitop); - if (num_socks > 0) - break; - } - if (display_number >= MAX_DISPLAYS) { - error("Failed to allocate internet-domain X11 display socket."); - return -1; - } - /* Start listening for connections on the socket. */ - for (n = 0; n < num_socks; n++) { - sock = socks[n]; - if (listen(sock, 5) < 0) { - int i; - error("listen: %.100s", strerror(errno)); - for (i = 0; i < num_socks; i++) - close(socks[i]); - return -1; - } - } - - /* Allocate a channel for each socket. */ - for (n = 0; n < num_socks; n++) { - sock = socks[n]; - nc = channel_new("x11 listener", - SSH_CHANNEL_X11_LISTENER, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, - 0, xstrdup("X11 inet listener"), 1); - nc->single_connection = single_connection; - } - - /* Return the display number for the DISPLAY environment variable. */ - *display_numberp = display_number; - return (0); -} - -static int -connect_local_xsocket(u_int dnr) -{ - int sock; - struct sockaddr_un addr; - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - error("socket: %.100s", strerror(errno)); - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X, dnr); - if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0) - return sock; - close(sock); - error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); - return -1; -} - -int -x11_connect_display(void) -{ - int display_number, sock = 0; - const char *display; - char buf[1024], *cp; - struct addrinfo hints, *ai, *aitop; - char strport[NI_MAXSERV]; - int gaierr; - - /* Try to open a socket for the local X server. */ - display = getenv("DISPLAY"); - if (!display) { - error("DISPLAY not set."); - return -1; - } - /* - * Now we decode the value of the DISPLAY variable and make a - * connection to the real X server. - */ - - /* - * Check if it is a unix domain socket. Unix domain displays are in - * one of the following formats: unix:d[.s], :d[.s], ::d[.s] - */ - if (strncmp(display, "unix:", 5) == 0 || - display[0] == ':') { - /* Connect to the unix domain socket. */ - if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) { - error("Could not parse display number from DISPLAY: %.100s", - display); - return -1; - } - /* Create a socket. */ - sock = connect_local_xsocket(display_number); - if (sock < 0) - return -1; - - /* OK, we now have a connection to the display. */ - return sock; - } - /* - * Connect to an inet socket. The DISPLAY value is supposedly - * hostname:d[.s], where hostname may also be numeric IP address. - */ - strlcpy(buf, display, sizeof(buf)); - cp = strchr(buf, ':'); - if (!cp) { - error("Could not find ':' in DISPLAY: %.100s", display); - return -1; - } - *cp = 0; - /* buf now contains the host name. But first we parse the display number. */ - if (sscanf(cp + 1, "%d", &display_number) != 1) { - error("Could not parse display number from DISPLAY: %.100s", - display); - return -1; - } - - /* Look up the host address */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", 6000 + display_number); - if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { - error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr)); - return -1; - } - for (ai = aitop; ai; ai = ai->ai_next) { - /* Create a socket. */ - sock = socket(ai->ai_family, SOCK_STREAM, 0); - if (sock < 0) { - debug("socket: %.100s", strerror(errno)); - continue; - } - /* Connect it to the display. */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - debug("connect %.100s port %d: %.100s", buf, - 6000 + display_number, strerror(errno)); - close(sock); - continue; - } - /* Success */ - break; - } - freeaddrinfo(aitop); - if (!ai) { - error("connect %.100s port %d: %.100s", buf, 6000 + display_number, - strerror(errno)); - return -1; - } - set_nodelay(sock); - return sock; -} - -/* - * This is called when SSH_SMSG_X11_OPEN is received. The packet contains - * the remote channel number. We should do whatever we want, and respond - * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. - */ - -void -x11_input_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - int remote_id, sock = 0; - char *remote_host; - - debug("Received X11 open request."); - - remote_id = packet_get_int(); - - if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) { - remote_host = packet_get_string(NULL); - } else { - remote_host = xstrdup("unknown (remote did not supply name)"); - } - packet_check_eom(); - - /* Obtain a connection to the real X display. */ - sock = x11_connect_display(); - if (sock != -1) { - /* Allocate a channel for this connection. */ - c = channel_new("connected x11 socket", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0, - remote_host, 1); - c->remote_id = remote_id; - c->force_drain = 1; - } - if (c == NULL) { - /* Send refusal to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_id); - } else { - /* Send a confirmation to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_id); - packet_put_int(c->self); - } - packet_send(); -} - -/* dummy protocol handler that denies SSH-1 requests (agent/x11) */ -void -deny_input_open(int type, u_int32_t seq, void *ctxt) -{ - int rchan = packet_get_int(); - - switch (type) { - case SSH_SMSG_AGENT_OPEN: - error("Warning: ssh server tried agent forwarding."); - break; - case SSH_SMSG_X11_OPEN: - error("Warning: ssh server tried X11 forwarding."); - break; - default: - error("deny_input_open: type %d", type); - break; - } - error("Warning: this is probably a break in attempt by a malicious server."); - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(rchan); - packet_send(); -} - -/* - * Requests forwarding of X11 connections, generates fake authentication - * data, and enables authentication spoofing. - * This should be called in the client only. - */ -void -x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, - const char *proto, const char *data) -{ - u_int data_len = (u_int) strlen(data) / 2; - u_int i, value; - char *new_data; - int screen_number; - const char *cp; - u_int32_t rand = 0; - - cp = disp; - if (disp) - cp = strchr(disp, ':'); - if (cp) - cp = strchr(cp, '.'); - if (cp) - screen_number = atoi(cp + 1); - else - screen_number = 0; - - /* Save protocol name. */ - x11_saved_proto = xstrdup(proto); - - /* - * Extract real authentication data and generate fake data of the - * same length. - */ - x11_saved_data = xmalloc(data_len); - x11_fake_data = xmalloc(data_len); - for (i = 0; i < data_len; i++) { - if (sscanf(data + 2 * i, "%2x", &value) != 1) - fatal("x11_request_forwarding: bad authentication data: %.100s", data); - if (i % 4 == 0) - rand = arc4random(); - x11_saved_data[i] = value; - x11_fake_data[i] = rand & 0xff; - rand >>= 8; - } - x11_saved_data_len = data_len; - x11_fake_data_len = data_len; - - /* Convert the fake data into hex. */ - new_data = tohex(x11_fake_data, data_len); - - /* Send the request packet. */ - if (compat20) { - channel_request_start(client_session_id, "x11-req", 0); - packet_put_char(0); /* XXX bool single connection */ - } else { - packet_start(SSH_CMSG_X11_REQUEST_FORWARDING); - } - packet_put_cstring(proto); - packet_put_cstring(new_data); - packet_put_int(screen_number); - packet_send(); - packet_write_wait(); - xfree(new_data); -} - - -/* -- agent forwarding */ - -/* Sends a message to the server to request authentication fd forwarding. */ - -void -auth_request_forwarding(void) -{ - packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING); - packet_send(); - packet_write_wait(); -} - -/* This is called to process an SSH_SMSG_AGENT_OPEN message. */ - -void -auth_input_open_request(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - int remote_id, sock; - char *name; - - /* Read the remote channel number from the message. */ - remote_id = packet_get_int(); - packet_check_eom(); - - /* - * Get a connection to the local authentication agent (this may again - * get forwarded). - */ - sock = ssh_get_authentication_socket(); - - /* - * If we could not connect the agent, send an error message back to - * the server. This should never happen unless the agent dies, - * because authentication forwarding is only enabled if we have an - * agent. - */ - if (sock >= 0) { - name = xstrdup("authentication agent connection"); - c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, - -1, 0, 0, 0, name, 1); - c->remote_id = remote_id; - c->force_drain = 1; - } - if (c == NULL) { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_id); - } else { - /* Send a confirmation to the remote host. */ - debug("Forwarding authentication connection."); - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_id); - packet_put_int(c->self); - } - packet_send(); -} diff --git a/usr/src/cmd/ssh/libssh/common/cipher-ctr.c b/usr/src/cmd/ssh/libssh/common/cipher-ctr.c deleted file mode 100644 index d728064b53..0000000000 --- a/usr/src/cmd/ssh/libssh/common/cipher-ctr.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2003 Markus Friedl <markus@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: cipher-ctr.c,v 1.4 2004/02/06 23:41:13 dtucker Exp $"); - -#include <openssl/evp.h> - -#include "log.h" -#include "xmalloc.h" -#include <openssl/aes.h> - -const EVP_CIPHER *evp_aes_128_ctr(void); -void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); - -struct ssh_aes_ctr_ctx -{ - AES_KEY aes_ctx; - u_char aes_counter[AES_BLOCK_SIZE]; -}; - -/* - * increment counter 'ctr', - * the counter is of size 'len' bytes and stored in network-byte-order. - * (LSB at ctr[len-1], MSB at ctr[0]) - */ -static void -ssh_ctr_inc(u_char *ctr, u_int len) -{ - int i; - - for (i = len - 1; i >= 0; i--) - if (++ctr[i]) /* continue on overflow */ - return; -} - -static int -ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, - u_int len) -{ - struct ssh_aes_ctr_ctx *c; - u_int n = 0; - u_char buf[AES_BLOCK_SIZE]; - - if (len == 0) - return (1); - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) - return (0); - - while ((len--) > 0) { - if (n == 0) { - AES_encrypt(c->aes_counter, buf, &c->aes_ctx); - ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); - } - *(dest++) = *(src++) ^ buf[n]; - n = (n + 1) % AES_BLOCK_SIZE; - } - return (1); -} - -static int -ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, - int enc) -{ - struct ssh_aes_ctr_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } - if (key != NULL) - AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, - &c->aes_ctx); - if (iv != NULL) - memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); - return (1); -} - -static int -ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) -{ - struct ssh_aes_ctr_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - } - return (1); -} - -void -ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) -{ - struct ssh_aes_ctr_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) - fatal("ssh_aes_ctr_iv: no context"); - if (doset) - memcpy(c->aes_counter, iv, len); - else - memcpy(iv, c->aes_counter, len); -} - -/* - * Function fills an EVP_CIPHER structure for AES CTR functions based on the NID - * and the key length. - */ -static const EVP_CIPHER * -evp_aes_ctr(const char *nid, int key_len, EVP_CIPHER *aes_ctr) -{ - memset(aes_ctr, 0, sizeof(EVP_CIPHER)); - /* - * If the PKCS#11 engine is used the AES CTR NIDs were dynamically - * created during the engine initialization. If the engine is not used - * we work with NID_undef's which is OK since in that case OpenSSL - * doesn't use NIDs at all. - */ - if ((aes_ctr->nid = OBJ_ln2nid(nid)) != NID_undef) - debug3("%s NID found", nid); - - aes_ctr->block_size = AES_BLOCK_SIZE; - aes_ctr->iv_len = AES_BLOCK_SIZE; - aes_ctr->key_len = key_len; - aes_ctr->init = ssh_aes_ctr_init; - aes_ctr->cleanup = ssh_aes_ctr_cleanup; - aes_ctr->do_cipher = ssh_aes_ctr; - aes_ctr->flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | - EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; - return (aes_ctr); -} - -const EVP_CIPHER * -evp_aes_128_ctr(void) -{ - static EVP_CIPHER aes_ctr; - - return (evp_aes_ctr("aes-128-ctr", 16, &aes_ctr)); -} - -const EVP_CIPHER * -evp_aes_192_ctr(void) -{ - static EVP_CIPHER aes_ctr; - - return (evp_aes_ctr("aes-192-ctr", 24, &aes_ctr)); -} - -const EVP_CIPHER * -evp_aes_256_ctr(void) -{ - static EVP_CIPHER aes_ctr; - - return (evp_aes_ctr("aes-256-ctr", 32, &aes_ctr)); -} diff --git a/usr/src/cmd/ssh/libssh/common/cipher.c b/usr/src/cmd/ssh/libssh/common/cipher.c deleted file mode 100644 index 3cb001a150..0000000000 --- a/usr/src/cmd/ssh/libssh/common/cipher.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 1999 Niels Provos. All rights reserved. - * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.61 2002/07/12 15:50:17 markus Exp $"); - -#include "xmalloc.h" -#include "log.h" -#include "cipher.h" - -#include <openssl/md5.h> - -/* - * Symmetric ciphers can be offloaded to any engine through the EVP API only. - * However, OpenSSL doesn't offer AES in counter mode through EVP. So, we must - * define our own EVP functions. - */ -extern const EVP_CIPHER *evp_aes_128_ctr(void); -extern const EVP_CIPHER *evp_aes_192_ctr(void); -extern const EVP_CIPHER *evp_aes_256_ctr(void); -extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); - -static const EVP_CIPHER *evp_ssh1_3des(void); -static const EVP_CIPHER *evp_ssh1_bf(void); - -struct Cipher { - char *name; - int number; /* for ssh1 only */ - u_int block_size; - u_int key_len; - u_int discard_len; - const EVP_CIPHER *(*evptype)(void); -} ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, 0, EVP_enc_null }, - { "des", SSH_CIPHER_DES, 8, 8, 0, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, 0, evp_ssh1_3des }, - { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, evp_ssh1_bf }, - { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, EVP_des_ede3_cbc }, - { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_bf_cbc }, -#ifdef SOLARIS_SSH_ENABLE_CAST5_128 - { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_cast5_cbc }, -#endif /* SOLARIS_SSH_ENABLE_CAST5_128 */ - { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, EVP_rc4 }, - { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, EVP_rc4 }, - { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, EVP_rc4 }, - { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, EVP_aes_128_cbc }, - { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, EVP_aes_192_cbc }, - { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, - { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr }, - { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_192_ctr }, - { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_256_ctr }, - { NULL, SSH_CIPHER_ILLEGAL, 0, 0, 0, NULL } -}; - -/*--*/ - -u_int -cipher_blocksize(Cipher *c) -{ - return (c->block_size); -} - -u_int -cipher_keylen(Cipher *c) -{ - return (c->key_len); -} - -u_int -cipher_get_number(Cipher *c) -{ - return (c->number); -} - -u_int -cipher_mask_ssh1(int client) -{ - u_int mask = 0; - mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ - mask |= 1 << SSH_CIPHER_BLOWFISH; - if (client) { - mask |= 1 << SSH_CIPHER_DES; - } - return mask; -} - -Cipher * -cipher_by_name(const char *name) -{ - Cipher *c; - for (c = ciphers; c->name != NULL; c++) - if (strcasecmp(c->name, name) == 0) - return c; - return NULL; -} - -Cipher * -cipher_by_number(int id) -{ - Cipher *c; - for (c = ciphers; c->name != NULL; c++) - if (c->number == id) - return c; - return NULL; -} - -#define CIPHER_SEP "," -int -ciphers_valid(const char *names) -{ - Cipher *c; - char *ciphers, *cp; - char *p; - - if (names == NULL || strcmp(names, "") == 0) - return 0; - ciphers = cp = xstrdup(names); - for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; - (p = strsep(&cp, CIPHER_SEP))) { - c = cipher_by_name(p); - if (c == NULL || c->number != SSH_CIPHER_SSH2) { - debug("bad cipher %s [%s]", p, names); - xfree(ciphers); - return 0; - } else { - debug3("cipher ok: %s [%s]", p, names); - } - } - debug3("ciphers ok: [%s]", names); - xfree(ciphers); - return 1; -} - -/* - * Parses the name of the cipher. Returns the number of the corresponding - * cipher, or -1 on error. - */ - -int -cipher_number(const char *name) -{ - Cipher *c; - if (name == NULL) - return -1; - c = cipher_by_name(name); - return (c==NULL) ? -1 : c->number; -} - -char * -cipher_name(int id) -{ - Cipher *c = cipher_by_number(id); - return (c==NULL) ? "<unknown>" : c->name; -} - -void -cipher_init(CipherContext *cc, Cipher *cipher, - const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, - int encrypt) -{ - static int dowarn = 1; - const EVP_CIPHER *type; - int klen; - u_char *junk, *discard; - - if (cipher->number == SSH_CIPHER_DES) { - if (dowarn) { - error("Warning: use of DES is strongly discouraged " - "due to cryptographic weaknesses"); - dowarn = 0; - } - if (keylen > 8) - keylen = 8; - } - cc->plaintext = (cipher->number == SSH_CIPHER_NONE); - - if (keylen < cipher->key_len) - fatal("cipher_init: key length %d is insufficient for %s.", - keylen, cipher->name); - if (iv != NULL && ivlen < cipher->block_size) - fatal("cipher_init: iv length %d is insufficient for %s.", - ivlen, cipher->name); - cc->cipher = cipher; - - type = (*cipher->evptype)(); - - EVP_CIPHER_CTX_init(&cc->evp); - /* - * cc->evp is of type EVP_CIPHER_CTX and its key_len will be set to the - * default value here for the cipher type. If the requested key length - * is different from the default value we will call EVP_CipherInit() - * again, see below. - */ - if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, - (encrypt == CIPHER_ENCRYPT)) == 0) - fatal("cipher_init: EVP_CipherInit failed for %s", - cipher->name); - klen = EVP_CIPHER_CTX_key_length(&cc->evp); - if (klen > 0 && keylen != klen) { - debug("cipher_init: set keylen (%d -> %d)", klen, keylen); - if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) - fatal("cipher_init: set keylen failed (%d -> %d)", - klen, keylen); - } - if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) - fatal("cipher_init: EVP_CipherInit: set key failed for %s", - cipher->name); - - if (cipher->discard_len > 0) { - junk = xmalloc(cipher->discard_len); - discard = xmalloc(cipher->discard_len); - if (EVP_Cipher(&cc->evp, discard, junk, - cipher->discard_len) == 0) - fatal("cipher_init: EVP_Cipher failed during discard"); - memset(discard, 0, cipher->discard_len); - xfree(junk); - xfree(discard); - } -} - -void -cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - if (len % cc->cipher->block_size) - fatal("cipher_encrypt: bad plaintext length %d", len); - if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0) - fatal("evp_crypt: EVP_Cipher failed"); -} - -void -cipher_cleanup(CipherContext *cc) -{ - if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) - error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); -} - -/* - * Selects the cipher, and keys if by computing the MD5 checksum of the - * passphrase and using the resulting 16 bytes as the key. - */ - -void -cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase, int encrypt) -{ - MD5_CTX md; - u_char digest[16]; - - MD5_Init(&md); - MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); - MD5_Final(digest, &md); - - cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt); - - memset(digest, 0, sizeof(digest)); - memset(&md, 0, sizeof(md)); -} - -/* Implementations for other non-EVP ciphers */ - -/* - * This is used by SSH1: - * - * What kind of triple DES are these 2 routines? - * - * Why is there a redundant initialization vector? - * - * If only iv3 was used, then, this would till effect have been - * outer-cbc. However, there is also a private iv1 == iv2 which - * perhaps makes differential analysis easier. On the other hand, the - * private iv1 probably makes the CRC-32 attack ineffective. This is a - * result of that there is no longer any known iv1 to use when - * choosing the X block. - */ -struct ssh1_3des_ctx -{ - EVP_CIPHER_CTX k1, k2, k3; -}; - -static int -ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, - int enc) -{ - struct ssh1_3des_ctx *c; - u_char *k1, *k2, *k3; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } - if (key == NULL) - return (1); - if (enc == -1) - enc = ctx->encrypt; - k1 = k2 = k3 = (u_char *) key; - k2 += 8; - if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { - if (enc) - k3 += 16; - else - k1 += 16; - } - EVP_CIPHER_CTX_init(&c->k1); - EVP_CIPHER_CTX_init(&c->k2); - EVP_CIPHER_CTX_init(&c->k3); - if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || - EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || - EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - return (0); - } - return (1); -} - -static int -ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len) -{ - struct ssh1_3des_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - error("ssh1_3des_cbc: no context"); - return (0); - } - if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || - EVP_Cipher(&c->k2, dest, dest, len) == 0 || - EVP_Cipher(&c->k3, dest, dest, len) == 0) - return (0); - return (1); -} - -static int -ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) -{ - struct ssh1_3des_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - } - return (1); -} - -static const EVP_CIPHER * -evp_ssh1_3des(void) -{ - static EVP_CIPHER ssh1_3des; - - memset(&ssh1_3des, 0, sizeof(EVP_CIPHER)); - ssh1_3des.nid = NID_undef; - ssh1_3des.block_size = 8; - ssh1_3des.iv_len = 0; - ssh1_3des.key_len = 16; - ssh1_3des.init = ssh1_3des_init; - ssh1_3des.cleanup = ssh1_3des_cleanup; - ssh1_3des.do_cipher = ssh1_3des_cbc; - ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; - return (&ssh1_3des); -} - -/* - * SSH1 uses a variation on Blowfish, all bytes must be swapped before - * and after encryption/decryption. Thus the swap_bytes stuff (yuk). - */ -static void -swap_bytes(const u_char *src, u_char *dst, int n) -{ - u_char c[4]; - - /* Process 4 bytes every lap. */ - for (n = n / 4; n > 0; n--) { - c[3] = *src++; - c[2] = *src++; - c[1] = *src++; - c[0] = *src++; - - *dst++ = c[0]; - *dst++ = c[1]; - *dst++ = c[2]; - *dst++ = c[3]; - } -} - -static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL; - -static int -bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len) -{ - int ret; - - swap_bytes(in, out, len); - ret = (*orig_bf)(ctx, out, out, len); - swap_bytes(out, out, len); - return (ret); -} - -static const EVP_CIPHER * -evp_ssh1_bf(void) -{ - static EVP_CIPHER ssh1_bf; - - memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER)); - orig_bf = ssh1_bf.do_cipher; - ssh1_bf.nid = NID_undef; - ssh1_bf.do_cipher = bf_ssh1_cipher; - ssh1_bf.key_len = 32; - return (&ssh1_bf); -} - -/* - * Exports an IV from the CipherContext required to export the key - * state back from the unprivileged child to the privileged parent - * process. - */ - -int -cipher_get_keyiv_len(CipherContext *cc) -{ - Cipher *c = cc->cipher; - int ivlen; - - if (c->number == SSH_CIPHER_3DES) - ivlen = 24; - else - ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); - return (ivlen); -} - -void -cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) -{ - Cipher *c = cc->cipher; - u_char *civ = NULL; - int evplen; - - switch (c->number) { - case SSH_CIPHER_SSH2: - case SSH_CIPHER_DES: - case SSH_CIPHER_BLOWFISH: - evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); - if (evplen == 0) - return; - if (evplen != len) - fatal("%s: wrong iv length %d != %d", __func__, - evplen, len); - - if (c->evptype == evp_aes_128_ctr) { - ssh_aes_ctr_iv(&cc->evp, 0, iv, len); - return; - } else { - civ = cc->evp.iv; - } - break; - case SSH_CIPHER_3DES: { - struct ssh1_3des_ctx *desc; - if (len != 24) - fatal("%s: bad 3des iv length: %d", __func__, len); - desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); - if (desc == NULL) - fatal("%s: no 3des context", __func__); - debug3("%s: Copying 3DES IV", __func__); - memcpy(iv, desc->k1.iv, 8); - memcpy(iv + 8, desc->k2.iv, 8); - memcpy(iv + 16, desc->k3.iv, 8); - return; - } - default: - fatal("%s: bad cipher %d", __func__, c->number); - } - memcpy(iv, civ, len); -} - -void -cipher_set_keyiv(CipherContext *cc, u_char *iv) -{ - Cipher *c = cc->cipher; - u_char *div = NULL; - int evplen = 0; - - switch (c->number) { - case SSH_CIPHER_SSH2: - case SSH_CIPHER_DES: - case SSH_CIPHER_BLOWFISH: - evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); - if (evplen == 0) - return; - - if (c->evptype == evp_aes_128_ctr) { - ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen); - return; - } else { - div = cc->evp.iv; - } - break; - case SSH_CIPHER_3DES: { - struct ssh1_3des_ctx *desc; - desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); - if (desc == NULL) - fatal("%s: no 3des context", __func__); - debug3("%s: Installed 3DES IV", __func__); - memcpy(desc->k1.iv, iv, 8); - memcpy(desc->k2.iv, iv + 8, 8); - memcpy(desc->k3.iv, iv + 16, 8); - return; - } - default: - fatal("%s: bad cipher %d", __func__, c->number); - } - memcpy(div, iv, evplen); -} - -#if OPENSSL_VERSION_NUMBER < 0x00907000L -#define EVP_X_STATE(evp) &(evp).c -#define EVP_X_STATE_LEN(evp) sizeof((evp).c) -#else -#define EVP_X_STATE(evp) (evp).cipher_data -#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size -#endif - -int -cipher_get_keycontext(CipherContext *cc, u_char *dat) -{ - int plen = 0; - Cipher *c = cc->cipher; - - if (c->evptype == EVP_rc4) { - plen = EVP_X_STATE_LEN(cc->evp); - if (dat == NULL) - return (plen); - memcpy(dat, EVP_X_STATE(cc->evp), plen); - } - return (plen); -} - -void -cipher_set_keycontext(CipherContext *cc, u_char *dat) -{ - Cipher *c = cc->cipher; - int plen; - - if (c->evptype == EVP_rc4) { - plen = EVP_X_STATE_LEN(cc->evp); - memcpy(EVP_X_STATE(cc->evp), dat, plen); - } -} diff --git a/usr/src/cmd/ssh/libssh/common/compat.c b/usr/src/cmd/ssh/libssh/common/compat.c deleted file mode 100644 index 6d85d6e511..0000000000 --- a/usr/src/cmd/ssh/libssh/common/compat.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: compat.c,v 1.65 2002/09/27 10:42:09 mickey Exp $"); - -#include "buffer.h" -#include "packet.h" -#include "xmalloc.h" -#include "compat.h" -#include "log.h" -#include "match.h" - -int compat13 = 0; -int compat20 = 0; -uint32_t datafellows = 0; - -void -enable_compat20(void) -{ - debug("Enabling compatibility mode for protocol 2.0"); - compat20 = 1; -} -void -enable_compat13(void) -{ - debug("Enabling compatibility mode for protocol 1.3"); - compat13 = 1; -} -/* datafellows bug compatibility */ -void -compat_datafellows(const char *version) -{ - int i; - static struct { - char *pat; - uint32_t bugs; - } check[] = { - { "OpenSSH-2.0*," - "OpenSSH-2.1*," - "OpenSSH_2.1*," - "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| - SSH_OLD_DHGEX|SSH_BUG_NOREKEY| - SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| - SSH_OLD_DHGEX|SSH_BUG_NOREKEY| - SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| - SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| - SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.5.0p1*," - "OpenSSH_2.5.1p1*", - SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| - SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| - SSH_OLD_GSSAPI|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.5.0*," - "OpenSSH_2.5.1*," - "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| - SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| - SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.9p*", SSH_BUG_EXTEOF|SSH_OLD_GSSAPI| - SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_2.*," - "OpenSSH_3.0*," - "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR| - SSH_OLD_GSSAPI|SSH_BUG_GSSAPI_BER| - SSH_BUG_GSSKEX_HOSTKEY}, - { "OpenSSH_3.2*," - "OpenSSH_3.3*," - "OpenSSH_3.4*," - "OpenSSH_3.5*", SSH_BUG_GSSAPI_BER|SSH_OLD_GSSAPI| - SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_3.6*," - "OpenSSH_3.7*," - "OpenSSH_3.8*", SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, - { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR}, - { "OpenSSH*", 0 }, - { "Sun_SSH_1.0.*", SSH_BUG_NOREKEY| - SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR}, - { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| - SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR}, - { "Sun_SSH_1.1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING}, - { "Sun_SSH_1.1.2*", SSH_OLD_FORWARD_ADDR}, - { "Sun_SSH_1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING}, - { "Sun_SSH_1.2*", SSH_BUG_STRING_ENCODING}, - { "Sun_SSH_1.3*", SSH_BUG_STRING_ENCODING}, - { "Sun_SSH_1.4*", 0 }, - { "Sun_SSH_1.5*", 0 }, - { "Sun_SSH_*", 0 }, - { "*MindTerm*", 0 }, - { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| - SSH_OLD_SESSIONID|SSH_BUG_DEBUG| - SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| - SSH_BUG_FIRSTKEX }, - { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| - SSH_OLD_SESSIONID|SSH_BUG_DEBUG| - SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| - SSH_BUG_FIRSTKEX }, - { "2.0.13*," - "2.0.14*," - "2.0.15*," - "2.0.16*," - "2.0.17*," - "2.0.18*," - "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| - SSH_OLD_SESSIONID|SSH_BUG_DEBUG| - SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| - SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| - SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| - SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, - { "2.0.11*," - "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| - SSH_OLD_SESSIONID|SSH_BUG_DEBUG| - SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| - SSH_BUG_PKAUTH|SSH_BUG_PKOK| - SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| - SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, - { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| - SSH_OLD_SESSIONID|SSH_BUG_DEBUG| - SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| - SSH_BUG_PKAUTH|SSH_BUG_PKOK| - SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| - SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN| - SSH_BUG_FIRSTKEX }, - { "2.2.0*," - "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| - SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX }, - { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5| - SSH_BUG_FIRSTKEX }, - { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ - { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX| - SSH_BUG_RFWD_ADDR}, - { "3.0.*", SSH_BUG_DEBUG }, - { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, - { "1.7 SecureFX*", SSH_OLD_SESSIONID }, - { "1.2.18*," - "1.2.19*," - "1.2.20*," - "1.2.21*," - "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, - { "1.3.2*", /* F-Secure */ - SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, - { "1.2.1*," - "1.2.2*," - "1.2.3*", SSH_BUG_K5USER }, - { "*SSH Compatible Server*", /* Netscreen */ - SSH_BUG_PASSWORDPAD }, - { "*OSU_0*," - "OSU_1.0*," - "OSU_1.1*," - "OSU_1.2*," - "OSU_1.3*," - "OSU_1.4*," - "OSU_1.5alpha1*," - "OSU_1.5alpha2*," - "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, - { "*SSH_Version_Mapper*", - SSH_BUG_SCANNER }, - { "Probe-*", - SSH_BUG_PROBE }, - { NULL, 0 } - }; - - /* process table, return first match */ - for (i = 0; check[i].pat; i++) { - if (match_pattern_list(version, check[i].pat, - strlen(check[i].pat), 0) == 1) { - debug("match: %s pat %s", version, check[i].pat); - datafellows = check[i].bugs; - return; - } - } - debug("no match: %s", version); -} - -#define SEP "," -int -proto_spec(const char *spec) -{ - char *s, *p, *q; - int ret = SSH_PROTO_UNKNOWN; - - if (spec == NULL) - return ret; - q = s = xstrdup(spec); - for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { - switch (atoi(p)) { - case 1: - if (ret == SSH_PROTO_UNKNOWN) - ret |= SSH_PROTO_1_PREFERRED; - ret |= SSH_PROTO_1; - break; - case 2: - ret |= SSH_PROTO_2; - break; - default: - log("ignoring bad proto spec: '%s'.", p); - break; - } - } - xfree(s); - return ret; -} - -char * -compat_cipher_proposal(char *cipher_prop) -{ - Buffer b; - char *orig_prop, *fix_ciphers; - char *cp, *tmp; - - if (!(datafellows & SSH_BUG_BIGENDIANAES)) - return(cipher_prop); - - buffer_init(&b); - tmp = orig_prop = xstrdup(cipher_prop); - while ((cp = strsep(&tmp, ",")) != NULL) { - if (strncmp(cp, "aes", 3) != 0) { - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - buffer_append(&b, cp, strlen(cp)); - } - } - buffer_append(&b, "\0", 1); - fix_ciphers = xstrdup(buffer_ptr(&b)); - buffer_free(&b); - xfree(orig_prop); - debug2("Original cipher proposal: %s", cipher_prop); - debug2("Compat cipher proposal: %s", fix_ciphers); - if (!*fix_ciphers) - fatal("No available ciphers found."); - - return(fix_ciphers); -} diff --git a/usr/src/cmd/ssh/libssh/common/compress.c b/usr/src/cmd/ssh/libssh/common/compress.c deleted file mode 100644 index 6a4965c461..0000000000 --- a/usr/src/cmd/ssh/libssh/common/compress.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Interface to packet compression for ssh. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: compress.c,v 1.19 2002/03/18 17:31:54 provos Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "log.h" -#include "buffer.h" -#include "zlib.h" -#include "compress.h" - -z_stream incoming_stream; -z_stream outgoing_stream; -static int compress_init_send_called = 0; -static int compress_init_recv_called = 0; -static int inflate_failed = 0; -static int deflate_failed = 0; - -/* - * Initializes compression; level is compression level from 1 to 9 - * (as in gzip). - */ - -void -buffer_compress_init_send(int level) -{ - if (compress_init_send_called == 1) - deflateEnd(&outgoing_stream); - compress_init_send_called = 1; - debug("Enabling compression at level %d.", level); - if (level < 1 || level > 9) - fatal("Bad compression level %d.", level); - deflateInit(&outgoing_stream, level); -} -void -buffer_compress_init_recv(void) -{ - if (compress_init_recv_called == 1) - inflateEnd(&incoming_stream); - compress_init_recv_called = 1; - inflateInit(&incoming_stream); -} - -/* Frees any data structures allocated for compression. */ - -void -buffer_compress_uninit(void) -{ - debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f", - outgoing_stream.total_in, outgoing_stream.total_out, - outgoing_stream.total_in == 0 ? 0.0 : - (double) outgoing_stream.total_out / outgoing_stream.total_in); - debug("compress incoming: raw data %lu, compressed %lu, factor %.2f", - incoming_stream.total_out, incoming_stream.total_in, - incoming_stream.total_out == 0 ? 0.0 : - (double) incoming_stream.total_in / incoming_stream.total_out); - if (compress_init_recv_called == 1 && inflate_failed == 0) - inflateEnd(&incoming_stream); - if (compress_init_send_called == 1 && deflate_failed == 0) - deflateEnd(&outgoing_stream); -} - -/* - * Compresses the contents of input_buffer into output_buffer. All packets - * compressed using this function will form a single compressed data stream; - * however, data will be flushed at the end of every call so that each - * output_buffer can be decompressed independently (but in the appropriate - * order since they together form a single compression stream) by the - * receiver. This appends the compressed data to the output buffer. - */ - -void -buffer_compress(Buffer * input_buffer, Buffer * output_buffer) -{ - u_char buf[4096]; - int status; - - /* This case is not handled below. */ - if (buffer_len(input_buffer) == 0) - return; - - /* Input is the contents of the input buffer. */ - outgoing_stream.next_in = buffer_ptr(input_buffer); - outgoing_stream.avail_in = buffer_len(input_buffer); - - /* Loop compressing until deflate() returns with avail_out != 0. */ - do { - /* Set up fixed-size output buffer. */ - outgoing_stream.next_out = buf; - outgoing_stream.avail_out = sizeof(buf); - - /* Compress as much data into the buffer as possible. */ - status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH); - switch (status) { - case Z_OK: - /* Append compressed data to output_buffer. */ - buffer_append(output_buffer, buf, - sizeof(buf) - outgoing_stream.avail_out); - break; - default: - deflate_failed = 1; - fatal("buffer_compress: deflate returned %d", status); - /* NOTREACHED */ - } - } while (outgoing_stream.avail_out == 0); -} - -/* - * Uncompresses the contents of input_buffer into output_buffer. All packets - * uncompressed using this function will form a single compressed data - * stream; however, data will be flushed at the end of every call so that - * each output_buffer. This must be called for the same size units that the - * buffer_compress was called, and in the same order that buffers compressed - * with that. This appends the uncompressed data to the output buffer. - */ - -void -buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer) -{ - u_char buf[4096]; - int status; - - incoming_stream.next_in = buffer_ptr(input_buffer); - incoming_stream.avail_in = buffer_len(input_buffer); - - for (;;) { - /* Set up fixed-size output buffer. */ - incoming_stream.next_out = buf; - incoming_stream.avail_out = sizeof(buf); - - status = inflate(&incoming_stream, Z_PARTIAL_FLUSH); - switch (status) { - case Z_OK: - buffer_append(output_buffer, buf, - sizeof(buf) - incoming_stream.avail_out); - break; - case Z_BUF_ERROR: - /* - * Comments in zlib.h say that we should keep calling - * inflate() until we get an error. This appears to - * be the error that we get. - */ - return; - default: - inflate_failed = 1; - fatal("buffer_uncompress: inflate returned %d", status); - /* NOTREACHED */ - } - } -} diff --git a/usr/src/cmd/ssh/libssh/common/crc32.c b/usr/src/cmd/ssh/libssh/common/crc32.c deleted file mode 100644 index 213b7b8aa8..0000000000 --- a/usr/src/cmd/ssh/libssh/common/crc32.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - * - * First, the polynomial itself and its table of feedback terms. The - * polynomial is - * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 - * - * Note that we take it "backwards" and put the highest-order term in - * the lowest-order bit. The X^32 term is "implied"; the LSB is the - * X^31 term, etc. The X^0 term (usually shown as "+1") results in - * the MSB being 1 - * - * Note that the usual hardware shift register implementation, which - * is what we're using (we're merely optimizing it by doing eight-bit - * chunks at a time) shifts bits into the lowest-order term. In our - * implementation, that means shifting towards the right. Why do we - * do it this way? Because the calculated CRC must be transmitted in - * order from highest-order term to lowest-order term. UARTs transmit - * characters in order from LSB to MSB. By storing the CRC this way - * we hand it to the UART in the order low-byte to high-byte; the UART - * sends each low-bit to hight-bit; and the result is transmission bit - * by bit from highest- to lowest-order term without requiring any bit - * shuffling on our part. Reception works similarly - * - * The feedback terms table consists of 256, 32-bit entries. Notes - * - * The table can be generated at runtime if desired; code to do so - * is shown later. It might not be obvious, but the feedback - * terms simply represent the results of eight shift/xor opera - * tions for all combinations of data and CRC register values - * - * The values must be right-shifted by eight bits by the "updcrc - * logic; the shift must be u_(bring in zeroes). On some - * hardware you could probably optimize the shift in assembler by - * using byte-swap instructions - * polynomial $edb88320 - */ - - -#include "includes.h" -RCSID("$OpenBSD: crc32.c,v 1.8 2000/12/19 23:17:56 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "crc32.h" - -static u_int crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d -}; - -/* Return a 32-bit CRC of the contents of the buffer. */ - -u_int -ssh_crc32(const u_char *s, u_int len) -{ - u_int i; - u_int crc32val; - - crc32val = 0; - for (i = 0; i < len; i ++) { - crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8); - } - return crc32val; -} diff --git a/usr/src/cmd/ssh/libssh/common/deattack.c b/usr/src/cmd/ssh/libssh/common/deattack.c deleted file mode 100644 index 82afd4f16b..0000000000 --- a/usr/src/cmd/ssh/libssh/common/deattack.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Cryptographic attack detector for ssh - source code - * - * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. - * - * All rights reserved. Redistribution and use in source and binary - * forms, with or without modification, are permitted provided that - * this copyright notice is retained. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR - * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS - * SOFTWARE. - * - * Ariel Futoransky <futo@core-sdi.com> - * <http://www.core-sdi.com> - */ - -#include "includes.h" -RCSID("$OpenBSD: deattack.c,v 1.18 2002/03/04 17:27:39 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "deattack.h" -#include "log.h" -#include "crc32.h" -#include "getput.h" -#include "xmalloc.h" -#include "deattack.h" - -/* - * CRC attack detection has a worst-case behaviour that is O(N^2) over - * the number of identical blocks in a packet. This behaviour can be - * exploited to create a limited denial of service attack. - * - * However, because we are dealing with encrypted data, identical - * blocks should only occur every 2^35 maximally-sized packets or so. - * Consequently, we can detect this DoS by looking for identical blocks - * in a packet. - * - * The parameter below determines how many identical blocks we will - * accept in a single packet, trading off between attack detection and - * likelihood of terminating a legitimate connection. A value of 32 - * corresponds to an average of 2^40 messages before an attack is - * misdetected - */ -#define MAX_IDENTICAL 32 - -/* SSH Constants */ -#define SSH_MAXBLOCKS (32 * 1024) -#define SSH_BLOCKSIZE (8) - -/* Hashing constants */ -#define HASH_MINSIZE (8 * 1024) -#define HASH_ENTRYSIZE (2) -#define HASH_FACTOR(x) ((x)*3/2) -#define HASH_UNUSEDCHAR (0xff) -#define HASH_UNUSED (0xffff) -#define HASH_IV (0xfffe) - -#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE) - - -/* Hash function (Input keys are cipher results) */ -#define HASH(x) GET_32BIT(x) - -#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE)) - -static void -crc_update(u_int32_t *a, u_int32_t b) -{ - b ^= *a; - *a = ssh_crc32((u_char *) &b, sizeof(b)); -} - -/* detect if a block is used in a particular pattern */ -static int -check_crc(u_char *S, u_char *buf, u_int32_t len, - u_char *IV) -{ - u_int32_t crc; - u_char *c; - - crc = 0; - if (IV && !CMP(S, IV)) { - crc_update(&crc, 1); - crc_update(&crc, 0); - } - for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) { - if (!CMP(S, c)) { - crc_update(&crc, 1); - crc_update(&crc, 0); - } else { - crc_update(&crc, 0); - crc_update(&crc, 0); - } - } - return (crc == 0); -} - - -/* Detect a crc32 compensation attack on a packet */ -int -detect_attack(u_char *buf, u_int32_t len, u_char *IV) -{ - static u_int16_t *h = (u_int16_t *) NULL; - static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE; - u_int32_t i, j; - u_int32_t l, same; - u_char *c; - u_char *d; - - if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || - len % SSH_BLOCKSIZE != 0) { - fatal("detect_attack: bad length %d", len); - } - for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2) - ; - - if (h == NULL) { - debug("Installing crc compensation attack detector."); - n = l; - h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE); - } else { - if (l > n) { - n = l; - h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE); - } - } - - if (len <= HASH_MINBLOCKS) { - for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) { - if (IV && (!CMP(c, IV))) { - if ((check_crc(c, buf, len, IV))) - return (DEATTACK_DETECTED); - else - break; - } - for (d = buf; d < c; d += SSH_BLOCKSIZE) { - if (!CMP(c, d)) { - if ((check_crc(c, buf, len, IV))) - return (DEATTACK_DETECTED); - else - break; - } - } - } - return (DEATTACK_OK); - } - memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE); - - if (IV) - h[HASH(IV) & (n - 1)] = HASH_IV; - - for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { - for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED; - i = (i + 1) & (n - 1)) { - if (h[i] == HASH_IV) { - if (!CMP(c, IV)) { - if (check_crc(c, buf, len, IV)) - return (DEATTACK_DETECTED); - else - break; - } - } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) { - if (++same > MAX_IDENTICAL) - return (DEATTACK_DOS_DETECTED); - if (check_crc(c, buf, len, IV)) - return (DEATTACK_DETECTED); - else - break; - } - } - h[i] = j; - } - return (DEATTACK_OK); -} diff --git a/usr/src/cmd/ssh/libssh/common/dh.c b/usr/src/cmd/ssh/libssh/common/dh.c deleted file mode 100644 index 9293db7bb7..0000000000 --- a/usr/src/cmd/ssh/libssh/common/dh.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: dh.c,v 1.22 2002/06/27 08:49:44 markus Exp $"); - -#include "xmalloc.h" - -#include <openssl/bn.h> -#include <openssl/dh.h> -#include <openssl/evp.h> - -#include "buffer.h" -#include "cipher.h" -#include "kex.h" -#include "dh.h" -#include "pathnames.h" -#include "log.h" -#include "misc.h" - -static int -parse_prime(int linenum, char *line, struct dhgroup *dhg) -{ - char *cp, *arg; - char *strsize, *gen, *prime; - - cp = line; - arg = strdelim(&cp); - /* Ignore leading whitespace */ - if (*arg == '\0') - arg = strdelim(&cp); - if (!arg || !*arg || *arg == '#') - return 0; - - /* time */ - if (cp == NULL || *arg == '\0') - goto fail; - arg = strsep(&cp, " "); /* type */ - if (cp == NULL || *arg == '\0') - goto fail; - arg = strsep(&cp, " "); /* tests */ - if (cp == NULL || *arg == '\0') - goto fail; - arg = strsep(&cp, " "); /* tries */ - if (cp == NULL || *arg == '\0') - goto fail; - strsize = strsep(&cp, " "); /* size */ - if (cp == NULL || *strsize == '\0' || - (dhg->size = atoi(strsize)) == 0) - goto fail; - /* The whole group is one bit larger */ - dhg->size++; - gen = strsep(&cp, " "); /* gen */ - if (cp == NULL || *gen == '\0') - goto fail; - prime = strsep(&cp, " "); /* prime */ - if (cp != NULL || *prime == '\0') - goto fail; - - if ((dhg->g = BN_new()) == NULL) - fatal("parse_prime: BN_new failed"); - if ((dhg->p = BN_new()) == NULL) - fatal("parse_prime: BN_new failed"); - if (BN_hex2bn(&dhg->g, gen) == 0) - goto failclean; - - if (BN_hex2bn(&dhg->p, prime) == 0) - goto failclean; - - if (BN_num_bits(dhg->p) != dhg->size) - goto failclean; - - return (1); - - failclean: - BN_clear_free(dhg->g); - BN_clear_free(dhg->p); - fail: - error("Bad prime description in line %d", linenum); - return (0); -} - -DH * -choose_dh(int min, int wantbits, int max) -{ - FILE *f; - char line[2048]; - int best, bestcount, which; - int linenum; - struct dhgroup dhg; - - if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL && - (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) { - log("WARNING: %s does not exist, using old modulus", _PATH_DH_MODULI); - return (dh_new_group1()); - } - - linenum = 0; - best = bestcount = 0; - while (fgets(line, sizeof(line), f)) { - linenum++; - if (!parse_prime(linenum, line, &dhg)) - continue; - BN_clear_free(dhg.g); - BN_clear_free(dhg.p); - - if (dhg.size > max || dhg.size < min) - continue; - - if ((dhg.size > wantbits && dhg.size < best) || - (dhg.size > best && best < wantbits)) { - best = dhg.size; - bestcount = 0; - } - if (dhg.size == best) - bestcount++; - } - rewind(f); - - if (bestcount == 0) { - fclose(f); - log("WARNING: no suitable primes in %s", _PATH_DH_PRIMES); - return (NULL); - } - - linenum = 0; - which = arc4random() % bestcount; - while (fgets(line, sizeof(line), f)) { - if (!parse_prime(linenum, line, &dhg)) - continue; - if ((dhg.size > max || dhg.size < min) || - dhg.size != best || - linenum++ != which) { - BN_clear_free(dhg.g); - BN_clear_free(dhg.p); - continue; - } - break; - } - fclose(f); - if (linenum != which+1) - fatal("WARNING: line %d disappeared in %s, giving up", - which, _PATH_DH_PRIMES); - - return (dh_new_group(dhg.g, dhg.p)); -} - -/* diffie-hellman-group1-sha1 */ - -int -dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) -{ - int i; - int n = BN_num_bits(dh_pub); - int bits_set = 0; - - if (dh_pub->neg) { - log("invalid public DH value: negativ"); - return 0; - } - for (i = 0; i <= n; i++) - if (BN_is_bit_set(dh_pub, i)) - bits_set++; - debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); - - /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ - if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1)) - return 1; - log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p)); - return 0; -} - -void -dh_gen_key(DH *dh, int need) -{ - int i, bits_set = 0, tries = 0; - - if (dh->p == NULL) - fatal("dh_gen_key: dh->p == NULL"); - if (2*need >= BN_num_bits(dh->p)) - fatal("dh_gen_key: group too small: %d (2*need %d)", - BN_num_bits(dh->p), 2*need); - do { - if (dh->priv_key != NULL) - BN_clear_free(dh->priv_key); - if ((dh->priv_key = BN_new()) == NULL) - fatal("dh_gen_key: BN_new failed"); - /* generate a 2*need bits random private exponent */ - if (!BN_rand(dh->priv_key, 2*need, 0, 0)) - fatal("dh_gen_key: BN_rand failed"); - if (DH_generate_key(dh) == 0) - fatal("dh_gen_key: DH_generate_key() failed"); - for (i = 0; i <= BN_num_bits(dh->priv_key); i++) - if (BN_is_bit_set(dh->priv_key, i)) - bits_set++; - debug("dh_gen_key: priv key bits set: %d/%d", - bits_set, BN_num_bits(dh->priv_key)); - if (tries++ > 10) - fatal("dh_gen_key: too many bad keys: giving up"); - } while (!dh_pub_is_valid(dh, dh->pub_key)); -} - -DH * -dh_new_group_asc(const char *gen, const char *modulus) -{ - DH *dh; - - if ((dh = DH_new()) == NULL) - fatal("dh_new_group_asc: DH_new"); - - if (BN_hex2bn(&dh->p, modulus) == 0) - fatal("BN_hex2bn p"); - if (BN_hex2bn(&dh->g, gen) == 0) - fatal("BN_hex2bn g"); - - return (dh); -} - -/* - * This just returns the group, we still need to generate the exchange - * value. - */ - -DH * -dh_new_group(BIGNUM *gen, BIGNUM *modulus) -{ - DH *dh; - - if ((dh = DH_new()) == NULL) - fatal("dh_new_group: DH_new"); - dh->p = modulus; - dh->g = gen; - - return (dh); -} - -DH * -dh_new_group1(void) -{ - static char *gen = "2", *group1 = - "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" - "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" - "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" - "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" - "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" - "FFFFFFFF" "FFFFFFFF"; - - return (dh_new_group_asc(gen, group1)); -} - -/* - * Estimates the group order for a Diffie-Hellman group that has an - * attack complexity approximately the same as O(2**bits). Estimate - * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3))) - */ - -int -dh_estimate(int bits) -{ - - if (bits < 64) - return (512); /* O(2**63) */ - if (bits < 128) - return (1024); /* O(2**86) */ - if (bits < 192) - return (2048); /* O(2**116) */ - return (4096); /* O(2**156) */ -} diff --git a/usr/src/cmd/ssh/libssh/common/dispatch.c b/usr/src/cmd/ssh/libssh/common/dispatch.c deleted file mode 100644 index f2bf9b6847..0000000000 --- a/usr/src/cmd/ssh/libssh/common/dispatch.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: dispatch.c,v 1.15 2002/01/11 13:39:36 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "ssh1.h" -#include "ssh2.h" -#include "log.h" -#include "dispatch.h" -#include "packet.h" -#include "compat.h" - -#define DISPATCH_MIN 0 -#define DISPATCH_MAX 255 - -dispatch_fn *dispatch[DISPATCH_MAX]; - -void -dispatch_protocol_error(int type, u_int32_t seq, void *ctxt) -{ - log("dispatch_protocol_error: type %d seq %u", type, seq); - if (!compat20) - fatal("protocol error"); - packet_start(SSH2_MSG_UNIMPLEMENTED); - packet_put_int(seq); - packet_send(); - packet_write_wait(); -} -void -dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt) -{ - log("dispatch_protocol_ignore: type %d seq %u", type, seq); -} -void -dispatch_init(dispatch_fn *dflt) -{ - u_int i; - for (i = 0; i < DISPATCH_MAX; i++) - dispatch[i] = dflt; -} -void -dispatch_range(u_int from, u_int to, dispatch_fn *fn) -{ - u_int i; - - for (i = from; i <= to; i++) { - if (i >= DISPATCH_MAX) - break; - dispatch[i] = fn; - } -} -void -dispatch_set(int type, dispatch_fn *fn) -{ - dispatch[type] = fn; -} -void -dispatch_run(int mode, int *done, void *ctxt) -{ - for (;;) { - int type; - u_int32_t seqnr; - - if (mode == DISPATCH_BLOCK) { - type = packet_read_seqnr(&seqnr); - } else { - type = packet_read_poll_seqnr(&seqnr); - if (type == SSH_MSG_NONE) - return; - } - if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL) - (*dispatch[type])(type, seqnr, ctxt); - else - packet_disconnect("protocol error: rcvd type %d", type); - if (done != NULL && *done) - return; - } -} diff --git a/usr/src/cmd/ssh/libssh/common/engine.c b/usr/src/cmd/ssh/libssh/common/engine.c deleted file mode 100644 index 0541c658df..0000000000 --- a/usr/src/cmd/ssh/libssh/common/engine.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -#include "log.h" -#include "engine.h" - -#define PKCS11_ENGINE "pkcs11" - -/* - * Loads the PKCS#11 engine if the UseOpenSSLEngine is set to yes which is the - * default value. - */ -ENGINE * -pkcs11_engine_load(int use_engine) -{ - ENGINE *e = NULL; - - debug("use_engine is '%s'", use_engine == 1 ? "yes" : "no"); - if (use_engine == 0) - return (NULL); - - ENGINE_load_pk11(); - /* get structural reference */ - if ((e = ENGINE_by_id(PKCS11_ENGINE)) == NULL) { - error("%s engine does not exist", PKCS11_ENGINE); - return (NULL); - } - - /* get functional reference */ - if (ENGINE_init(e) == 0) { - error("can't initialize %s engine", PKCS11_ENGINE); - return (NULL); - } - - debug("%s engine initialized, now setting it as default for " - "RSA, DSA, and symmetric ciphers", PKCS11_ENGINE); - - /* - * Offloading RSA, DSA and symmetric ciphers to the engine is all we - * want. We don't offload Diffie-Helmann since we use longer DH keys - * than supported in ncp/n2cp (2048 bits). And, we don't offload digest - * operations since that would be beneficial if only big packets were - * processed (~8K). However, that's not the case. For example, - * SSH_MSG_CHANNEL_WINDOW_ADJUST messages are always small. Given the - * fact that digest operations are fast in software and the inherent - * overhead of offloading anything to HW is quite big, not offloading - * digests to HW actually makes SSH data transfer faster. - */ - if (!ENGINE_set_default_RSA(e)) { - error("can't use %s engine for RSA", PKCS11_ENGINE); - return (NULL); - } - if (!ENGINE_set_default_DSA(e)) { - error("can't use %s engine for DSA", PKCS11_ENGINE); - return (NULL); - } - if (!ENGINE_set_default_ciphers(e)) { - error("can't use %s engine for symmetric ciphers", - PKCS11_ENGINE); - return (NULL); - } - - debug("%s engine initialization complete", PKCS11_ENGINE); - return (e); -} - -/* - * Finishes the PKCS#11 engine after all remaining structural and functional - * references to the ENGINE structure are freed. - */ -void -pkcs11_engine_finish(void *engine) -{ - ENGINE *e = (ENGINE *)engine; - - debug("in pkcs11_engine_finish(), engine pointer is %p", e); - /* UseOpenSSLEngine was 'no' */ - if (engine == NULL) - return; - - debug("unregistering RSA"); - ENGINE_unregister_RSA(e); - debug("unregistering DSA"); - ENGINE_unregister_DSA(e); - debug("unregistering ciphers"); - ENGINE_unregister_ciphers(e); - - debug("calling ENGINE_finish()"); - ENGINE_finish(engine); - debug("calling ENGINE_remove()"); - ENGINE_remove(engine); - debug("calling ENGINE_free()"); - ENGINE_free(engine); - debug("%s engine finished", PKCS11_ENGINE); -} diff --git a/usr/src/cmd/ssh/libssh/common/entropy.c b/usr/src/cmd/ssh/libssh/common/entropy.c deleted file mode 100644 index c661b74496..0000000000 --- a/usr/src/cmd/ssh/libssh/common/entropy.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2001 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#include <openssl/rand.h> -#include <openssl/crypto.h> - -#include "ssh.h" -#include "misc.h" -#include "xmalloc.h" -#include "atomicio.h" -#include "pathnames.h" -#include "log.h" - -/* - * Portable OpenSSH PRNG seeding: - * If OpenSSL has not "internally seeded" itself (e.g. pulled data from - * /dev/random), then we execute a "ssh-rand-helper" program which - * collects entropy and writes it to stdout. The child program must - * write at least RANDOM_SEED_SIZE bytes. The child is run with stderr - * attached, so error/debugging output should be visible. - * - * XXX: we should tell the child how many bytes we need. - */ - -RCSID("$Id: entropy.c,v 1.44 2002/06/09 19:41:48 mouring Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef OPENSSL_PRNG_ONLY -#define RANDOM_SEED_SIZE 48 -static uid_t original_uid, original_euid; -#endif - -void -seed_rng(void) -{ -#ifndef OPENSSL_PRNG_ONLY - int devnull; - int p[2]; - pid_t pid; - int ret; - unsigned char buf[RANDOM_SEED_SIZE]; - mysig_t old_sigchld; - - if (RAND_status() == 1) { - debug3("RNG is ready, skipping seeding"); - return; - } - - debug3("Seeding PRNG from %s", SSH_RAND_HELPER); - - if ((devnull = open("/dev/null", O_RDWR)) == -1) - fatal("Couldn't open /dev/null: %s", strerror(errno)); - if (pipe(p) == -1) - fatal("pipe: %s", strerror(errno)); - - old_sigchld = mysignal(SIGCHLD, SIG_DFL); - if ((pid = fork()) == -1) - fatal("Couldn't fork: %s", strerror(errno)); - if (pid == 0) { - dup2(devnull, STDIN_FILENO); - dup2(p[1], STDOUT_FILENO); - /* Keep stderr open for errors */ - close(p[0]); - close(p[1]); - close(devnull); - - if (original_uid != original_euid && - ( seteuid(getuid()) == -1 || - setuid(original_uid) == -1) ) { - fprintf(stderr, "(rand child) setuid(%d): %s\n", - original_uid, strerror(errno)); - _exit(1); - } - - execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL); - fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n", - SSH_RAND_HELPER, strerror(errno)); - _exit(1); - } - - close(devnull); - close(p[1]); - - memset(buf, '\0', sizeof(buf)); - ret = atomicio(read, p[0], buf, sizeof(buf)); - if (ret == -1) - fatal("Couldn't read from ssh-rand-helper: %s", - strerror(errno)); - if (ret != sizeof(buf)) - fatal("ssh-rand-helper child produced insufficient data"); - - close(p[0]); - - if (waitpid(pid, &ret, 0) == -1) - fatal("Couldn't wait for ssh-rand-helper completion: %s", - strerror(errno)); - mysignal(SIGCHLD, old_sigchld); - - /* We don't mind if the child exits upon a SIGPIPE */ - if (!WIFEXITED(ret) && - (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE)) - fatal("ssh-rand-helper terminated abnormally"); - if (WEXITSTATUS(ret) != 0) - fatal("ssh-rand-helper exit with exit status %d", ret); - - RAND_add(buf, sizeof(buf), sizeof(buf)); - memset(buf, '\0', sizeof(buf)); - -#endif /* OPENSSL_PRNG_ONLY */ - if (RAND_status() != 1) - fatal("PRNG is not seeded"); -} - -void -init_rng(void) -{ - /* - * OpenSSL version numbers: MNNFFPPS: major minor fix patch status - * We match major, minor, fix and status (not patch) - */ - if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) - fatal("OpenSSL version mismatch. Built against %lx, you " - "have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); - -#ifndef OPENSSL_PRNG_ONLY - if ((original_uid = getuid()) == -1) - fatal("getuid: %s", strerror(errno)); - if ((original_euid = geteuid()) == -1) - fatal("geteuid: %s", strerror(errno)); -#endif -} - diff --git a/usr/src/cmd/ssh/libssh/common/fatal.c b/usr/src/cmd/ssh/libssh/common/fatal.c deleted file mode 100644 index 0b5038f365..0000000000 --- a/usr/src/cmd/ssh/libssh/common/fatal.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: fatal.c,v 1.1 2002/02/22 12:20:34 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "log.h" - -/* Fatal messages. This function never returns. */ - -void -fatal(const char *fmt,...) -{ - va_list args; - va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); - va_end(args); - fatal_cleanup(); -} diff --git a/usr/src/cmd/ssh/libssh/common/g11n.c b/usr/src/cmd/ssh/libssh/common/g11n.c deleted file mode 100644 index 558b410c96..0000000000 --- a/usr/src/cmd/ssh/libssh/common/g11n.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - * 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 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <errno.h> -#include <locale.h> -#include <langinfo.h> -#include <iconv.h> -#include <ctype.h> -#include <wctype.h> -#include <strings.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include "includes.h" -#include "xmalloc.h" -#include "xlist.h" -#include "compat.h" -#include "log.h" - -#ifdef MIN -#undef MIN -#endif /* MIN */ - -#define MIN(x, y) ((x) < (y) ? (x) : (y)) - -#define LOCALE_PATH "/usr/bin/locale" - -/* two-char country code, '-' and two-char region code */ -#define LANGTAG_MAX 5 - -static int locale_cmp(const void *d1, const void *d2); -static char *g11n_locale2langtag(char *locale); - -static char *do_iconv(iconv_t cd, const char *s, uint_t *lenp, char **err_str); - -/* - * native_codeset records the codeset of the default system locale. - * It is used to convert the contents of file (eg /etc/issue) which is - * supposed to be in the codeset of default system locale. - */ -static char *native_codeset; - -/* - * Convert locale string name into a language tag. The caller is responsible for - * freeing the memory allocated for the result. - */ -static char * -g11n_locale2langtag(char *locale) -{ - char *langtag; - - /* base cases */ - if (!locale || !*locale) - return (NULL); - - if (strcmp(locale, "POSIX") == 0 || strcmp(locale, "C") == 0) - return (xstrdup("i-default")); - - /* punt for language codes which are not exactly 2 letters */ - if (strlen(locale) < 2 || - !isalpha(locale[0]) || - !isalpha(locale[1]) || - (locale[2] != '\0' && - locale[2] != '_' && - locale[2] != '.' && - locale[2] != '@')) - return (NULL); - - - /* we have a primary language sub-tag */ - langtag = (char *)xmalloc(LANGTAG_MAX + 1); - - strncpy(langtag, locale, 2); - langtag[2] = '\0'; - - /* do we have country sub-tag? For example: cs_CZ */ - if (locale[2] == '_') { - if (strlen(locale) < 5 || - !isalpha(locale[3]) || - !isalpha(locale[4]) || - (locale[5] != '\0' && (locale[5] != '.' && - locale[5] != '@'))) { - return (langtag); - } - - /* example: create cs-CZ from cs_CZ */ - if (snprintf(langtag, 6, "%.*s-%.*s", 2, locale, 2, - locale + 3) == 5) - return (langtag); - } - - /* in all other cases we just use the primary language sub-tag */ - return (langtag); -} - -uint_t -g11n_langtag_is_default(char *langtag) -{ - return (strcmp(langtag, "i-default") == 0); -} - -/* - * This lang tag / locale matching function works only for two-character - * language primary sub-tags and two-character country sub-tags. - */ -uint_t -g11n_langtag_matches_locale(char *langtag, char *locale) -{ - /* match "i-default" to the process' current locale if possible */ - if (g11n_langtag_is_default(langtag)) { - if (strcasecmp(locale, "POSIX") == 0 || - strcasecmp(locale, "C") == 0) - return (1); - else - return (0); - } - - /* - * locale must be at least 2 chars long and the lang part must be - * exactly two characters - */ - if (strlen(locale) < 2 || - (!isalpha(locale[0]) || !isalpha(locale[1]) || - (locale[2] != '\0' && locale[2] != '_' && - locale[2] != '.' && locale[2] != '@'))) - return (0); - - /* same thing with the langtag */ - if (strlen(langtag) < 2 || - (!isalpha(langtag[0]) || !isalpha(langtag[1]) || - (langtag[2] != '\0' && langtag[2] != '-'))) - return (0); - - /* primary language sub-tag and the locale's language part must match */ - if (strncasecmp(langtag, locale, 2) != 0) - return (0); - - /* - * primary language sub-tag and the locale's language match, now - * fuzzy check country part - */ - - /* neither langtag nor locale have more than one component */ - if (langtag[2] == '\0' && - (locale[2] == '\0' || locale[2] == '.' || locale[2] == '@')) - return (2); - - /* langtag has only one sub-tag... */ - if (langtag[2] == '\0') - return (1); - - /* locale has no country code... */ - if (locale[2] == '\0' || locale[2] == '.' || locale[2] == '@') - return (1); - - /* langtag has more than one subtag and the locale has a country code */ - - /* ignore second subtag if not two chars */ - if (strlen(langtag) < 5) - return (1); - - if (!isalpha(langtag[3]) || !isalpha(langtag[4]) || - (langtag[5] != '\0' && langtag[5] != '-')) - return (1); - - /* ignore rest of locale if there is no two-character country part */ - if (strlen(locale) < 5) - return (1); - - if (locale[2] != '_' || !isalpha(locale[3]) || !isalpha(locale[4]) || - (locale[5] != '\0' && locale[5] != '.' && locale[5] != '@')) - return (1); - - /* if the country part matches, return 2 */ - if (strncasecmp(&langtag[3], &locale[3], 2) == 0) - return (2); - - return (1); -} - -char * -g11n_getlocale() -{ - /* we have one text domain - always set it */ - (void) textdomain(TEXT_DOMAIN); - - /* if the locale is not set, set it from the env vars */ - if (!setlocale(LC_MESSAGES, NULL)) - (void) setlocale(LC_MESSAGES, ""); - - return (setlocale(LC_MESSAGES, NULL)); -} - -void -g11n_setlocale(int category, const char *locale) -{ - char *curr; - - if (native_codeset == NULL) { - /* set default locale, and record current codeset */ - (void) setlocale(LC_ALL, ""); - curr = nl_langinfo(CODESET); - native_codeset = xstrdup(curr); - } - - /* we have one text domain - always set it */ - (void) textdomain(TEXT_DOMAIN); - - if (!locale) - return; - - if (*locale && ((curr = setlocale(category, NULL))) && - strcmp(curr, locale) == 0) - return; - - /* if <category> is bogus, setlocale() will do nothing */ - (void) setlocale(category, locale); -} - -char ** -g11n_getlocales() -{ - FILE *locale_out; - uint_t n_elems, list_size, long_line = 0; - char **list; - char locale[64]; /* 64 bytes is plenty for locale names */ - - if ((locale_out = popen(LOCALE_PATH " -a", "r")) == NULL) - return (NULL); - - /* - * start with enough room for 65 locales - that's a lot fewer than - * all the locales available for installation, but a lot more than - * what most users will need and install - */ - n_elems = 0; - list_size = 192; - list = (char **) xmalloc(sizeof (char *) * (list_size + 1)); - memset(list, 0, sizeof (char *) * (list_size + 1)); - - while (fgets(locale, sizeof (locale), locale_out)) { - /* skip long locale names (if any) */ - if (!strchr(locale, '\n')) { - long_line = 1; - continue; - } else if (long_line) { - long_line = 0; - continue; - } - - if (strncmp(locale, "iso_8859", 8) == 0) - /* ignore locale names like "iso_8859-1" */ - continue; - - if (n_elems == list_size) { - list_size *= 2; - list = (char **)xrealloc((void *) list, - (list_size + 1) * sizeof (char *)); - memset(&list[n_elems + 1], 0, - sizeof (char *) * (list_size - n_elems + 1)); - } - - *(strchr(locale, '\n')) = '\0'; /* remove the trailing \n */ - list[n_elems++] = xstrdup(locale); - } - - (void) pclose(locale_out); - - if (n_elems == 0) { - xfree(list); - return (NULL); - } - - list[n_elems] = NULL; - - qsort(list, n_elems - 1, sizeof (char *), locale_cmp); - return (list); -} - -char * -g11n_getlangs() -{ - char *locale; - - if (getenv("SSH_LANGS")) - return (xstrdup(getenv("SSH_LANGS"))); - - locale = g11n_getlocale(); - - if (!locale || !*locale) - return (xstrdup("i-default")); - - return (g11n_locale2langtag(locale)); -} - -char * -g11n_locales2langs(char **locale_set) -{ - char **p, **r, **q; - char *langtag, *langs; - int locales, skip; - - for (locales = 0, p = locale_set; p && *p; p++) - locales++; - - r = (char **)xmalloc((locales + 1) * sizeof (char *)); - memset(r, 0, (locales + 1) * sizeof (char *)); - - for (p = locale_set; p && *p && ((p - locale_set) <= locales); p++) { - skip = 0; - if ((langtag = g11n_locale2langtag(*p)) == NULL) - continue; - for (q = r; (q - r) < locales; q++) { - if (!*q) - break; - if (*q && strcmp(*q, langtag) == 0) - skip = 1; - } - if (!skip) - *(q++) = langtag; - else - xfree(langtag); - *q = NULL; - } - - langs = xjoin(r, ','); - g11n_freelist(r); - - return (langs); -} - -static int -sortcmp(const void *d1, const void *d2) -{ - char *s1 = *(char **)d1; - char *s2 = *(char **)d2; - - return (strcmp(s1, s2)); -} - -int -g11n_langtag_match(char *langtag1, char *langtag2) -{ - int len1, len2; - char c1, c2; - - len1 = (strchr(langtag1, '-')) ? - (strchr(langtag1, '-') - langtag1) - : strlen(langtag1); - - len2 = (strchr(langtag2, '-')) ? - (strchr(langtag2, '-') - langtag2) - : strlen(langtag2); - - /* no match */ - if (len1 != len2 || strncmp(langtag1, langtag2, len1) != 0) - return (0); - - c1 = *(langtag1 + len1); - c2 = *(langtag2 + len2); - - /* no country sub-tags - exact match */ - if (c1 == '\0' && c2 == '\0') - return (2); - - /* one langtag has a country sub-tag, the other doesn't */ - if (c1 == '\0' || c2 == '\0') - return (1); - - /* can't happen - both langtags have a country sub-tag */ - if (c1 != '-' || c2 != '-') - return (1); - - /* compare country subtags */ - langtag1 = langtag1 + len1 + 1; - langtag2 = langtag2 + len2 + 1; - - len1 = (strchr(langtag1, '-')) ? - (strchr(langtag1, '-') - langtag1) : strlen(langtag1); - - len2 = (strchr(langtag2, '-')) ? - (strchr(langtag2, '-') - langtag2) : strlen(langtag2); - - if (len1 != len2 || strncmp(langtag1, langtag2, len1) != 0) - return (1); - - /* country tags matched - exact match */ - return (2); -} - -char * -g11n_langtag_set_intersect(char *set1, char *set2) -{ - char **list1, **list2, **list3, **p, **q, **r; - char *set3, *lang_subtag; - uint_t n1, n2, n3; - uint_t do_append; - - list1 = xsplit(set1, ','); - list2 = xsplit(set2, ','); - - for (n1 = 0, p = list1; p && *p; p++, n1++) - ; - for (n2 = 0, p = list2; p && *p; p++, n2++) - ; - - list3 = (char **) xmalloc(sizeof (char *) * (n1 + n2 + 1)); - *list3 = NULL; - - /* - * we must not sort the user langtags - sorting or not the server's - * should not affect the outcome - */ - qsort(list2, n2, sizeof (char *), sortcmp); - - for (n3 = 0, p = list1; p && *p; p++) { - do_append = 0; - for (q = list2; q && *q; q++) { - if (g11n_langtag_match(*p, *q) != 2) continue; - /* append element */ - for (r = list3; (r - list3) <= (n1 + n2); r++) { - do_append = 1; - if (!*r) - break; - if (strcmp(*p, *r) == 0) { - do_append = 0; - break; - } - } - if (do_append && n3 <= (n1 + n2)) { - list3[n3++] = xstrdup(*p); - list3[n3] = NULL; - } - } - } - - for (p = list1; p && *p; p++) { - do_append = 0; - for (q = list2; q && *q; q++) { - if (g11n_langtag_match(*p, *q) != 1) - continue; - - /* append element */ - lang_subtag = xstrdup(*p); - if (strchr(lang_subtag, '-')) - *(strchr(lang_subtag, '-')) = '\0'; - for (r = list3; (r - list3) <= (n1 + n2); r++) { - do_append = 1; - if (!*r) - break; - if (strcmp(lang_subtag, *r) == 0) { - do_append = 0; - break; - } - } - if (do_append && n3 <= (n1 + n2)) { - list3[n3++] = lang_subtag; - list3[n3] = NULL; - } else - xfree(lang_subtag); - } - } - - set3 = xjoin(list3, ','); - xfree_split_list(list1); - xfree_split_list(list2); - xfree_split_list(list3); - - return (set3); -} - -char * -g11n_clnt_langtag_negotiate(char *clnt_langtags, char *srvr_langtags) -{ - char *list, *result; - char **xlist; - - /* g11n_langtag_set_intersect uses xmalloc - should not return NULL */ - list = g11n_langtag_set_intersect(clnt_langtags, srvr_langtags); - - if (!list) - return (NULL); - - xlist = xsplit(list, ','); - - xfree(list); - - if (!xlist || !*xlist) - return (NULL); - - result = xstrdup(*xlist); - xfree_split_list(xlist); - - return (result); -} - -/* - * Compare locales, preferring UTF-8 codesets to others, otherwise doing - * a stright strcmp() - */ -static int -locale_cmp(const void *d1, const void *d2) -{ - char *dot_ptr; - char *s1 = *(char **)d1; - char *s2 = *(char **)d2; - int s1_is_utf8 = 0; - int s2_is_utf8 = 0; - - /* check if s1 is a UTF-8 locale */ - if (((dot_ptr = strchr((char *)s1, '.')) != NULL) && - (*dot_ptr != '\0') && (strncmp(dot_ptr + 1, "UTF-8", 5) == 0) && - (*(dot_ptr + 6) == '\0' || *(dot_ptr + 6) == '@')) { - s1_is_utf8++; - } - - /* check if s2 is a UTF-8 locale */ - if (((dot_ptr = strchr((char *)s2, '.')) != NULL) && - (*dot_ptr != '\0') && (strncmp(dot_ptr + 1, "UTF-8", 5) == 0) && - (*(dot_ptr + 6) == '\0' || *(dot_ptr + 6) == '@')) { - s2_is_utf8++; - } - - /* prefer UTF-8 locales */ - if (s1_is_utf8 && !s2_is_utf8) - return (-1); - - if (s2_is_utf8 && !s1_is_utf8) - return (1); - - /* prefer any locale over the default locales */ - if (strcmp(s1, "C") == 0 || strcmp(s1, "POSIX") == 0 || - strcmp(s1, "common") == 0) { - if (strcmp(s2, "C") != 0 && strcmp(s2, "POSIX") != 0 && - strcmp(s2, "common") != 0) - return (1); - } - - if (strcmp(s2, "C") == 0 || strcmp(s2, "POSIX") == 0 || - strcmp(s2, "common") == 0) { - if (strcmp(s1, "C") != 0 && - strcmp(s1, "POSIX") != 0 && - strcmp(s1, "common") != 0) - return (-1); - } - - return (strcmp(s1, s2)); -} - - -char ** -g11n_langtag_set_locale_set_intersect(char *langtag_set, char **locale_set) -{ - char **langtag_list, **result, **p, **q, **r; - char *s; - uint_t do_append, n_langtags, n_locales, n_results, max_results; - - if (locale_set == NULL) - return (NULL); - - /* count lang tags and locales */ - for (n_locales = 0, p = locale_set; p && *p; p++) - n_locales++; - - n_langtags = ((s = langtag_set) != NULL && *s && *s != ',') ? 1 : 0; - /* count the number of langtags */ - for (; s = strchr(s, ','); s++, n_langtags++) - ; - - qsort(locale_set, n_locales, sizeof (char *), locale_cmp); - - langtag_list = xsplit(langtag_set, ','); - for (n_langtags = 0, p = langtag_list; p && *p; p++, n_langtags++) - ; - - max_results = MIN(n_locales, n_langtags) * 2; - result = (char **) xmalloc(sizeof (char *) * (max_results + 1)); - *result = NULL; - n_results = 0; - - /* more specific matches first */ - for (p = langtag_list; p && *p; p++) { - do_append = 0; - for (q = locale_set; q && *q; q++) { - if (g11n_langtag_matches_locale(*p, *q) == 2) { - do_append = 1; - for (r = result; (r - result) <= - MIN(n_locales, n_langtags); r++) { - if (!*r) - break; - if (strcmp(*q, *r) == 0) { - do_append = 0; - break; - } - } - if (do_append && n_results < max_results) { - result[n_results++] = xstrdup(*q); - result[n_results] = NULL; - } - break; - } - } - } - - for (p = langtag_list; p && *p; p++) { - do_append = 0; - for (q = locale_set; q && *q; q++) { - if (g11n_langtag_matches_locale(*p, *q) == 1) { - do_append = 1; - for (r = result; (r - result) <= - MIN(n_locales, n_langtags); r++) { - if (!*r) - break; - if (strcmp(*q, *r) == 0) { - do_append = 0; - break; - } - } - if (do_append && n_results < max_results) { - result[n_results++] = xstrdup(*q); - result[n_results] = NULL; - } - break; - } - } - } - - xfree_split_list(langtag_list); - - return (result); -} - -char * -g11n_srvr_locale_negotiate(char *clnt_langtags, char **srvr_locales) -{ - char **results, **locales, *result = NULL; - - if (srvr_locales == NULL) - locales = g11n_getlocales(); - else - locales = srvr_locales; - - if ((results = g11n_langtag_set_locale_set_intersect(clnt_langtags, - locales)) == NULL) - goto err; - - if (*results != NULL) - result = xstrdup(*results); - - xfree_split_list(results); - -err: - if (locales != NULL && locales != srvr_locales) - g11n_freelist(locales); - return (result); -} - -/* - * Functions for converting to UTF-8 from the local codeset and - * converting from UTF-8 to the local codeset. - * - * The error_str parameter is an pointer to a char variable where to - * store a string suitable for use with error() or fatal() or friends. - * It is also used for an error indicator when NULL is returned. - * - * If conversion isn't necessary, *error_str is set to NULL, and - * NULL is returned. - * If conversion error occured, *error_str points to an error message, - * and NULL is returned. - */ -char * -g11n_convert_from_utf8(const char *str, uint_t *lenp, char **error_str) -{ - static char *last_codeset; - static iconv_t cd = (iconv_t)-1; - char *codeset; - - *error_str = NULL; - - codeset = nl_langinfo(CODESET); - - if (strcmp(codeset, "UTF-8") == 0) - return (NULL); - - if (last_codeset == NULL || strcmp(codeset, last_codeset) != 0) { - if (last_codeset != NULL) { - xfree(last_codeset); - last_codeset = NULL; - } - if (cd != (iconv_t)-1) - (void) iconv_close(cd); - - if ((cd = iconv_open(codeset, "UTF-8")) == (iconv_t)-1) { - *error_str = gettext("Cannot convert UTF-8 " - "strings to the local codeset"); - return (NULL); - } - last_codeset = xstrdup(codeset); - } - return (do_iconv(cd, str, lenp, error_str)); -} - -char * -g11n_convert_to_utf8(const char *str, uint_t *lenp, - int native, char **error_str) -{ - static char *last_codeset; - static iconv_t cd = (iconv_t)-1; - char *codeset; - - *error_str = NULL; - - if (native) - codeset = native_codeset; - else - codeset = nl_langinfo(CODESET); - - if (strcmp(codeset, "UTF-8") == 0) - return (NULL); - - if (last_codeset == NULL || strcmp(codeset, last_codeset) != 0) { - if (last_codeset != NULL) { - xfree(last_codeset); - last_codeset = NULL; - } - if (cd != (iconv_t)-1) - (void) iconv_close(cd); - - if ((cd = iconv_open("UTF-8", codeset)) == (iconv_t)-1) { - *error_str = gettext("Cannot convert the " - "local codeset strings to UTF-8"); - return (NULL); - } - last_codeset = xstrdup(codeset); - } - return (do_iconv(cd, str, lenp, error_str)); -} - -/* - * Wrapper around iconv() - * - * The caller is responsible for freeing the result. NULL is returned when - * (errno && errno != E2BIG) (i.e., EILSEQ, EINVAL, EBADF). - * The caller must ensure that the input string isn't NULL pointer. - */ -static char * -do_iconv(iconv_t cd, const char *str, uint_t *lenp, char **err_str) -{ - int ilen, olen; - size_t ileft, oleft; - char *ostr, *optr; - const char *istr; - - ilen = *lenp; - olen = ilen + 1; - - ostr = NULL; - for (;;) { - olen *= 2; - oleft = olen; - ostr = optr = xrealloc(ostr, olen); - istr = (const char *)str; - if ((ileft = ilen) == 0) - break; - - if (iconv(cd, &istr, &ileft, &optr, &oleft) != (size_t)-1) { - /* success: generate reset sequence */ - if (iconv(cd, NULL, NULL, - &optr, &oleft) == (size_t)-1 && errno == E2BIG) { - continue; - } - break; - } - /* failed */ - if (errno != E2BIG) { - oleft = olen; - (void) iconv(cd, NULL, NULL, &ostr, &oleft); - xfree(ostr); - *err_str = gettext("Codeset conversion failed"); - return (NULL); - } - } - olen = optr - ostr; - optr = xmalloc(olen + 1); - (void) memcpy(optr, ostr, olen); - xfree(ostr); - - optr[olen] = '\0'; - *lenp = olen; - - return (optr); -} - -/* - * A filter for output string. Control and unprintable characters - * are converted into visible form (eg "\ooo"). - */ -char * -g11n_filter_string(char *s) -{ - int mb_cur_max = MB_CUR_MAX; - int mblen, len; - char *os = s; - wchar_t wc; - char *obuf, *op; - - /* all character may be converted into the form of \ooo */ - obuf = op = xmalloc(strlen(s) * 4 + 1); - - while (*s != '\0') { - mblen = mbtowc(&wc, s, mb_cur_max); - if (mblen <= 0) { - mblen = 1; - wc = (unsigned char)*s; - } - if (!iswprint(wc) && - wc != L'\n' && wc != L'\r' && wc != L'\t') { - /* - * control chars which need to be replaced - * with safe character sequence. - */ - while (mblen != 0) { - op += sprintf(op, "\\%03o", - (unsigned char)*s++); - mblen--; - } - } else { - while (mblen != 0) { - *op++ = *s++; - mblen--; - } - } - } - *op = '\0'; - len = op - obuf + 1; - op = xrealloc(os, len); - (void) memcpy(op, obuf, len); - xfree(obuf); - return (op); -} - -/* - * Once we negotiated with a langtag, server need to map it to a system - * locale. That is done based on the locale supported on the server side. - * We know (with the locale supported on Solaris) how the langtag is - * mapped to. However, from the client point of view, there is no way to - * know exactly what locale(encoding) will be used. - * - * With the bug fix of SSH_BUG_STRING_ENCODING, it is guaranteed that the - * UTF-8 characters always come over the wire, so it is no longer the problem - * as long as both side has the bug fix. However if the server side doesn't - * have the fix, client can't safely perform the code conversion since the - * incoming character encoding is unknown. - * - * To alleviate this situation, we take an empirical approach to find - * encoding from langtag. - * - * If langtag has a subtag, we can directly map the langtag to UTF-8 locale - * (eg en-US can be mapped to en_US.UTF-8) with a few exceptions. - * Certain xx_YY locales don't support UTF-8 encoding (probably due to lack - * of L10N support ..). Those are: - * - * no_NO, no_NY, sr_SP, sr_YU - * - * They all use ISO8859-X encoding. - * - * For those "xx" langtags, some of them can be mapped to "xx.UTF-8", - * but others cannot. So we need to use the "xx" as the locale name. - * Those locales are: - * - * ar, ca, cs, da, et, fi, he, hu, ja, lt, lv, nl, no, pt, sh, th, tr - * - * Their encoding vary. They could be ISO8859-X or EUC or something else. - * So we don't perform code conversion for these langtags. - */ -static const char *non_utf8_langtag[] = { - "no-NO", "no-NY", "sr-SP", "sr-YU", - "ar", "ca", "cs", "da", "et", "fi", "he", "hu", "ja", - "lt", "lv", "nl", "no", "pt", "sh", "th", "tr", NULL}; - -void -g11n_test_langtag(const char *lang, int server) -{ - const char **lp; - - if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) { - /* - * We negotiated with real locale name (not lang tag). - * We shouldn't expect UTF-8, thus shouldn't do code - * conversion. - */ - datafellows |= SSH_BUG_STRING_ENCODING; - return; - } - - if (datafellows & SSH_BUG_STRING_ENCODING) { - if (server) { - /* - * Whatever bug exists in the client side, server - * side has nothing to do, since server has no way - * to know what actual encoding is used on the client - * side. For example, even if we negotiated with - * en_US, client locale could be en_US.ISO8859-X or - * en_US.UTF-8. - */ - return; - } - /* - * We are on the client side. We'll check with known - * locales to see if non-UTF8 characters could come in. - */ - for (lp = non_utf8_langtag; *lp != NULL; lp++) { - if (strcmp(lang, *lp) == 0) - break; - } - if (*lp == NULL) { - debug2("Server is expected to use UTF-8 locale"); - datafellows &= ~SSH_BUG_STRING_ENCODING; - } else { - /* - * Server is expected to use non-UTF8 encoding. - */ - debug2("Enforcing no code conversion: %s", lang); - } - } -} - -/* - * Free all strings in the list and then free the list itself. We know that the - * list ends with a NULL pointer. - */ -void -g11n_freelist(char **list) -{ - int i = 0; - - while (list[i] != NULL) { - xfree(list[i]); - i++; - } - - xfree(list); -} diff --git a/usr/src/cmd/ssh/libssh/common/hostfile.c b/usr/src/cmd/ssh/libssh/common/hostfile.c deleted file mode 100644 index f71463a973..0000000000 --- a/usr/src/cmd/ssh/libssh/common/hostfile.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for manipulating the known hosts files. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. - * Copyright (c) 1999 Niels Provos. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $OpenBSD: hostfile.c,v 1.45 2006/08/03 03:34:42 deraadt Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#include <openssl/hmac.h> -#include <openssl/sha.h> - -#include "packet.h" -#include "xmalloc.h" -#include "match.h" -#include "key.h" -#include "hostfile.h" -#include "log.h" - -/* - * Format of a hashed hostname is <MAGIC><SALT>|<HASHED_HOSTNAME>. <MAGIC> is - * "|1|". As in non-hashed hostnames this whole string is then followed by a - * space, a key type and the key (which is out of scope of this function). - * - * Example what can be in 's': - * - * |1|t17NtsuXSLwP0H0eYdd8vJeNakM=|9XFVPh3jZUrfY6YCWn8Ua5eGZtA= - */ -static int -extract_salt(const char *s, u_int l, char *salt, size_t salt_len) -{ - char *p; - u_char *b64salt; - u_int b64len; - int ret; - - if (l < sizeof(HASH_MAGIC) - 1) { - debug2("extract_salt: string too short"); - return (-1); - } - if (strncmp(s, HASH_MAGIC, sizeof(HASH_MAGIC) - 1) != 0) { - debug2("extract_salt: invalid magic identifier"); - return (-1); - } - s += sizeof(HASH_MAGIC) - 1; - l -= sizeof(HASH_MAGIC) - 1; - if ((p = memchr(s, HASH_DELIM, l)) == NULL) { - debug2("extract_salt: missing salt termination character"); - return (-1); - } - - b64len = p - s; - /* Sanity check */ - if (b64len == 0 || b64len > 1024) { - debug2("extract_salt: bad encoded salt length %u", b64len); - return (-1); - } - b64salt = xmalloc(1 + b64len); - memcpy(b64salt, s, b64len); - b64salt[b64len] = '\0'; - - ret = __b64_pton(b64salt, (u_char *) salt, salt_len); - xfree(b64salt); - if (ret == -1) { - debug2("extract_salt: salt decode error"); - return (-1); - } - if (ret != SHA_DIGEST_LENGTH) { - debug2("extract_salt: expected salt len %d, got %d", - SHA_DIGEST_LENGTH, ret); - return (-1); - } - - return (0); -} - -char * -host_hash(const char *host, const char *name_from_hostfile, u_int src_len) -{ - const EVP_MD *md = EVP_sha1(); - HMAC_CTX mac_ctx; - char salt[256], result[256], uu_salt[512], uu_result[512]; - static char encoded[1024]; - u_int i, len; - - len = EVP_MD_size(md); - - if (name_from_hostfile == NULL) { - /* Create new salt */ - for (i = 0; i < len; i++) - salt[i] = arc4random(); - } else { - /* Extract salt from known host entry */ - if (extract_salt(name_from_hostfile, src_len, salt, - sizeof(salt)) == -1) - return (NULL); - } - - HMAC_Init(&mac_ctx, salt, len, md); - HMAC_Update(&mac_ctx, (u_char *) host, strlen(host)); - HMAC_Final(&mac_ctx, (u_char *) result, NULL); - HMAC_cleanup(&mac_ctx); - - if (__b64_ntop((u_char *) salt, len, uu_salt, sizeof(uu_salt)) == -1 || - __b64_ntop((u_char *) result, len, uu_result, sizeof(uu_result)) == -1) - fatal("host_hash: __b64_ntop failed"); - - snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt, - HASH_DELIM, uu_result); - - return (encoded); -} - -/* - * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the - * pointer over the key. Skips any whitespace at the beginning and at end. - */ - -int -hostfile_read_key(char **cpp, u_int *bitsp, Key *ret) -{ - char *cp; - - /* Skip leading whitespace. */ - for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) - ; - - if (key_read(ret, &cp) != 1) - return 0; - - /* Skip trailing whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - - /* Return results. */ - *cpp = cp; - *bitsp = key_size(ret); - return 1; -} - -static int -hostfile_check_key(int bits, const Key *key, const char *host, const char *filename, int linenum) -{ - if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) - return 1; - if (bits != BN_num_bits(key->rsa->n)) { - log("Warning: %s, line %d: keysize mismatch for host %s: " - "actual %d vs. announced %d.", - filename, linenum, host, BN_num_bits(key->rsa->n), bits); - log("Warning: replace %d with %d in %s, line %d.", - bits, BN_num_bits(key->rsa->n), filename, linenum); - } - return 1; -} - -/* - * Checks whether the given host (which must be in all lowercase) is already - * in the list of our known hosts. Returns HOST_OK if the host is known and - * has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED - * if the host is known but used to have a different host key. - * - * If no 'key' has been specified and a key of type 'keytype' is known - * for the specified host, then HOST_FOUND is returned. - */ - -static HostStatus -check_host_in_hostfile_by_key_or_type(const char *filename, - const char *host, const Key *key, int keytype, Key *found, int *numret) -{ - FILE *f; - char line[8192]; - int linenum = 0; - u_int kbits; - char *cp, *cp2, *hashed_host; - HostStatus end_return; - - debug3("check_host_in_hostfile: filename %s", filename); - - /* Open the file containing the list of known hosts. */ - f = fopen(filename, "r"); - if (!f) - return HOST_NEW; - - /* - * Return value when the loop terminates. This is set to - * HOST_CHANGED if we have seen a different key for the host and have - * not found the proper one. - */ - end_return = HOST_NEW; - - /* Go through the file. */ - while (fgets(line, sizeof(line), f)) { - cp = line; - linenum++; - - /* Skip any leading whitespace, comments and empty lines. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '#' || *cp == '\n') - continue; - - /* Find the end of the host name portion. */ - for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) - ; - - /* Check if the host name matches. */ - if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) { - if (*cp != HASH_DELIM) - continue; - hashed_host = host_hash(host, cp, (u_int) (cp2 - cp)); - if (hashed_host == NULL) { - debug("Invalid hashed host line %d of %s", - linenum, filename); - continue; - } - if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0) - continue; - } - - /* Got a match. Skip host name. */ - cp = cp2; - - /* - * Extract the key from the line. This will skip any leading - * whitespace. Ignore badly formatted lines. - */ - if (!hostfile_read_key(&cp, &kbits, found)) - continue; - - if (numret != NULL) - *numret = linenum; - - if (key == NULL) { - /* we found a key of the requested type */ - if (found->type == keytype) { - fclose(f); - return HOST_FOUND; - } - continue; - } - - if (!hostfile_check_key(kbits, found, host, filename, linenum)) - continue; - - /* Check if the current key is the same as the given key. */ - if (key_equal(key, found)) { - /* Ok, they match. */ - debug3("check_host_in_hostfile: match line %d", linenum); - fclose(f); - return HOST_OK; - } - /* - * They do not match. We will continue to go through the - * file; however, we note that we will not return that it is - * new. - */ - end_return = HOST_CHANGED; - } - /* Clear variables and close the file. */ - fclose(f); - - /* - * Return either HOST_NEW or HOST_CHANGED, depending on whether we - * saw a different key for the host. - */ - return end_return; -} - -HostStatus -check_host_in_hostfile(const char *filename, const char *host, const Key *key, - Key *found, int *numret) -{ - if (key == NULL) - fatal("no key to look up"); - return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0, - found, numret)); -} - -int -lookup_key_in_hostfile_by_type(const char *filename, const char *host, - int keytype, Key *found, int *numret) -{ - return (check_host_in_hostfile_by_key_or_type(filename, host, NULL, - keytype, found, numret) == HOST_FOUND); -} - -/* - * Appends an entry to the host file. Returns false if the entry could not - * be appended. - */ - -int -add_host_to_hostfile(const char *filename, const char *host, const Key *key, - int store_hash) -{ - FILE *f; - int success = 0; - char *hashed_host = NULL; - - if (key == NULL) - return 1; /* XXX ? */ - f = fopen(filename, "a"); - if (!f) - return 0; - - if (store_hash) { - if ((hashed_host = host_hash(host, NULL, 0)) == NULL) { - error("add_host_to_hostfile: host_hash failed"); - fclose(f); - return 0; - } - } - fprintf(f, "%s ", store_hash ? hashed_host : host); - - if (key_write(key, f)) { - success = 1; - } else { - error("add_host_to_hostfile: saving key in %s failed", filename); - } - fprintf(f, "\n"); - fclose(f); - return success; -} diff --git a/usr/src/cmd/ssh/libssh/common/kex.c b/usr/src/cmd/ssh/libssh/common/kex.c deleted file mode 100644 index 0eb9e780fa..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kex.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); - -#include <locale.h> - -#include <openssl/crypto.h> - -#include "ssh2.h" -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "packet.h" -#include "compat.h" -#include "cipher.h" -#include "kex.h" -#include "key.h" -#include "log.h" -#include "mac.h" -#include "match.h" -#include "dispatch.h" -#include "g11n.h" - -#ifdef GSSAPI -#include "ssh-gss.h" -#endif - -#define KEX_COOKIE_LEN 16 - -char *session_lang = NULL; - - -/* prototype */ -static void kex_do_hook(Kex *kex); -static void kex_kexinit_finish(Kex *); -static void kex_choose_conf(Kex *); - -/* put algorithm proposal into buffer */ -static -void -kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) -{ - int i; - - buffer_clear(b); - /* - * add a dummy cookie, the cookie will be overwritten by - * kex_send_kexinit(), each time a kexinit is set - */ - for (i = 0; i < KEX_COOKIE_LEN; i++) - buffer_put_char(b, 0); - for (i = 0; i < PROPOSAL_MAX; i++) - buffer_put_cstring(b, proposal[i]); - buffer_put_char(b, 0); /* first_kex_packet_follows */ - buffer_put_int(b, 0); /* uint32 reserved */ -} - -/* parse buffer and return algorithm proposal */ -static -char ** -kex_buf2prop(Buffer *raw, int *first_kex_follows) -{ - Buffer b; - int i; - char **proposal; - - proposal = xmalloc(PROPOSAL_MAX * sizeof(char *)); - - buffer_init(&b); - buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); - /* skip cookie */ - for (i = 0; i < KEX_COOKIE_LEN; i++) - buffer_get_char(&b); - /* extract kex init proposal strings */ - for (i = 0; i < PROPOSAL_MAX; i++) { - proposal[i] = buffer_get_string(&b,NULL); - debug2("kex_parse_kexinit: %s", proposal[i]); - } - /* first kex follows / reserved */ - i = buffer_get_char(&b); - if (first_kex_follows != NULL) - *first_kex_follows = i; - debug2("kex_parse_kexinit: first_kex_follows %d ", i); - i = buffer_get_int(&b); - debug2("kex_parse_kexinit: reserved %d ", i); - buffer_free(&b); - return proposal; -} - -static -void -kex_prop_free(char **proposal) -{ - int i; - - for (i = 0; i < PROPOSAL_MAX; i++) - xfree(proposal[i]); - xfree(proposal); -} - -static void -kex_protocol_error(int type, u_int32_t seq, void *ctxt) -{ - error("Hm, kex protocol error: type %d seq %u", type, seq); -} - -static void -kex_reset_dispatch(void) -{ -#ifdef ALTPRIVSEP - /* unprivileged sshd has a kex packet handler that must not be reset */ - debug3("kex_reset_dispatch -- should we dispatch_set(KEXINIT) here? %d && !%d", - packet_is_server(), packet_is_monitor()); - if (packet_is_server() && !packet_is_monitor()) { - debug3("kex_reset_dispatch -- skipping dispatch_set(KEXINIT) in unpriv proc"); - return; - } -#endif /* ALTPRIVSEP */ - - dispatch_range(SSH2_MSG_TRANSPORT_MIN, - SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); -} - -void -kex_finish(Kex *kex) -{ - kex_reset_dispatch(); - - packet_start(SSH2_MSG_NEWKEYS); - packet_send(); - /* packet_write_wait(); */ - debug("SSH2_MSG_NEWKEYS sent"); - -#ifdef ALTPRIVSEP - if (packet_is_monitor()) - goto skip_newkeys; -#endif /* ALTPRIVSEP */ - debug("expecting SSH2_MSG_NEWKEYS"); - packet_read_expect(SSH2_MSG_NEWKEYS); - packet_check_eom(); - debug("SSH2_MSG_NEWKEYS received"); -#ifdef ALTPRIVSEP -skip_newkeys: -#endif /* ALTPRIVSEP */ - - kex->done = 1; - kex->initial_kex_done = 1; /* never to be cleared once set */ - buffer_clear(&kex->peer); - /* buffer_clear(&kex->my); */ - kex->flags &= ~KEX_INIT_SENT; - xfree(kex->name); - kex->name = NULL; -} - -void -kex_send_kexinit(Kex *kex) -{ - u_int32_t rand = 0; - u_char *cookie; - int i; - - if (kex == NULL) { - error("kex_send_kexinit: no kex, cannot rekey"); - return; - } - if (kex->flags & KEX_INIT_SENT) { - debug("KEX_INIT_SENT"); - return; - } - kex->done = 0; - - /* update my proposal -- e.g., add/remove GSS kexalgs */ - kex_do_hook(kex); - - /* generate a random cookie */ - if (buffer_len(&kex->my) < KEX_COOKIE_LEN) - fatal("kex_send_kexinit: kex proposal too short"); - cookie = buffer_ptr(&kex->my); - for (i = 0; i < KEX_COOKIE_LEN; i++) { - if (i % 4 == 0) - rand = arc4random(); - cookie[i] = rand; - rand >>= 8; - } - packet_start(SSH2_MSG_KEXINIT); - packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); - packet_send(); - debug("SSH2_MSG_KEXINIT sent"); - kex->flags |= KEX_INIT_SENT; -} - -void -kex_input_kexinit(int type, u_int32_t seq, void *ctxt) -{ - char *ptr; - u_int dlen; - int i; - Kex *kex = (Kex *)ctxt; - - debug("SSH2_MSG_KEXINIT received"); - if (kex == NULL) - fatal("kex_input_kexinit: no kex, cannot rekey"); - - ptr = packet_get_raw(&dlen); - buffer_append(&kex->peer, ptr, dlen); - - /* discard packet */ - for (i = 0; i < KEX_COOKIE_LEN; i++) - packet_get_char(); - for (i = 0; i < PROPOSAL_MAX; i++) - xfree(packet_get_string(NULL)); - (void) packet_get_char(); - (void) packet_get_int(); - packet_check_eom(); - - kex_kexinit_finish(kex); -} - -/* - * This is for GSS keyex, where actual KEX offer can change at rekey - * time due to credential expiration/renewal... - */ -static -void -kex_do_hook(Kex *kex) -{ - char **prop; - - if (kex->kex_hook == NULL) - return; - - /* Unmarshall my proposal, let the hook modify it, remarshall it */ - prop = kex_buf2prop(&kex->my, NULL); - buffer_clear(&kex->my); - (kex->kex_hook)(kex, prop); - kex_prop2buf(&kex->my, prop); - kex_prop_free(prop); -} - -/* Initiate the key exchange by sending the SSH2_MSG_KEXINIT message. */ -void -kex_start(Kex *kex) -{ - kex_send_kexinit(kex); - kex_reset_dispatch(); -} - -/* - * Allocate a key exchange structure and populate it with a proposal we are - * going to use. This function does not start the actual key exchange. - */ -Kex * -kex_setup(const char *host, char *proposal[PROPOSAL_MAX], Kex_hook_func hook) -{ - Kex *kex; - - kex = xmalloc(sizeof(*kex)); - memset(kex, 0, sizeof(*kex)); - buffer_init(&kex->peer); - buffer_init(&kex->my); - - kex->kex_hook = hook; /* called by kex_send_kexinit() */ - - if (host != NULL && *host != '\0') - kex->serverhost = xstrdup(host); - else - kex->server = 1; - - kex_prop2buf(&kex->my, proposal); - - return kex; -} - -static void -kex_kexinit_finish(Kex *kex) -{ - if (!(kex->flags & KEX_INIT_SENT)) - kex_send_kexinit(kex); - - kex_choose_conf(kex); - - if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && - kex->kex[kex->kex_type] != NULL) - (kex->kex[kex->kex_type])(kex); - else - fatal("Unsupported key exchange %d", kex->kex_type); -} - -static void -choose_lang(char **lang, char *client, char *server) -{ - if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) - *lang = match_list(client, server, NULL); - else - *lang = g11n_srvr_locale_negotiate(client, NULL); -} - -/* - * Make the message clear enough so that if this happens the user can figure out - * the workaround of changing the Ciphers option. - */ -#define CLIENT_ERR_MSG \ - "Client and server could not agree on a common cipher:\n" \ - " client: %s\n" \ - " server: %s\n" \ - "\n" \ - "The client cipher list can be controlled using the \"Ciphers\" option, \n" \ - "see ssh_config(4) for more information. The \"-o Ciphers=<cipher-list>\"\n" \ - "option may be used to temporarily override the ciphers the client\n" \ - "offers." - -/* - * The server side message goes to syslogd and we do not want to send multiline - * messages there. What's more, the server side notification may be shorter - * since we expect that an administrator will deal with that, not the user. - */ -#define SERVER_ERR_MSG \ - "Client and server could not agree on a common cipher: client \"%s\", " \ - "server \"%s\". The server cipher list can be controlled using the " \ - "\"Ciphers\" option, see sshd_config(4) for more information." - -static void -choose_enc(int is_server, Enc *enc, char *client, char *server) -{ - char *name = match_list(client, server, NULL); - - if (name == NULL) { - if (is_server == 1) - fatal(SERVER_ERR_MSG, client, server); - else - fatal(CLIENT_ERR_MSG, client, server); - } - - if ((enc->cipher = cipher_by_name(name)) == NULL) - fatal("matching cipher is not supported: %s", name); - - enc->name = name; - enc->enabled = 0; - enc->iv = NULL; - enc->key = NULL; - enc->key_len = cipher_keylen(enc->cipher); - enc->block_size = cipher_blocksize(enc->cipher); -} - -static void -choose_mac(Mac *mac, char *client, char *server) -{ - char *name = match_list(client, server, NULL); - if (name == NULL) - fatal("no matching mac found: client %s server %s", - client, server); - if (mac_setup(mac, name) < 0) - fatal("unsupported mac %s", name); - /* truncate the key */ - if (datafellows & SSH_BUG_HMAC) - mac->key_len = 16; - mac->name = name; - mac->key = NULL; - mac->enabled = 0; -} - -static void -choose_comp(Comp *comp, char *client, char *server) -{ - char *name = match_list(client, server, NULL); - if (name == NULL) - fatal("no matching comp found: client %s server %s", client, server); - if (strcmp(name, "zlib") == 0) { - comp->type = 1; - } else if (strcmp(name, "none") == 0) { - comp->type = 0; - } else { - fatal("unsupported comp %s", name); - } - comp->name = name; -} - -static void -choose_kex(Kex *k, char *client, char *server) -{ - k->name = match_list(client, server, NULL); - if (k->name == NULL) - fatal("no common kex alg: client '%s', server '%s'", client, - server); - /* XXX Finish 3.6/7 merge of kex stuff -- choose_kex() done */ - if (strcmp(k->name, KEX_DH1) == 0) { - k->kex_type = KEX_DH_GRP1_SHA1; - } else if (strcmp(k->name, KEX_DHGEX) == 0) { - k->kex_type = KEX_DH_GEX_SHA1; -#ifdef GSSAPI - } else if (strncmp(k->name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) == 0) { - k->kex_type = KEX_GSS_GRP1_SHA1; -#endif - } else - fatal("bad kex alg %s", k->name); -} - -static void -choose_hostkeyalg(Kex *k, char *client, char *server) -{ - char *hostkeyalg = match_list(client, server, NULL); - if (hostkeyalg == NULL) - fatal("no hostkey alg"); - k->hostkey_type = key_type_from_name(hostkeyalg); - if (k->hostkey_type == KEY_UNSPEC) - fatal("bad hostkey alg '%s'", hostkeyalg); - xfree(hostkeyalg); -} - -static int -proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) -{ - static int check[] = { - PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 - }; - int *idx; - char *p; - - for (idx = &check[0]; *idx != -1; idx++) { - if ((p = strchr(my[*idx], ',')) != NULL) - *p = '\0'; - if ((p = strchr(peer[*idx], ',')) != NULL) - *p = '\0'; - if (strcmp(my[*idx], peer[*idx]) != 0) { - debug2("proposal mismatch: my %s peer %s", - my[*idx], peer[*idx]); - return (0); - } - } - debug2("proposals match"); - return (1); -} - -static void -kex_choose_conf(Kex *kex) -{ - Newkeys *newkeys; - char **my, **peer; - char **cprop, **sprop; - char *p_langs_c2s, *p_langs_s2c; /* peer's langs */ - char *plangs = NULL; /* peer's langs*/ - char *mlangs = NULL; /* my langs */ - int nenc, nmac, ncomp; - int mode; - int ctos; /* direction: if true client-to-server */ - int need; - int first_kex_follows, type; - - my = kex_buf2prop(&kex->my, NULL); - peer = kex_buf2prop(&kex->peer, &first_kex_follows); - - if (kex->server) { - cprop=peer; - sprop=my; - } else { - cprop=my; - sprop=peer; - } - - /* Algorithm Negotiation */ - for (mode = 0; mode < MODE_MAX; mode++) { - newkeys = xmalloc(sizeof(*newkeys)); - memset(newkeys, 0, sizeof(*newkeys)); - kex->newkeys[mode] = newkeys; - ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); - nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; - nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; - ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; - choose_enc(kex->server, &newkeys->enc, cprop[nenc], sprop[nenc]); - choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); - choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); - debug("kex: %s %s %s %s", - ctos ? "client->server" : "server->client", - newkeys->enc.name, - newkeys->mac.name, - newkeys->comp.name); - } - choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); - choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], - sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); - need = 0; - for (mode = 0; mode < MODE_MAX; mode++) { - newkeys = kex->newkeys[mode]; - if (need < newkeys->enc.key_len) - need = newkeys->enc.key_len; - if (need < newkeys->enc.block_size) - need = newkeys->enc.block_size; - if (need < newkeys->mac.key_len) - need = newkeys->mac.key_len; - } - /* XXX need runden? */ - kex->we_need = need; - - /* ignore the next message if the proposals do not match */ - if (first_kex_follows && !proposals_match(my, peer) && - !(datafellows & SSH_BUG_FIRSTKEX)) { - type = packet_read(); - debug2("skipping next packet (type %u)", type); - } - - /* Language/locale negotiation -- not worth doing on re-key */ - - if (!kex->initial_kex_done) { - p_langs_c2s = peer[PROPOSAL_LANG_CTOS]; - p_langs_s2c = peer[PROPOSAL_LANG_STOC]; - debug("Peer sent proposed langtags, ctos: %s", p_langs_c2s); - debug("Peer sent proposed langtags, stoc: %s", p_langs_s2c); - plangs = NULL; - - /* We propose the same langs for each protocol direction */ - mlangs = my[PROPOSAL_LANG_STOC]; - debug("We proposed langtags, ctos: %s", my[PROPOSAL_LANG_CTOS]); - debug("We proposed langtags, stoc: %s", mlangs); - - /* - * Why oh why did they bother with negotiating langs for - * each protocol direction?! - * - * The semantics of this are vaguely specified, but one can - * imagine using one language (locale) for the whole session and - * a different one for message localization (e.g., 'en_US.UTF-8' - * overall and 'fr' for messages). Weird? Maybe. But lang - * tags don't include codeset info, like locales do... - * - * So, server-side we want: - * - setlocale(LC_ALL, c2s_locale); - * and - * - setlocale(LC_MESSAGES, s2c_locale); - * - * Client-side we don't really care. But we could do: - * - * - when very verbose, tell the use what lang the server's - * messages are in, if left out in the protocol - * - when sending messages to the server, and if applicable, we - * can localize them according to the language negotiated for - * that direction. - * - * But for now we do nothing on the client side. - */ - if ((p_langs_c2s && *p_langs_c2s) && !(p_langs_s2c && *p_langs_s2c)) - plangs = p_langs_c2s; - else if ((p_langs_s2c && *p_langs_s2c) && !(p_langs_c2s && *p_langs_c2s)) - plangs = p_langs_s2c; - else - plangs = p_langs_c2s; - - if (kex->server) { - if (plangs && mlangs && *plangs && *mlangs) { - char *locale; - - g11n_test_langtag(plangs, 1); - - choose_lang(&locale, plangs, mlangs); - if (locale) { - g11n_setlocale(LC_ALL, locale); - debug("Negotiated main locale: %s", locale); - packet_send_debug("Negotiated main locale: %s", locale); - xfree(locale); - } - if (plangs != p_langs_s2c && - p_langs_s2c && *p_langs_s2c) { - choose_lang(&locale, p_langs_s2c, mlangs); - if (locale) { - g11n_setlocale(LC_MESSAGES, locale); - debug("Negotiated messages locale: %s", locale); - packet_send_debug("Negotiated " - "messages locale: %s", locale); - xfree(locale); - } - } - } - } - else { - if (plangs && mlangs && *plangs && *mlangs && - !(datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS)) { - char *lang; - lang = g11n_clnt_langtag_negotiate(mlangs, plangs); - if (lang) { - session_lang = lang; - debug("Negotiated lang: %s", lang); - g11n_test_langtag(lang, 0); - } - } - } - } - - kex_prop_free(my); - kex_prop_free(peer); -} - -static u_char * -derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) -{ - Buffer b; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - char c = id; - int have; - int mdsz = EVP_MD_size(evp_md); - u_char *digest = xmalloc(roundup(need, mdsz)); - - buffer_init(&b); - buffer_put_bignum2(&b, shared_secret); - - /* K1 = HASH(K || H || "A" || session_id) */ - EVP_DigestInit(&md, evp_md); - if (!(datafellows & SSH_BUG_DERIVEKEY)) - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestUpdate(&md, hash, mdsz); - EVP_DigestUpdate(&md, &c, 1); - EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); - EVP_DigestFinal(&md, digest, NULL); - - /* - * expand key: - * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) - * Key = K1 || K2 || ... || Kn - */ - for (have = mdsz; need > have; have += mdsz) { - EVP_DigestInit(&md, evp_md); - if (!(datafellows & SSH_BUG_DERIVEKEY)) - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestUpdate(&md, hash, mdsz); - EVP_DigestUpdate(&md, digest, have); - EVP_DigestFinal(&md, digest + have, NULL); - } - buffer_free(&b); -#ifdef DEBUG_KEX - fprintf(stderr, "key '%c'== ", c); - dump_digest("key", digest, need); -#endif - return digest; -} - -Newkeys *current_keys[MODE_MAX]; - -#define NKEYS 6 -void -kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) -{ - u_char *keys[NKEYS]; - int i, mode, ctos; - - for (i = 0; i < NKEYS; i++) - keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); - - debug2("kex_derive_keys"); - for (mode = 0; mode < MODE_MAX; mode++) { - current_keys[mode] = kex->newkeys[mode]; - kex->newkeys[mode] = NULL; - ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); - current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; - current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; - current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; - } -} - -Newkeys * -kex_get_newkeys(int mode) -{ - Newkeys *ret; - - ret = current_keys[mode]; - current_keys[mode] = NULL; - return ret; -} - -#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) -void -dump_digest(char *msg, u_char *digest, int len) -{ - int i; - - fprintf(stderr, "%s\n", msg); - for (i = 0; i< len; i++) { - fprintf(stderr, "%02x", digest[i]); - if (i%32 == 31) - fprintf(stderr, "\n"); - else if (i%8 == 7) - fprintf(stderr, " "); - } - fprintf(stderr, "\n"); -} -#endif diff --git a/usr/src/cmd/ssh/libssh/common/kexdh.c b/usr/src/cmd/ssh/libssh/common/kexdh.c deleted file mode 100644 index b15ecd2c5b..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexdh.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/crypto.h> -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" - -u_char * -kex_dh_hash( - char *client_version_string, - char *server_version_string, - char *ckexinit, int ckexinitlen, - char *skexinit, int skexinitlen, - u_char *serverhostkeyblob, int sbloblen, - BIGNUM *client_dh_pub, - BIGNUM *server_dh_pub, - BIGNUM *shared_secret) -{ - Buffer b; - static u_char digest[EVP_MAX_MD_SIZE]; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - - buffer_init(&b); - buffer_put_cstring(&b, client_version_string); - buffer_put_cstring(&b, server_version_string); - - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - buffer_put_int(&b, ckexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, ckexinit, ckexinitlen); - buffer_put_int(&b, skexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, skexinit, skexinitlen); - - buffer_put_string(&b, serverhostkeyblob, sbloblen); - buffer_put_bignum2(&b, client_dh_pub); - buffer_put_bignum2(&b, server_dh_pub); - buffer_put_bignum2(&b, shared_secret); - -#ifdef DEBUG_KEX - buffer_dump(&b); -#endif - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); - - buffer_free(&b); - -#ifdef DEBUG_KEX - dump_digest("hash", digest, EVP_MD_size(evp_md)); -#endif - return digest; -} diff --git a/usr/src/cmd/ssh/libssh/common/kexdhc.c b/usr/src/cmd/ssh/libssh/common/kexdhc.c deleted file mode 100644 index 1c75f8449f..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexdhc.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/crypto.h> -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" - -void -kexdh_client(Kex *kex) -{ - BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; - DH *dh; - Key *server_host_key; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf, *hash; - u_int klen, kout, slen, sbloblen; - - /* generate and send 'e', client DH public key */ - dh = dh_new_group1(); - dh_gen_key(dh, kex->we_need * 8); - packet_start(SSH2_MSG_KEXDH_INIT); - packet_put_bignum2(dh->pub_key); - packet_send(); - - debug("sending SSH2_MSG_KEXDH_INIT"); -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); - fprintf(stderr, "\n"); -#endif - - debug("expecting SSH2_MSG_KEXDH_REPLY"); - packet_read_expect(SSH2_MSG_KEXDH_REPLY); - - /* key, cert */ - server_host_key_blob = packet_get_string(&sbloblen); - server_host_key = key_from_blob(server_host_key_blob, sbloblen); - if (server_host_key == NULL) - fatal("cannot decode server_host_key_blob"); - if (server_host_key->type != kex->hostkey_type) - fatal("type mismatch for decoded server_host_key_blob"); - if (kex->verify_host_key == NULL) - fatal("cannot verify server_host_key"); - if (kex->verify_host_key(server_host_key) == -1) - fatal("server_host_key verification failed"); - - /* DH paramter f, server public DH key */ - if ((dh_server_pub = BN_new()) == NULL) - fatal("dh_server_pub == NULL"); - packet_get_bignum2(dh_server_pub); - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_server_pub= "); - BN_print_fp(stderr, dh_server_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_server_pub)); -#endif - - /* signed H */ - signature = packet_get_string(&slen); - packet_check_eom(); - - if (!dh_pub_is_valid(dh, dh_server_pub)) - packet_disconnect("bad server public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - kout = DH_compute_key(kbuf, dh_server_pub, dh); -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexdh_client: BN_new failed"); - BN_bin2bn(kbuf, kout, shared_secret); - memset(kbuf, 0, klen); - xfree(kbuf); - - /* calc and verify H */ - hash = kex_dh_hash( - kex->client_version_string, - kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - server_host_key_blob, sbloblen, - dh->pub_key, - dh_server_pub, - shared_secret - ); - xfree(server_host_key_blob); - BN_clear_free(dh_server_pub); - DH_free(dh); - - if (key_verify(server_host_key, signature, slen, hash, 20) != 1) - fatal("key_verify failed for server_host_key"); - key_free(server_host_key); - xfree(signature); - - /* save session id */ - if (kex->session_id == NULL) { - kex->session_id_len = 20; - kex->session_id = xmalloc(kex->session_id_len); - memcpy(kex->session_id, hash, kex->session_id_len); - } - - kex_derive_keys(kex, hash, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); -} diff --git a/usr/src/cmd/ssh/libssh/common/kexdhs.c b/usr/src/cmd/ssh/libssh/common/kexdhs.c deleted file mode 100644 index 5e14b1333f..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexdhs.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/crypto.h> -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" - -void -kexdh_server(Kex *kex) -{ - BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; - DH *dh; - Key *server_host_key; - u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int sbloblen, klen, kout; - u_int slen; - - /* generate server DH public key */ - dh = dh_new_group1(); - dh_gen_key(dh, kex->we_need * 8); - - debug("expecting SSH2_MSG_KEXDH_INIT"); - packet_read_expect(SSH2_MSG_KEXDH_INIT); - - if (kex->load_host_key == NULL) - fatal("Cannot load hostkey"); - server_host_key = kex->load_host_key(kex->hostkey_type); - if (server_host_key == NULL) - fatal("Unsupported hostkey type %d", kex->hostkey_type); - - /* key, cert */ - if ((dh_client_pub = BN_new()) == NULL) - fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub); - packet_check_eom(); - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_client_pub= "); - BN_print_fp(stderr, dh_client_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_client_pub)); -#endif - -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); - fprintf(stderr, "\n"); -#endif - if (!dh_pub_is_valid(dh, dh_client_pub)) - packet_disconnect("bad client public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - kout = DH_compute_key(kbuf, dh_client_pub, dh); -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexdh_server: BN_new failed"); - BN_bin2bn(kbuf, kout, shared_secret); - memset(kbuf, 0, klen); - xfree(kbuf); - - key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); - - /* calc H */ - hash = kex_dh_hash( - kex->client_version_string, - kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), - server_host_key_blob, sbloblen, - dh_client_pub, - dh->pub_key, - shared_secret - ); - BN_clear_free(dh_client_pub); - - /* save session id := H */ - /* XXX hashlen depends on KEX */ - if (kex->session_id == NULL) { - kex->session_id_len = 20; - kex->session_id = xmalloc(kex->session_id_len); - memcpy(kex->session_id, hash, kex->session_id_len); - } - - /* sign H */ - /* XXX hashlen depends on KEX */ - key_sign(server_host_key, &signature, &slen, hash, 20); - - /* destroy_sensitive_data(); */ - - /* send server hostkey, DH pubkey 'f' and singed H */ - packet_start(SSH2_MSG_KEXDH_REPLY); - packet_put_string(server_host_key_blob, sbloblen); - packet_put_bignum2(dh->pub_key); /* f */ - packet_put_string(signature, slen); - packet_send(); - - xfree(signature); - xfree(server_host_key_blob); - /* have keys, free DH */ - DH_free(dh); - - kex_derive_keys(kex, hash, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); -} diff --git a/usr/src/cmd/ssh/libssh/common/kexgex.c b/usr/src/cmd/ssh/libssh/common/kexgex.c deleted file mode 100644 index 3652e1c020..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexgex.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" -#include "compat.h" - -u_char * -kexgex_hash( - char *client_version_string, - char *server_version_string, - char *ckexinit, int ckexinitlen, - char *skexinit, int skexinitlen, - u_char *serverhostkeyblob, int sbloblen, - int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen, - BIGNUM *client_dh_pub, - BIGNUM *server_dh_pub, - BIGNUM *shared_secret) -{ - Buffer b; - static u_char digest[EVP_MAX_MD_SIZE]; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - - buffer_init(&b); - buffer_put_cstring(&b, client_version_string); - buffer_put_cstring(&b, server_version_string); - - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - buffer_put_int(&b, ckexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, ckexinit, ckexinitlen); - buffer_put_int(&b, skexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, skexinit, skexinitlen); - - buffer_put_string(&b, serverhostkeyblob, sbloblen); - if (min == -1 || max == -1) - buffer_put_int(&b, wantbits); - else { - buffer_put_int(&b, min); - buffer_put_int(&b, wantbits); - buffer_put_int(&b, max); - } - buffer_put_bignum2(&b, prime); - buffer_put_bignum2(&b, gen); - buffer_put_bignum2(&b, client_dh_pub); - buffer_put_bignum2(&b, server_dh_pub); - buffer_put_bignum2(&b, shared_secret); - -#ifdef DEBUG_KEXDH - buffer_dump(&b); -#endif - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); - - buffer_free(&b); - -#ifdef DEBUG_KEXDH - dump_digest("hash", digest, EVP_MD_size(evp_md)); -#endif - return digest; -} diff --git a/usr/src/cmd/ssh/libssh/common/kexgexc.c b/usr/src/cmd/ssh/libssh/common/kexgexc.c deleted file mode 100644 index 5fddebaed9..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexgexc.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" -#include "compat.h" - -void -kexgex_client(Kex *kex) -{ - BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; - BIGNUM *p = NULL, *g = NULL; - Key *server_host_key; - u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int klen, kout, slen, sbloblen; - int min, max, nbits; - DH *dh; - - nbits = dh_estimate(kex->we_need * 8); - - if (datafellows & SSH_OLD_DHGEX) { - debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent"); - - /* Old GEX request */ - packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD); - packet_put_int(nbits); - min = DH_GRP_MIN; - max = DH_GRP_MAX; - } else { - debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent"); - - /* New GEX request */ - min = DH_GRP_MIN; - max = DH_GRP_MAX; - packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST); - packet_put_int(min); - packet_put_int(nbits); - packet_put_int(max); - } -#ifdef DEBUG_KEXDH - fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", - min, nbits, max); -#endif - packet_send(); - - debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); - packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP); - - if ((p = BN_new()) == NULL) - fatal("BN_new"); - packet_get_bignum2(p); - if ((g = BN_new()) == NULL) - fatal("BN_new"); - packet_get_bignum2(g); - packet_check_eom(); - - if (BN_num_bits(p) < min || BN_num_bits(p) > max) - fatal("DH_GEX group out of range: %d !< %d !< %d", - min, BN_num_bits(p), max); - - dh = dh_new_group(g, p); - dh_gen_key(dh, kex->we_need * 8); - -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); - fprintf(stderr, "\n"); -#endif - - debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); - /* generate and send 'e', client DH public key */ - packet_start(SSH2_MSG_KEX_DH_GEX_INIT); - packet_put_bignum2(dh->pub_key); - packet_send(); - - debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); - packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY); - - /* key, cert */ - server_host_key_blob = packet_get_string(&sbloblen); - server_host_key = key_from_blob(server_host_key_blob, sbloblen); - if (server_host_key == NULL) - fatal("cannot decode server_host_key_blob"); - if (server_host_key->type != kex->hostkey_type) - fatal("type mismatch for decoded server_host_key_blob"); - if (kex->verify_host_key == NULL) - fatal("cannot verify server_host_key"); - if (kex->verify_host_key(server_host_key) == -1) - fatal("server_host_key verification failed"); - - /* DH paramter f, server public DH key */ - if ((dh_server_pub = BN_new()) == NULL) - fatal("dh_server_pub == NULL"); - packet_get_bignum2(dh_server_pub); - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_server_pub= "); - BN_print_fp(stderr, dh_server_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_server_pub)); -#endif - - /* signed H */ - signature = packet_get_string(&slen); - packet_check_eom(); - - if (!dh_pub_is_valid(dh, dh_server_pub)) - packet_disconnect("bad server public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - kout = DH_compute_key(kbuf, dh_server_pub, dh); -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexgex_client: BN_new failed"); - BN_bin2bn(kbuf, kout, shared_secret); - memset(kbuf, 0, klen); - xfree(kbuf); - - if (datafellows & SSH_OLD_DHGEX) - min = max = -1; - - /* calc and verify H */ - hash = kexgex_hash( - kex->client_version_string, - kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - server_host_key_blob, sbloblen, - min, nbits, max, - dh->p, dh->g, - dh->pub_key, - dh_server_pub, - shared_secret - ); - /* have keys, free DH */ - DH_free(dh); - xfree(server_host_key_blob); - BN_clear_free(dh_server_pub); - - if (key_verify(server_host_key, signature, slen, hash, 20) != 1) - fatal("key_verify failed for server_host_key"); - key_free(server_host_key); - xfree(signature); - - /* save session id */ - if (kex->session_id == NULL) { - kex->session_id_len = 20; - kex->session_id = xmalloc(kex->session_id_len); - memcpy(kex->session_id, hash, kex->session_id_len); - } - kex_derive_keys(kex, hash, shared_secret); - BN_clear_free(shared_secret); - - kex_finish(kex); -} diff --git a/usr/src/cmd/ssh/libssh/common/kexgexs.c b/usr/src/cmd/ssh/libssh/common/kexgexs.c deleted file mode 100644 index b0bd4e3272..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexgexs.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" -#include "compat.h" - -void -kexgex_server(Kex *kex) -{ - BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; - Key *server_host_key; - DH *dh; - u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int sbloblen, klen, kout, slen; - int min = -1, max = -1, nbits = -1, type; - - if (kex->load_host_key == NULL) - fatal("Cannot load hostkey"); - server_host_key = kex->load_host_key(kex->hostkey_type); - if (server_host_key == NULL) - fatal("Unsupported hostkey type %d", kex->hostkey_type); - - type = packet_read(); - switch (type) { - case SSH2_MSG_KEX_DH_GEX_REQUEST: - debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); - min = packet_get_int(); - nbits = packet_get_int(); - max = packet_get_int(); - min = MAX(DH_GRP_MIN, min); - max = MIN(DH_GRP_MAX, max); - break; - case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: - debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); - nbits = packet_get_int(); - min = DH_GRP_MIN; - max = DH_GRP_MAX; - /* unused for old GEX */ - break; - default: - fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); - } - packet_check_eom(); - - if (max < min || nbits < min || max < nbits) - fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", - min, nbits, max); - - /* Contact privileged parent */ - dh = choose_dh(min, nbits, max); - if (dh == NULL) - packet_disconnect("Protocol error: no matching DH grp found"); - - debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); - packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); - packet_put_bignum2(dh->p); - packet_put_bignum2(dh->g); - packet_send(); - - /* flush */ - packet_write_wait(); - - /* Compute our exchange value in parallel with the client */ - dh_gen_key(dh, kex->we_need * 8); - - debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); - packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT); - - /* key, cert */ - if ((dh_client_pub = BN_new()) == NULL) - fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub); - packet_check_eom(); - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_client_pub= "); - BN_print_fp(stderr, dh_client_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_client_pub)); -#endif - -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); - fprintf(stderr, "\n"); -#endif - if (!dh_pub_is_valid(dh, dh_client_pub)) - packet_disconnect("bad client public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - kout = DH_compute_key(kbuf, dh_client_pub, dh); -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexgex_server: BN_new failed"); - BN_bin2bn(kbuf, kout, shared_secret); - memset(kbuf, 0, klen); - xfree(kbuf); - - key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); - - if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) - min = max = -1; - - /* calc H */ /* XXX depends on 'kex' */ - hash = kexgex_hash( - kex->client_version_string, - kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), - server_host_key_blob, sbloblen, - min, nbits, max, - dh->p, dh->g, - dh_client_pub, - dh->pub_key, - shared_secret - ); - BN_clear_free(dh_client_pub); - - /* save session id := H */ - /* XXX hashlen depends on KEX */ - if (kex->session_id == NULL) { - kex->session_id_len = 20; - kex->session_id = xmalloc(kex->session_id_len); - memcpy(kex->session_id, hash, kex->session_id_len); - } - - /* sign H */ - /* XXX hashlen depends on KEX */ - key_sign(server_host_key, &signature, &slen, hash, 20); - - /* destroy_sensitive_data(); */ - - /* send server hostkey, DH pubkey 'f' and singed H */ - debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); - packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); - packet_put_string(server_host_key_blob, sbloblen); - packet_put_bignum2(dh->pub_key); /* f */ - packet_put_string(signature, slen); - packet_send(); - - xfree(signature); - xfree(server_host_key_blob); - /* have keys, free DH */ - DH_free(dh); - - kex_derive_keys(kex, hash, shared_secret); - BN_clear_free(shared_secret); - - kex_finish(kex); -} diff --git a/usr/src/cmd/ssh/libssh/common/kexgssc.c b/usr/src/cmd/ssh/libssh/common/kexgssc.c deleted file mode 100644 index 60c91ed57b..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexgssc.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - - -#include "includes.h" - -#ifdef GSSAPI - -#include <openssl/crypto.h> -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "canohost.h" -#include "ssh2.h" -#include "ssh-gss.h" - -extern char *xxx_host; - -Gssctxt *xxx_gssctxt; - -static void kexgss_verbose_cleanup(void *arg); - -void -kexgss_client(Kex *kex) -{ - gss_buffer_desc gssbuf, send_tok, recv_tok, msg_tok; - gss_buffer_t token_ptr; - gss_OID mech = GSS_C_NULL_OID; - Gssctxt *ctxt = NULL; - OM_uint32 maj_status, min_status, smaj_status, smin_status; - unsigned int klen, kout; - DH *dh; - BIGNUM *dh_server_pub = 0; - BIGNUM *shared_secret = 0; - Key *server_host_key = NULL; - unsigned char *kbuf; - unsigned char *hash; - unsigned char *server_host_key_blob = NULL; - char *msg, *lang; - int type = 0; - int first = 1; - uint_t sbloblen = 0; - uint_t strlen; - - /* Map the negotiated kex name to a mech OID */ - ssh_gssapi_oid_of_kexname(kex->name, &mech); - if (mech == GSS_C_NULL_OID) - fatal("Couldn't match the negotiated GSS key exchange"); - - ssh_gssapi_build_ctx(&ctxt, 1, mech); - - /* This code should match that in ssh_dh1_client */ - - /* Step 1 - e is dh->pub_key */ - dh = dh_new_group1(); - dh_gen_key(dh, kex->we_need * 8); - - /* This is f, we initialise it now to make life easier */ - dh_server_pub = BN_new(); - if (dh_server_pub == NULL) { - fatal("dh_server_pub == NULL"); - } - - token_ptr = GSS_C_NO_BUFFER; - - recv_tok.value = NULL; - recv_tok.length = 0; - - do { - debug("Calling gss_init_sec_context"); - - maj_status = ssh_gssapi_init_ctx(ctxt, xxx_host, - kex->options.gss_deleg_creds, token_ptr, &send_tok); - - if (GSS_ERROR(maj_status)) { - ssh_gssapi_error(ctxt, "performing GSS-API protected " - "SSHv2 key exchange"); - (void) gss_release_buffer(&min_status, &send_tok); - packet_disconnect("A GSS-API error occurred during " - "GSS-API protected SSHv2 key exchange\n"); - } - - /* If we've got an old receive buffer get rid of it */ - if (token_ptr != GSS_C_NO_BUFFER) { - /* We allocated recv_tok */ - xfree(recv_tok.value); - recv_tok.value = NULL; - recv_tok.length = 0; - token_ptr = GSS_C_NO_BUFFER; - } - - if (maj_status == GSS_S_COMPLETE) { - /* If mutual state flag is not true, kex fails */ - if (!(ctxt->flags & GSS_C_MUTUAL_FLAG)) { - fatal("Mutual authentication failed"); - } - /* If integ avail flag is not true kex fails */ - if (!(ctxt->flags & GSS_C_INTEG_FLAG)) { - fatal("Integrity check failed"); - } - } - - /* - * If we have data to send, then the last message that we - * received cannot have been a 'complete'. - */ - if (send_tok.length != 0) { - if (first) { - packet_start(SSH2_MSG_KEXGSS_INIT); - packet_put_string(send_tok.value, - send_tok.length); - packet_put_bignum2(dh->pub_key); - first = 0; - } else { - packet_start(SSH2_MSG_KEXGSS_CONTINUE); - packet_put_string(send_tok.value, - send_tok.length); - } - (void) gss_release_buffer(&min_status, &send_tok); - packet_send(); - packet_write_wait(); - - - /* - * If we've sent them data, they'd better be polite and - * reply. - */ - -next_packet: - /* - * We need to catch connection closing w/o error - * tokens or messages so we can tell the user - * _something_ more useful than "Connection - * closed by ..." - * - * We use a fatal cleanup function as that's - * all, really, that we can do for now. - */ - fatal_add_cleanup(kexgss_verbose_cleanup, NULL); - type = packet_read(); - fatal_remove_cleanup(kexgss_verbose_cleanup, NULL); - switch (type) { - case SSH2_MSG_KEXGSS_HOSTKEY: - debug("Received KEXGSS_HOSTKEY"); - server_host_key_blob = - packet_get_string(&sbloblen); - server_host_key = - key_from_blob(server_host_key_blob, - sbloblen); - goto next_packet; /* there MUSt be another */ - break; - case SSH2_MSG_KEXGSS_CONTINUE: - debug("Received GSSAPI_CONTINUE"); - if (maj_status == GSS_S_COMPLETE) - packet_disconnect("Protocol error: " - "received GSS-API context token " - "though the context was already " - "established"); - recv_tok.value = packet_get_string(&strlen); - recv_tok.length = strlen; /* u_int vs. size_t */ - break; - case SSH2_MSG_KEXGSS_COMPLETE: - debug("Received GSSAPI_COMPLETE"); - packet_get_bignum2(dh_server_pub); - msg_tok.value = packet_get_string(&strlen); - msg_tok.length = strlen; /* u_int vs. size_t */ - - /* Is there a token included? */ - if (packet_get_char()) { - recv_tok.value = - packet_get_string(&strlen); - /* u_int/size_t */ - recv_tok.length = strlen; - } - if (recv_tok.length > 0 && - maj_status == GSS_S_COMPLETE) { - packet_disconnect("Protocol error: " - "received GSS-API context token " - "though the context was already " - "established"); - } else if (recv_tok.length == 0 && - maj_status == GSS_S_CONTINUE_NEEDED) { - /* No token included */ - packet_disconnect("Protocol error: " - "did not receive expected " - "GSS-API context token"); - } - break; - case SSH2_MSG_KEXGSS_ERROR: - smaj_status = packet_get_int(); - smin_status = packet_get_int(); - msg = packet_get_string(NULL); - lang = packet_get_string(NULL); - xfree(lang); - error("Server had a GSS-API error; the " - "connection will close (%d/%d):\n%s", - smaj_status, smin_status, msg); - error("Use the GssKeyEx option to disable " - "GSS-API key exchange and try again."); - packet_disconnect("The server had a GSS-API " - "error during GSS-API protected SSHv2 " - "key exchange\n"); - break; - default: - packet_disconnect("Protocol error: " - "didn't expect packet type %d", type); - } - if (recv_tok.value) - token_ptr = &recv_tok; - } else { - /* No data, and not complete */ - if (maj_status != GSS_S_COMPLETE) { - fatal("Not complete, and no token output"); - } - } - } while (maj_status == GSS_S_CONTINUE_NEEDED); - - /* - * We _must_ have received a COMPLETE message in reply from the - * server, which will have set dh_server_pub and msg_tok. - */ - if (type != SSH2_MSG_KEXGSS_COMPLETE) - fatal("Expected SSH2_MSG_KEXGSS_COMPLETE never arrived"); - if (maj_status != GSS_S_COMPLETE) - fatal("Internal error in GSS-API protected SSHv2 key exchange"); - - /* Check f in range [1, p-1] */ - if (!dh_pub_is_valid(dh, dh_server_pub)) - packet_disconnect("bad server public DH value"); - - /* compute K=f^x mod p */ - klen = DH_size(dh); - kbuf = xmalloc(klen); - kout = DH_compute_key(kbuf, dh_server_pub, dh); - - shared_secret = BN_new(); - BN_bin2bn(kbuf, kout, shared_secret); - (void) memset(kbuf, 0, klen); - xfree(kbuf); - - /* The GSS hash is identical to the DH one */ - hash = kex_dh_hash( - kex->client_version_string, - kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - server_host_key_blob, sbloblen, /* server host key */ - dh->pub_key, /* e */ - dh_server_pub, /* f */ - shared_secret); /* K */ - - gssbuf.value = hash; - gssbuf.length = 20; - - /* Verify that H matches the token we just got. */ - if ((maj_status = gss_verify_mic(&min_status, ctxt->context, &gssbuf, - &msg_tok, NULL))) { - packet_disconnect("Hash's MIC didn't verify"); - } - - if (server_host_key && kex->accept_host_key != NULL) - (void) kex->accept_host_key(server_host_key); - - DH_free(dh); - - xxx_gssctxt = ctxt; /* for gss keyex w/ mic userauth */ - - /* save session id */ - if (kex->session_id == NULL) { - kex->session_id_len = 20; - kex->session_id = xmalloc(kex->session_id_len); - (void) memcpy(kex->session_id, hash, kex->session_id_len); - } - - kex_derive_keys(kex, hash, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); -} - -/* ARGSUSED */ -static -void -kexgss_verbose_cleanup(void *arg) -{ - error("The GSS-API protected key exchange has failed without " - "indication\nfrom the server, possibly due to misconfiguration " - "of the server."); - error("Use the GssKeyEx option to disable GSS-API key exchange " - "and try again."); -} - -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/libssh/common/kexgsss.c b/usr/src/cmd/ssh/libssh/common/kexgsss.c deleted file mode 100644 index 9ee8b630bb..0000000000 --- a/usr/src/cmd/ssh/libssh/common/kexgsss.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#ifdef GSSAPI - -#include <openssl/crypto.h> -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "compat.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" -#include "ssh-gss.h" -#include "auth.h" - -Gssctxt *xxx_gssctxt; -extern Authctxt *x_authctxt; - -static void kex_gss_send_error(Gssctxt *ctxt); - -void -kexgss_server(Kex *kex) -{ - OM_uint32 maj_status, min_status; - gss_buffer_desc gssbuf, send_tok, recv_tok, msg_tok; - Gssctxt *ctxt = NULL; - unsigned int klen, kout; - unsigned int sbloblen = 0; - unsigned char *kbuf, *hash; - unsigned char *server_host_key_blob = NULL; - DH *dh; - Key *server_host_key = NULL; - BIGNUM *shared_secret = NULL; - BIGNUM *dh_client_pub = NULL; - int type = 0; - uint_t slen; - gss_OID oid; - - /* - * Load host key to advertise in a SSH_MSG_KEXGSS_HOSTKEY packet - * -- unlike KEX_DH/KEX_GEX no host key, no problem since it's - * the GSS-API that provides for server host authentication. - */ - if (kex->load_host_key != NULL && - !(datafellows & SSH_BUG_GSSKEX_HOSTKEY)) - server_host_key = kex->load_host_key(kex->hostkey_type); - if (server_host_key != NULL) - key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); - - - /* Initialise GSSAPI */ - - ssh_gssapi_oid_of_kexname(kex->name, &oid); - if (oid == GSS_C_NULL_OID) { - fatal("Couldn't match the negotiated GSS key exchange"); - } - - ssh_gssapi_build_ctx(&xxx_gssctxt, 0, oid); - - ctxt = xxx_gssctxt; - - do { - debug("Wait SSH2_MSG_GSSAPI_INIT"); - type = packet_read(); - switch (type) { - case SSH2_MSG_KEXGSS_INIT: - if (dh_client_pub != NULL) - fatal("Received KEXGSS_INIT after " - "initialising"); - recv_tok.value = packet_get_string(&slen); - recv_tok.length = slen; /* int vs. size_t */ - - dh_client_pub = BN_new(); - - if (dh_client_pub == NULL) - fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub); - - /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ - if (sbloblen) { - packet_start(SSH2_MSG_KEXGSS_HOSTKEY); - packet_put_string(server_host_key_blob, - sbloblen); - packet_send(); - packet_write_wait(); - } - break; - case SSH2_MSG_KEXGSS_CONTINUE: - recv_tok.value = packet_get_string(&slen); - recv_tok.length = slen; /* int vs. size_t */ - break; - default: - packet_disconnect("Protocol error: didn't expect " - "packet type %d", type); - } - - maj_status = ssh_gssapi_accept_ctx(ctxt, &recv_tok, &send_tok); - - xfree(recv_tok.value); /* We allocated this, not gss */ - - if (dh_client_pub == NULL) - fatal("No client public key"); - - if (maj_status == GSS_S_CONTINUE_NEEDED) { - debug("Sending GSSAPI_CONTINUE"); - packet_start(SSH2_MSG_KEXGSS_CONTINUE); - packet_put_string(send_tok.value, send_tok.length); - packet_send(); - packet_write_wait(); - (void) gss_release_buffer(&min_status, &send_tok); - } - } while (maj_status == GSS_S_CONTINUE_NEEDED); - - if (GSS_ERROR(maj_status)) { - kex_gss_send_error(ctxt); - if (send_tok.length > 0) { - packet_start(SSH2_MSG_KEXGSS_CONTINUE); - packet_put_string(send_tok.value, send_tok.length); - packet_send(); - packet_write_wait(); - (void) gss_release_buffer(&min_status, &send_tok); - } - fatal("accept_ctx died"); - } - - debug("gss_complete"); - if (!(ctxt->flags & GSS_C_MUTUAL_FLAG)) - fatal("Mutual authentication flag wasn't set"); - - if (!(ctxt->flags & GSS_C_INTEG_FLAG)) - fatal("Integrity flag wasn't set"); - - dh = dh_new_group1(); - dh_gen_key(dh, kex->we_need * 8); - - if (!dh_pub_is_valid(dh, dh_client_pub)) - packet_disconnect("bad client public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - kout = DH_compute_key(kbuf, dh_client_pub, dh); - - shared_secret = BN_new(); - BN_bin2bn(kbuf, kout, shared_secret); - (void) memset(kbuf, 0, klen); - xfree(kbuf); - - /* The GSSAPI hash is identical to the Diffie Helman one */ - hash = kex_dh_hash( - kex->client_version_string, - kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), - server_host_key_blob, sbloblen, - dh_client_pub, - dh->pub_key, - shared_secret); - - BN_free(dh_client_pub); - - if (kex->session_id == NULL) { - kex->session_id_len = 20; - kex->session_id = xmalloc(kex->session_id_len); - (void) memcpy(kex->session_id, hash, kex->session_id_len); - } else if (x_authctxt != NULL && x_authctxt->success) { - ssh_gssapi_storecreds(ctxt, x_authctxt); - } - - /* Should fix kex_dh_hash to output hash length */ - gssbuf.length = 20; /* yes, it's always 20 (SHA-1) */ - gssbuf.value = hash; /* and it's static constant storage */ - - if (GSS_ERROR(ssh_gssapi_get_mic(ctxt, &gssbuf, &msg_tok))) { - kex_gss_send_error(ctxt); - fatal("Couldn't get MIC"); - } - - packet_start(SSH2_MSG_KEXGSS_COMPLETE); - packet_put_bignum2(dh->pub_key); - packet_put_string((char *)msg_tok.value, msg_tok.length); - (void) gss_release_buffer(&min_status, &msg_tok); - - if (send_tok.length != 0) { - packet_put_char(1); /* true */ - packet_put_string((char *)send_tok.value, send_tok.length); - (void) gss_release_buffer(&min_status, &send_tok); - } else { - packet_put_char(0); /* false */ - } - packet_send(); - packet_write_wait(); - - DH_free(dh); - - kex_derive_keys(kex, hash, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); -} - -static void -kex_gss_send_error(Gssctxt *ctxt) { - char *errstr; - OM_uint32 maj, min; - - errstr = ssh_gssapi_last_error(ctxt, &maj, &min); - if (errstr) { - packet_start(SSH2_MSG_KEXGSS_ERROR); - packet_put_int(maj); - packet_put_int(min); - packet_put_cstring(errstr); - packet_put_cstring(""); - packet_send(); - packet_write_wait(); - /* XXX - We should probably log the error locally here */ - xfree(errstr); - } -} -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/libssh/common/key.c b/usr/src/cmd/ssh/libssh/common/key.c deleted file mode 100644 index f648d3b640..0000000000 --- a/usr/src/cmd/ssh/libssh/common/key.c +++ /dev/null @@ -1,876 +0,0 @@ -/* - * read_bignum(): - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: key.c,v 1.49 2002/09/09 14:54:14 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/evp.h> - -#include "xmalloc.h" -#include "key.h" -#include "rsa.h" -#include "ssh-dss.h" -#include "ssh-rsa.h" -#include "uuencode.h" -#include "buffer.h" -#include "bufaux.h" -#include "log.h" - -Key * -key_new(int type) -{ - Key *k; - RSA *rsa; - DSA *dsa; - k = xmalloc(sizeof(*k)); - k->type = type; - k->flags = 0; - k->dsa = NULL; - k->rsa = NULL; - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if ((rsa = RSA_new()) == NULL) - fatal("key_new: RSA_new failed"); - if ((rsa->n = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((rsa->e = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - k->rsa = rsa; - break; - case KEY_DSA: - if ((dsa = DSA_new()) == NULL) - fatal("key_new: DSA_new failed"); - if ((dsa->p = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->q = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->g = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->pub_key = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - k->dsa = dsa; - break; - case KEY_UNSPEC: - break; - default: - fatal("key_new: bad key type %d", k->type); - break; - } - return k; -} - -Key * -key_new_private(int type) -{ - Key *k = key_new(type); - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if ((k->rsa->d = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->iqmp = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->q = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->p = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->dmq1 = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->dmp1 = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - break; - case KEY_DSA: - if ((k->dsa->priv_key = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - break; - case KEY_UNSPEC: - break; - default: - break; - } - return k; -} - -void -key_free(Key *k) -{ - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if (k->rsa != NULL) - RSA_free(k->rsa); - k->rsa = NULL; - break; - case KEY_DSA: - if (k->dsa != NULL) - DSA_free(k->dsa); - k->dsa = NULL; - break; - case KEY_UNSPEC: - break; - default: - fatal("key_free: bad key type %d", k->type); - break; - } - xfree(k); -} -int -key_equal(const Key *a, const Key *b) -{ - if (a == NULL || b == NULL || a->type != b->type) - return 0; - switch (a->type) { - case KEY_RSA1: - case KEY_RSA: - return a->rsa != NULL && b->rsa != NULL && - BN_cmp(a->rsa->e, b->rsa->e) == 0 && - BN_cmp(a->rsa->n, b->rsa->n) == 0; - break; - case KEY_DSA: - return a->dsa != NULL && b->dsa != NULL && - BN_cmp(a->dsa->p, b->dsa->p) == 0 && - BN_cmp(a->dsa->q, b->dsa->q) == 0 && - BN_cmp(a->dsa->g, b->dsa->g) == 0 && - BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; - break; - default: - fatal("key_equal: bad key type %d", a->type); - break; - } - return 0; -} - -static u_char * -key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) -{ - const EVP_MD *md = NULL; - EVP_MD_CTX ctx; - u_char *blob = NULL; - u_char *retval = NULL; - u_int len = 0; - int nlen, elen; - - *dgst_raw_length = 0; - - switch (dgst_type) { - case SSH_FP_MD5: - md = EVP_md5(); - break; - case SSH_FP_SHA1: - md = EVP_sha1(); - break; - default: - fatal("key_fingerprint_raw: bad digest type %d", - dgst_type); - } - switch (k->type) { - case KEY_RSA1: - nlen = BN_num_bytes(k->rsa->n); - elen = BN_num_bytes(k->rsa->e); - len = nlen + elen; - blob = xmalloc(len); - BN_bn2bin(k->rsa->n, blob); - BN_bn2bin(k->rsa->e, blob + nlen); - break; - case KEY_DSA: - case KEY_RSA: - key_to_blob(k, &blob, &len); - break; - case KEY_UNSPEC: - return retval; - break; - default: - fatal("key_fingerprint_raw: bad key type %d", k->type); - break; - } - if (blob != NULL) { - retval = xmalloc(EVP_MAX_MD_SIZE); - EVP_DigestInit(&ctx, md); - EVP_DigestUpdate(&ctx, blob, len); - EVP_DigestFinal(&ctx, retval, dgst_raw_length); - memset(blob, 0, len); - xfree(blob); - } else { - fatal("key_fingerprint_raw: blob is null"); - } - return retval; -} - -static char * -key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len) -{ - char *retval; - int i; - - retval = xmalloc(dgst_raw_len * 3 + 1); - retval[0] = '\0'; - for (i = 0; i < dgst_raw_len; i++) { - char hex[4]; - snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); - strlcat(retval, hex, dgst_raw_len * 3); - } - retval[(dgst_raw_len * 3) - 1] = '\0'; - return retval; -} - -static char * -key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len) -{ - char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; - char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', - 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; - u_int i, j = 0, rounds, seed = 1; - char *retval; - - rounds = (dgst_raw_len / 2) + 1; - retval = xmalloc(sizeof(char) * (rounds*6)); - retval[j++] = 'x'; - for (i = 0; i < rounds; i++) { - u_int idx0, idx1, idx2, idx3, idx4; - if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { - idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + - seed) % 6; - idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; - idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + - (seed / 6)) % 6; - retval[j++] = vowels[idx0]; - retval[j++] = consonants[idx1]; - retval[j++] = vowels[idx2]; - if ((i + 1) < rounds) { - idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; - idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; - retval[j++] = consonants[idx3]; - retval[j++] = '-'; - retval[j++] = consonants[idx4]; - seed = ((seed * 5) + - ((((u_int)(dgst_raw[2 * i])) * 7) + - ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; - } - } else { - idx0 = seed % 6; - idx1 = 16; - idx2 = seed / 6; - retval[j++] = vowels[idx0]; - retval[j++] = consonants[idx1]; - retval[j++] = vowels[idx2]; - } - } - retval[j++] = 'x'; - retval[j++] = '\0'; - return retval; -} - -char * -key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) -{ - char *retval = NULL; - u_char *dgst_raw; - u_int dgst_raw_len; - - dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); - if (!dgst_raw) - fatal("key_fingerprint: null from key_fingerprint_raw()"); - switch (dgst_rep) { - case SSH_FP_HEX: - retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); - break; - case SSH_FP_BUBBLEBABBLE: - retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); - break; - default: - fatal("key_fingerprint_ex: bad digest representation %d", - dgst_rep); - break; - } - memset(dgst_raw, 0, dgst_raw_len); - xfree(dgst_raw); - return retval; -} - -/* - * Reads a multiple-precision integer in decimal from the buffer, and advances - * the pointer. The integer must already be initialized. This function is - * permitted to modify the buffer. This leaves *cpp to point just beyond the - * last processed (and maybe modified) character. Note that this may modify - * the buffer containing the number. - */ -static int -read_bignum(char **cpp, BIGNUM * value) -{ - char *cp = *cpp; - int old; - - /* Skip any leading whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - - /* Check that it begins with a decimal digit. */ - if (*cp < '0' || *cp > '9') - return 0; - - /* Save starting position. */ - *cpp = cp; - - /* Move forward until all decimal digits skipped. */ - for (; *cp >= '0' && *cp <= '9'; cp++) - ; - - /* Save the old terminating character, and replace it by \0. */ - old = *cp; - *cp = 0; - - /* Parse the number. */ - if (BN_dec2bn(&value, *cpp) == 0) - return 0; - - /* Restore old terminating character. */ - *cp = old; - - /* Move beyond the number and return success. */ - *cpp = cp; - return 1; -} - -static int -write_bignum(FILE *f, BIGNUM *num) -{ - char *buf = BN_bn2dec(num); - if (buf == NULL) { - error("write_bignum: BN_bn2dec() failed"); - return 0; - } - fprintf(f, " %s", buf); - OPENSSL_free(buf); - return 1; -} - -/* returns 1 ok, -1 error */ -int -key_read(Key *ret, char **cpp) -{ - Key *k; - int success = -1; - char *cp, *space; - int len, n, type; - u_int bits; - u_char *blob; - - cp = *cpp; - - switch (ret->type) { - case KEY_RSA1: - /* Get number of bits. */ - if (*cp < '0' || *cp > '9') - return -1; /* Bad bit count... */ - for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) - bits = 10 * bits + *cp - '0'; - if (bits == 0) - return -1; - *cpp = cp; - /* Get public exponent, public modulus. */ - if (!read_bignum(cpp, ret->rsa->e)) - return -1; - if (!read_bignum(cpp, ret->rsa->n)) - return -1; - success = 1; - break; - case KEY_UNSPEC: - case KEY_RSA: - case KEY_DSA: - space = strchr(cp, ' '); - if (space == NULL) { - debug3("key_read: no space"); - return -1; - } - *space = '\0'; - type = key_type_from_name(cp); - *space = ' '; - if (type == KEY_UNSPEC) { - debug3("key_read: no key found"); - return -1; - } - cp = space+1; - if (*cp == '\0') { - debug3("key_read: short string"); - return -1; - } - if (ret->type == KEY_UNSPEC) { - ret->type = type; - } else if (ret->type != type) { - /* is a key, but different type */ - debug3("key_read: type mismatch"); - return -1; - } - len = 2*strlen(cp); - blob = xmalloc(len); - n = uudecode(cp, blob, len); - if (n < 0) { - error("key_read: uudecode %s failed", cp); - xfree(blob); - return -1; - } - k = key_from_blob(blob, n); - xfree(blob); - if (k == NULL) { - error("key_read: key_from_blob %s failed", cp); - return -1; - } - if (k->type != type) { - error("key_read: type mismatch: encoding error"); - key_free(k); - return -1; - } -/*XXXX*/ - if (ret->type == KEY_RSA) { - if (ret->rsa != NULL) - RSA_free(ret->rsa); - ret->rsa = k->rsa; - k->rsa = NULL; - success = 1; -#ifdef DEBUG_PK - RSA_print_fp(stderr, ret->rsa, 8); -#endif - } else { - if (ret->dsa != NULL) - DSA_free(ret->dsa); - ret->dsa = k->dsa; - k->dsa = NULL; - success = 1; -#ifdef DEBUG_PK - DSA_print_fp(stderr, ret->dsa, 8); -#endif - } -/*XXXX*/ - key_free(k); - if (success != 1) - break; - /* advance cp: skip whitespace and data */ - while (*cp == ' ' || *cp == '\t') - cp++; - while (*cp != '\0' && *cp != ' ' && *cp != '\t') - cp++; - *cpp = cp; - break; - default: - fatal("key_read: bad key type: %d", ret->type); - break; - } - return success; -} - -int -key_write(const Key *key, FILE *f) -{ - int n, success = 0; - u_int len, bits = 0; - u_char *blob; - char *uu; - - if (key->type == KEY_RSA1 && key->rsa != NULL) { - /* size of modulus 'n' */ - bits = BN_num_bits(key->rsa->n); - fprintf(f, "%u", bits); - if (write_bignum(f, key->rsa->e) && - write_bignum(f, key->rsa->n)) { - success = 1; - } else { - error("key_write: failed for RSA key"); - } - } else if ((key->type == KEY_DSA && key->dsa != NULL) || - (key->type == KEY_RSA && key->rsa != NULL)) { - key_to_blob(key, &blob, &len); - uu = xmalloc(2*len); - n = uuencode(blob, len, uu, 2*len); - if (n > 0) { - fprintf(f, "%s %s", key_ssh_name(key), uu); - success = 1; - } - xfree(blob); - xfree(uu); - } - return success; -} - -char * -key_type(Key *k) -{ - switch (k->type) { - case KEY_RSA1: - return "RSA1"; - break; - case KEY_RSA: - return "RSA"; - break; - case KEY_DSA: - return "DSA"; - break; - } - return "unknown"; -} - -char * -key_ssh_name(const Key *k) -{ - switch (k->type) { - case KEY_RSA: - return "ssh-rsa"; - break; - case KEY_DSA: - return "ssh-dss"; - break; - } - return "ssh-unknown"; -} - -u_int -key_size(Key *k) -{ - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - return BN_num_bits(k->rsa->n); - break; - case KEY_DSA: - return BN_num_bits(k->dsa->p); - break; - } - return 0; -} - -static RSA * -rsa_generate_private_key(u_int bits) -{ - RSA *private; - private = RSA_generate_key(bits, 35, NULL, NULL); - if (private == NULL) - fatal("rsa_generate_private_key: key generation failed."); - return private; -} - -static DSA* -dsa_generate_private_key(u_int bits) -{ - DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); - if (private == NULL) - fatal("dsa_generate_private_key: DSA_generate_parameters failed"); - if (!DSA_generate_key(private)) - fatal("dsa_generate_private_key: DSA_generate_key failed."); - if (private == NULL) - fatal("dsa_generate_private_key: NULL."); - return private; -} - -Key * -key_generate(int type, u_int bits) -{ - Key *k = key_new(KEY_UNSPEC); - switch (type) { - case KEY_DSA: - k->dsa = dsa_generate_private_key(bits); - break; - case KEY_RSA: - case KEY_RSA1: - k->rsa = rsa_generate_private_key(bits); - break; - default: - fatal("key_generate: unknown type %d", type); - } - k->type = type; - return k; -} - -Key * -key_from_private(Key *k) -{ - Key *n = NULL; - switch (k->type) { - case KEY_DSA: - n = key_new(k->type); - BN_copy(n->dsa->p, k->dsa->p); - BN_copy(n->dsa->q, k->dsa->q); - BN_copy(n->dsa->g, k->dsa->g); - BN_copy(n->dsa->pub_key, k->dsa->pub_key); - break; - case KEY_RSA: - case KEY_RSA1: - n = key_new(k->type); - BN_copy(n->rsa->n, k->rsa->n); - BN_copy(n->rsa->e, k->rsa->e); - break; - default: - fatal("key_from_private: unknown type %d", k->type); - break; - } - return n; -} - -int -key_type_from_name(char *name) -{ - if (strcmp(name, "rsa1") == 0) { - return KEY_RSA1; - } else if (strcmp(name, "rsa") == 0) { - return KEY_RSA; - } else if (strcmp(name, "dsa") == 0) { - return KEY_DSA; - } else if (strcmp(name, "ssh-rsa") == 0) { - return KEY_RSA; - } else if (strcmp(name, "ssh-dss") == 0) { - return KEY_DSA; - } else if (strcmp(name, "null") == 0){ - return KEY_NULL; - } - debug2("key_type_from_name: unknown key type '%s'", name); - return KEY_UNSPEC; -} - -int -key_names_valid2(const char *names) -{ - char *s, *cp, *p; - - if (names == NULL || strcmp(names, "") == 0) - return 0; - s = cp = xstrdup(names); - for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { - switch (key_type_from_name(p)) { - case KEY_RSA1: - case KEY_UNSPEC: - xfree(s); - return 0; - } - } - debug3("key names ok: [%s]", names); - xfree(s); - return 1; -} - -Key * -key_from_blob(u_char *blob, int blen) -{ - Buffer b; - char *ktype; - int rlen, type; - Key *key = NULL; - -#ifdef DEBUG_PK - dump_base64(stderr, blob, blen); -#endif - buffer_init(&b); - buffer_append(&b, blob, blen); - if ((ktype = buffer_get_string_ret(&b, NULL)) == NULL) { - error("key_from_blob: can't read key type"); - goto out; - } - - type = key_type_from_name(ktype); - - switch (type) { - case KEY_RSA: - key = key_new(type); - if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || - buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { - error("key_from_blob: can't read rsa key"); - key_free(key); - key = NULL; - goto out; - } -#ifdef DEBUG_PK - RSA_print_fp(stderr, key->rsa, 8); -#endif - break; - case KEY_DSA: - key = key_new(type); - if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { - error("key_from_blob: can't read dsa key"); - key_free(key); - key = NULL; - goto out; - } -#ifdef DEBUG_PK - DSA_print_fp(stderr, key->dsa, 8); -#endif - break; - case KEY_UNSPEC: - key = key_new(type); - break; - default: - error("key_from_blob: cannot handle type %s", ktype); - goto out; - } - rlen = buffer_len(&b); - if (key != NULL && rlen != 0) - error("key_from_blob: remaining bytes in key blob %d", rlen); - out: - if (ktype != NULL) - xfree(ktype); - buffer_free(&b); - return key; -} - -int -key_to_blob(const Key *key, u_char **blobp, u_int *lenp) -{ - Buffer b; - int len; - - if (key == NULL) { - error("key_to_blob: key == NULL"); - return 0; - } - buffer_init(&b); - switch (key->type) { - case KEY_DSA: - buffer_put_cstring(&b, key_ssh_name(key)); - buffer_put_bignum2(&b, key->dsa->p); - buffer_put_bignum2(&b, key->dsa->q); - buffer_put_bignum2(&b, key->dsa->g); - buffer_put_bignum2(&b, key->dsa->pub_key); - break; - case KEY_RSA: - buffer_put_cstring(&b, key_ssh_name(key)); - buffer_put_bignum2(&b, key->rsa->e); - buffer_put_bignum2(&b, key->rsa->n); - break; - default: - error("key_to_blob: unsupported key type %d", key->type); - buffer_free(&b); - return 0; - } - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; - if (blobp != NULL) { - *blobp = xmalloc(len); - memcpy(*blobp, buffer_ptr(&b), len); - } - memset(buffer_ptr(&b), 0, len); - buffer_free(&b); - return len; -} - -int -key_sign( - Key *key, - u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - switch (key->type) { - case KEY_DSA: - return ssh_dss_sign(key, sigp, lenp, data, datalen); - break; - case KEY_RSA: - return ssh_rsa_sign(key, sigp, lenp, data, datalen); - break; - default: - error("key_sign: illegal key type %d", key->type); - return -1; - break; - } -} - -/* - * key_verify returns 1 for a correct signature, 0 for an incorrect signature - * and -1 on error. - */ -int -key_verify( - Key *key, - u_char *signature, u_int signaturelen, - u_char *data, u_int datalen) -{ - if (signaturelen == 0) - return -1; - - switch (key->type) { - case KEY_DSA: - return ssh_dss_verify(key, signature, signaturelen, data, datalen); - break; - case KEY_RSA: - return ssh_rsa_verify(key, signature, signaturelen, data, datalen); - break; - default: - error("key_verify: illegal key type %d", key->type); - return -1; - break; - } -} - -/* Converts a private to a public key */ -Key * -key_demote(Key *k) -{ - Key *pk; - - pk = xmalloc(sizeof(*pk)); - pk->type = k->type; - pk->flags = k->flags; - pk->dsa = NULL; - pk->rsa = NULL; - - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if ((pk->rsa = RSA_new()) == NULL) - fatal("key_demote: RSA_new failed"); - if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) - fatal("key_demote: BN_dup failed"); - break; - case KEY_DSA: - if ((pk->dsa = DSA_new()) == NULL) - fatal("key_demote: DSA_new failed"); - if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) - fatal("key_demote: BN_dup failed"); - break; - default: - fatal("key_free: bad key type %d", k->type); - break; - } - - return (pk); -} diff --git a/usr/src/cmd/ssh/libssh/common/llib-lssh b/usr/src/cmd/ssh/libssh/common/llib-lssh deleted file mode 100644 index c44090abe6..0000000000 --- a/usr/src/cmd/ssh/libssh/common/llib-lssh +++ /dev/null @@ -1,130 +0,0 @@ -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -/* - * 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 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <includes.h> -#include <ssh.h> -#include <atomicio.h> -#include <auth.h> -#include <auth-pam.h> -#include <auth2-pam.h> -#include <authfd.h> -#include <authfile.h> -#include <auth-options.h> -#include <base64.h> -#include <bindresvport.h> -#include <bsd-arc4random.h> -#include <bsd-cray.h> -#include <bsd-cygwin_util.h> -#include <bsd-getpeereid.h> -#include <bsd-misc.h> -#include <bsd-snprintf.h> -#include <bsd-waitpid.h> -#include <bufaux.h> -#include <buffer.h> -#include <canohost.h> -#include <channels.h> -#include <cipher.h> -#include <clientloop.h> -#include <compat.h> -#include <compress.h> -#include <config.h> -#include <crc32.h> -#include <deattack.h> -#include <defines.h> -#include <dh.h> -#include <dirname.h> -#include <dispatch.h> -#include <entropy.h> -#include <fake-gai-errnos.h> -#include <fake-getaddrinfo.h> -#include <fake-getnameinfo.h> -#include <fake-socket.h> -#include <g11n.h> -#include <getcwd.h> -#include <getgrouplist.h> -#include <getopt.h> -#include <getput.h> -#include <glob.h> -#include <groupaccess.h> -#include <hostfile.h> -#include <inet_ntoa.h> -#include <inet_ntop.h> -#include <kex.h> -#include <key.h> -#include <log.h> -#include <loginrec.h> -#include <mac.h> -#include <match.h> -#include <misc.h> -#include <mktemp.h> -#include <mpaux.h> -#include <msg.h> -#include <myproposal.h> -#include <openbsd-compat.h> -#include <packet.h> -#include <pathnames.h> -#include <port-aix.h> -#include <port-irix.h> -#include <proxy-io.h> -#include <readconf.h> -#include <readpass.h> -#include <readpassphrase.h> -#include <realpath.h> -#include <rresvport.h> -#include <rsa.h> -#include <servconf.h> -#include <serverloop.h> -#include <session.h> -#include <setproctitle.h> -#include <sftp-common.h> -#include <sftp.h> -#include <sftp-client.h> -#include <sigact.h> -#include <ssh1.h> -#include <ssh2.h> -#include <sshconnect.h> -#include <ssh-dss.h> -#include <sshlogin.h> -#include <sshpty.h> -#include <ssh-rsa.h> -#include <sshtty.h> -#include <strlcat.h> -#include <strlcpy.h> -#include <strmode.h> -#include <sys-queue.h> -#include <sys-tree.h> -#include <tildexpand.h> -#include <uidswap.h> -#include <uuencode.h> -#include <version.h> -#include <xlist.h> -#include <xmalloc.h> -#include <xmmap.h> - -extern uid_t original_real_uid; -extern char *__progname; - diff --git a/usr/src/cmd/ssh/libssh/common/log.c b/usr/src/cmd/ssh/libssh/common/log.c deleted file mode 100644 index 79e4cace6e..0000000000 --- a/usr/src/cmd/ssh/libssh/common/log.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: log.c,v 1.24 2002/07/19 15:43:33 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "log.h" -#include "xmalloc.h" - -#include <atomic.h> -#include <syslog.h> - -static LogLevel log_level = SYSLOG_LEVEL_INFO; -static int log_on_stderr = 1; -static int log_facility = LOG_AUTH; -static char *argv0; - -extern char *__progname; - -static const char *log_txt_prefix = ""; - -/* textual representation of log-facilities/levels */ - -static struct { - const char *name; - SyslogFacility val; -} log_facilities[] = { - { "DAEMON", SYSLOG_FACILITY_DAEMON }, - { "USER", SYSLOG_FACILITY_USER }, - { "AUTH", SYSLOG_FACILITY_AUTH }, -#ifdef LOG_AUTHPRIV - { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, -#endif - { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, - { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, - { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, - { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, - { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, - { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, - { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, - { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, - { NULL, SYSLOG_FACILITY_NOT_SET } -}; - -static struct { - const char *name; - LogLevel val; -} log_levels[] = -{ - { "QUIET", SYSLOG_LEVEL_QUIET }, - { "FATAL", SYSLOG_LEVEL_FATAL }, - { "ERROR", SYSLOG_LEVEL_ERROR }, - { "NOTICE", SYSLOG_LEVEL_NOTICE }, - { "INFO", SYSLOG_LEVEL_INFO }, - { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, - { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, - { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, - { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, - { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, - { NULL, SYSLOG_LEVEL_NOT_SET } -}; - -SyslogFacility -log_facility_number(char *name) -{ - int i; - - if (name != NULL) - for (i = 0; log_facilities[i].name; i++) - if (strcasecmp(log_facilities[i].name, name) == 0) - return log_facilities[i].val; - return SYSLOG_FACILITY_NOT_SET; -} - -LogLevel -log_level_number(char *name) -{ - int i; - - if (name != NULL) - for (i = 0; log_levels[i].name; i++) - if (strcasecmp(log_levels[i].name, name) == 0) - return log_levels[i].val; - return SYSLOG_LEVEL_NOT_SET; -} - -void -set_log_txt_prefix(const char *txt) -{ - log_txt_prefix = txt; -} - -/* Error messages that should be logged. */ - -void -error(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_ERROR, fmt, args); - va_end(args); -} - -void -notice(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_NOTICE, fmt, args); - va_end(args); -} - -/* Log this message (information that usually should go to the log). */ - -void -log(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_INFO, fmt, args); - va_end(args); -} - -/* More detailed messages (information that does not need to go to the log). */ - -void -verbose(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); - va_end(args); -} - -/* Debugging messages that should not be logged during normal operation. */ - -void -debug(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); - va_end(args); -} - -void -debug2(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); - va_end(args); -} - -void -debug3(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); - va_end(args); -} - -/* Fatal cleanup */ - -struct fatal_cleanup { - struct fatal_cleanup *next; - void (*proc) (void *); - void *context; -}; - -static struct fatal_cleanup *fatal_cleanups = NULL; - -/* Registers a cleanup function to be called by fatal() before exiting. */ - -void -fatal_add_cleanup(void (*proc) (void *), void *context) -{ - struct fatal_cleanup *cu; - - cu = xmalloc(sizeof(*cu)); - cu->proc = proc; - cu->context = context; - cu->next = fatal_cleanups; - fatal_cleanups = cu; -} - -/* Removes a cleanup function to be called at fatal(). */ - -void -fatal_remove_cleanup(void (*proc) (void *context), void *context) -{ - struct fatal_cleanup **cup, *cu; - - for (cup = &fatal_cleanups; *cup; cup = &cu->next) { - cu = *cup; - if (cu->proc == proc && cu->context == context) { - *cup = cu->next; - xfree(cu); - return; - } - } - debug3("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx", - (u_long) proc, (u_long) context); -} - -/* Remove all cleanups, to be called after fork() */ -void -fatal_remove_all_cleanups(void) -{ - struct fatal_cleanup *cu, *next_cu; - - for (cu = fatal_cleanups; cu; cu = next_cu) { - next_cu = cu->next; - xfree(cu); - } - - fatal_cleanups = NULL; -} - -/* Cleanup and exit. Make sure each cleanup is called only once. */ -void -fatal_cleanup(void) -{ - struct fatal_cleanup *cu, *next_cu; - static volatile u_int called = 0; - - if (atomic_cas_uint(&called, 0, 1) == 1) - exit(255); - /* Call cleanup functions. */ - for (cu = fatal_cleanups; cu; cu = next_cu) { - next_cu = cu->next; - debug("Calling cleanup 0x%lx(0x%lx)", - (u_long) cu->proc, (u_long) cu->context); - (*cu->proc) (cu->context); - } - exit(255); -} - - -/* - * Initialize the log. - */ - -void -log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) -{ - argv0 = av0; - - switch (level) { - case SYSLOG_LEVEL_QUIET: - case SYSLOG_LEVEL_FATAL: - case SYSLOG_LEVEL_ERROR: - case SYSLOG_LEVEL_NOTICE: - case SYSLOG_LEVEL_INFO: - case SYSLOG_LEVEL_VERBOSE: - case SYSLOG_LEVEL_DEBUG1: - case SYSLOG_LEVEL_DEBUG2: - case SYSLOG_LEVEL_DEBUG3: - log_level = level; - break; - default: - fprintf(stderr, "Unrecognized internal syslog level code %d\n", - (int) level); - exit(1); - } - - log_on_stderr = on_stderr; - if (on_stderr) - return; - - switch (facility) { - case SYSLOG_FACILITY_DAEMON: - log_facility = LOG_DAEMON; - break; - case SYSLOG_FACILITY_USER: - log_facility = LOG_USER; - break; - case SYSLOG_FACILITY_AUTH: - log_facility = LOG_AUTH; - break; -#ifdef LOG_AUTHPRIV - case SYSLOG_FACILITY_AUTHPRIV: - log_facility = LOG_AUTHPRIV; - break; -#endif - case SYSLOG_FACILITY_LOCAL0: - log_facility = LOG_LOCAL0; - break; - case SYSLOG_FACILITY_LOCAL1: - log_facility = LOG_LOCAL1; - break; - case SYSLOG_FACILITY_LOCAL2: - log_facility = LOG_LOCAL2; - break; - case SYSLOG_FACILITY_LOCAL3: - log_facility = LOG_LOCAL3; - break; - case SYSLOG_FACILITY_LOCAL4: - log_facility = LOG_LOCAL4; - break; - case SYSLOG_FACILITY_LOCAL5: - log_facility = LOG_LOCAL5; - break; - case SYSLOG_FACILITY_LOCAL6: - log_facility = LOG_LOCAL6; - break; - case SYSLOG_FACILITY_LOCAL7: - log_facility = LOG_LOCAL7; - break; - default: - fprintf(stderr, - "Unrecognized internal syslog facility code %d\n", - (int) facility); - exit(1); - } -} - -#define MSGBUFSIZ 1024 - -/* PRINTFLIKE2 */ -void -do_log(LogLevel level, const char *fmt, va_list args) -{ - char msgbuf[MSGBUFSIZ]; - char fmtbuf[MSGBUFSIZ]; - char *txt = NULL; - int pri = LOG_INFO; - int do_gettext = log_on_stderr; /* - * Localize user messages - not - * syslog()ed messages. - */ - - if (level > log_level) - return; - - switch (level) { - case SYSLOG_LEVEL_FATAL: - if (!log_on_stderr) - txt = "fatal"; - pri = LOG_CRIT; - break; - case SYSLOG_LEVEL_ERROR: - if (!log_on_stderr) - txt = "error"; - pri = LOG_ERR; - break; - case SYSLOG_LEVEL_NOTICE: - pri = LOG_NOTICE; - break; - case SYSLOG_LEVEL_INFO: - pri = LOG_INFO; - break; - case SYSLOG_LEVEL_VERBOSE: - pri = LOG_INFO; - break; - case SYSLOG_LEVEL_DEBUG1: - txt = "debug1"; - pri = LOG_DEBUG; - /* - * Don't localize debug messages - such are not intended - * for users but for support staff whose preferred - * language is unknown, therefore we default to the - * language used in the source code: English. - */ - do_gettext = 0; - break; - case SYSLOG_LEVEL_DEBUG2: - txt = "debug2"; - pri = LOG_DEBUG; - do_gettext = 0; /* Don't localize debug messages. */ - break; - case SYSLOG_LEVEL_DEBUG3: - txt = "debug3"; - pri = LOG_DEBUG; - do_gettext = 0; /* Don't localize debug messages. */ - break; - default: - txt = "internal error"; - pri = LOG_ERR; - break; - } - if (txt != NULL) { - snprintf(fmtbuf, sizeof(fmtbuf), "%s%s: %s", log_txt_prefix, - do_gettext ? gettext(txt) : txt, - do_gettext ? gettext(fmt) : fmt); - vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); - } else { - vsnprintf(msgbuf, sizeof(msgbuf), - do_gettext ? gettext(fmt) : fmt, - args); - } - if (log_on_stderr) { - fprintf(stderr, "%s\r\n", msgbuf); - } else { - openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); - syslog(pri, "%.500s", msgbuf); - closelog(); - } -} diff --git a/usr/src/cmd/ssh/libssh/common/mac.c b/usr/src/cmd/ssh/libssh/common/mac.c deleted file mode 100644 index e25f5eb95d..0000000000 --- a/usr/src/cmd/ssh/libssh/common/mac.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: mac.c,v 1.5 2002/05/16 22:02:50 markus Exp $"); - -#include <openssl/hmac.h> - -#include "xmalloc.h" -#include "getput.h" -#include "log.h" -#include "cipher.h" -#include "kex.h" -#include "mac.h" -#include "misc.h" - -#define SSH_EVP 1 /* OpenSSL EVP-based MAC */ - -struct { - char *name; - int type; - const EVP_MD * (*mdfunc)(void); - int truncatebits; /* truncate digest if != 0 */ - int key_len; /* will be used if we have UMAC */ -} macs[] = { - { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1 }, - { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1 }, - { "hmac-md5", SSH_EVP, EVP_md5, 0, -1 }, - { "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1 }, -#ifdef SOLARIS_SSH_ENABLE_RIPEMD160 - { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1 }, - { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, -1 }, -#endif /* SOLARIS_SSH_ENABLE_RIPEMD160 */ - { NULL, 0, NULL, 0, -1 } -}; - -static void -mac_setup_by_id(Mac *mac, int which) -{ - int evp_len; - mac->type = macs[which].type; - if (mac->type == SSH_EVP) { - mac->evp_md = (*macs[which].mdfunc)(); - if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0) - fatal("mac %s len %d", mac->name, evp_len); - mac->key_len = mac->mac_len = (u_int)evp_len; - } else - fatal("wrong MAC type (%d)", mac->type); - if (macs[which].truncatebits != 0) - mac->mac_len = macs[which].truncatebits / 8; -} - -int -mac_setup(Mac *mac, char *name) -{ - int i; - - for (i = 0; macs[i].name; i++) { - if (strcmp(name, macs[i].name) == 0) { - if (mac != NULL) - mac_setup_by_id(mac, i); - debug2("mac_setup: found %s", name); - return (0); - } - } - debug2("mac_setup: unknown %s", name); - return (-1); -} - -int -mac_init(Mac *mac) -{ - if (mac->key == NULL) - fatal("mac_init: no key"); - switch (mac->type) { - case SSH_EVP: - if (mac->evp_md == NULL) - return -1; - HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md); - return 0; - default: - return -1; - } -} - -u_char * -mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) -{ - static u_char m[EVP_MAX_MD_SIZE]; - u_char b[4]; - - if (mac->mac_len > sizeof(m)) - fatal("mac_compute: mac too long %u %lu", - mac->mac_len, (u_long)sizeof(m)); - - switch (mac->type) { - case SSH_EVP: - put_u32(b, seqno); - /* reset HMAC context */ - HMAC_Init(&mac->evp_ctx, NULL, 0, NULL); - HMAC_Update(&mac->evp_ctx, b, sizeof(b)); - HMAC_Update(&mac->evp_ctx, data, datalen); - HMAC_Final(&mac->evp_ctx, m, NULL); - break; - default: - fatal("mac_compute: unknown MAC type"); - } - - return (m); -} - -void -mac_clear(Mac *mac) -{ - if (mac->evp_md != NULL) - HMAC_cleanup(&mac->evp_ctx); - mac->evp_md = NULL; -} - -/* XXX copied from ciphers_valid */ -#define MAC_SEP "," -int -mac_valid(const char *names) -{ - char *maclist, *cp, *p; - - if (names == NULL || strcmp(names, "") == 0) - return (0); - maclist = cp = xstrdup(names); - for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; - (p = strsep(&cp, MAC_SEP))) { - if (mac_setup(NULL, p) < 0) { - debug("bad mac %s [%s]", p, names); - xfree(maclist); - return (0); - } else { - debug3("mac ok: %s [%s]", p, names); - } - } - debug3("macs ok: [%s]", names); - xfree(maclist); - return (1); -} diff --git a/usr/src/cmd/ssh/libssh/common/match.c b/usr/src/cmd/ssh/libssh/common/match.c deleted file mode 100644 index 4724d435e7..0000000000 --- a/usr/src/cmd/ssh/libssh/common/match.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Simple pattern matching, with '*' and '?' as wildcards. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: match.c,v 1.19 2002/03/01 13:12:10 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "match.h" -#include "xmalloc.h" - -/* - * Returns true if the given string matches the pattern (which may contain ? - * and * as wildcards), and zero if it does not match. - */ - -int -match_pattern(const char *s, const char *pattern) -{ - for (;;) { - /* If at end of pattern, accept if also at end of string. */ - if (!*pattern) - return !*s; - - if (*pattern == '*') { - /* Skip the asterisk. */ - pattern++; - - /* If at end of pattern, accept immediately. */ - if (!*pattern) - return 1; - - /* If next character in pattern is known, optimize. */ - if (*pattern != '?' && *pattern != '*') { - /* - * Look instances of the next character in - * pattern, and try to match starting from - * those. - */ - for (; *s; s++) - if (*s == *pattern && - match_pattern(s + 1, pattern + 1)) - return 1; - /* Failed. */ - return 0; - } - /* - * Move ahead one character at a time and try to - * match at each position. - */ - for (; *s; s++) - if (match_pattern(s, pattern)) - return 1; - /* Failed. */ - return 0; - } - /* - * There must be at least one more character in the string. - * If we are at the end, fail. - */ - if (!*s) - return 0; - - /* Check if the next character of the string is acceptable. */ - if (*pattern != '?' && *pattern != *s) - return 0; - - /* Move to the next character, both in string and in pattern. */ - s++; - pattern++; - } - /* NOTREACHED */ -} - -/* - * Tries to match the string against the - * comma-separated sequence of subpatterns (each possibly preceded by ! to - * indicate negation). Returns -1 if negation matches, 1 if there is - * a positive match, 0 if there is no match at all. - */ - -int -match_pattern_list(const char *string, const char *pattern, u_int len, - int dolower) -{ - char sub[1024]; - int negated; - int got_positive; - u_int i, subi; - - got_positive = 0; - for (i = 0; i < len;) { - /* Check if the subpattern is negated. */ - if (pattern[i] == '!') { - negated = 1; - i++; - } else - negated = 0; - - /* - * Extract the subpattern up to a comma or end. Convert the - * subpattern to lowercase. - */ - for (subi = 0; - i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; - subi++, i++) - sub[subi] = dolower && isupper(pattern[i]) ? - tolower(pattern[i]) : pattern[i]; - /* If subpattern too long, return failure (no match). */ - if (subi >= sizeof(sub) - 1) - return 0; - - /* If the subpattern was terminated by a comma, skip the comma. */ - if (i < len && pattern[i] == ',') - i++; - - /* Null-terminate the subpattern. */ - sub[subi] = '\0'; - - /* Try to match the subpattern against the string. */ - if (match_pattern(string, sub)) { - if (negated) - return -1; /* Negative */ - else - got_positive = 1; /* Positive */ - } - } - - /* - * Return success if got a positive match. If there was a negative - * match, we have already returned -1 and never get here. - */ - return got_positive; -} - -/* - * Tries to match the host name (which must be in all lowercase) against the - * comma-separated sequence of subpatterns (each possibly preceded by ! to - * indicate negation). Returns -1 if negation matches, 1 if there is - * a positive match, 0 if there is no match at all. - */ -int -match_hostname(const char *host, const char *pattern, u_int len) -{ - return match_pattern_list(host, pattern, len, 1); -} - -/* - * returns 0 if we get a negative match for the hostname or the ip - * or if we get no match at all. returns 1 otherwise. - */ -int -match_host_and_ip(const char *host, const char *ipaddr, - const char *patterns) -{ - int mhost, mip; - - /* negative ipaddr match */ - if ((mip = match_hostname(ipaddr, patterns, strlen(patterns))) == -1) - return 0; - /* negative hostname match */ - if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1) - return 0; - /* no match at all */ - if (mhost == 0 && mip == 0) - return 0; - return 1; -} - -/* - * match user, user@host_or_ip, user@host_or_ip_list against pattern - */ -int -match_user(const char *user, const char *host, const char *ipaddr, - const char *pattern) -{ - char *p, *pat; - int ret; - - if ((p = strchr(pattern,'@')) == NULL) - return match_pattern(user, pattern); - - pat = xstrdup(pattern); - p = strchr(pat, '@'); - *p++ = '\0'; - - if ((ret = match_pattern(user, pat)) == 1) - ret = match_host_and_ip(host, ipaddr, p); - xfree(pat); - - return ret; -} - -/* - * Returns first item from client-list that is also supported by server-list, - * caller must xfree() returned string. - */ -#define MAX_PROP 40 -#define SEP "," -char * -match_list(const char *client, const char *server, u_int *next) -{ - char *sproposals[MAX_PROP]; - char *c, *s, *p, *ret, *cp, *sp; - int i, j, nproposals; - - c = cp = xstrdup(client); - s = sp = xstrdup(server); - - for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0'; - (p = strsep(&sp, SEP)), i++) { - if (i < MAX_PROP) - sproposals[i] = p; - else - break; - } - nproposals = i; - - for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0'; - (p = strsep(&cp, SEP)), i++) { - for (j = 0; j < nproposals; j++) { - if (strcmp(p, sproposals[j]) == 0) { - ret = xstrdup(p); - if (next != NULL) - *next = (cp == NULL) ? - strlen(c) : cp - c; - xfree(c); - xfree(s); - return ret; - } - } - } - if (next != NULL) - *next = strlen(c); - xfree(c); - xfree(s); - return NULL; -} diff --git a/usr/src/cmd/ssh/libssh/common/misc.c b/usr/src/cmd/ssh/libssh/common/misc.c deleted file mode 100644 index e73d3f364b..0000000000 --- a/usr/src/cmd/ssh/libssh/common/misc.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $"); - -#include "misc.h" -#include "log.h" -#include "xmalloc.h" - -/* remove newline at end of string */ -char * -chop(char *s) -{ - char *t = s; - while (*t) { - if (*t == '\n' || *t == '\r') { - *t = '\0'; - return s; - } - t++; - } - return s; - -} - -/* set/unset filedescriptor to non-blocking */ -void -set_nonblock(int fd) -{ - int val; - - val = fcntl(fd, F_GETFL, 0); - if (val < 0) { - error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); - return; - } - if (val & O_NONBLOCK) { - debug2("fd %d is O_NONBLOCK", fd); - return; - } - debug("fd %d setting O_NONBLOCK", fd); - val |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, val) == -1) - debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", - fd, strerror(errno)); -} - -void -unset_nonblock(int fd) -{ - int val; - - val = fcntl(fd, F_GETFL, 0); - if (val < 0) { - error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); - return; - } - if (!(val & O_NONBLOCK)) { - debug2("fd %d is not O_NONBLOCK", fd); - return; - } - debug("fd %d clearing O_NONBLOCK", fd); - val &= ~O_NONBLOCK; - if (fcntl(fd, F_SETFL, val) == -1) - debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", - fd, strerror(errno)); -} - -/* disable nagle on socket */ -void -set_nodelay(int fd) -{ - int opt; - socklen_t optlen; - - optlen = sizeof opt; - if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { - error("getsockopt TCP_NODELAY: %.100s", strerror(errno)); - return; - } - if (opt == 1) { - debug2("fd %d is TCP_NODELAY", fd); - return; - } - opt = 1; - debug("fd %d setting TCP_NODELAY", fd); - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) - error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); -} - -/* Characters considered whitespace in strsep calls. */ -#define WHITESPACE " \t\r\n" - -/* - * Function returns a pointer to the 1st token on the line. Such a token can - * be an empty string in the case of '*s' equal to " value". It changes the - * first whitespace token or '=' character after the 1st token to '\0'. Upon - * return it changes '*s' to point to the first character of the next token. - * That token may be an empty string if the 1st token was followed only by - * whitespace or it could be a NULL pointer if the line contained one token - * only. - */ -char * -strdelim(char **s) -{ - char *old; - int wspace = 0; - - if (*s == NULL) - return NULL; - - old = *s; - - *s = strpbrk(*s, WHITESPACE "="); - if (*s == NULL) - return (old); - - /* Allow only one '=' to be skipped */ - if (*s[0] == '=') - wspace = 1; - *s[0] = '\0'; - - *s += strspn(*s + 1, WHITESPACE) + 1; - if (*s[0] == '=' && !wspace) - *s += strspn(*s + 1, WHITESPACE) + 1; - - return (old); -} - -struct passwd * -pwcopy(struct passwd *pw) -{ - struct passwd *copy = xmalloc(sizeof(*copy)); - - memset(copy, 0, sizeof(*copy)); - copy->pw_name = xstrdup(pw->pw_name); - copy->pw_passwd = xstrdup(pw->pw_passwd); - copy->pw_gecos = xstrdup(pw->pw_gecos); - copy->pw_uid = pw->pw_uid; - copy->pw_gid = pw->pw_gid; -#ifdef HAVE_PW_EXPIRE_IN_PASSWD - copy->pw_expire = pw->pw_expire; -#endif -#ifdef HAVE_PW_CHANGE_IN_PASSWD - copy->pw_change = pw->pw_change; -#endif -#ifdef HAVE_PW_CLASS_IN_PASSWD - copy->pw_class = xstrdup(pw->pw_class); -#endif - copy->pw_dir = xstrdup(pw->pw_dir); - copy->pw_shell = xstrdup(pw->pw_shell); - return copy; -} - -void -pwfree(struct passwd **pw) -{ - struct passwd *p; - - if (pw == NULL || *pw == NULL) - return; - - p = *pw; - *pw = NULL; - - xfree(p->pw_name); - xfree(p->pw_passwd); - xfree(p->pw_gecos); -#ifdef HAVE_PW_CLASS_IN_PASSWD - xfree(p->pw_class); -#endif - xfree(p->pw_dir); - xfree(p->pw_shell); - xfree(p); -} - -/* - * Convert ASCII string to TCP/IP port number. - * Port must be >0 and <=65535. - * Return 0 if invalid. - */ -int -a2port(const char *s) -{ - long port; - char *endp; - - errno = 0; - port = strtol(s, &endp, 0); - if (s == endp || *endp != '\0' || - (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) || - port <= 0 || port > 65535) - return 0; - - return port; -} - -#define SECONDS 1 -#define MINUTES (SECONDS * 60) -#define HOURS (MINUTES * 60) -#define DAYS (HOURS * 24) -#define WEEKS (DAYS * 7) - -/* - * Convert a time string into seconds; format is - * a sequence of: - * time[qualifier] - * - * Valid time qualifiers are: - * <none> seconds - * s|S seconds - * m|M minutes - * h|H hours - * d|D days - * w|W weeks - * - * Examples: - * 90m 90 minutes - * 1h30m 90 minutes - * 2d 2 days - * 1w 1 week - * - * Return -1 if time string is invalid. - */ -long -convtime(const char *s) -{ - long total, secs; - const char *p; - char *endp; - - errno = 0; - total = 0; - p = s; - - if (p == NULL || *p == '\0') - return -1; - - while (*p) { - secs = strtol(p, &endp, 10); - if (p == endp || - (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || - secs < 0) - return -1; - - switch (*endp++) { - case '\0': - endp--; - break; - case 's': - case 'S': - break; - case 'm': - case 'M': - secs *= MINUTES; - break; - case 'h': - case 'H': - secs *= HOURS; - break; - case 'd': - case 'D': - secs *= DAYS; - break; - case 'w': - case 'W': - secs *= WEEKS; - break; - default: - return -1; - } - total += secs; - if (total < 0) - return -1; - p = endp; - } - - return total; -} - -/* - * Search for next delimiter between hostnames/addresses and ports. - * Argument may be modified (for termination). - * Returns *cp if parsing succeeds. - * *cp is set to the start of the next delimiter, if one was found. - * If this is the last field, *cp is set to NULL. - */ -char * -hpdelim(char **cp) -{ - char *s, *old; - - if (cp == NULL || *cp == NULL) - return NULL; - - old = s = *cp; - if (*s == '[') { - if ((s = strchr(s, ']')) == NULL) - return NULL; - else - s++; - } else if ((s = strpbrk(s, ":/")) == NULL) - s = *cp + strlen(*cp); /* skip to end (see first case below) */ - - switch (*s) { - case '\0': - *cp = NULL; /* no more fields*/ - break; - - case ':': - case '/': - *s = '\0'; /* terminate */ - *cp = s + 1; - break; - - default: - return NULL; - } - - return old; -} - -char * -cleanhostname(char *host) -{ - if (*host == '[' && host[strlen(host) - 1] == ']') { - host[strlen(host) - 1] = '\0'; - return (host + 1); - } else - return host; -} - -char * -colon(char *cp) -{ - int flag = 0; - - if (*cp == ':') /* Leading colon is part of file name. */ - return (0); - if (*cp == '[') - flag = 1; - - for (; *cp; ++cp) { - if (*cp == '@' && *(cp+1) == '[') - flag = 1; - if (*cp == ']' && *(cp+1) == ':' && flag) - return (cp+1); - if (*cp == ':' && !flag) - return (cp); - if (*cp == '/') - return (0); - } - return (0); -} - -/* function to assist building execv() arguments */ -/* PRINTFLIKE2 */ -void -addargs(arglist *args, char *fmt, ...) -{ - va_list ap; - char buf[1024]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (args->list == NULL) { - args->nalloc = 32; - args->num = 0; - } else if (args->num+2 >= args->nalloc) - args->nalloc *= 2; - - args->list = xrealloc(args->list, args->nalloc * sizeof(char *)); - args->list[args->num++] = xstrdup(buf); - args->list[args->num] = NULL; -} - -void -replacearg(arglist *args, u_int which, char *fmt, ...) -{ - va_list ap; - char *cp; - int r; - - va_start(ap, fmt); - r = vasprintf(&cp, fmt, ap); - va_end(ap); - if (r == -1) - fatal("replacearg: argument too long"); - - if (which >= args->num) - fatal("replacearg: tried to replace invalid arg %d >= %d", - which, args->num); - xfree(args->list[which]); - args->list[which] = cp; -} - -void -freeargs(arglist *args) -{ - u_int i; - - if (args->list != NULL) { - for (i = 0; i < args->num; i++) - xfree(args->list[i]); - xfree(args->list); - args->nalloc = args->num = 0; - args->list = NULL; - } -} - -/* - * Expand a string with a set of %[char] escapes. A number of escapes may be - * specified as (char *escape_chars, char *replacement) pairs. The list must - * be terminated by a NULL escape_char. Returns replaced string in memory - * allocated by xmalloc. - */ -char * -percent_expand(const char *string, ...) -{ -#define EXPAND_MAX_KEYS 16 - struct { - const char *key; - const char *repl; - } keys[EXPAND_MAX_KEYS]; - u_int num_keys, i, j; - char buf[4096]; - va_list ap; - - /* Gather keys */ - va_start(ap, string); - for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { - keys[num_keys].key = va_arg(ap, char *); - if (keys[num_keys].key == NULL) - break; - keys[num_keys].repl = va_arg(ap, char *); - if (keys[num_keys].repl == NULL) - fatal("percent_expand: NULL replacement"); - } - va_end(ap); - - if (num_keys >= EXPAND_MAX_KEYS) - fatal("percent_expand: too many keys"); - - /* Expand string */ - *buf = '\0'; - for (i = 0; *string != '\0'; string++) { - if (*string != '%') { - append: - buf[i++] = *string; - if (i >= sizeof(buf)) - fatal("percent_expand: string too long"); - buf[i] = '\0'; - continue; - } - string++; - if (*string == '%') - goto append; - for (j = 0; j < num_keys; j++) { - if (strchr(keys[j].key, *string) != NULL) { - i = strlcat(buf, keys[j].repl, sizeof(buf)); - if (i >= sizeof(buf)) - fatal("percent_expand: string too long"); - break; - } - } - if (j >= num_keys) - fatal("percent_expand: unknown key %%%c", *string); - } - return (xstrdup(buf)); -#undef EXPAND_MAX_KEYS -} - -/* - * Ensure that file descriptors 0, 1 and 2 are open or directed to /dev/null, - * do not touch those that are already open. - */ -void -sanitise_stdfd(void) -{ - int nullfd, dupfd; - - if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { - fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno)); - exit(1); - } - while (++dupfd <= 2) { - /* Only clobber closed fds */ - if (fcntl(dupfd, F_GETFL, 0) >= 0) - continue; - if (dup2(nullfd, dupfd) == -1) { - fprintf(stderr, "dup2: %s", strerror(errno)); - exit(1); - } - } - if (nullfd > 2) - close(nullfd); -} - -char * -tohex(const void *vp, size_t l) -{ - const u_char *p = (const u_char *)vp; - char b[3], *r; - size_t i, hl; - - if (l > 65536) - return xstrdup("tohex: length > 65536"); - - hl = l * 2 + 1; - r = xcalloc(1, hl); - for (i = 0; i < l; i++) { - snprintf(b, sizeof(b), "%02x", p[i]); - strlcat(r, b, hl); - } - return (r); -} - -u_int64_t -get_u64(const void *vp) -{ - const u_char *p = (const u_char *)vp; - u_int64_t v; - - v = (u_int64_t)p[0] << 56; - v |= (u_int64_t)p[1] << 48; - v |= (u_int64_t)p[2] << 40; - v |= (u_int64_t)p[3] << 32; - v |= (u_int64_t)p[4] << 24; - v |= (u_int64_t)p[5] << 16; - v |= (u_int64_t)p[6] << 8; - v |= (u_int64_t)p[7]; - - return (v); -} - -u_int32_t -get_u32(const void *vp) -{ - const u_char *p = (const u_char *)vp; - u_int32_t v; - - v = (u_int32_t)p[0] << 24; - v |= (u_int32_t)p[1] << 16; - v |= (u_int32_t)p[2] << 8; - v |= (u_int32_t)p[3]; - - return (v); -} - -u_int16_t -get_u16(const void *vp) -{ - const u_char *p = (const u_char *)vp; - u_int16_t v; - - v = (u_int16_t)p[0] << 8; - v |= (u_int16_t)p[1]; - - return (v); -} - -void -put_u64(void *vp, u_int64_t v) -{ - u_char *p = (u_char *)vp; - - p[0] = (u_char)(v >> 56) & 0xff; - p[1] = (u_char)(v >> 48) & 0xff; - p[2] = (u_char)(v >> 40) & 0xff; - p[3] = (u_char)(v >> 32) & 0xff; - p[4] = (u_char)(v >> 24) & 0xff; - p[5] = (u_char)(v >> 16) & 0xff; - p[6] = (u_char)(v >> 8) & 0xff; - p[7] = (u_char)v & 0xff; -} - -void -put_u32(void *vp, u_int32_t v) -{ - u_char *p = (u_char *)vp; - - p[0] = (u_char)(v >> 24) & 0xff; - p[1] = (u_char)(v >> 16) & 0xff; - p[2] = (u_char)(v >> 8) & 0xff; - p[3] = (u_char)v & 0xff; -} - - -void -put_u16(void *vp, u_int16_t v) -{ - u_char *p = (u_char *)vp; - - p[0] = (u_char)(v >> 8) & 0xff; - p[1] = (u_char)v & 0xff; -} - -mysig_t -mysignal(int sig, mysig_t act) -{ -#ifdef HAVE_SIGACTION - struct sigaction sa, osa; - - if (sigaction(sig, NULL, &osa) == -1) - return (mysig_t) -1; - if (osa.sa_handler != act) { - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; -#if defined(SA_INTERRUPT) - if (sig == SIGALRM) - sa.sa_flags |= SA_INTERRUPT; -#endif - sa.sa_handler = act; - if (sigaction(sig, &sa, NULL) == -1) - return (mysig_t) -1; - } - return (osa.sa_handler); -#else - return (signal(sig, act)); -#endif -} - -/* - * Return true if argument is one of "yes", "true", "no" or "false". If - * 'active' is 0 than we are in a non-matching Host section of the - * configuration file so we check the syntax but will not set the value of - * '*option'. Otherwise we set its value if not already set. - */ -int -get_yes_no_flag(int *option, const char *arg, const char *filename, int linenum, - int active) -{ - int value = -1; - - if (arg == NULL || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) - value = 1; - else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) - value = 0; - - if (active && *option == -1 && value != -1) - *option = value; - - return (value != -1); -} - -/* - * Convert a string to lowercase. The string returned is an internally allocated - * one so the consumer of this function is not expected to change it or free it. - */ -char * -tolowercase(const char *s) -{ - int i, len; - static int lenret = 0; - static char *ret = NULL; - - /* allocate a new string if the old one it not long enough to store s */ - len = strlen(s) + 1; - if (len > lenret) { - if (ret != NULL) - xfree(ret); - ret = xmalloc(len); - lenret = len; - } - - /* process the string including the ending '\0' */ - for (i = 0; i < len; ++i) - ret[i] = tolower(s[i]); - - return (ret); -} diff --git a/usr/src/cmd/ssh/libssh/common/mpaux.c b/usr/src/cmd/ssh/libssh/common/mpaux.c deleted file mode 100644 index 1b77961b62..0000000000 --- a/usr/src/cmd/ssh/libssh/common/mpaux.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file contains various auxiliary functions related to multiple - * precision integers. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: mpaux.c,v 1.16 2001/02/08 19:30:52 itojun Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/bn.h> -#include "getput.h" -#include "xmalloc.h" - -#include <openssl/md5.h> - -#include "mpaux.h" - -void -compute_session_id(u_char session_id[16], - u_char cookie[8], - BIGNUM* host_key_n, - BIGNUM* session_key_n) -{ - u_int host_key_bytes = BN_num_bytes(host_key_n); - u_int session_key_bytes = BN_num_bytes(session_key_n); - u_int bytes = host_key_bytes + session_key_bytes; - u_char *buf = xmalloc(bytes); - MD5_CTX md; - - BN_bn2bin(host_key_n, buf); - BN_bn2bin(session_key_n, buf + host_key_bytes); - MD5_Init(&md); - MD5_Update(&md, buf, bytes); - MD5_Update(&md, cookie, 8); - MD5_Final(session_id, &md); - memset(buf, 0, bytes); - xfree(buf); -} diff --git a/usr/src/cmd/ssh/libssh/common/msg.c b/usr/src/cmd/ssh/libssh/common/msg.c deleted file mode 100644 index 26c5eeec61..0000000000 --- a/usr/src/cmd/ssh/libssh/common/msg.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: msg.c,v 1.4 2002/07/01 16:15:25 deraadt Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "buffer.h" -#include "getput.h" -#include "log.h" -#include "atomicio.h" -#include "msg.h" - -void -ssh_msg_send(int fd, u_char type, Buffer *m) -{ - u_char buf[5]; - u_int mlen = buffer_len(m); - - debug3("ssh_msg_send: type %u", (unsigned int)type & 0xff); - - PUT_32BIT(buf, mlen + 1); - buf[4] = type; /* 1st byte of payload is mesg-type */ - if (atomicio(write, fd, buf, sizeof(buf)) != sizeof(buf)) - fatal("ssh_msg_send: write"); - if (atomicio(write, fd, buffer_ptr(m), mlen) != mlen) - fatal("ssh_msg_send: write"); -} - -int -ssh_msg_recv(int fd, Buffer *m) -{ - u_char buf[4]; - ssize_t res; - u_int msg_len; - - debug3("ssh_msg_recv entering"); - - res = atomicio(read, fd, buf, sizeof(buf)); - if (res != sizeof(buf)) { - if (res == 0) - return -1; - fatal("ssh_msg_recv: read: header %ld", (long)res); - } - msg_len = GET_32BIT(buf); - if (msg_len > 256 * 1024) - fatal("ssh_msg_recv: read: bad msg_len %u", msg_len); - buffer_clear(m); - buffer_append_space(m, msg_len); - res = atomicio(read, fd, buffer_ptr(m), msg_len); - if (res != msg_len) - fatal("ssh_msg_recv: read: %ld != msg_len", (long)res); - return 0; -} diff --git a/usr/src/cmd/ssh/libssh/common/nchan.c b/usr/src/cmd/ssh/libssh/common/nchan.c deleted file mode 100644 index 82a371af5b..0000000000 --- a/usr/src/cmd/ssh/libssh/common/nchan.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: nchan.c,v 1.47 2002/06/19 00:27:55 deraadt Exp $"); - -#include "ssh1.h" -#include "ssh2.h" -#include "buffer.h" -#include "packet.h" -#include "channels.h" -#include "compat.h" -#include "log.h" - -/* - * SSH Protocol 1.5 aka New Channel Protocol - * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored. - * Written by Markus Friedl in October 1999 - * - * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the - * tear down of channels: - * - * 1.3: strict request-ack-protocol: - * CLOSE -> - * <- CLOSE_CONFIRM - * - * 1.5: uses variations of: - * IEOF -> - * <- OCLOSE - * <- IEOF - * OCLOSE -> - * i.e. both sides have to close the channel - * - * 2.0: the EOF messages are optional - * - * See the debugging output from 'ssh -v' and 'sshd -d' of - * ssh-1.2.27 as an example. - * - */ - -/* functions manipulating channel states */ -/* - * EVENTS update channel input/output states execute ACTIONS - */ -/* - * ACTIONS: should never update the channel states - */ -static void chan_send_ieof1(Channel *); -static void chan_send_oclose1(Channel *); -static void chan_send_close2(Channel *); -static void chan_send_eof2(Channel *); -static void chan_send_eow2(Channel *); - -/* helper */ -static void chan_shutdown_write(Channel *); -static void chan_shutdown_read(Channel *); - -static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; -static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; - -static void -chan_set_istate(Channel *c, u_int next) -{ - if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED) - fatal("chan_set_istate: bad state %d -> %d", c->istate, next); - debug("channel %d: input %s -> %s", c->self, istates[c->istate], - istates[next]); - c->istate = next; -} -static void -chan_set_ostate(Channel *c, u_int next) -{ - if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED) - fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next); - debug("channel %d: output %s -> %s", c->self, ostates[c->ostate], - ostates[next]); - c->ostate = next; -} - -/* - * SSH1 specific implementation of event functions - */ - -static void -chan_rcvd_oclose1(Channel *c) -{ - debug("channel %d: rcvd oclose", c->self); - switch (c->istate) { - case CHAN_INPUT_WAIT_OCLOSE: - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - case CHAN_INPUT_OPEN: - chan_shutdown_read(c); - chan_send_ieof1(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - case CHAN_INPUT_WAIT_DRAIN: - /* both local read_failed and remote write_failed */ - chan_send_ieof1(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - default: - error("channel %d: protocol error: rcvd_oclose for istate %d", - c->self, c->istate); - return; - } -} -void -chan_read_failed(Channel *c) -{ - debug("channel %d: read failed", c->self); - switch (c->istate) { - case CHAN_INPUT_OPEN: - chan_shutdown_read(c); - chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); - break; - default: - error("channel %d: chan_read_failed for istate %d", - c->self, c->istate); - break; - } -} -void -chan_ibuf_empty(Channel *c) -{ - debug("channel %d: ibuf empty", c->self); - if (buffer_len(&c->input)) { - error("channel %d: chan_ibuf_empty for non empty buffer", - c->self); - return; - } - switch (c->istate) { - case CHAN_INPUT_WAIT_DRAIN: - if (compat20) { - if (!(c->flags & CHAN_CLOSE_SENT)) - chan_send_eof2(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - } else { - chan_send_ieof1(c); - chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE); - } - break; - default: - error("channel %d: chan_ibuf_empty for istate %d", - c->self, c->istate); - break; - } -} -static void -chan_rcvd_ieof1(Channel *c) -{ - debug("channel %d: rcvd ieof", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); - break; - case CHAN_OUTPUT_WAIT_IEOF: - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - break; - default: - error("channel %d: protocol error: rcvd_ieof for ostate %d", - c->self, c->ostate); - break; - } -} -static void -chan_write_failed1(Channel *c) -{ - debug("channel %d: write failed", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - chan_shutdown_write(c); - chan_send_oclose1(c); - chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF); - break; - case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); - chan_send_oclose1(c); - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - break; - default: - error("channel %d: chan_write_failed for ostate %d", - c->self, c->ostate); - break; - } -} -void -chan_obuf_empty(Channel *c) -{ - debug("channel %d: obuf empty", c->self); - if (buffer_len(&c->output)) { - error("channel %d: chan_obuf_empty for non empty buffer", - c->self); - return; - } - switch (c->ostate) { - case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); - if (!compat20) - chan_send_oclose1(c); - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - break; - default: - error("channel %d: internal error: obuf_empty for ostate %d", - c->self, c->ostate); - break; - } -} -static void -chan_send_ieof1(Channel *c) -{ - debug("channel %d: send ieof", c->self); - switch (c->istate) { - case CHAN_INPUT_OPEN: - case CHAN_INPUT_WAIT_DRAIN: - packet_start(SSH_MSG_CHANNEL_INPUT_EOF); - packet_put_int(c->remote_id); - packet_send(); - break; - default: - error("channel %d: cannot send ieof for istate %d", - c->self, c->istate); - break; - } -} -static void -chan_send_oclose1(Channel *c) -{ - debug("channel %d: send oclose", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - case CHAN_OUTPUT_WAIT_DRAIN: - buffer_clear(&c->output); - packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - break; - default: - error("channel %d: cannot send oclose for ostate %d", - c->self, c->ostate); - break; - } -} - -/* - * the same for SSH2 - */ -static void -chan_rcvd_close2(Channel *c) -{ - debug("channel %d: rcvd close", c->self); - if (c->flags & CHAN_CLOSE_RCVD) - error("channel %d: protocol error: close rcvd twice", c->self); - c->flags |= CHAN_CLOSE_RCVD; - if (c->type == SSH_CHANNEL_LARVAL) { - /* tear down larval channels immediately */ - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - chan_set_istate(c, CHAN_INPUT_CLOSED); - return; - } - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - /* - * wait until a data from the channel is consumed if a CLOSE - * is received - */ - chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); - break; - } - switch (c->istate) { - case CHAN_INPUT_OPEN: - chan_shutdown_read(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - case CHAN_INPUT_WAIT_DRAIN: - chan_send_eof2(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - } -} -void -chan_rcvd_eow(Channel *c) -{ - debug2("channel %d: rcvd eow", c->self); - switch (c->istate) { - case CHAN_INPUT_OPEN: - chan_shutdown_read(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - } -} -static void -chan_rcvd_eof2(Channel *c) -{ - debug("channel %d: rcvd eof", c->self); - c->flags |= CHAN_EOF_RCVD; - if (c->ostate == CHAN_OUTPUT_OPEN) - chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); -} -static void -chan_write_failed2(Channel *c) -{ - debug("channel %d: write failed", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); - if (strcmp(c->ctype, "session") == 0) - chan_send_eow2(c); - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - break; - default: - error("channel %d: chan_write_failed for ostate %d", - c->self, c->ostate); - break; - } -} -static void -chan_send_eof2(Channel *c) -{ - debug("channel %d: send eof", c->self); - switch (c->istate) { - case CHAN_INPUT_WAIT_DRAIN: - packet_start(SSH2_MSG_CHANNEL_EOF); - packet_put_int(c->remote_id); - packet_send(); - c->flags |= CHAN_EOF_SENT; - break; - default: - error("channel %d: cannot send eof for istate %d", - c->self, c->istate); - break; - } -} -static void -chan_send_close2(Channel *c) -{ - debug("channel %d: send close", c->self); - if (c->ostate != CHAN_OUTPUT_CLOSED || - c->istate != CHAN_INPUT_CLOSED) { - error("channel %d: cannot send close for istate/ostate %d/%d", - c->self, c->istate, c->ostate); - } else if (c->flags & CHAN_CLOSE_SENT) { - error("channel %d: already sent close", c->self); - } else { - packet_start(SSH2_MSG_CHANNEL_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - c->flags |= CHAN_CLOSE_SENT; - } -} -static void -chan_send_eow2(Channel *c) -{ - debug2("channel %d: send eow", c->self); - if (c->ostate == CHAN_OUTPUT_CLOSED) { - error("channel %d: must not sent eow on closed output", - c->self); - return; - } - packet_start(SSH2_MSG_CHANNEL_REQUEST); - packet_put_int(c->remote_id); - packet_put_cstring("eow@openssh.com"); - packet_put_char(0); - packet_send(); -} - -/* shared */ - -void -chan_rcvd_ieof(Channel *c) -{ - if (compat20) - chan_rcvd_eof2(c); - else - chan_rcvd_ieof1(c); - if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && - buffer_len(&c->output) == 0 && - !CHANNEL_EFD_OUTPUT_ACTIVE(c)) - chan_obuf_empty(c); -} -void -chan_rcvd_oclose(Channel *c) -{ - if (compat20) - chan_rcvd_close2(c); - else - chan_rcvd_oclose1(c); -} -void -chan_write_failed(Channel *c) -{ - if (compat20) - chan_write_failed2(c); - else - chan_write_failed1(c); -} - -void -chan_mark_dead(Channel *c) -{ - c->type = SSH_CHANNEL_ZOMBIE; -} - -int -chan_is_dead(Channel *c, int send) -{ - if (c->type == SSH_CHANNEL_ZOMBIE) { - debug("channel %d: zombie", c->self); - return 1; - } - if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) - return 0; - if (!compat20) { - debug("channel %d: is dead", c->self); - return 1; - } - if ((datafellows & SSH_BUG_EXTEOF) && - c->extended_usage == CHAN_EXTENDED_WRITE && - c->efd != -1 && - buffer_len(&c->extended) > 0) { - debug2("channel %d: active efd: %d len %d", - c->self, c->efd, buffer_len(&c->extended)); - return 0; - } - if (!(c->flags & CHAN_CLOSE_SENT)) { - if (send) { - chan_send_close2(c); - } else { - /* channel would be dead if we sent a close */ - if (c->flags & CHAN_CLOSE_RCVD) { - debug("channel %d: almost dead", - c->self); - return 1; - } - } - } - if ((c->flags & CHAN_CLOSE_SENT) && - (c->flags & CHAN_CLOSE_RCVD)) { - debug("channel %d: is dead", c->self); - return 1; - } - return 0; -} - -/* helper */ -static void -chan_shutdown_write(Channel *c) -{ - buffer_clear(&c->output); - if (compat20 && c->type == SSH_CHANNEL_LARVAL) - return; - /* shutdown failure is allowed if write failed already */ - debug("channel %d: close_write", c->self); - if (c->sock != -1) { - if (shutdown(c->sock, SHUT_WR) < 0) - debug("channel %d: chan_shutdown_write: " - "shutdown() failed for fd%d: %.100s", - c->self, c->sock, strerror(errno)); - } else { - if (channel_close_fd(&c->wfd) < 0) - log("channel %d: chan_shutdown_write: " - "close() failed for fd%d: %.100s", - c->self, c->wfd, strerror(errno)); - } -} -static void -chan_shutdown_read(Channel *c) -{ - if (compat20 && c->type == SSH_CHANNEL_LARVAL) - return; - debug("channel %d: close_read", c->self); - if (c->sock != -1) { - /* - * shutdown(sock, SHUT_READ) may return ENOTCONN if the - * write side has been closed already. (bug on Linux) - * HP-UX may return ENOTCONN also. - */ - if (shutdown(c->sock, SHUT_RD) < 0 - && errno != ENOTCONN) - error("channel %d: chan_shutdown_read: " - "shutdown() failed for fd%d [i%d o%d]: %.100s", - c->self, c->sock, c->istate, c->ostate, - strerror(errno)); - } else { - if (channel_close_fd(&c->rfd) < 0) - log("channel %d: chan_shutdown_read: " - "close() failed for fd%d: %.100s", - c->self, c->rfd, strerror(errno)); - } -} diff --git a/usr/src/cmd/ssh/libssh/common/packet.c b/usr/src/cmd/ssh/libssh/common/packet.c deleted file mode 100644 index 1221db134a..0000000000 --- a/usr/src/cmd/ssh/libssh/common/packet.c +++ /dev/null @@ -1,1845 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file contains code implementing the packet protocol and communication - * with the other side. This same code is used both on client and server side. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * SSH2 packet format added by Markus Friedl. - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */ - -#include "includes.h" - -#include "sys-queue.h" -#include "xmalloc.h" -#include "buffer.h" -#include "packet.h" -#include "bufaux.h" -#include "crc32.h" -#include "getput.h" -#include "compress.h" -#include "deattack.h" -#include "channels.h" -#include "compat.h" -#include "ssh1.h" -#include "ssh2.h" -#include "cipher.h" -#include "kex.h" -#include "mac.h" -#include "log.h" -#include "canohost.h" -#include "misc.h" -#include "ssh.h" -#include "engine.h" - -/* PKCS#11 engine */ -ENGINE *e; - -#ifdef ALTPRIVSEP -static int packet_server = 0; -static int packet_monitor = 0; -#endif /* ALTPRIVSEP */ - -#ifdef PACKET_DEBUG -#define DBG(x) x -#else -#define DBG(x) -#endif - -static void packet_send2(void); - -/* - * This variable contains the file descriptors used for communicating with - * the other side. connection_in is used for reading; connection_out for - * writing. These can be the same descriptor, in which case it is assumed to - * be a socket. - */ -static int connection_in = -1; -static int connection_out = -1; - -/* Protocol flags for the remote side. */ -static u_int remote_protocol_flags = 0; - -/* Encryption context for receiving data. This is only used for decryption. */ -static CipherContext receive_context; - -/* Encryption context for sending data. This is only used for encryption. */ -static CipherContext send_context; - -/* Buffer for raw input data from the socket. */ -Buffer input; - -/* Buffer for raw output data going to the socket. */ -Buffer output; - -/* Buffer for the partial outgoing packet being constructed. */ -static Buffer outgoing_packet; - -/* Buffer for the incoming packet currently being processed. */ -static Buffer incoming_packet; - -/* Scratch buffer for packet compression/decompression. */ -static Buffer compression_buffer; -static int compression_buffer_ready = 0; - -/* Flag indicating whether packet compression/decompression is enabled. */ -static int packet_compression = 0; - -/* default maximum packet size */ -int max_packet_size = 32768; - -/* Flag indicating whether this module has been initialized. */ -static int initialized = 0; - -/* Set to true if the connection is interactive. */ -static int interactive_mode = 0; - -/* Session key information for Encryption and MAC */ -Newkeys *newkeys[MODE_MAX]; -static struct packet_state { - u_int32_t seqnr; - u_int32_t packets; - u_int64_t blocks; -} p_read, p_send; - -static u_int64_t max_blocks_in, max_blocks_out; -static u_int32_t rekey_limit; - -/* Session key for protocol v1 */ -static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; -static u_int ssh1_keylen; - -/* roundup current message to extra_pad bytes */ -static u_char extra_pad = 0; - -struct packet { - TAILQ_ENTRY(packet) next; - u_char type; - Buffer payload; -}; -TAILQ_HEAD(, packet) outgoing; - -/* - * Part of what -f option and ~& escape sequence do in the client is that they - * will force it to daemonize itself. Due to the fork safety rules inherent in - * any PKCS#11 environment, if the engine is used we must do a key re-exchange - * before forking a child to negotiate the new keys. Those keys will be used to - * inicialize the new crypto contexts. This involves finishing the engine in the - * parent and reinitializing it again in both processes after fork() returns. - * This approach also leaves protocol 1 out since it doesn't support rekeying. - */ -int will_daemonize; - -#ifdef PACKET_DEBUG -/* This function dumps data onto stderr. This is for debugging only. */ -void -data_dump(void *data, u_int len) -{ - Buffer buf; - - buffer_init(&buf); - buffer_append(&buf, data, len); - buffer_dump(&buf); - buffer_free(&buf); -} -#endif - -/* - * Sets the descriptors used for communication. Disables encryption until - * packet_set_encryption_key is called. - */ -void -packet_set_connection(int fd_in, int fd_out) -{ - Cipher *none = cipher_by_name("none"); - - if (none == NULL) - fatal("packet_set_connection: cannot load cipher 'none'"); - connection_in = fd_in; - connection_out = fd_out; - cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_ENCRYPT); - cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_DECRYPT); - newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; - if (!initialized) { - initialized = 1; - buffer_init(&input); - buffer_init(&output); - buffer_init(&outgoing_packet); - buffer_init(&incoming_packet); - TAILQ_INIT(&outgoing); - } else { - buffer_clear(&input); - buffer_clear(&output); - buffer_clear(&outgoing_packet); - buffer_clear(&incoming_packet); - } - - /* - * Prime the cache for get_remote_ipaddr() while we have a - * socket on which to do a getpeername(). - */ - (void) get_remote_ipaddr(); - - /* Kludge: arrange the close function to be called from fatal(). */ - fatal_add_cleanup((void (*) (void *)) packet_close, NULL); -} - -/* Returns 1 if remote host is connected via socket, 0 if not. */ - -int -packet_connection_is_on_socket(void) -{ - struct sockaddr_storage from, to; - socklen_t fromlen, tolen; - - /* filedescriptors in and out are the same, so it's a socket */ - if (connection_in != -1 && connection_in == connection_out) - return 1; - fromlen = sizeof(from); - memset(&from, 0, sizeof(from)); - if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) - return 0; - tolen = sizeof(to); - memset(&to, 0, sizeof(to)); - if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) - return 0; - if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) - return 0; - if (from.ss_family != AF_INET && from.ss_family != AF_INET6) - return 0; - return 1; -} - -/* returns 1 if connection is via ipv4 */ - -int -packet_connection_is_ipv4(void) -{ - struct sockaddr_storage to; - socklen_t tolen = sizeof(to); - - memset(&to, 0, sizeof(to)); - if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) - return 0; - if (to.ss_family == AF_INET) - return 1; -#ifdef IPV4_IN_IPV6 - if (to.ss_family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) - return 1; -#endif - return 0; -} - -/* Sets the connection into non-blocking mode. */ - -void -packet_set_nonblocking(void) -{ - /* Set the socket into non-blocking mode. */ - if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %.100s", strerror(errno)); - - if (connection_out != connection_in) { - if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %.100s", strerror(errno)); - } -} - -/* Returns the socket used for reading. */ - -int -packet_get_connection_in(void) -{ - return connection_in; -} - -/* Returns the descriptor used for writing. */ - -int -packet_get_connection_out(void) -{ - return connection_out; -} - -/* Closes the connection and clears and frees internal data structures. */ - -void -packet_close(void) -{ - if (!initialized) - return; - initialized = 0; - if (connection_in == connection_out) { - shutdown(connection_out, SHUT_RDWR); - close(connection_out); - } else { - close(connection_in); - close(connection_out); - } - buffer_free(&input); - buffer_free(&output); - buffer_free(&outgoing_packet); - buffer_free(&incoming_packet); - if (compression_buffer_ready) { - buffer_free(&compression_buffer); - buffer_compress_uninit(); - compression_buffer_ready = 0; - } - cipher_cleanup(&send_context); - cipher_cleanup(&receive_context); -} - -/* Sets remote side protocol flags. */ - -void -packet_set_protocol_flags(u_int protocol_flags) -{ - remote_protocol_flags = protocol_flags; -} - -/* Returns the remote protocol flags set earlier by the above function. */ - -u_int -packet_get_protocol_flags(void) -{ - return remote_protocol_flags; -} - -/* - * Starts packet compression from the next packet on in both directions. - * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. - */ - -static void -packet_init_compression(void) -{ - if (compression_buffer_ready == 1) - return; - compression_buffer_ready = 1; - buffer_init(&compression_buffer); -} - -void -packet_start_compression(int level) -{ -#ifdef ALTPRIVSEP - /* shouldn't happen! */ - if (packet_monitor) - fatal("INTERNAL ERROR: The monitor cannot compress."); -#endif /* ALTPRIVSEP */ - - if (packet_compression && !compat20) - fatal("Compression already enabled."); - packet_compression = 1; - packet_init_compression(); - buffer_compress_init_send(level); - buffer_compress_init_recv(); -} - -/* - * Causes any further packets to be encrypted using the given key. The same - * key is used for both sending and reception. However, both directions are - * encrypted independently of each other. - */ - -void -packet_set_encryption_key(const u_char *key, u_int keylen, - int number) -{ - Cipher *cipher = cipher_by_number(number); - - if (cipher == NULL) - fatal("packet_set_encryption_key: unknown cipher number %d", number); - if (keylen < 20) - fatal("packet_set_encryption_key: keylen too small: %d", keylen); - if (keylen > SSH_SESSION_KEY_LENGTH) - fatal("packet_set_encryption_key: keylen too big: %d", keylen); - memcpy(ssh1_key, key, keylen); - ssh1_keylen = keylen; - cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); - cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); -} - -u_int -packet_get_encryption_key(u_char *key) -{ - if (key == NULL) - return (ssh1_keylen); - memcpy(key, ssh1_key, ssh1_keylen); - return (ssh1_keylen); -} - -/* Start constructing a packet to send. */ -void -packet_start(u_char type) -{ - u_char buf[9]; - int len; - - DBG(debug("packet_start[%d]", type)); - len = compat20 ? 6 : 9; - memset(buf, 0, len - 1); - buf[len - 1] = type; - buffer_clear(&outgoing_packet); - buffer_append(&outgoing_packet, buf, len); -} - -/* Append payload. */ -void -packet_put_char(int value) -{ - char ch = value; - - buffer_append(&outgoing_packet, &ch, 1); -} - -void -packet_put_int(u_int value) -{ - buffer_put_int(&outgoing_packet, value); -} - -void -packet_put_string(const void *buf, u_int len) -{ - buffer_put_string(&outgoing_packet, buf, len); -} - -void -packet_put_cstring(const char *str) -{ - buffer_put_cstring(&outgoing_packet, str); -} - -void -packet_put_utf8_cstring(const char *str) -{ - if (datafellows & SSH_BUG_STRING_ENCODING) - buffer_put_cstring(&outgoing_packet, str); - else - buffer_put_utf8_cstring(&outgoing_packet, str); -} - -void -packet_put_utf8_string(const char *str, uint_t len) -{ - if (datafellows & SSH_BUG_STRING_ENCODING) - buffer_put_string(&outgoing_packet, str, len); - else - buffer_put_utf8_string(&outgoing_packet, str, len); -} - -void -packet_put_raw(const void *buf, u_int len) -{ - buffer_append(&outgoing_packet, buf, len); -} - -void -packet_put_bignum(BIGNUM * value) -{ - buffer_put_bignum(&outgoing_packet, value); -} - -void -packet_put_bignum2(BIGNUM * value) -{ - buffer_put_bignum2(&outgoing_packet, value); -} - -/* - * Finalizes and sends the packet. If the encryption key has been set, - * encrypts the packet before sending. - */ - -static void -packet_send1(void) -{ - u_char buf[8], *cp; - int i, padding, len; - u_int checksum; - u_int32_t rnd = 0; - - /* - * If using packet compression, compress the payload of the outgoing - * packet. - */ - if (packet_compression) { - buffer_clear(&compression_buffer); - /* Skip padding. */ - buffer_consume(&outgoing_packet, 8); - /* padding */ - buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); - buffer_compress(&outgoing_packet, &compression_buffer); - buffer_clear(&outgoing_packet); - buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), - buffer_len(&compression_buffer)); - } - /* Compute packet length without padding (add checksum, remove padding). */ - len = buffer_len(&outgoing_packet) + 4 - 8; - - /* Insert padding. Initialized to zero in packet_start1() */ - padding = 8 - len % 8; - if (!send_context.plaintext) { - cp = buffer_ptr(&outgoing_packet); - for (i = 0; i < padding; i++) { - if (i % 4 == 0) - rnd = arc4random(); - cp[7 - i] = rnd & 0xff; - rnd >>= 8; - } - } - buffer_consume(&outgoing_packet, 8 - padding); - - /* Add check bytes. */ - checksum = ssh_crc32(buffer_ptr(&outgoing_packet), - buffer_len(&outgoing_packet)); - PUT_32BIT(buf, checksum); - buffer_append(&outgoing_packet, buf, 4); - -#ifdef PACKET_DEBUG - fprintf(stderr, "packet_send plain: "); - buffer_dump(&outgoing_packet); -#endif - - /* Append to output. */ - PUT_32BIT(buf, len); - buffer_append(&output, buf, 4); - cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); - cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), - buffer_len(&outgoing_packet)); - -#ifdef PACKET_DEBUG - debug("encrypted output queue now contains (%d bytes):\n", - buffer_len(&output)); - buffer_dump(&output); -#endif - - buffer_clear(&outgoing_packet); - - /* - * Note that the packet is now only buffered in output. It won\'t be - * actually sent until packet_write_wait or packet_write_poll is - * called. - */ -} - -void -set_newkeys(int mode) -{ - Enc *enc; - Mac *mac; - Comp *comp; - CipherContext *cc; - u_int64_t *max_blocks; - int crypt_type; - - debug2("set_newkeys: mode %d", mode); - - if (mode == MODE_OUT) { - cc = &send_context; - crypt_type = CIPHER_ENCRYPT; - p_send.packets = p_send.blocks = 0; - max_blocks = &max_blocks_out; - } else { - cc = &receive_context; - crypt_type = CIPHER_DECRYPT; - p_read.packets = p_read.blocks = 0; - max_blocks = &max_blocks_in; - } - - debug("set_newkeys: setting new keys for '%s' mode", - mode == MODE_IN ? "in" : "out"); - - if (newkeys[mode] != NULL) { - cipher_cleanup(cc); - free_keys(newkeys[mode]); - } - - newkeys[mode] = kex_get_newkeys(mode); - if (newkeys[mode] == NULL) - fatal("newkeys: no keys for mode %d", mode); - enc = &newkeys[mode]->enc; - mac = &newkeys[mode]->mac; - comp = &newkeys[mode]->comp; - if (mac_init(mac) == 0) - mac->enabled = 1; -#ifdef PACKET_DEBUG - debug("new encryption key:\n"); - data_dump(enc->key, enc->key_len); - debug("new encryption IV:\n"); - data_dump(enc->iv, enc->block_size); - debug("new MAC key:\n"); - data_dump(mac->key, mac->key_len); -#endif - cipher_init(cc, enc->cipher, enc->key, enc->key_len, - enc->iv, enc->block_size, crypt_type); - /* Deleting the keys does not gain extra security */ - /* memset(enc->iv, 0, enc->block_size); - memset(enc->key, 0, enc->key_len); */ - if (comp->type != 0 && comp->enabled == 0) { - packet_init_compression(); - if (mode == MODE_OUT) - buffer_compress_init_send(6); - else - buffer_compress_init_recv(); - comp->enabled = 1; - } - - /* - * In accordance to the RFCs listed below we enforce the key - * re-exchange for: - * - * - every 1GB of transmitted data if the selected cipher block size - * is less than 16 bytes (3DES, Blowfish) - * - every 2^(2*B) cipher blocks transmitted (B is block size in bytes) - * if the cipher block size is greater than or equal to 16 bytes (AES) - * - and we never send more than 2^32 SSH packets using the same keys. - * The recommendation of 2^31 packets is not enforced here but in - * packet_need_rekeying(). There is also a hard check in - * packet_send2_wrapped() that we don't send more than 2^32 packets. - * - * Note that if the SSH_BUG_NOREKEY compatibility flag is set then no - * automatic rekeying is performed nor do we enforce the 3rd rule. - * This means that we can be always forced by the opposite side to never - * initiate automatic key re-exchange. This might change in the future. - * - * The RekeyLimit option keyword may only enforce more frequent key - * renegotiation, never less. For more information on key renegotiation, - * see: - * - * - RFC 4253 (SSH Transport Layer Protocol), section "9. Key - * Re-Exchange" - * - RFC 4344 (SSH Transport Layer Encryption Modes), sections "3. - * Rekeying" and "6.1 Rekeying Considerations" - */ - if (enc->block_size >= 16) - *max_blocks = (u_int64_t)1 << (enc->block_size * 2); - else - *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; - - if (rekey_limit) - *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); -} - -void -free_keys(Newkeys *keys) -{ - Enc *enc; - Mac *mac; - Comp *comp; - - enc = &keys->enc; - mac = &keys->mac; - comp = &keys->comp; - xfree(enc->name); - xfree(enc->iv); - xfree(enc->key); - - memset(mac->key, 0, mac->key_len); - xfree(mac->key); - xfree(mac->name); - mac_clear(mac); - - xfree(comp->name); - xfree(keys); -} - -/* - * Process SSH2_MSG_NEWKEYS message. If we are using the engine we must have - * both SSH2_MSG_NEWKEYS processed before we can finish the engine, fork, and - * reinitialize the crypto contexts. We can't fork before processing the 2nd - * message otherwise we couldn't encrypt/decrypt that message at all - note that - * parent's PKCS#11 sessions are useless after the fork and we must process - * both SSH2_MSG_NEWKEYS messages using the old keys. - */ -void -process_newkeys(int mode) -{ - /* this function is for the client only */ - if (packet_is_server() != 0) - return; - - if (will_daemonize == FIRST_NEWKEYS_PROCESSED) { - debug3("both SSH2_MSG_NEWKEYS processed, will daemonize now"); - cipher_cleanup(&send_context); - cipher_cleanup(&receive_context); - pkcs11_engine_finish(e); - if (daemon(1, 1) < 0) { - fatal("daemon() failed: %.200s", - strerror(errno)); - } - e = pkcs11_engine_load(e != NULL ? 1 : 0); - - set_newkeys(MODE_OUT); - set_newkeys(MODE_IN); - will_daemonize = SECOND_NEWKEYS_PROCESSED; - packet_send2(); - } else { - if (will_daemonize == DAEMONIZING_REQUESTED) - will_daemonize = FIRST_NEWKEYS_PROCESSED; - else - set_newkeys(mode); - } -} - -/* - * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) - */ -static void -packet_send2_wrapped(void) -{ - u_char type, *cp, *macbuf = NULL; - u_char padlen, pad; - u_int packet_length = 0; - u_int i, len; - u_int32_t rnd = 0; - Enc *enc = NULL; - Mac *mac = NULL; - Comp *comp = NULL; - int block_size; - - if (newkeys[MODE_OUT] != NULL) { - enc = &newkeys[MODE_OUT]->enc; - mac = &newkeys[MODE_OUT]->mac; - comp = &newkeys[MODE_OUT]->comp; - } - block_size = enc ? enc->block_size : 8; - - cp = buffer_ptr(&outgoing_packet); - type = cp[5]; - -#ifdef PACKET_DEBUG - debug("plain output packet to be processed (%d bytes):\n", - buffer_len(&outgoing_packet)); - buffer_dump(&outgoing_packet); -#endif - - if (comp && comp->enabled) { - len = buffer_len(&outgoing_packet); - /* skip header, compress only payload */ - buffer_consume(&outgoing_packet, 5); - buffer_clear(&compression_buffer); - buffer_compress(&outgoing_packet, &compression_buffer); - buffer_clear(&outgoing_packet); - buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); - buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), - buffer_len(&compression_buffer)); - DBG(debug("compression: raw %d compressed %d", len, - buffer_len(&outgoing_packet))); - } - - /* sizeof (packet_len + pad_len + payload) */ - len = buffer_len(&outgoing_packet); - - /* - * calc size of padding, alloc space, get random data, - * minimum padding is 4 bytes - */ - padlen = block_size - (len % block_size); - if (padlen < 4) - padlen += block_size; - if (extra_pad) { - /* will wrap if extra_pad+padlen > 255 */ - extra_pad = roundup(extra_pad, block_size); - pad = extra_pad - ((len + padlen) % extra_pad); - debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", - pad, len, padlen, extra_pad); - padlen += pad; - extra_pad = 0; - } - cp = buffer_append_space(&outgoing_packet, padlen); - if (enc && !send_context.plaintext) { - /* random padding */ - for (i = 0; i < padlen; i++) { - if (i % 4 == 0) - rnd = arc4random(); - cp[i] = rnd & 0xff; - rnd >>= 8; - } - } else { - /* clear padding */ - memset(cp, 0, padlen); - } - /* packet_length includes payload, padding and padding length field */ - packet_length = buffer_len(&outgoing_packet) - 4; - cp = buffer_ptr(&outgoing_packet); - PUT_32BIT(cp, packet_length); - cp[4] = padlen; - DBG(debug("will send %d bytes (includes padlen %d)", - packet_length + 4, padlen)); - - /* compute MAC over seqnr and packet(length fields, payload, padding) */ - if (mac && mac->enabled) { - macbuf = mac_compute(mac, p_send.seqnr, - buffer_ptr(&outgoing_packet), - buffer_len(&outgoing_packet)); - DBG(debug("done calc MAC out #%d", p_send.seqnr)); - } - /* encrypt packet and append to output buffer. */ - cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); - cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), - buffer_len(&outgoing_packet)); - /* append unencrypted MAC */ - if (mac && mac->enabled) - buffer_append(&output, (char *)macbuf, mac->mac_len); -#ifdef PACKET_DEBUG - debug("encrypted output queue now contains (%d bytes):\n", - buffer_len(&output)); - buffer_dump(&output); -#endif - /* increment sequence number for outgoing packets */ - if (++p_send.seqnr == 0) - log("outgoing seqnr wraps around"); - - /* - * RFC 4344: 3.1. First Rekeying Recommendation - * - * "Because of possible information leakage through the MAC tag after a - * key exchange, .... an SSH implementation SHOULD NOT send more than - * 2**32 packets before rekeying again." - * - * The code below is a hard check so that we are sure we don't go across - * the suggestion. However, since the largest cipher block size we have - * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the - * same key while performing periodic rekeying. - */ - if (++p_send.packets == 0) - if (!(datafellows & SSH_BUG_NOREKEY)) - fatal("too many packets encrypted with same key"); - p_send.blocks += (packet_length + 4) / block_size; - buffer_clear(&outgoing_packet); - - if (type == SSH2_MSG_NEWKEYS) { - /* - * set_newkeys(MODE_OUT) in the client. Note that in the - * unprivileged child, set_newkeys() for MODE_OUT are set after - * SSH2_MSG_NEWKEYS is read from the monitor and forwarded to - * the client side. - */ - process_newkeys(MODE_OUT); - } -} - -/* - * Packets we deal with here are plain until we encrypt them in - * packet_send2_wrapped(). - * - * As already mentioned in a comment at process_newkeys() function we must not - * fork() until both SSH2_MSG_NEWKEYS packets were processed. Until this is done - * we must queue all packets so that they can be encrypted with the new keys and - * then sent to the other side. However, what can happen here is that we get - * SSH2_MSG_NEWKEYS after we sent it. In that situation we must call - * packet_send2() anyway to empty the queue, and set the rekey flag to the - * finished state. If we didn't do that we would just hang and enqueue data. - */ -static void -packet_send2(void) -{ - static int rekeying = 0; - struct packet *p; - u_char type, *cp; - - if (will_daemonize != SECOND_NEWKEYS_PROCESSED) { - cp = buffer_ptr(&outgoing_packet); - type = cp[5]; - - /* during rekeying we can only send key exchange messages */ - if (rekeying) { - if (!((type >= SSH2_MSG_TRANSPORT_MIN) && - (type <= SSH2_MSG_TRANSPORT_MAX))) { - debug("enqueue a plain packet because rekex in " - "progress [type %u]", type); - p = xmalloc(sizeof(*p)); - p->type = type; - memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); - buffer_init(&outgoing_packet); - TAILQ_INSERT_TAIL(&outgoing, p, next); - return; - } - } - - /* rekeying starts with sending KEXINIT */ - if (type == SSH2_MSG_KEXINIT) - rekeying = 1; - - packet_send2_wrapped(); - } - - /* after rekex is done we can process the queue of plain packets */ - if (will_daemonize == SECOND_NEWKEYS_PROCESSED || - (will_daemonize == NOT_DAEMONIZING && type == SSH2_MSG_NEWKEYS)) { - rekeying = 0; - will_daemonize = NOT_DAEMONIZING; - while ((p = TAILQ_FIRST(&outgoing)) != NULL) { - type = p->type; - debug("dequeuing a plain packet since rekex is over " - "[type %u]", type); - buffer_free(&outgoing_packet); - memcpy(&outgoing_packet, &p->payload, sizeof(Buffer)); - TAILQ_REMOVE(&outgoing, p, next); - xfree(p); - packet_send2_wrapped(); - } - } -} - -void -packet_send(void) -{ - if (compat20) - packet_send2(); - else - packet_send1(); - DBG(debug("packet_send done")); -} - -/* - * Waits until a packet has been received, and returns its type. Note that - * no other data is processed until this returns, so this function should not - * be used during the interactive session. - * - * The function is also used in the monitor to read the authentication context - * in aps_read_auth_context() via packet_read_seqnr(), before the monitor enters - * aps_monitor_loop() and starts using the process_input() function. - */ -int -packet_read_seqnr(u_int32_t *seqnr_p) -{ - int type, len; - fd_set *setp; - char buf[8192]; - DBG(debug("packet_read()")); - - setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * - sizeof(fd_mask)); - - /* Since we are blocking, ensure that all written packets have been sent. */ - packet_write_wait(); - - /* Stay in the loop until we have received a complete packet. */ - for (;;) { - /* Try to read a packet from the buffer. */ - type = packet_read_poll_seqnr(seqnr_p); - if (!compat20 && ( - type == SSH_SMSG_SUCCESS - || type == SSH_SMSG_FAILURE - || type == SSH_CMSG_EOF - || type == SSH_CMSG_EXIT_CONFIRMATION)) - packet_check_eom(); - /* If we got a packet, return it. */ - if (type != SSH_MSG_NONE) { - xfree(setp); - return type; - } - /* - * Otherwise, wait for some data to arrive, add it to the - * buffer, and try again. - */ - memset(setp, 0, howmany(connection_in + 1, NFDBITS) * - sizeof(fd_mask)); - FD_SET(connection_in, setp); - - /* Wait for some data to arrive. */ - while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && - (errno == EAGAIN || errno == EINTR)) - ; - - /* Read data from the socket. */ - len = read(connection_in, buf, sizeof(buf)); - if (len == 0) { - if (packet_connection_is_on_socket()) - log("Connection closed by %.200s", - get_remote_ipaddr()); - else - debug("child closed the communication pipe " - "before user auth was finished"); - fatal_cleanup(); - } - if (len < 0) { - if (packet_connection_is_on_socket()) - fatal("Read from socket failed: %.100s", - strerror(errno)); - else - fatal("Read from communication pipe failed: " - "%.100s", strerror(errno)); - } - /* Append it to the buffer. */ - packet_process_incoming(buf, len); - } - /* NOTREACHED */ -} - -int -packet_read(void) -{ - return packet_read_seqnr(NULL); -} - -/* - * Waits until a packet has been received, verifies that its type matches - * that given, and gives a fatal error and exits if there is a mismatch. - */ - -void -packet_read_expect(int expected_type) -{ - int type; - - type = packet_read(); - if (type != expected_type) - packet_disconnect("Protocol error: expected packet type %d, got %d", - expected_type, type); -} - -/* Checks if a full packet is available in the data received so far via - * packet_process_incoming. If so, reads the packet; otherwise returns - * SSH_MSG_NONE. This does not wait for data from the connection. - * - * SSH_MSG_DISCONNECT is handled specially here. Also, - * SSH_MSG_IGNORE messages are skipped by this function and are never returned - * to higher levels. - */ - -static int -packet_read_poll1(void) -{ - u_int len, padded_len; - u_char *cp, type; - u_int checksum, stored_checksum; - - /* Check if input size is less than minimum packet size. */ - if (buffer_len(&input) < 4 + 8) - return SSH_MSG_NONE; - /* Get length of incoming packet. */ - cp = buffer_ptr(&input); - len = GET_32BIT(cp); - if (len < 1 + 2 + 2 || len > 256 * 1024) - packet_disconnect("Bad packet length %d.", len); - padded_len = (len + 8) & ~7; - - /* Check if the packet has been entirely received. */ - if (buffer_len(&input) < 4 + padded_len) - return SSH_MSG_NONE; - - /* The entire packet is in buffer. */ - - /* Consume packet length. */ - buffer_consume(&input, 4); - - /* - * Cryptographic attack detector for ssh - * (C)1998 CORE-SDI, Buenos Aires Argentina - * Ariel Futoransky(futo@core-sdi.com) - */ - if (!receive_context.plaintext) { - switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) { - case DEATTACK_DETECTED: - packet_disconnect("crc32 compensation attack: " - "network attack detected"); - break; - case DEATTACK_DOS_DETECTED: - packet_disconnect("deattack denial of " - "service detected"); - break; - } - } - - /* Decrypt data to incoming_packet. */ - buffer_clear(&incoming_packet); - cp = buffer_append_space(&incoming_packet, padded_len); - cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); - - buffer_consume(&input, padded_len); - -#ifdef PACKET_DEBUG - debug("read_poll plain/full:\n"); - buffer_dump(&incoming_packet); -#endif - - /* Compute packet checksum. */ - checksum = ssh_crc32(buffer_ptr(&incoming_packet), - buffer_len(&incoming_packet) - 4); - - /* Skip padding. */ - buffer_consume(&incoming_packet, 8 - len % 8); - - /* Test check bytes. */ - if (len != buffer_len(&incoming_packet)) - packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", - len, buffer_len(&incoming_packet)); - - cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; - stored_checksum = GET_32BIT(cp); - if (checksum != stored_checksum) - packet_disconnect("Corrupted check bytes on input."); - buffer_consume_end(&incoming_packet, 4); - - if (packet_compression) { - buffer_clear(&compression_buffer); - buffer_uncompress(&incoming_packet, &compression_buffer); - buffer_clear(&incoming_packet); - buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), - buffer_len(&compression_buffer)); - } - type = buffer_get_char(&incoming_packet); - return type; -} - -static int -packet_read_poll2(u_int32_t *seqnr_p) -{ - static u_int packet_length = 0; - u_int padlen, need; - u_char *macbuf, *cp, type; - int maclen, block_size; - Enc *enc = NULL; - Mac *mac = NULL; - Comp *comp = NULL; - - if (newkeys[MODE_IN] != NULL) { - enc = &newkeys[MODE_IN]->enc; - mac = &newkeys[MODE_IN]->mac; - comp = &newkeys[MODE_IN]->comp; - } - maclen = mac && mac->enabled ? mac->mac_len : 0; - block_size = enc ? enc->block_size : 8; - - if (packet_length == 0) { - /* - * check if input size is less than the cipher block size, - * decrypt first block and extract length of incoming packet - */ - if (buffer_len(&input) < block_size) - return SSH_MSG_NONE; -#ifdef PACKET_DEBUG - debug("encrypted data we have in read queue (%d bytes):\n", - buffer_len(&input)); - buffer_dump(&input); -#endif - buffer_clear(&incoming_packet); - cp = buffer_append_space(&incoming_packet, block_size); - cipher_crypt(&receive_context, cp, buffer_ptr(&input), - block_size); - cp = buffer_ptr(&incoming_packet); - packet_length = GET_32BIT(cp); - if (packet_length < 1 + 4 || packet_length > 256 * 1024) { - packet_disconnect("Bad packet length."); - } - DBG(debug("input: packet len %u", packet_length + 4)); - buffer_consume(&input, block_size); - } - /* we have a partial packet of block_size bytes */ - need = 4 + packet_length - block_size; - DBG(debug("partial packet %d, still need %d, maclen %d", block_size, - need, maclen)); - if (need % block_size != 0) - packet_disconnect("Bad packet length."); - /* - * check if the entire packet has been received and - * decrypt into incoming_packet - */ - if (buffer_len(&input) < need + maclen) - return SSH_MSG_NONE; -#ifdef PACKET_DEBUG - debug("in read_poll, the encrypted input queue now contains " - "(%d bytes):\n", buffer_len(&input)); - buffer_dump(&input); -#endif - cp = buffer_append_space(&incoming_packet, need); - cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); - buffer_consume(&input, need); - /* - * compute MAC over seqnr and packet, - * increment sequence number for incoming packet - */ - if (mac && mac->enabled) { - macbuf = mac_compute(mac, p_read.seqnr, - buffer_ptr(&incoming_packet), - buffer_len(&incoming_packet)); - if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) - packet_disconnect("Corrupted MAC on input."); - DBG(debug("MAC #%d ok", p_read.seqnr)); - buffer_consume(&input, mac->mac_len); - } - if (seqnr_p != NULL) - *seqnr_p = p_read.seqnr; - if (++p_read.seqnr == 0) - log("incoming seqnr wraps around"); - - /* see above for the comment on "First Rekeying Recommendation" */ - if (++p_read.packets == 0) - if (!(datafellows & SSH_BUG_NOREKEY)) - fatal("too many packets with same key"); - p_read.blocks += (packet_length + 4) / block_size; - - /* get padlen */ - cp = buffer_ptr(&incoming_packet); - padlen = cp[4]; - DBG(debug("input: padlen %d", padlen)); - if (padlen < 4) - packet_disconnect("Corrupted padlen %d on input.", padlen); - - /* skip packet size + padlen, discard padding */ - buffer_consume(&incoming_packet, 4 + 1); - buffer_consume_end(&incoming_packet, padlen); - - DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); - if (comp && comp->enabled) { - buffer_clear(&compression_buffer); - buffer_uncompress(&incoming_packet, &compression_buffer); - buffer_clear(&incoming_packet); - buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), - buffer_len(&compression_buffer)); - DBG(debug("input: len after de-compress %d", - buffer_len(&incoming_packet))); - } - /* - * get packet type, implies consume. - * return length of payload (without type field) - */ - type = buffer_get_char(&incoming_packet); - if (type == SSH2_MSG_NEWKEYS) { - /* - * set_newkeys(MODE_IN) in the client because it doesn't have a - * dispatch function for SSH2_MSG_NEWKEYS in contrast to the - * server processes. Note that in the unprivileged child, - * set_newkeys() for MODE_IN are set in dispatch function - * altprivsep_rekey() after SSH2_MSG_NEWKEYS packet is received - * from the client. - */ - process_newkeys(MODE_IN); - } - -#ifdef PACKET_DEBUG - debug("decrypted input packet [type %d]:\n", type); - buffer_dump(&incoming_packet); -#endif - /* reset for next packet */ - packet_length = 0; - return type; -} - -/* - * This tries to read a packet from the buffer of received data. Note that it - * doesn't read() anything from the network socket. - */ -int -packet_read_poll_seqnr(u_int32_t *seqnr_p) -{ - u_int reason, seqnr; - u_char type; - char *msg; - - for (;;) { - if (compat20) { - type = packet_read_poll2(seqnr_p); - DBG(debug("received packet type %d", type)); - switch (type) { - case SSH2_MSG_IGNORE: - break; - case SSH2_MSG_DEBUG: - packet_get_char(); - msg = packet_get_utf8_string(NULL); - msg = g11n_filter_string(msg); - debug("Remote: %.900s", msg); - xfree(msg); - msg = packet_get_string(NULL); - xfree(msg); - break; - case SSH2_MSG_DISCONNECT: - reason = packet_get_int(); - msg = packet_get_utf8_string(NULL); - msg = g11n_filter_string(msg); - log("Received disconnect from %s: %u: %.400s", - get_remote_ipaddr(), reason, msg); - xfree(msg); - fatal_cleanup(); - break; - case SSH2_MSG_UNIMPLEMENTED: - seqnr = packet_get_int(); - debug("Received SSH2_MSG_UNIMPLEMENTED for %u", - seqnr); - break; - default: - return type; - break; - } - } else { - type = packet_read_poll1(); - DBG(debug("received packet type %d", type)); - switch (type) { - case SSH_MSG_IGNORE: - break; - case SSH_MSG_DEBUG: - msg = packet_get_string(NULL); - debug("Remote: %.900s", msg); - xfree(msg); - break; - case SSH_MSG_DISCONNECT: - msg = packet_get_string(NULL); - log("Received disconnect from %s: %.400s", - get_remote_ipaddr(), msg); - fatal_cleanup(); - xfree(msg); - break; - default: - return type; - break; - } - } - } -} - -int -packet_read_poll(void) -{ - return packet_read_poll_seqnr(NULL); -} - -/* - * Buffers the given amount of input characters. This is intended to be used - * together with packet_read_poll. - */ - -void -packet_process_incoming(const char *buf, u_int len) -{ - buffer_append(&input, buf, len); -} - -/* Returns a character from the packet. */ - -u_int -packet_get_char(void) -{ - char ch; - - buffer_get(&incoming_packet, &ch, 1); - return (u_char) ch; -} - -/* Returns an integer from the packet data. */ - -u_int -packet_get_int(void) -{ - return buffer_get_int(&incoming_packet); -} - -/* - * Returns an arbitrary precision integer from the packet data. The integer - * must have been initialized before this call. - */ - -void -packet_get_bignum(BIGNUM * value) -{ - buffer_get_bignum(&incoming_packet, value); -} - -void -packet_get_bignum2(BIGNUM * value) -{ - buffer_get_bignum2(&incoming_packet, value); -} - -void * -packet_get_raw(u_int *length_ptr) -{ - u_int bytes = buffer_len(&incoming_packet); - - if (length_ptr != NULL) - *length_ptr = bytes; - return buffer_ptr(&incoming_packet); -} - -int -packet_remaining(void) -{ - return buffer_len(&incoming_packet); -} - -/* - * Returns a string from the packet data. The string is allocated using - * xmalloc; it is the responsibility of the calling program to free it when - * no longer needed. The length_ptr argument may be NULL, or point to an - * integer into which the length of the string is stored. - */ - -void * -packet_get_string(u_int *length_ptr) -{ - return buffer_get_string(&incoming_packet, length_ptr); -} - -char * -packet_get_utf8_string(uint_t *length_ptr) -{ - if (datafellows & SSH_BUG_STRING_ENCODING) - return (buffer_get_string(&incoming_packet, length_ptr)); - else - return (buffer_get_utf8_string(&incoming_packet, length_ptr)); -} - -/* - * Sends a diagnostic message from the server to the client. This message - * can be sent at any time (but not while constructing another message). The - * message is printed immediately, but only if the client is being executed - * in verbose mode. These messages are primarily intended to ease debugging - * authentication problems. The length of the formatted message must not - * exceed 1024 bytes. This will automatically call packet_write_wait. - */ - -void -packet_send_debug(const char *fmt,...) -{ - char buf[1024]; - va_list args; - - if (compat20 && (datafellows & SSH_BUG_DEBUG)) - return; - - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), gettext(fmt), args); - va_end(args); - -#ifdef ALTPRIVSEP - /* shouldn't happen */ - if (packet_monitor) { - debug("packet_send_debug: %s", buf); - return; - } -#endif /* ALTPRIVSEP */ - - if (compat20) { - packet_start(SSH2_MSG_DEBUG); - packet_put_char(0); /* bool: always display */ - packet_put_utf8_cstring(buf); - packet_put_cstring(""); - } else { - packet_start(SSH_MSG_DEBUG); - packet_put_cstring(buf); - } - packet_send(); - packet_write_wait(); -} - -/* - * Logs the error plus constructs and sends a disconnect packet, closes the - * connection, and exits. This function never returns. The error message - * should not contain a newline. The length of the formatted message must - * not exceed 1024 bytes. - */ - -void -packet_disconnect(const char *fmt,...) -{ - char buf[1024]; - va_list args; - static int disconnecting = 0; - - if (disconnecting) /* Guard against recursive invocations. */ - fatal("packet_disconnect called recursively."); - disconnecting = 1; - - /* - * Format the message. Note that the caller must make sure the - * message is of limited size. - */ - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - -#ifdef ALTPRIVSEP - /* - * If we packet_disconnect() in the monitor the fatal cleanups will take - * care of the child. See main() in sshd.c. We don't send the packet - * disconnect message here because: a) the child might not be looking - * for it and b) because we don't really know if the child is compat20 - * or not as we lost that information when packet_set_monitor() was - * called. - */ - if (packet_monitor) - goto close_stuff; -#endif /* ALTPRIVSEP */ - - /* Send the disconnect message to the other side, and wait for it to get sent. */ - if (compat20) { - packet_start(SSH2_MSG_DISCONNECT); - packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); - packet_put_utf8_cstring(buf); - packet_put_cstring(""); - } else { - packet_start(SSH_MSG_DISCONNECT); - packet_put_cstring(buf); - } - packet_send(); - packet_write_wait(); - -#ifdef ALTPRIVSEP -close_stuff: -#endif /* ALTPRIVSEP */ - /* Stop listening for connections. */ - channel_close_all(); - - /* Close the connection. */ - packet_close(); - - /* Display the error locally and exit. */ - log("Disconnecting: %.100s", buf); - fatal_cleanup(); -} - -/* Checks if there is any buffered output, and tries to write some of the output. */ - -void -packet_write_poll(void) -{ - int len = buffer_len(&output); - - if (len > 0) { - len = write(connection_out, buffer_ptr(&output), len); - if (len <= 0) { - if (errno == EAGAIN) - return; - else - fatal("Write failed: %.100s", strerror(errno)); - } -#ifdef PACKET_DEBUG - debug("in packet_write_poll, %d bytes just sent to the " - "remote side", len); -#endif - buffer_consume(&output, len); - } -} - -/* - * Calls packet_write_poll repeatedly until all pending output data has been - * written. - */ - -void -packet_write_wait(void) -{ - fd_set *setp; - - setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * - sizeof(fd_mask)); - packet_write_poll(); - while (packet_have_data_to_write()) { - memset(setp, 0, howmany(connection_out + 1, NFDBITS) * - sizeof(fd_mask)); - FD_SET(connection_out, setp); - while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && - (errno == EAGAIN || errno == EINTR)) - ; - packet_write_poll(); - } - xfree(setp); -} - -/* Returns true if there is buffered data to write to the connection. */ - -int -packet_have_data_to_write(void) -{ - return buffer_len(&output) != 0; -} - -/* Returns true if there is not too much data to write to the connection. */ - -int -packet_not_very_much_data_to_write(void) -{ - if (interactive_mode) - return buffer_len(&output) < 16384; - else - return buffer_len(&output) < 128 * 1024; -} - -/* Informs that the current session is interactive. Sets IP flags for that. */ - -void -packet_set_interactive(int interactive) -{ - static int called = 0; -#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) - int lowdelay = IPTOS_LOWDELAY; - int throughput = IPTOS_THROUGHPUT; -#endif - - if (called) - return; - called = 1; - - /* Record that we are in interactive mode. */ - interactive_mode = interactive; - - /* Only set socket options if using a socket. */ - if (!packet_connection_is_on_socket()) - return; - /* - * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only - */ - if (interactive) { - /* - * Set IP options for an interactive connection. Use - * IPTOS_LOWDELAY and TCP_NODELAY. - */ -#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) - if (packet_connection_is_ipv4()) { - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, - &lowdelay, sizeof(lowdelay)) < 0) - error("setsockopt IPTOS_LOWDELAY: %.100s", - strerror(errno)); - } -#endif - set_nodelay(connection_in); - } -#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) - else if (packet_connection_is_ipv4()) { - /* - * Set IP options for a non-interactive connection. Use - * IPTOS_THROUGHPUT. - */ - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, - sizeof(throughput)) < 0) - error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); - } -#endif -} - -/* Returns true if the current connection is interactive. */ - -int -packet_is_interactive(void) -{ - return interactive_mode; -} - -int -packet_set_maxsize(int s) -{ - static int called = 0; - - if (called) { - log("packet_set_maxsize: called twice: old %d new %d", - max_packet_size, s); - return -1; - } - if (s < 4 * 1024 || s > 1024 * 1024) { - log("packet_set_maxsize: bad size %d", s); - return -1; - } - called = 1; - debug("packet_set_maxsize: setting to %d", s); - max_packet_size = s; - return s; -} - -/* roundup current message to pad bytes */ -void -packet_add_padding(u_char pad) -{ - extra_pad = pad; -} - -/* - * 9.2. Ignored Data Message - * - * byte SSH_MSG_IGNORE - * string data - * - * All implementations MUST understand (and ignore) this message at any - * time (after receiving the protocol version). No implementation is - * required to send them. This message can be used as an additional - * protection measure against advanced traffic analysis techniques. - */ -void -packet_send_ignore(int nbytes) -{ - u_int32_t rnd = 0; - int i; - -#ifdef ALTPRIVSEP - /* shouldn't happen -- see packet_set_monitor() */ - if (packet_monitor) - return; -#endif /* ALTPRIVSEP */ - - packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); - packet_put_int(nbytes); - for (i = 0; i < nbytes; i++) { - if (i % 4 == 0) - rnd = arc4random(); - packet_put_char((u_char)rnd & 0xff); - rnd >>= 8; - } -} - -#define MAX_PACKETS (1U<<31) -int -packet_need_rekeying(void) -{ - if (datafellows & SSH_BUG_NOREKEY) - return 0; - return - (p_send.packets > MAX_PACKETS) || - (p_read.packets > MAX_PACKETS) || - (max_blocks_out && (p_send.blocks > max_blocks_out)) || - (max_blocks_in && (p_read.blocks > max_blocks_in)); -} - -void -packet_set_rekey_limit(u_int32_t bytes) -{ - rekey_limit = bytes; -} - -#ifdef ALTPRIVSEP -void -packet_set_server(void) -{ - packet_server = 1; -} - -int -packet_is_server(void) -{ - return (packet_server); -} - -void -packet_set_monitor(int pipe) -{ - int dup_fd; - - packet_server = 1; - packet_monitor = 1; - - /* - * Awful hack follows. - * - * For SSHv1 the monitor does not process any SSHv1 packets, only - * ALTPRIVSEP packets. We take advantage of that here to keep changes - * to packet.c to a minimum by using the SSHv2 binary packet protocol, - * with cipher "none," mac "none" and compression alg "none," as the - * basis for the monitor protocol. And so to force packet.c to treat - * packets as SSHv2 we force compat20 == 1 here. - * - * For completeness and to help future developers catch this we also - * force compat20 == 1 in the monitor loop, in serverloop.c. - */ - compat20 = 1; - - /* - * NOTE: Assumptions below! - * - * - lots of packet.c code assumes that (connection_in == - * connection_out) -> connection is socket - * - * - packet_close() does not shutdown() the connection fildes - * if connection_in != connection_out - * - * - other code assumes the connection is a socket if - * connection_in == connection_out - */ - - if ((dup_fd = dup(pipe)) < 0) - fatal("Monitor failed to start: %s", strerror(errno)); - - /* - * make sure that the monitor's child's socket is not shutdown(3SOCKET) - * when we packet_close(). Setting connection_out to -1 will take care - * of that. - */ - if (packet_connection_is_on_socket()) - connection_out = -1; - - /* - * Now clean up the state related to the server socket. As a side - * effect, we also clean up existing cipher contexts that were - * initialized with 'none' cipher in packet_set_connection(). That - * function was called in the child server process shortly after the - * master SSH process forked. However, all of that is reinialized again - * by another packet_set_connection() call right below. - */ - packet_close(); - - /* - * Now make the monitor pipe look like the ssh connection which means - * that connection_in and connection_out will be set to the - * communication pipe descriptors. - */ - packet_set_connection(pipe, dup_fd); -} - -/* - * We temporarily need to set connection_in and connection_out descriptors so - * that we can make use of existing code that gets the IP address and hostname - * of the peer to write a login/logout record. It's not nice but we would have - * to change more code when implementing the PKCS#11 engine support. - */ -void -packet_set_fds(int fd, int restore) -{ - static int stored_fd; - - if (stored_fd == 0 && restore == 0) { - debug3("packet_set_fds: saving %d, installing %d", - connection_in, fd); - stored_fd = connection_in; - /* we don't have a socket in inetd mode */ - if (fd != -1) - connection_in = connection_out = fd; - return; - } - - if (restore == 1) { - debug3("restoring %d to connection_in/out", stored_fd); - connection_in = connection_out = stored_fd; - } -} - -int -packet_is_monitor(void) -{ - return (packet_monitor); -} -#endif /* ALTPRIVSEP */ diff --git a/usr/src/cmd/ssh/libssh/common/progressmeter.c b/usr/src/cmd/ssh/libssh/common/progressmeter.c deleted file mode 100644 index 65d28fb596..0000000000 --- a/usr/src/cmd/ssh/libssh/common/progressmeter.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2003 Nils Nordman. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $OpenBSD: progressmeter.c,v 1.37 2006/08/03 03:34:42 deraadt Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/uio.h> - -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include "progressmeter.h" -#include "atomicio.h" -#include "misc.h" - -#define DEFAULT_WINSIZE 80 -#define MAX_WINSIZE 512 -#define PADDING 1 /* padding between the progress indicators */ -#define UPDATE_INTERVAL 1 /* update the progress meter every second */ -#define STALL_TIME 5 /* we're stalled after this many seconds */ - -/* determines whether we can output to the terminal */ -static int can_output(void); - -/* formats and inserts the specified size into the given buffer */ -static void format_size(char *, int, off_t); -static void format_rate(char *, int, off_t); - -/* window resizing */ -static void sig_winch(int); -static void setscreensize(void); - -/* updates the progressmeter to reflect the current state of the transfer */ -void refresh_progress_meter(void); - -/* signal handler for updating the progress meter */ -static void update_progress_meter(int); - -static time_t start; /* start progress */ -static time_t last_update; /* last progress update */ -static char *file; /* name of the file being transferred */ -static off_t end_pos; /* ending position of transfer */ -static off_t cur_pos; /* transfer position as of last refresh */ -static volatile off_t *counter; /* progress counter */ -static long stalled; /* how long we have been stalled */ -static int bytes_per_second; /* current speed in bytes per second */ -static int win_size; /* terminal window size */ -static volatile sig_atomic_t win_resized; /* for window resizing */ - -/* units for format_size */ -static const char unit[] = " KMGT"; - -static int -can_output(void) -{ - return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); -} - -static void -format_rate(char *buf, int size, off_t bytes) -{ - int i; - - bytes *= 100; - for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++) - bytes = (bytes + 512) / 1024; - if (i == 0) { - i++; - bytes = (bytes + 512) / 1024; - } - snprintf(buf, size, "%3lld.%1lld%c%s", - (long long) (bytes + 5) / 100, - (long long) (bytes + 5) / 10 % 10, - unit[i], - i ? "B" : " "); -} - -static void -format_size(char *buf, int size, off_t bytes) -{ - int i; - - for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++) - bytes = (bytes + 512) / 1024; - snprintf(buf, size, "%4lld%c%s", - (long long) bytes, - unit[i], - i ? "B" : " "); -} - -void -refresh_progress_meter(void) -{ - char buf[MAX_WINSIZE + 1]; - time_t now; - off_t transferred; - double elapsed; - int percent; - off_t bytes_left; - int cur_speed; - int hours, minutes, seconds; - int i, len; - int file_len; - - transferred = *counter - cur_pos; - cur_pos = *counter; - now = time(NULL); - bytes_left = end_pos - cur_pos; - - if (bytes_left > 0) - elapsed = now - last_update; - else { - elapsed = now - start; - /* Calculate true total speed when done */ - transferred = end_pos; - bytes_per_second = 0; - } - - /* calculate speed */ - if (elapsed != 0) - cur_speed = (int)(transferred / elapsed); - else - cur_speed = transferred; - -#define AGE_FACTOR 0.9 - if (bytes_per_second != 0) { - bytes_per_second = (int)((bytes_per_second * AGE_FACTOR) + - (cur_speed * (1.0 - AGE_FACTOR))); - } else - bytes_per_second = cur_speed; - - /* filename */ - buf[0] = '\0'; - file_len = win_size - 35; - if (file_len > 0) { - len = snprintf(buf, file_len + 1, "\r%s", file); - if (len < 0) - len = 0; - if (len >= file_len + 1) - len = file_len; - for (i = len; i < file_len; i++) - buf[i] = ' '; - buf[file_len] = '\0'; - } - - /* percent of transfer done */ - if (end_pos != 0) - percent = (int)(((float)cur_pos / end_pos) * 100); - else - percent = 100; - snprintf(buf + strlen(buf), win_size - strlen(buf), - " %3d%% ", percent); - - /* amount transferred */ - format_size(buf + strlen(buf), win_size - strlen(buf), - cur_pos); - strlcat(buf, " ", win_size); - - /* bandwidth usage */ - format_rate(buf + strlen(buf), win_size - strlen(buf), - (off_t)bytes_per_second); - strlcat(buf, "/s ", win_size); - - /* ETA */ - if (!transferred) - stalled += elapsed; - else - stalled = 0; - - if (stalled >= STALL_TIME) - strlcat(buf, "- stalled -", win_size); - else if (bytes_per_second == 0 && bytes_left) - strlcat(buf, " --:-- ETA", win_size); - else { - if (bytes_left > 0) - seconds = bytes_left / bytes_per_second; - else - seconds = (int)elapsed; - - hours = seconds / 3600; - seconds -= hours * 3600; - minutes = seconds / 60; - seconds -= minutes * 60; - - if (hours != 0) - snprintf(buf + strlen(buf), win_size - strlen(buf), - "%d:%02d:%02d", hours, minutes, seconds); - else - snprintf(buf + strlen(buf), win_size - strlen(buf), - " %02d:%02d", minutes, seconds); - - if (bytes_left > 0) - strlcat(buf, " ETA", win_size); - else - strlcat(buf, " ", win_size); - } - - atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); - last_update = now; -} - -/*ARGSUSED*/ -static void -update_progress_meter(int ignore) -{ - int save_errno; - - save_errno = errno; - - if (win_resized) { - setscreensize(); - win_resized = 0; - } - if (can_output()) - refresh_progress_meter(); - - signal(SIGALRM, update_progress_meter); - alarm(UPDATE_INTERVAL); - errno = save_errno; -} - -void -start_progress_meter(char *f, off_t filesize, off_t *ctr) -{ - start = last_update = time(NULL); - file = f; - end_pos = filesize; - cur_pos = 0; - counter = ctr; - stalled = 0; - bytes_per_second = 0; - - setscreensize(); - if (can_output()) - refresh_progress_meter(); - - signal(SIGALRM, update_progress_meter); - signal(SIGWINCH, sig_winch); - alarm(UPDATE_INTERVAL); -} - -void -stop_progress_meter(void) -{ - alarm(0); - - if (!can_output()) - return; - - /* Ensure we complete the progress */ - if (cur_pos != end_pos) - refresh_progress_meter(); - - atomicio(vwrite, STDOUT_FILENO, "\n", 1); -} - -/*ARGSUSED*/ -static void -sig_winch(int sig) -{ - win_resized = 1; -} - -static void -setscreensize(void) -{ - struct winsize winsize; - - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 && - winsize.ws_col != 0) { - if (winsize.ws_col > MAX_WINSIZE) - win_size = MAX_WINSIZE; - else - win_size = winsize.ws_col; - } else - win_size = DEFAULT_WINSIZE; - win_size += 1; /* trailing \0 */ -} diff --git a/usr/src/cmd/ssh/libssh/common/proxy-io.c b/usr/src/cmd/ssh/libssh/common/proxy-io.c deleted file mode 100644 index c025f28f0a..0000000000 --- a/usr/src/cmd/ssh/libssh/common/proxy-io.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <unistd.h> -#include "proxy-io.h" - -int -proxy_read_write_loop(int readfd, int writefd) -{ - int rbytes, bytes_to_write, bytes_written; - char readbuf[BUFFER_SIZ]; - char *ptr; - - rbytes = read(readfd, readbuf, sizeof (readbuf)); - - if (rbytes > 0) { - bytes_to_write = rbytes; - ptr = readbuf; - while (bytes_to_write > 0) { - if ((bytes_written = - write(writefd, ptr, bytes_to_write)) < 0) { - perror("write"); - return (0); - } - bytes_to_write -= bytes_written; - ptr += bytes_written; - } - } else if (rbytes <= 0) { - return (0); - } - /* Read and write successful */ - return (1); -} diff --git a/usr/src/cmd/ssh/libssh/common/radix.c b/usr/src/cmd/ssh/libssh/common/radix.c deleted file mode 100644 index 4200f71b3b..0000000000 --- a/usr/src/cmd/ssh/libssh/common/radix.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 1999 Dug Song. All rights reserved. - * Copyright (c) 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#include "uuencode.h" - -RCSID("$OpenBSD: radix.c,v 1.22 2002/09/09 14:54:15 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef AFS -#include <krb.h> - -#include <radix.h> -#include "bufaux.h" - -int -creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen) -{ - Buffer b; - int ret; - - buffer_init(&b); - - buffer_put_char(&b, 1); /* version */ - - buffer_append(&b, creds->service, strlen(creds->service)); - buffer_put_char(&b, '\0'); - buffer_append(&b, creds->instance, strlen(creds->instance)); - buffer_put_char(&b, '\0'); - buffer_append(&b, creds->realm, strlen(creds->realm)); - buffer_put_char(&b, '\0'); - buffer_append(&b, creds->pname, strlen(creds->pname)); - buffer_put_char(&b, '\0'); - buffer_append(&b, creds->pinst, strlen(creds->pinst)); - buffer_put_char(&b, '\0'); - - /* Null string to repeat the realm. */ - buffer_put_char(&b, '\0'); - - buffer_put_int(&b, creds->issue_date); - buffer_put_int(&b, krb_life_to_time(creds->issue_date, - creds->lifetime)); - buffer_append(&b, creds->session, sizeof(creds->session)); - buffer_put_short(&b, creds->kvno); - - /* 32 bit size + data */ - buffer_put_string(&b, creds->ticket_st.dat, creds->ticket_st.length); - - ret = uuencode(buffer_ptr(&b), buffer_len(&b), (char *)buf, buflen); - - buffer_free(&b); - return ret; -} - -#define GETSTRING(b, t, tlen) \ - do { \ - int i, found = 0; \ - for (i = 0; i < tlen; i++) { \ - if (buffer_len(b) == 0) \ - goto done; \ - t[i] = buffer_get_char(b); \ - if (t[i] == '\0') { \ - found = 1; \ - break; \ - } \ - } \ - if (!found) \ - goto done; \ - } while(0) - -int -radix_to_creds(const char *buf, CREDENTIALS *creds) -{ - Buffer b; - u_char *space; - char c, version, *p; - u_int endTime, len; - int blen, ret; - - ret = 0; - blen = strlen(buf); - - /* sanity check for size */ - if (blen > 8192) - return 0; - - buffer_init(&b); - space = buffer_append_space(&b, blen); - - /* check version and length! */ - len = uudecode(buf, space, blen); - if (len < 1) - goto done; - - version = buffer_get_char(&b); - - GETSTRING(&b, creds->service, sizeof creds->service); - GETSTRING(&b, creds->instance, sizeof creds->instance); - GETSTRING(&b, creds->realm, sizeof creds->realm); - GETSTRING(&b, creds->pname, sizeof creds->pname); - GETSTRING(&b, creds->pinst, sizeof creds->pinst); - - if (buffer_len(&b) == 0) - goto done; - - /* Ignore possibly different realm. */ - while (buffer_len(&b) > 0 && (c = buffer_get_char(&b)) != '\0') - ; - - if (buffer_len(&b) == 0) - goto done; - - creds->issue_date = buffer_get_int(&b); - - endTime = buffer_get_int(&b); - creds->lifetime = krb_time_to_life(creds->issue_date, endTime); - - len = buffer_len(&b); - if (len < sizeof(creds->session)) - goto done; - memcpy(&creds->session, buffer_ptr(&b), sizeof(creds->session)); - buffer_consume(&b, sizeof(creds->session)); - - creds->kvno = buffer_get_short(&b); - - p = buffer_get_string(&b, &len); - if (len < 0 || len > sizeof(creds->ticket_st.dat)) - goto done; - memcpy(&creds->ticket_st.dat, p, len); - creds->ticket_st.length = len; - - ret = 1; -done: - buffer_free(&b); - return ret; -} -#endif /* AFS */ diff --git a/usr/src/cmd/ssh/libssh/common/readconf.c b/usr/src/cmd/ssh/libssh/common/readconf.c deleted file mode 100644 index b1e7f89c7a..0000000000 --- a/usr/src/cmd/ssh/libssh/common/readconf.c +++ /dev/null @@ -1,1276 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Functions for reading the configuration files. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright 2013 Joyent, Inc. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $"); - -#include "ssh.h" -#include "xmalloc.h" -#include "compat.h" -#include "cipher.h" -#include "pathnames.h" -#include "log.h" -#include "readconf.h" -#include "match.h" -#include "misc.h" -#include "kex.h" -#include "mac.h" - -/* Format of the configuration file: - - # Configuration data is parsed as follows: - # 1. command line options - # 2. user-specific file - # 3. system-wide file - # Any configuration value is only changed the first time it is set. - # Thus, host-specific definitions should be at the beginning of the - # configuration file, and defaults at the end. - - # Host-specific declarations. These may override anything above. A single - # host may match multiple declarations; these are processed in the order - # that they are given in. - - Host *.ngs.fi ngs.fi - User foo - - Host fake.com - HostName another.host.name.real.org - User blaah - Port 34289 - ForwardX11 no - ForwardAgent no - - Host books.com - RemoteForward 9999 shadows.cs.hut.fi:9999 - Cipher 3des - - Host fascist.blob.com - Port 23123 - User tylonen - RhostsAuthentication no - PasswordAuthentication no - - Host puukko.hut.fi - User t35124p - ProxyCommand ssh-proxy %h %p - - Host *.fr - PublicKeyAuthentication no - - Host *.su - Cipher none - PasswordAuthentication no - - # Defaults for various options - Host * - ForwardAgent no - ForwardX11 no - RhostsAuthentication yes - PasswordAuthentication yes - RSAAuthentication yes - RhostsRSAAuthentication yes - StrictHostKeyChecking yes - KeepAlives no - IdentityFile ~/.ssh/identity - Port 22 - EscapeChar ~ - -*/ - -/* Keyword tokens. */ - -typedef enum { - oBadOption, - oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, - oRhostsAuthentication, - oPasswordAuthentication, oRSAAuthentication, - oChallengeResponseAuthentication, oXAuthLocation, -#if defined(KRB4) || defined(KRB5) - oKerberosAuthentication, -#endif -#ifdef GSSAPI - oGssKeyEx, oGssAuthentication, oGssDelegateCreds, -#ifdef GSI - oGssGlobusDelegateLimitedCreds, -#endif /* GSI */ -#endif /* GSSAPI */ -#if defined(AFS) || defined(KRB5) - oKerberosTgtPassing, -#endif -#ifdef AFS - oAFSTokenPassing, -#endif - oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, - oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, - oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, - oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, - oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, - oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, - oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, - oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, - oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, - oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, - oClearAllForwardings, oNoHostAuthenticationForLocalhost, - oFallBackToRsh, oUseRsh, oConnectTimeout, oHashKnownHosts, - oServerAliveInterval, oServerAliveCountMax, oDisableBanner, - oIgnoreIfUnknown, oRekeyLimit, oUseOpenSSLEngine, - oDeprecated -} OpCodes; - -/* Textual representations of the tokens. */ - -static struct { - const char *name; - OpCodes opcode; -} keywords[] = { - { "forwardagent", oForwardAgent }, - { "forwardx11", oForwardX11 }, - { "forwardx11trusted", oForwardX11Trusted }, - { "xauthlocation", oXAuthLocation }, - { "gatewayports", oGatewayPorts }, - { "useprivilegedport", oUsePrivilegedPort }, - { "rhostsauthentication", oRhostsAuthentication }, - { "passwordauthentication", oPasswordAuthentication }, - { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, - { "kbdinteractivedevices", oKbdInteractiveDevices }, - { "rsaauthentication", oRSAAuthentication }, - { "pubkeyauthentication", oPubkeyAuthentication }, - { "dsaauthentication", oPubkeyAuthentication }, /* alias */ - { "rhostsrsaauthentication", oRhostsRSAAuthentication }, - { "hostbasedauthentication", oHostbasedAuthentication }, - { "challengeresponseauthentication", oChallengeResponseAuthentication }, - { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ - { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ -#if defined(KRB4) || defined(KRB5) - { "kerberosauthentication", oKerberosAuthentication }, -#endif -#ifdef GSSAPI - { "gssapikeyexchange", oGssKeyEx }, - { "gssapiauthentication", oGssAuthentication }, - { "gssapidelegatecredentials", oGssDelegateCreds }, - { "gsskeyex", oGssKeyEx }, /* alias */ - { "gssauthentication", oGssAuthentication }, /* alias */ - { "gssdelegatecreds", oGssDelegateCreds }, /* alias */ -#ifdef GSI - /* For backwards compatability with old 1.2.27 client code */ - { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */ - { "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds }, -#endif /* GSI */ -#endif /* GSSAPI */ -#if defined(AFS) || defined(KRB5) - { "kerberostgtpassing", oKerberosTgtPassing }, -#endif -#ifdef AFS - { "afstokenpassing", oAFSTokenPassing }, -#endif - { "fallbacktorsh", oFallBackToRsh }, - { "usersh", oUseRsh }, - { "identityfile", oIdentityFile }, - { "identityfile2", oIdentityFile }, /* alias */ - { "hostname", oHostName }, - { "hostkeyalias", oHostKeyAlias }, - { "proxycommand", oProxyCommand }, - { "port", oPort }, - { "cipher", oCipher }, - { "ciphers", oCiphers }, - { "macs", oMacs }, - { "protocol", oProtocol }, - { "remoteforward", oRemoteForward }, - { "localforward", oLocalForward }, - { "user", oUser }, - { "host", oHost }, - { "escapechar", oEscapeChar }, - { "globalknownhostsfile", oGlobalKnownHostsFile }, - { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ - { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, - { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ - { "connectionattempts", oConnectionAttempts }, - { "batchmode", oBatchMode }, - { "checkhostip", oCheckHostIP }, - { "stricthostkeychecking", oStrictHostKeyChecking }, - { "compression", oCompression }, - { "compressionlevel", oCompressionLevel }, - { "tcpkeepalive", oKeepAlives }, - { "keepalive", oKeepAlives }, /* obsolete */ - { "numberofpasswordprompts", oNumberOfPasswordPrompts }, - { "loglevel", oLogLevel }, - { "dynamicforward", oDynamicForward }, - { "preferredauthentications", oPreferredAuthentications }, - { "hostkeyalgorithms", oHostKeyAlgorithms }, - { "bindaddress", oBindAddress }, - { "smartcarddevice", oSmartcardDevice }, - { "clearallforwardings", oClearAllForwardings }, - { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, - { "rekeylimit", oRekeyLimit }, - { "connecttimeout", oConnectTimeout }, - { "serveraliveinterval", oServerAliveInterval }, - { "serveralivecountmax", oServerAliveCountMax }, - { "disablebanner", oDisableBanner }, - { "hashknownhosts", oHashKnownHosts }, - { "ignoreifunknown", oIgnoreIfUnknown }, - { "useopensslengine", oUseOpenSSLEngine }, - { NULL, oBadOption } -}; - -/* - * Adds a local TCP/IP port forward to options. Never returns if there is an - * error. - */ - -void -add_local_forward(Options *options, const Forward *newfwd) -{ - Forward *fwd; -#ifndef NO_IPPORT_RESERVED_CONCEPT - extern uid_t original_real_uid; - if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) - fatal("Privileged ports can only be forwarded by root."); -#endif - if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) - fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); - fwd = &options->local_forwards[options->num_local_forwards++]; - - fwd->listen_host = (newfwd->listen_host == NULL) ? - NULL : xstrdup(newfwd->listen_host); - fwd->listen_port = newfwd->listen_port; - fwd->connect_host = xstrdup(newfwd->connect_host); - fwd->connect_port = newfwd->connect_port; -} - -/* - * Adds a remote TCP/IP port forward to options. Never returns if there is - * an error. - */ - -void -add_remote_forward(Options *options, const Forward *newfwd) -{ - Forward *fwd; - if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) - fatal("Too many remote forwards (max %d).", - SSH_MAX_FORWARDS_PER_DIRECTION); - fwd = &options->remote_forwards[options->num_remote_forwards++]; - - fwd->listen_host = (newfwd->listen_host == NULL) ? - NULL : xstrdup(newfwd->listen_host); - fwd->listen_port = newfwd->listen_port; - fwd->connect_host = xstrdup(newfwd->connect_host); - fwd->connect_port = newfwd->connect_port; -} - -static void -clear_forwardings(Options *options) -{ - int i; - - for (i = 0; i < options->num_local_forwards; i++) { - if (options->local_forwards[i].listen_host != NULL) - xfree(options->local_forwards[i].listen_host); - xfree(options->local_forwards[i].connect_host); - } - options->num_local_forwards = 0; - for (i = 0; i < options->num_remote_forwards; i++) { - if (options->remote_forwards[i].listen_host != NULL) - xfree(options->remote_forwards[i].listen_host); - xfree(options->remote_forwards[i].connect_host); - } - options->num_remote_forwards = 0; -} - -/* - * Returns the number of the token pointed to by cp or oBadOption. - */ - -static OpCodes -parse_token(const char *cp, const char *filename, int linenum) -{ - u_int i; - - for (i = 0; keywords[i].name; i++) - if (strcasecmp(cp, keywords[i].name) == 0) - return keywords[i].opcode; - - debug("%s: line %d: unknown configuration option: %s", - filename, linenum, cp); - return oBadOption; -} - -/* - * Processes a single option line as used in the configuration files. This - * only sets those values that have not already been set. - */ - -int -process_config_line(Options *options, const char *host, - char *line, const char *filename, int linenum, - int *activep) -{ - char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; - int opcode, *intptr, value, scale, i; - long long orig, val64; - StoredOption *so; - Forward fwd; - - s = line; - /* Get the keyword. (Each line is supposed to begin with a keyword). */ - keyword = strdelim(&s); - /* Ignore leading whitespace. */ - if (*keyword == '\0') - keyword = strdelim(&s); - if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') - return 0; - - opcode = parse_token(keyword, filename, linenum); - - switch (opcode) { - case oBadOption: - if (options->unknown_opts_num == MAX_UNKNOWN_OPTIONS) { - error("we can't have more than %d unknown options:", - MAX_UNKNOWN_OPTIONS); - for (i = 0; i < MAX_UNKNOWN_OPTIONS; ++i) { - so = &options->unknown_opts[i]; - error("%s:%d:%s", - so->filename, so->linenum, so->keyword); - xfree(so->keyword); - xfree(so->filename); - } - fatal("too many unknown options found, can't continue"); - } - - /* unknown options will be processed later */ - so = &options->unknown_opts[options->unknown_opts_num]; - so->keyword = xstrdup(keyword); - so->filename = xstrdup(filename); - so->linenum = linenum; - options->unknown_opts_num++; - return (0); - - /* NOTREACHED */ - case oConnectTimeout: - intptr = &options->connection_timeout; -parse_time: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%s line %d: missing time value.", - filename, linenum); - if ((value = convtime(arg)) == -1) - fatal("%s line %d: invalid time value.", - filename, linenum); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case oForwardAgent: - intptr = &options->forward_agent; -parse_flag: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); - value = 0; /* To avoid compiler warning... */ - if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) - value = 1; - else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) - value = 0; - else - fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case oForwardX11: - intptr = &options->forward_x11; - goto parse_flag; - - case oForwardX11Trusted: - intptr = &options->forward_x11_trusted; - goto parse_flag; - - case oGatewayPorts: - intptr = &options->gateway_ports; - goto parse_flag; - - case oUsePrivilegedPort: - intptr = &options->use_privileged_port; - goto parse_flag; - - case oRhostsAuthentication: - intptr = &options->rhosts_authentication; - goto parse_flag; - - case oPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; - - case oKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; - - case oKbdInteractiveDevices: - charptr = &options->kbd_interactive_devices; - goto parse_string; - - case oPubkeyAuthentication: - intptr = &options->pubkey_authentication; - goto parse_flag; - - case oRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; - - case oRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; - - case oHostbasedAuthentication: - intptr = &options->hostbased_authentication; - goto parse_flag; - - case oChallengeResponseAuthentication: - intptr = &options->challenge_response_authentication; - goto parse_flag; -#if defined(KRB4) || defined(KRB5) - case oKerberosAuthentication: - intptr = &options->kerberos_authentication; - goto parse_flag; -#endif -#ifdef GSSAPI - case oGssKeyEx: - intptr = &options->gss_keyex; - goto parse_flag; - - case oGssAuthentication: - intptr = &options->gss_authentication; - goto parse_flag; - - case oGssDelegateCreds: - intptr = &options->gss_deleg_creds; - goto parse_flag; - -#ifdef GSI - case oGssGlobusDelegateLimitedCreds: - intptr = &options->gss_globus_deleg_limited_proxy; - goto parse_flag; -#endif /* GSI */ - -#endif /* GSSAPI */ - -#if defined(AFS) || defined(KRB5) - case oKerberosTgtPassing: - intptr = &options->kerberos_tgt_passing; - goto parse_flag; -#endif -#ifdef AFS - case oAFSTokenPassing: - intptr = &options->afs_token_passing; - goto parse_flag; -#endif - case oFallBackToRsh: - intptr = &options->fallback_to_rsh; - goto parse_flag; - - case oUseRsh: - intptr = &options->use_rsh; - goto parse_flag; - - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; - - case oCheckHostIP: - intptr = &options->check_host_ip; - goto parse_flag; - - case oStrictHostKeyChecking: - intptr = &options->strict_host_key_checking; - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing yes/no/ask argument.", - filename, linenum); - value = 0; /* To avoid compiler warning... */ - if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) - value = 1; - else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) - value = 0; - else if (strcmp(arg, "ask") == 0) - value = 2; - else - fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case oCompression: - intptr = &options->compression; - goto parse_flag; - - case oKeepAlives: - intptr = &options->keepalives; - goto parse_flag; - - case oNoHostAuthenticationForLocalhost: - intptr = &options->no_host_authentication_for_localhost; - goto parse_flag; - - case oNumberOfPasswordPrompts: - intptr = &options->number_of_password_prompts; - goto parse_int; - - case oCompressionLevel: - intptr = &options->compression_level; - goto parse_int; - - case oRekeyLimit: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (arg[0] < '0' || arg[0] > '9') - fatal("%.200s line %d: Bad number.", filename, linenum); - orig = val64 = strtoll(arg, &endofnumber, 10); - if (arg == endofnumber) - fatal("%.200s line %d: Bad number.", filename, linenum); - switch (toupper(*endofnumber)) { - case '\0': - scale = 1; - break; - case 'K': - scale = 1<<10; - break; - case 'M': - scale = 1<<20; - break; - case 'G': - scale = 1<<30; - break; - default: - fatal("%.200s line %d: Invalid RekeyLimit suffix", - filename, linenum); - } - val64 *= scale; - /* detect integer wrap and too-large limits */ - if ((val64 / scale) != orig || val64 > UINT_MAX) - fatal("%.200s line %d: RekeyLimit too large", - filename, linenum); - if (val64 < 16) - fatal("%.200s line %d: RekeyLimit too small", - filename, linenum); - if (*activep && options->rekey_limit == -1) - options->rekey_limit = (u_int32_t)val64; - break; - - case oIdentityFile: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (*activep) { - intptr = &options->num_identity_files; - if (*intptr >= SSH_MAX_IDENTITY_FILES) - fatal("%.200s line %d: Too many identity files specified (max %d).", - filename, linenum, SSH_MAX_IDENTITY_FILES); - charptr = &options->identity_files[*intptr]; - *charptr = xstrdup(arg); - *intptr = *intptr + 1; - } - break; - - case oXAuthLocation: - charptr=&options->xauth_location; - goto parse_string; - - case oUser: - charptr = &options->user; -parse_string: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (*activep && *charptr == NULL) - *charptr = xstrdup(arg); - break; - - case oGlobalKnownHostsFile: - charptr = &options->system_hostfile; - goto parse_string; - - case oUserKnownHostsFile: - charptr = &options->user_hostfile; - goto parse_string; - - case oGlobalKnownHostsFile2: - charptr = &options->system_hostfile2; - goto parse_string; - - case oUserKnownHostsFile2: - charptr = &options->user_hostfile2; - goto parse_string; - - case oHostName: - charptr = &options->hostname; - goto parse_string; - - case oHostKeyAlias: - charptr = &options->host_key_alias; - goto parse_string; - - case oPreferredAuthentications: - charptr = &options->preferred_authentications; - goto parse_string; - - case oBindAddress: - charptr = &options->bind_address; - goto parse_string; - - case oSmartcardDevice: - charptr = &options->smartcard_device; - goto parse_string; - - case oProxyCommand: - charptr = &options->proxy_command; - string = xstrdup(""); - while ((arg = strdelim(&s)) != NULL && *arg != '\0') { - string = xrealloc(string, strlen(string) + strlen(arg) + 2); - strcat(string, " "); - strcat(string, arg); - } - if (*activep && *charptr == NULL) - *charptr = string; - else - xfree(string); - return 0; - - case oPort: - intptr = &options->port; -parse_int: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (arg[0] < '0' || arg[0] > '9') - fatal("%.200s line %d: Bad number.", filename, linenum); - - /* Octal, decimal, or hex format? */ - value = strtol(arg, &endofnumber, 0); - if (arg == endofnumber) - fatal("%.200s line %d: Bad number.", filename, linenum); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case oConnectionAttempts: - intptr = &options->connection_attempts; - goto parse_int; - - case oCipher: - intptr = &options->cipher; - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - value = cipher_number(arg); - if (value == -1) - fatal("%.200s line %d: Bad cipher '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case oCiphers: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) - fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (*activep && options->ciphers == NULL) - options->ciphers = xstrdup(arg); - break; - - case oMacs: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) - fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (*activep && options->macs == NULL) - options->macs = xstrdup(arg); - break; - - case oHostKeyAlgorithms: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!key_names_valid2(arg)) - fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (*activep && options->hostkeyalgorithms == NULL) - options->hostkeyalgorithms = xstrdup(arg); - break; - - case oProtocol: - intptr = &options->protocol; - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - value = proto_spec(arg); - if (value == SSH_PROTO_UNKNOWN) - fatal("%.200s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (*activep && *intptr == SSH_PROTO_UNKNOWN) - *intptr = value; - break; - - case oLogLevel: - intptr = (int *) &options->log_level; - arg = strdelim(&s); - value = log_level_number(arg); - if (value == SYSLOG_LEVEL_NOT_SET) - fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : "<NONE>"); - if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) - *intptr = (LogLevel) value; - break; - - case oLocalForward: - case oRemoteForward: - arg = strdelim(&s); - if (arg == NULL || *arg == '\0') - fatal("%.200s line %d: Missing port argument.", - filename, linenum); - arg2 = strdelim(&s); - if (arg2 == NULL || *arg2 == '\0') - fatal("%.200s line %d: Missing target argument.", - filename, linenum); - - /* construct a string for parse_forward */ - snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); - - if (parse_forward(1, &fwd, fwdarg) == 0) - fatal("%.200s line %d: Bad forwarding specification.", - filename, linenum); - - if (*activep) { - if (opcode == oLocalForward) - add_local_forward(options, &fwd); - else if (opcode == oRemoteForward) - add_remote_forward(options, &fwd); - } - break; - - case oDynamicForward: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing port argument.", - filename, linenum); - - if (parse_forward(0, &fwd, arg) == 0) { - fatal("%.200s line %d: Bad dynamic forwarding specification.", - filename, linenum); - } - - if (*activep) { - fwd.connect_host = "socks"; - add_local_forward(options, &fwd); - } - break; - - case oClearAllForwardings: - intptr = &options->clear_forwardings; - goto parse_flag; - - case oHost: - *activep = 0; - while ((arg = strdelim(&s)) != NULL && *arg != '\0') - if (match_pattern(host, arg)) { - debug("Applying options for %.100s", arg); - *activep = 1; - break; - } - /* Avoid garbage check below, as strdelim is done. */ - return 0; - - case oEscapeChar: - intptr = &options->escape_char; - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (arg[0] == '^' && arg[2] == 0 && - (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) - value = (u_char) arg[1] & 31; - else if (strlen(arg) == 1) - value = (u_char) arg[0]; - else if (strcmp(arg, "none") == 0) - value = SSH_ESCAPECHAR_NONE; - else { - fatal("%.200s line %d: Bad escape character.", - filename, linenum); - /* NOTREACHED */ - value = 0; /* Avoid compiler warning. */ - } - if (*activep && *intptr == -1) - *intptr = value; - break; - - case oServerAliveInterval: - intptr = &options->server_alive_interval; - goto parse_time; - - case oServerAliveCountMax: - intptr = &options->server_alive_count_max; - goto parse_int; - - case oHashKnownHosts: - intptr = &options->hash_known_hosts; - goto parse_flag; - - case oDisableBanner: - arg = strdelim(&s); - if (get_yes_no_flag(&options->disable_banner, arg, filename, - linenum, *activep) == 1) - break; - - if (strcmp(arg, "in-exec-mode") == 0) - options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE; - else - fatal("%.200s line %d: Bad yes/no/in-exec-mode " - "argument.", filename, linenum); - break; - - case oIgnoreIfUnknown: - charptr = &options->ignore_if_unknown; - goto parse_string; - - case oUseOpenSSLEngine: - intptr = &options->use_openssl_engine; - goto parse_flag; - - case oDeprecated: - debug("%s line %d: Deprecated option \"%s\"", - filename, linenum, keyword); - return 0; - - default: - fatal("process_config_line: Unimplemented opcode %d", opcode); - } - - /* Check that there is no garbage at end of line. */ - if ((arg = strdelim(&s)) != NULL && *arg != '\0') { - fatal("%.200s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); - } - return 0; -} - - -/* - * Reads the config file and modifies the options accordingly. Options - * should already be initialized before this call. This never returns if - * there is an error. If the file does not exist, this returns 0. - */ - -int -read_config_file(const char *filename, const char *host, Options *options) -{ - FILE *f; - char line[1024]; - int active, linenum; - - /* Open the file. */ - f = fopen(filename, "r"); - if (!f) - return 0; - - debug("Reading configuration data %.200s", filename); - - /* - * Mark that we are now processing the options. This flag is turned - * on/off by Host specifications. - */ - active = 1; - linenum = 0; - while (fgets(line, sizeof(line), f)) { - /* Update line number counter. */ - linenum++; - process_config_line(options, host, line, filename, linenum, &active); - } - fclose(f); - return 1; -} - -/* - * Initializes options to special values that indicate that they have not yet - * been set. Read_config_file will only set options with this value. Options - * are processed in the following order: command line, user config file, - * system config file. Last, fill_default_options is called. - */ - -void -initialize_options(Options * options) -{ - memset(options, 'X', sizeof(*options)); - options->forward_agent = -1; - options->forward_x11 = -1; - options->forward_x11_trusted = -1; - options->xauth_location = NULL; - options->gateway_ports = -1; - options->use_privileged_port = -1; - options->rhosts_authentication = -1; - options->rsa_authentication = -1; - options->pubkey_authentication = -1; - options->challenge_response_authentication = -1; -#ifdef GSSAPI - options->gss_keyex = -1; - options->gss_authentication = -1; - options->gss_deleg_creds = -1; -#ifdef GSI - options->gss_globus_deleg_limited_proxy = -1; -#endif /* GSI */ -#endif /* GSSAPI */ - -#if defined(KRB4) || defined(KRB5) - options->kerberos_authentication = -1; -#endif -#if defined(AFS) || defined(KRB5) - options->kerberos_tgt_passing = -1; -#endif -#ifdef AFS - options->afs_token_passing = -1; -#endif - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; - options->rhosts_rsa_authentication = -1; - options->hostbased_authentication = -1; - options->batch_mode = -1; - options->check_host_ip = -1; - options->strict_host_key_checking = -1; - options->compression = -1; - options->keepalives = -1; - options->compression_level = -1; - options->port = -1; - options->connection_attempts = -1; - options->connection_timeout = -1; - options->number_of_password_prompts = -1; - options->cipher = -1; - options->ciphers = NULL; - options->macs = NULL; - options->hostkeyalgorithms = NULL; - options->protocol = SSH_PROTO_UNKNOWN; - options->num_identity_files = 0; - options->hostname = NULL; - options->host_key_alias = NULL; - options->proxy_command = NULL; - options->user = NULL; - options->escape_char = -1; - options->system_hostfile = NULL; - options->user_hostfile = NULL; - options->system_hostfile2 = NULL; - options->user_hostfile2 = NULL; - options->num_local_forwards = 0; - options->num_remote_forwards = 0; - options->clear_forwardings = -1; - options->log_level = SYSLOG_LEVEL_NOT_SET; - options->preferred_authentications = NULL; - options->bind_address = NULL; - options->smartcard_device = NULL; - options->no_host_authentication_for_localhost = -1; - options->rekey_limit = -1; - options->fallback_to_rsh = -1; - options->use_rsh = -1; - options->server_alive_interval = -1; - options->server_alive_count_max = -1; - options->hash_known_hosts = -1; - options->ignore_if_unknown = NULL; - options->unknown_opts_num = 0; - options->disable_banner = -1; - options->use_openssl_engine = -1; -} - -/* - * Called after processing other sources of option data, this fills those - * options for which no value has been specified with their default values. - */ - -void -fill_default_options(Options * options) -{ - int len; - - if (options->forward_agent == -1) - options->forward_agent = 0; - if (options->forward_x11 == -1) - options->forward_x11 = 0; - /* - * Unlike OpenSSH, we keep backward compatibility for '-X' option - * which means that X11 forwarding is trusted by default. - */ - if (options->forward_x11_trusted == -1) - options->forward_x11_trusted = 1; - if (options->xauth_location == NULL) - options->xauth_location = _PATH_XAUTH; - if (options->gateway_ports == -1) - options->gateway_ports = 0; - if (options->use_privileged_port == -1) - options->use_privileged_port = 0; - if (options->rhosts_authentication == -1) - options->rhosts_authentication = 0; - if (options->rsa_authentication == -1) - options->rsa_authentication = 1; - if (options->pubkey_authentication == -1) - options->pubkey_authentication = 1; - if (options->challenge_response_authentication == -1) - options->challenge_response_authentication = 1; -#ifdef GSSAPI - if (options->gss_keyex == -1) - options->gss_keyex = 1; - if (options->gss_authentication == -1) - options->gss_authentication = 1; - if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; -#ifdef GSI - if (options->gss_globus_deleg_limited_proxy == -1) - options->gss_globus_deleg_limited_proxy = 0; -#endif /* GSI */ -#endif /* GSSAPI */ -#if defined(KRB4) || defined(KRB5) - if (options->kerberos_authentication == -1) - options->kerberos_authentication = 1; -#endif -#if defined(AFS) || defined(KRB5) - if (options->kerberos_tgt_passing == -1) - options->kerberos_tgt_passing = 1; -#endif -#ifdef AFS - if (options->afs_token_passing == -1) - options->afs_token_passing = 1; -#endif - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) - options->kbd_interactive_authentication = 1; - if (options->rhosts_rsa_authentication == -1) - options->rhosts_rsa_authentication = 0; - if (options->hostbased_authentication == -1) - options->hostbased_authentication = 0; - if (options->batch_mode == -1) - options->batch_mode = 0; - if (options->check_host_ip == -1) - options->check_host_ip = 1; - if (options->strict_host_key_checking == -1) - options->strict_host_key_checking = 2; /* 2 is default */ - if (options->compression == -1) - options->compression = 0; - if (options->keepalives == -1) - options->keepalives = 1; - if (options->compression_level == -1) - options->compression_level = 6; - if (options->port == -1) - options->port = 0; /* Filled in ssh_connect. */ - if (options->connection_attempts == -1) - options->connection_attempts = 1; - if (options->number_of_password_prompts == -1) - options->number_of_password_prompts = 3; - /* Selected in ssh_login(). */ - if (options->cipher == -1) - options->cipher = SSH_CIPHER_NOT_SET; - /* options->ciphers, default set in myproposals.h */ - /* options->macs, default set in myproposals.h */ - /* options->hostkeyalgorithms, default set in myproposals.h */ - if (options->protocol == SSH_PROTO_UNKNOWN) - options->protocol = SSH_PROTO_1|SSH_PROTO_2; - if (options->num_identity_files == 0) { - if (options->protocol & SSH_PROTO_1) { - len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; - options->identity_files[options->num_identity_files] = - xmalloc(len); - snprintf(options->identity_files[options->num_identity_files++], - len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); - } - if (options->protocol & SSH_PROTO_2) { - len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; - options->identity_files[options->num_identity_files] = - xmalloc(len); - snprintf(options->identity_files[options->num_identity_files++], - len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); - - len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; - options->identity_files[options->num_identity_files] = - xmalloc(len); - snprintf(options->identity_files[options->num_identity_files++], - len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); - } - } - if (options->escape_char == -1) - options->escape_char = '~'; - if (options->system_hostfile == NULL) - options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; - if (options->user_hostfile == NULL) - options->user_hostfile = _PATH_SSH_USER_HOSTFILE; - if (options->system_hostfile2 == NULL) - options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; - if (options->user_hostfile2 == NULL) - options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; - if (options->log_level == SYSLOG_LEVEL_NOT_SET) - options->log_level = SYSLOG_LEVEL_INFO; - if (options->clear_forwardings == 1) - clear_forwardings(options); - if (options->no_host_authentication_for_localhost == -1) - options->no_host_authentication_for_localhost = 0; - if (options->rekey_limit == -1) - options->rekey_limit = 0; - if (options->fallback_to_rsh == -1) - options->fallback_to_rsh = 0; - if (options->use_rsh == -1) - options->use_rsh = 0; - if (options->server_alive_interval == -1) - options->server_alive_interval = 0; - if (options->server_alive_count_max == -1) - options->server_alive_count_max = 3; - if (options->hash_known_hosts == -1) - options->hash_known_hosts = 0; - if (options->disable_banner == -1) - options->disable_banner = 0; - if (options->use_openssl_engine == -1) - options->use_openssl_engine = 1; - /* options->proxy_command should not be set by default */ - /* options->user will be set in the main program if appropriate */ - /* options->hostname will be set in the main program if appropriate */ - /* options->host_key_alias should not be set by default */ - /* options->preferred_authentications will be set in ssh */ - /* options->ignore_if_unknown should not be set by default */ -} - -/* - * Parses a string containing a port forwarding specification of one of the - * two forms, short or long: - * - * [listenhost:]listenport - * [listenhost:]listenport:connecthost:connectport - * - * short forwarding specification is used for dynamic port forwarding and for - * port forwarding cancelation in process_cmdline(). The function returns number - * of arguments parsed or zero on any error. - */ -int -parse_forward(int long_form, Forward *fwd, const char *fwdspec) -{ - int i; - char *p, *cp, *fwdarg[5]; - - memset(fwd, '\0', sizeof(*fwd)); - - cp = p = xstrdup(fwdspec); - - /* skip leading spaces */ - while (isspace(*cp)) - cp++; - - for (i = 0; i < 5; ++i) - if ((fwdarg[i] = hpdelim(&cp)) == NULL) - break; - - if ((long_form == 0 && i > 2) || (long_form == 1 && i < 3) || (i == 5)) - goto fail_free; - - switch (i) { - case 0: - goto fail_free; - - case 1: - fwd->listen_host = NULL; - fwd->listen_port = a2port(fwdarg[0]); - break; - - case 2: - fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); - fwd->listen_port = a2port(fwdarg[1]); - break; - - case 3: - fwd->listen_host = NULL; - fwd->listen_port = a2port(fwdarg[0]); - fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); - fwd->connect_port = a2port(fwdarg[2]); - break; - - case 4: - fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); - fwd->listen_port = a2port(fwdarg[1]); - fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); - fwd->connect_port = a2port(fwdarg[3]); - break; - } - - if (fwd->listen_port == 0 || (fwd->connect_port == 0 && i > 2)) - goto fail_free; - - xfree(p); - return (i); - -fail_free: - if (p != NULL) - xfree(p); - if (fwd->connect_host != NULL) - xfree(fwd->connect_host); - if (fwd->listen_host != NULL) - xfree(fwd->listen_host); - return (0); -} - -/* - * Process previously stored unknown options. When this function is called we - * already have IgnoreIfUnknown set so finally we can decide whether each - * unknown option is to be ignored or not. - */ -void -process_unknown_options(Options *options) -{ - StoredOption *so; - int m, i, bad_options = 0; - - /* if there is no unknown option we are done */ - if (options->unknown_opts_num == 0) - return; - - /* - * Now go through the list of unknown options and report any one that - * is not explicitly listed in IgnoreIfUnknown option. If at least one - * such as that is found it's a show stopper. - */ - for (i = 0; i < options->unknown_opts_num; ++i) { - so = &options->unknown_opts[i]; - if (options->ignore_if_unknown == NULL) - m = 0; - else - m = match_pattern_list(tolowercase(so->keyword), - options->ignore_if_unknown, - strlen(options->ignore_if_unknown), 1); - if (m == 1) { - debug("%s: line %d: ignoring unknown option: %s", - so->filename, so->linenum, so->keyword); - } - else { - error("%s: line %d: unknown configuration option: %s", - so->filename, so->linenum, so->keyword); - bad_options++; - } - xfree(so->keyword); - xfree(so->filename); - } - - /* exit if we found at least one unignored unknown option */ - if (bad_options > 0) - fatal("terminating, %d bad configuration option(s)", - bad_options); -} diff --git a/usr/src/cmd/ssh/libssh/common/readpass.c b/usr/src/cmd/ssh/libssh/common/readpass.c deleted file mode 100644 index fa1f1a4982..0000000000 --- a/usr/src/cmd/ssh/libssh/common/readpass.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $"); - -#include "xmalloc.h" -#include "readpass.h" -#include "pathnames.h" -#include "log.h" -#include "ssh.h" -#include <langinfo.h> - -static char * -ssh_askpass(char *askpass, const char *msg) -{ - pid_t pid; - size_t len; - char *pass; - int p[2], status, ret; - char buf[1024]; - - if (fflush(stdout) != 0) - error("ssh_askpass: fflush: %s", strerror(errno)); - if (askpass == NULL) - fatal("internal error: askpass undefined"); - if (pipe(p) < 0) { - error("ssh_askpass: pipe: %s", strerror(errno)); - return xstrdup(""); - } - if ((pid = fork()) < 0) { - error("ssh_askpass: fork: %s", strerror(errno)); - return xstrdup(""); - } - if (pid == 0) { - seteuid(getuid()); - setuid(getuid()); - close(p[0]); - if (dup2(p[1], STDOUT_FILENO) < 0) - fatal("ssh_askpass: dup2: %s", strerror(errno)); - execlp(askpass, askpass, msg, (char *) 0); - fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno)); - } - close(p[1]); - - len = ret = 0; - do { - ret = read(p[0], buf + len, sizeof(buf) - 1 - len); - if (ret == -1 && errno == EINTR) - continue; - if (ret <= 0) - break; - len += ret; - } while (sizeof(buf) - 1 - len > 0); - buf[len] = '\0'; - - close(p[0]); - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - break; - - buf[strcspn(buf, "\r\n")] = '\0'; - pass = xstrdup(buf); - memset(buf, 0, sizeof(buf)); - return pass; -} - -/* - * Reads a passphrase from /dev/tty with echo turned off/on. Returns the - * passphrase (allocated with xmalloc). Exits if EOF is encountered. If - * RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no - * tty is available - */ -char * -read_passphrase(const char *prompt, int flags) -{ - char *askpass = NULL, *ret, buf[1024]; - int rppflags, use_askpass = 0, ttyfd; - - rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF; - if (flags & RP_ALLOW_STDIN) { - if (!isatty(STDIN_FILENO)) - use_askpass = 1; - } else { - rppflags |= RPP_REQUIRE_TTY; - ttyfd = open(_PATH_TTY, O_RDWR); - if (ttyfd >= 0) - close(ttyfd); - else - use_askpass = 1; - } - - if (use_askpass && getenv("DISPLAY")) { - if (getenv(SSH_ASKPASS_ENV)) - askpass = getenv(SSH_ASKPASS_ENV); - else - askpass = _PATH_SSH_ASKPASS_DEFAULT; - return ssh_askpass(askpass, prompt); - } - - if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) { - if (flags & RP_ALLOW_EOF) - return NULL; - return xstrdup(""); - } - - ret = xstrdup(buf); - memset(buf, 'x', sizeof buf); - return ret; -} - -int -ask_permission(const char *fmt, ...) -{ - va_list args; - char *p, prompt[1024]; - int allowed = 0; - char *yeschar = nl_langinfo(YESSTR); - - va_start(args, fmt); - vsnprintf(prompt, sizeof(prompt), fmt, args); - va_end(args); - - p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF); - if (p != NULL) { - /* - * Accept empty responses and responses consisting - * of the word "yes" as affirmative. - */ - if (*p == '\0' || *p == '\n' || - strncasecmp(p, yeschar, 1) == 0) - allowed = 1; - xfree(p); - } - - return (allowed); -} diff --git a/usr/src/cmd/ssh/libssh/common/rsa.c b/usr/src/cmd/ssh/libssh/common/rsa.c deleted file mode 100644 index f24a44a770..0000000000 --- a/usr/src/cmd/ssh/libssh/common/rsa.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 1999 Niels Provos. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Description of the RSA algorithm can be found e.g. from the following - * sources: - * - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994. - * - * Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to - * Computer Security. Prentice-Hall, 1989. - * - * Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill, - * 1994. - * - * R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications - * System and Method. US Patent 4,405,829, 1983. - * - * Hans Riesel: Prime Numbers and Computer Methods for Factorization. - * Birkhauser, 1994. - * - * The RSA Frequently Asked Questions document by RSA Data Security, - * Inc., 1995. - * - * RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as - * included below: - * - * [gone - had to be deleted - what a pity] - */ - -#include "includes.h" -RCSID("$OpenBSD: rsa.c,v 1.24 2001/12/27 18:22:16 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "rsa.h" -#include "log.h" -#include "xmalloc.h" - -void -rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) -{ - u_char *inbuf, *outbuf; - int len, ilen, olen; - - if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) - fatal("rsa_public_encrypt() exponent too small or not odd"); - - olen = BN_num_bytes(key->n); - outbuf = xmalloc(olen); - - ilen = BN_num_bytes(in); - inbuf = xmalloc(ilen); - BN_bn2bin(in, inbuf); - - if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, - RSA_PKCS1_PADDING)) <= 0) - fatal("rsa_public_encrypt() failed"); - - BN_bin2bn(outbuf, len, out); - - memset(outbuf, 0, olen); - memset(inbuf, 0, ilen); - xfree(outbuf); - xfree(inbuf); -} - -int -rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) -{ - u_char *inbuf, *outbuf; - int len, ilen, olen; - - olen = BN_num_bytes(key->n); - outbuf = xmalloc(olen); - - ilen = BN_num_bytes(in); - inbuf = xmalloc(ilen); - BN_bn2bin(in, inbuf); - - if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, - RSA_PKCS1_PADDING)) <= 0) { - error("rsa_private_decrypt() failed"); - } else { - BN_bin2bn(outbuf, len, out); - } - memset(outbuf, 0, olen); - memset(inbuf, 0, ilen); - xfree(outbuf); - xfree(inbuf); - return len; -} - -/* calculate p-1 and q-1 */ -void -rsa_generate_additional_parameters(RSA *rsa) -{ - BIGNUM *aux; - BN_CTX *ctx; - - if ((aux = BN_new()) == NULL) - fatal("rsa_generate_additional_parameters: BN_new failed"); - if ((ctx = BN_CTX_new()) == NULL) - fatal("rsa_generate_additional_parameters: BN_CTX_new failed"); - - BN_sub(aux, rsa->q, BN_value_one()); - BN_mod(rsa->dmq1, rsa->d, aux, ctx); - - BN_sub(aux, rsa->p, BN_value_one()); - BN_mod(rsa->dmp1, rsa->d, aux, ctx); - - BN_clear_free(aux); - BN_CTX_free(ctx); -} - diff --git a/usr/src/cmd/ssh/libssh/common/sftp-common.c b/usr/src/cmd/ssh/libssh/common/sftp-common.c deleted file mode 100644 index ead9e2406f..0000000000 --- a/usr/src/cmd/ssh/libssh/common/sftp-common.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2001 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $OpenBSD: sftp-common.c,v 1.20 2006/08/03 03:34:42 deraadt Exp $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> - -#include <grp.h> -#include <pwd.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <stdarg.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "log.h" - -#include "sftp.h" -#include "sftp-common.h" - -/* Clear contents of attributes structure */ -void -attrib_clear(Attrib *a) -{ - a->flags = 0; - a->size = 0; - a->uid = 0; - a->gid = 0; - a->perm = 0; - a->atime = 0; - a->mtime = 0; -} - -/* Convert from struct stat to filexfer attribs */ -void -stat_to_attrib(const struct stat *st, Attrib *a) -{ - attrib_clear(a); - a->flags = 0; - a->flags |= SSH2_FILEXFER_ATTR_SIZE; - a->size = st->st_size; - a->flags |= SSH2_FILEXFER_ATTR_UIDGID; - a->uid = st->st_uid; - a->gid = st->st_gid; - a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; - a->perm = st->st_mode; - a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME; - a->atime = st->st_atime; - a->mtime = st->st_mtime; -} - -/* Convert from filexfer attribs to struct stat */ -void -attrib_to_stat(const Attrib *a, struct stat *st) -{ - memset(st, 0, sizeof(*st)); - - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) - st->st_size = a->size; - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - st->st_uid = a->uid; - st->st_gid = a->gid; - } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - st->st_mode = a->perm; - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - st->st_atime = a->atime; - st->st_mtime = a->mtime; - } -} - -/* Decode attributes in buffer */ -Attrib * -decode_attrib(Buffer *b) -{ - static Attrib a; - - attrib_clear(&a); - a.flags = buffer_get_int(b); - if (a.flags & SSH2_FILEXFER_ATTR_SIZE) - a.size = buffer_get_int64(b); - if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { - a.uid = buffer_get_int(b); - a.gid = buffer_get_int(b); - } - if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - a.perm = buffer_get_int(b); - if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - a.atime = buffer_get_int(b); - a.mtime = buffer_get_int(b); - } - /* vendor-specific extensions */ - if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { - char *type, *data; - int i, count; - - count = buffer_get_int(b); - for (i = 0; i < count; i++) { - type = buffer_get_string(b, NULL); - data = buffer_get_string(b, NULL); - debug3("Got file attribute \"%s\"", type); - xfree(type); - xfree(data); - } - } - return &a; -} - -/* Encode attributes to buffer */ -void -encode_attrib(Buffer *b, const Attrib *a) -{ - buffer_put_int(b, a->flags); - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) - buffer_put_int64(b, a->size); - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - buffer_put_int(b, a->uid); - buffer_put_int(b, a->gid); - } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - buffer_put_int(b, a->perm); - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - buffer_put_int(b, a->atime); - buffer_put_int(b, a->mtime); - } -} - -/* Convert from SSH2_FX_ status to text error message */ -const char * -fx2txt(int status) -{ - switch (status) { - case SSH2_FX_OK: - return(gettext("No error")); - case SSH2_FX_EOF: - return(gettext("End of file")); - case SSH2_FX_NO_SUCH_FILE: - return(gettext("No such file or directory")); - case SSH2_FX_PERMISSION_DENIED: - return(gettext("Permission denied")); - case SSH2_FX_FAILURE: - return(gettext("Failure")); - case SSH2_FX_BAD_MESSAGE: - return(gettext("Bad message")); - case SSH2_FX_NO_CONNECTION: - return(gettext("No connection")); - case SSH2_FX_CONNECTION_LOST: - return(gettext("Connection lost")); - case SSH2_FX_OP_UNSUPPORTED: - return(gettext("Operation unsupported")); - default: - return(gettext("Unknown status")); - } - /* NOTREACHED */ -} - -/* - * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh - */ -char * -ls_file(const char *name, const struct stat *st, int remote) -{ - int ulen, glen, sz = 0; - struct passwd *pw; - struct group *gr; - struct tm *ltime = localtime(&st->st_mtime); - char *user, *group; - char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1]; - - strmode(st->st_mode, mode); - if (!remote && (pw = getpwuid(st->st_uid)) != NULL) { - user = pw->pw_name; - } else { - snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); - user = ubuf; - } - if (!remote && (gr = getgrgid(st->st_gid)) != NULL) { - group = gr->gr_name; - } else { - snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); - group = gbuf; - } - if (ltime != NULL) { - if (time(NULL) - st->st_mtime < (365*24*60*60)/2) - sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime); - else - sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime); - } - if (sz == 0) - tbuf[0] = '\0'; - ulen = MAX(strlen(user), 8); - glen = MAX(strlen(group), 8); - snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode, - (u_int)st->st_nlink, ulen, user, glen, group, - (unsigned long long)st->st_size, tbuf, name); - return xstrdup(buf); -} diff --git a/usr/src/cmd/ssh/libssh/common/ssh-dss.c b/usr/src/cmd/ssh/libssh/common/ssh-dss.c deleted file mode 100644 index f73a91672f..0000000000 --- a/usr/src/cmd/ssh/libssh/common/ssh-dss.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: ssh-dss.c,v 1.17 2002/07/04 10:41:47 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/bn.h> -#include <openssl/evp.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "compat.h" -#include "log.h" -#include "key.h" -#include "ssh-dss.h" - -#define INTBLOB_LEN 20 -#define SIGBLOB_LEN (2*INTBLOB_LEN) - -int -ssh_dss_sign(Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - DSA_SIG *sig; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; - u_int rlen, slen, len, dlen; - Buffer b; - - if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { - error("ssh_dss_sign: no DSA key"); - return -1; - } - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - - sig = DSA_do_sign(digest, dlen, key->dsa); - memset(digest, 'd', sizeof(digest)); - - if (sig == NULL) { - error("ssh_dss_sign: sign failed"); - return -1; - } - - rlen = BN_num_bytes(sig->r); - slen = BN_num_bytes(sig->s); - if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { - error("bad sig size %u %u", rlen, slen); - DSA_SIG_free(sig); - return -1; - } - memset(sigblob, 0, SIGBLOB_LEN); - BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); - BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); - DSA_SIG_free(sig); - - if (datafellows & SSH_BUG_SIGBLOB) { - if (lenp != NULL) - *lenp = SIGBLOB_LEN; - if (sigp != NULL) { - *sigp = xmalloc(SIGBLOB_LEN); - memcpy(*sigp, sigblob, SIGBLOB_LEN); - } - } else { - /* ietf-drafts */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-dss"); - buffer_put_string(&b, sigblob, SIGBLOB_LEN); - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; - if (sigp != NULL) { - *sigp = xmalloc(len); - memcpy(*sigp, buffer_ptr(&b), len); - } - buffer_free(&b); - } - return 0; -} -int -ssh_dss_verify(Key *key, u_char *signature, u_int signaturelen, - u_char *data, u_int datalen) -{ - DSA_SIG *sig; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], *sigblob; - u_int len, dlen; - int rlen, ret; - Buffer b; - - if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { - error("ssh_dss_verify: no DSA key"); - return -1; - } - - /* fetch signature */ - if (datafellows & SSH_BUG_SIGBLOB) { - sigblob = signature; - len = signaturelen; - } else { - /* ietf-drafts */ - char *ktype; - buffer_init(&b); - buffer_append(&b, signature, signaturelen); - ktype = buffer_get_string(&b, NULL); - if (strcmp("ssh-dss", ktype) != 0) { - error("ssh_dss_verify: cannot handle type %s", ktype); - buffer_free(&b); - xfree(ktype); - return -1; - } - xfree(ktype); - sigblob = buffer_get_string(&b, &len); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("ssh_dss_verify: " - "remaining bytes in signature %d", rlen); - xfree(sigblob); - return -1; - } - } - - if (len != SIGBLOB_LEN) { - fatal("bad sigbloblen %u != SIGBLOB_LEN", len); - } - - /* parse signature */ - if ((sig = DSA_SIG_new()) == NULL) - fatal("ssh_dss_verify: DSA_SIG_new failed"); - if ((sig->r = BN_new()) == NULL) - fatal("ssh_dss_verify: BN_new failed"); - if ((sig->s = BN_new()) == NULL) - fatal("ssh_dss_verify: BN_new failed"); - BN_bin2bn(sigblob, INTBLOB_LEN, sig->r); - BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s); - - if (!(datafellows & SSH_BUG_SIGBLOB)) { - memset(sigblob, 0, len); - xfree(sigblob); - } - - /* sha1 the data */ - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - - ret = DSA_do_verify(digest, dlen, sig, key->dsa); - memset(digest, 'd', sizeof(digest)); - - DSA_SIG_free(sig); - - debug("ssh_dss_verify: signature %s", - ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); - return ret; -} diff --git a/usr/src/cmd/ssh/libssh/common/ssh-gss.c b/usr/src/cmd/ssh/libssh/common/ssh-gss.c deleted file mode 100644 index 37aeb04873..0000000000 --- a/usr/src/cmd/ssh/libssh/common/ssh-gss.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -#ifdef GSSAPI - -#include "ssh.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "packet.h" -#include "compat.h" -#include <openssl/evp.h> -#include "cipher.h" -#include "kex.h" -#include "log.h" -#include "compat.h" -#include "xlist.h" - -#include <netdb.h> - -#include "ssh-gss.h" - -#ifdef HAVE_GSS_OID_TO_MECH -#include <gssapi/gssapi_ext.h> -#endif /* HAVE_GSS_OID_TO_MECH */ - -typedef struct { - char *encoded; - gss_OID oid; -} ssh_gss_kex_mapping; - -static ssh_gss_kex_mapping **gss_enc2oid = NULL; - -static void ssh_gssapi_encode_oid_for_kex(const gss_OID oid, char **enc_name); -static char *ssh_gssapi_make_kexalgs_list(gss_OID_set mechs, - const char *old_kexalgs); - -/* - * Populate gss_enc2oid table and return list of kexnames. - * - * If called with both mechs == GSS_C_NULL_OID_SET and kexname_list == NULL - * then cached gss_enc2oid table is cleaned up. - */ -void -ssh_gssapi_mech_oids_to_kexnames(const gss_OID_set mechs, char **kexname_list) -{ - ssh_gss_kex_mapping **new_gss_enc2oid, **p; - Buffer buf; - char *enc_name; - int i; - - if (kexname_list != NULL) - *kexname_list = NULL; /* default to failed */ - - if (mechs != GSS_C_NULL_OID_SET || kexname_list == NULL) { - /* Cleanup gss_enc2oid table */ - for (p = gss_enc2oid; p != NULL && *p != NULL; p++) { - if ((*p)->encoded) - xfree((*p)->encoded); - ssh_gssapi_release_oid(&(*p)->oid); - xfree(*p); - } - if (gss_enc2oid) - xfree(gss_enc2oid); - } - - if (mechs == GSS_C_NULL_OID_SET && kexname_list == NULL) - return; /* nothing left to do */ - - if (mechs) { - gss_OID mech; - /* Populate gss_enc2oid table */ - new_gss_enc2oid = xmalloc(sizeof (ssh_gss_kex_mapping *) * - (mechs->count + 1)); - memset(new_gss_enc2oid, 0, - sizeof (ssh_gss_kex_mapping *) * (mechs->count + 1)); - - for (i = 0; i < mechs->count; i++) { - mech = &mechs->elements[i]; - ssh_gssapi_encode_oid_for_kex((const gss_OID)mech, - &enc_name); - - if (!enc_name) - continue; - - new_gss_enc2oid[i] = - xmalloc(sizeof (ssh_gss_kex_mapping)); - (new_gss_enc2oid[i])->encoded = enc_name; - (new_gss_enc2oid[i])->oid = - ssh_gssapi_dup_oid(&mechs->elements[i]); - } - - /* Do this last to avoid run-ins with fatal_cleanups */ - gss_enc2oid = new_gss_enc2oid; - } - - if (!kexname_list) - return; /* nothing left to do */ - - /* Make kex name list */ - buffer_init(&buf); - for (p = gss_enc2oid; p && *p; p++) { - buffer_put_char(&buf, ','); - buffer_append(&buf, (*p)->encoded, strlen((*p)->encoded)); - } - - if (buffer_len(&buf) == 0) { - buffer_free(&buf); - return; - } - - buffer_consume(&buf, 1); /* consume leading ',' */ - buffer_put_char(&buf, '\0'); - - *kexname_list = xstrdup(buffer_ptr(&buf)); - buffer_free(&buf); -} - -void -ssh_gssapi_mech_oid_to_kexname(const gss_OID mech, char **kexname) -{ - ssh_gss_kex_mapping **p; - - if (mech == GSS_C_NULL_OID || !kexname) - return; - - *kexname = NULL; /* default to not found */ - if (gss_enc2oid) { - for (p = gss_enc2oid; p && *p; p++) { - if (mech->length == (*p)->oid->length && - memcmp(mech->elements, (*p)->oid->elements, - mech->length) == 0) - *kexname = xstrdup((*p)->encoded); - } - } - - if (*kexname) - return; /* found */ - - ssh_gssapi_encode_oid_for_kex(mech, kexname); -} - -void -ssh_gssapi_oid_of_kexname(const char *kexname, gss_OID *mech) -{ - ssh_gss_kex_mapping **p; - - if (!mech || !kexname || !*kexname) - return; - - *mech = GSS_C_NULL_OID; /* default to not found */ - - if (!gss_enc2oid) - return; - - for (p = gss_enc2oid; p && *p; p++) { - if (strcmp(kexname, (*p)->encoded) == 0) { - *mech = (*p)->oid; - return; - } - } -} - -static -void -ssh_gssapi_encode_oid_for_kex(const gss_OID oid, char **enc_name) -{ - Buffer buf; - OM_uint32 oidlen; - uint_t enclen; - const EVP_MD *evp_md = EVP_md5(); - EVP_MD_CTX md; - uchar_t digest[EVP_MAX_MD_SIZE]; - char *encoded; - - if (oid == GSS_C_NULL_OID || !enc_name) - return; - - *enc_name = NULL; - - oidlen = oid->length; - - /* No GSS mechs have OIDs as long as 128 -- simplify DER encoding */ - if (oidlen > 128) - return; /* fail gracefully */ - - /* - * NOTE: If we need to support SSH_BUG_GSSAPI_BER this is where - * we'd do it. - * - * That means using "Se3H81ismmOC3OE+FwYCiQ==" for the Kerberos - * V mech and "N3+k7/4wGxHyuP8Yxi4RhA==" for the GSI mech. Ick. - */ - - buffer_init(&buf); - - /* UNIVERSAL class tag for OBJECT IDENTIFIER */ - buffer_put_char(&buf, 0x06); - buffer_put_char(&buf, oidlen); /* one octet DER length -- see above */ - - /* OID elements */ - buffer_append(&buf, oid->elements, oidlen); - - /* Make digest */ - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&buf), buffer_len(&buf)); - EVP_DigestFinal(&md, digest, NULL); - buffer_free(&buf); - - /* Base 64 encoding */ - encoded = xmalloc(EVP_MD_size(evp_md)*2); - enclen = __b64_ntop(digest, EVP_MD_size(evp_md), - encoded, EVP_MD_size(evp_md) * 2); - buffer_init(&buf); - buffer_append(&buf, KEX_GSS_SHA1, sizeof (KEX_GSS_SHA1) - 1); - buffer_append(&buf, encoded, enclen); - buffer_put_char(&buf, '\0'); - - debug2("GSS-API Mechanism encoded as %s", encoded); - xfree(encoded); - - *enc_name = xstrdup(buffer_ptr(&buf)); - buffer_free(&buf); -} - -static char * -ssh_gssapi_make_kexalgs_list(gss_OID_set mechs, const char *old_kexalgs) -{ - char *gss_kexalgs, *new_kexalgs; - int len; - - if (mechs == GSS_C_NULL_OID_SET) - return (xstrdup(old_kexalgs)); /* never null */ - - ssh_gssapi_mech_oids_to_kexnames(mechs, &gss_kexalgs); - - if (gss_kexalgs == NULL || *gss_kexalgs == '\0') - return (xstrdup(old_kexalgs)); /* never null */ - - if (old_kexalgs == NULL || *old_kexalgs == '\0') - return (gss_kexalgs); - - len = strlen(old_kexalgs) + strlen(gss_kexalgs) + 2; - new_kexalgs = xmalloc(len); - (void) snprintf(new_kexalgs, len, "%s,%s", gss_kexalgs, old_kexalgs); - xfree(gss_kexalgs); - - return (new_kexalgs); -} - -void -ssh_gssapi_modify_kex(Kex *kex, gss_OID_set mechs, char **proposal) -{ - char *kexalgs, *orig_kexalgs, *p; - char **hostalg, *orig_hostalgs, *new_hostalgs; - char **hostalgs; - gss_OID_set dup_mechs; - OM_uint32 maj, min; - int i; - - if (kex == NULL || proposal == NULL || - proposal[PROPOSAL_KEX_ALGS] == NULL) { - fatal("INTERNAL ERROR (%s)", __func__); - } - - orig_hostalgs = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; - - if (kex->mechs == GSS_C_NULL_OID_SET && mechs == GSS_C_NULL_OID_SET) - return; /* didn't offer GSS last time, not offering now */ - - if (kex->mechs == GSS_C_NULL_OID_SET || mechs == GSS_C_NULL_OID_SET) - goto mod_offer; /* didn't offer last time or not offering now */ - - /* Check if mechs is congruent to kex->mechs (last offered) */ - if (kex->mechs->count == mechs->count) { - int present, matches = 0; - - for (i = 0; i < mechs->count; i++) { - maj = gss_test_oid_set_member(&min, - &kex->mechs->elements[i], mechs, &present); - - if (GSS_ERROR(maj)) { - mechs = GSS_C_NULL_OID_SET; - break; - } - - matches += (present) ? 1 : 0; - } - - if (matches == kex->mechs->count) - return; /* no change in offer from last time */ - } - -mod_offer: - /* - * Remove previously offered mechs from PROPOSAL_KEX_ALGS proposal - * - * ASSUMPTION: GSS-API kex algs always go in front, so removing - * them is a matter of skipping them. - */ - p = kexalgs = orig_kexalgs = proposal[PROPOSAL_KEX_ALGS]; - while (p != NULL && *p != '\0' && - strncmp(p, KEX_GSS_SHA1, strlen(KEX_GSS_SHA1)) == 0) { - - if ((p = strchr(p, ',')) == NULL) - break; - p++; - kexalgs = p; - - } - kexalgs = proposal[PROPOSAL_KEX_ALGS] = xstrdup(kexalgs); - xfree(orig_kexalgs); - - (void) gss_release_oid_set(&min, &kex->mechs); /* ok if !kex->mechs */ - - /* Not offering GSS kex algorithms now -> all done */ - if (mechs == GSS_C_NULL_OID_SET) - return; - - /* Remember mechs we're offering */ - maj = gss_create_empty_oid_set(&min, &dup_mechs); - if (GSS_ERROR(maj)) - return; - for (i = 0; i < mechs->count; i++) { - maj = gss_add_oid_set_member(&min, &mechs->elements[i], - &dup_mechs); - - if (GSS_ERROR(maj)) { - (void) gss_release_oid_set(&min, &dup_mechs); - return; - } - } - - /* Add mechs to kex algorithms ... */ - proposal[PROPOSAL_KEX_ALGS] = ssh_gssapi_make_kexalgs_list(mechs, - kexalgs); - xfree(kexalgs); - kex->mechs = dup_mechs; /* remember what we offer now */ - - /* - * ... and add null host key alg, if it wasn't there before, but - * not if we're the server and we have other host key algs to - * offer. - * - * NOTE: Never remove "null" host key alg once added. - */ - if (orig_hostalgs == NULL || *orig_hostalgs == '\0') { - proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null"); - } else if (!kex->server) { - hostalgs = xsplit(orig_hostalgs, ','); - for (hostalg = hostalgs; *hostalg != NULL; hostalg++) { - if (strcmp(*hostalg, "null") == 0) { - xfree_split_list(hostalgs); - return; - } - } - xfree_split_list(hostalgs); - - if (kex->mechs != GSS_C_NULL_OID_SET) { - int len; - - len = strlen(orig_hostalgs) + sizeof (",null"); - new_hostalgs = xmalloc(len); - (void) snprintf(new_hostalgs, len, "%s,null", - orig_hostalgs); - proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = new_hostalgs; - } - - xfree(orig_hostalgs); - } -} - -/* - * Yes, we harcode OIDs for some things, for now it's all we can do. - * - * We have to reference particular mechanisms due to lack of generality - * in the GSS-API in several areas: authorization, mapping principal - * names to usernames, "storing" delegated credentials, and discovering - * whether a mechanism is a pseudo-mechanism that negotiates mechanisms. - * - * Even if they were in some header file or if __gss_mech_to_oid() - * and/or __gss_oid_to_mech() were standard we'd still have to hardcode - * the mechanism names, and since the mechanisms have no standard names - * other than their OIDs it's actually worse [less portable] to hardcode - * names than OIDs, so we hardcode OIDs. - * - * SPNEGO is a difficult problem though -- it MUST NOT be used in SSHv2, - * but that's true of all possible pseudo-mechanisms that can perform - * mechanism negotiation, and SPNEGO could have new OIDs in the future. - * Ideally we could query each mechanism for its feature set and then - * ignore any mechanisms that negotiate mechanisms, but, alas, there's - * no interface to do that. - * - * In the future, if the necessary generic GSS interfaces for the issues - * listed above are made available (even if they differ by platform, as - * we can expect authorization interfaces will), then we can stop - * referencing specific mechanism OIDs here. - */ -int -ssh_gssapi_is_spnego(gss_OID oid) -{ - return (oid->length == 6 && - memcmp("\053\006\001\005\005\002", oid->elements, 6) == 0); -} - -int -ssh_gssapi_is_krb5(gss_OID oid) -{ - return (oid->length == 9 && - memcmp("\x2A\x86\x48\x86\xF7\x12\x01\x02\x02", - oid->elements, 9) == 0); -} - -int -ssh_gssapi_is_dh(gss_OID oid) -{ - return (oid->length == 9 && - memcmp("\053\006\004\001\052\002\032\002\005", - oid->elements, 9) == 0); -} - -int -ssh_gssapi_is_gsi(gss_OID oid) -{ - return (oid->length == 9 && - memcmp("\x2B\x06\x01\x04\x01\x9B\x50\x01\x01", - oid->elements, 9) == 0); -} - -const char * -ssh_gssapi_oid_to_name(gss_OID oid) -{ -#ifdef HAVE_GSS_OID_TO_MECH - return (__gss_oid_to_mech(oid)); -#else - if (ssh_gssapi_is_krb5(oid)) - return ("Kerberos"); - if (ssh_gssapi_is_gsi(oid)) - return ("GSI"); - return ("(unknown)"); -#endif /* HAVE_GSS_OID_TO_MECH */ -} - -char * -ssh_gssapi_oid_to_str(gss_OID oid) -{ -#ifdef HAVE_GSS_OID_TO_STR - gss_buffer_desc str_buf; - char *str; - OM_uint32 maj, min; - - maj = gss_oid_to_str(&min, oid, &str_buf); - - if (GSS_ERROR(maj)) - return (xstrdup("<gss_oid_to_str() failed>")); - - str = xmalloc(str_buf.length + 1); - memset(str, 0, str_buf.length + 1); - strlcpy(str, str_buf.value, str_buf.length + 1); - (void) gss_release_buffer(&min, &str_buf); - - return (str); -#else - return (xstrdup("<gss_oid_to_str() unsupported>")); -#endif /* HAVE_GSS_OID_TO_STR */ -} - -/* Check that the OID in a data stream matches that in the context */ -int -ssh_gssapi_check_mech_oid(Gssctxt *ctx, void *data, size_t len) -{ - - return (ctx != NULL && ctx->desired_mech != GSS_C_NULL_OID && - ctx->desired_mech->length == len && - memcmp(ctx->desired_mech->elements, data, len) == 0); -} - -/* Set the contexts OID from a data stream */ -void -ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len) -{ - if (ctx->actual_mech != GSS_C_NULL_OID) { - xfree(ctx->actual_mech->elements); - xfree(ctx->actual_mech); - } - ctx->actual_mech = xmalloc(sizeof (gss_OID_desc)); - ctx->actual_mech->length = len; - ctx->actual_mech->elements = xmalloc(len); - memcpy(ctx->actual_mech->elements, data, len); -} - -/* Set the contexts OID */ -void -ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid) -{ - ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length); -} - -/* All this effort to report an error ... */ - -void -ssh_gssapi_error(Gssctxt *ctxt, const char *where) -{ - char *errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL); - - if (where != NULL) - debug("GSS-API error while %s: %s", where, errmsg); - else - debug("GSS-API error: %s", errmsg); - - /* ssh_gssapi_last_error() can't return NULL */ - xfree(errmsg); -} - -char * -ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, - OM_uint32 *minor_status) -{ - OM_uint32 lmin, more; - OM_uint32 maj, min; - gss_OID mech = GSS_C_NULL_OID; - gss_buffer_desc msg; - Buffer b; - char *ret; - - buffer_init(&b); - - if (ctxt) { - /* Get status codes from the Gssctxt */ - maj = ctxt->major; - min = ctxt->minor; - /* Output them if desired */ - if (major_status) - *major_status = maj; - if (minor_status) - *minor_status = min; - /* Get mechanism for minor status display */ - mech = (ctxt->actual_mech != GSS_C_NULL_OID) ? - ctxt->actual_mech : ctxt->desired_mech; - } else if (major_status && minor_status) { - maj = *major_status; - min = *major_status; - } else { - maj = GSS_S_COMPLETE; - min = 0; - } - - more = 0; - /* The GSSAPI error */ - do { - gss_display_status(&lmin, maj, GSS_C_GSS_CODE, - GSS_C_NULL_OID, &more, &msg); - - buffer_append(&b, msg.value, msg.length); - buffer_put_char(&b, '\n'); - gss_release_buffer(&lmin, &msg); - } while (more != 0); - - /* The mechanism specific error */ - do { - /* - * If mech == GSS_C_NULL_OID we may get the default - * mechanism, whatever that is, and that may not be - * useful. - */ - gss_display_status(&lmin, min, GSS_C_MECH_CODE, mech, &more, - &msg); - - buffer_append(&b, msg.value, msg.length); - buffer_put_char(&b, '\n'); - - gss_release_buffer(&lmin, &msg); - } while (more != 0); - - buffer_put_char(&b, '\0'); - ret = xstrdup(buffer_ptr(&b)); - buffer_free(&b); - - return (ret); -} - -/* - * Initialise our GSSAPI context. We use this opaque structure to contain all - * of the data which both the client and server need to persist across - * {accept,init}_sec_context calls, so that when we do it from the userauth - * stuff life is a little easier - */ -void -ssh_gssapi_build_ctx(Gssctxt **ctx, int client, gss_OID mech) -{ - Gssctxt *newctx; - - - newctx = (Gssctxt*)xmalloc(sizeof (Gssctxt)); - memset(newctx, 0, sizeof (Gssctxt)); - - - newctx->local = client; - newctx->desired_mech = ssh_gssapi_dup_oid(mech); - - /* This happens to be redundant given the memset() above */ - newctx->major = GSS_S_COMPLETE; - newctx->context = GSS_C_NO_CONTEXT; - newctx->actual_mech = GSS_C_NULL_OID; - newctx->desired_name = GSS_C_NO_NAME; - newctx->src_name = GSS_C_NO_NAME; - newctx->dst_name = GSS_C_NO_NAME; - newctx->creds = GSS_C_NO_CREDENTIAL; - newctx->deleg_creds = GSS_C_NO_CREDENTIAL; - - newctx->default_creds = (*ctx != NULL) ? (*ctx)->default_creds : 0; - - ssh_gssapi_delete_ctx(ctx); - - *ctx = newctx; -} - -gss_OID -ssh_gssapi_dup_oid(gss_OID oid) -{ - gss_OID new_oid; - - new_oid = xmalloc(sizeof (gss_OID_desc)); - - new_oid->elements = xmalloc(oid->length); - new_oid->length = oid->length; - memcpy(new_oid->elements, oid->elements, oid->length); - - return (new_oid); -} - -gss_OID -ssh_gssapi_make_oid(size_t length, void *elements) -{ - gss_OID_desc oid; - - oid.length = length; - oid.elements = elements; - - return (ssh_gssapi_dup_oid(&oid)); -} - -void -ssh_gssapi_release_oid(gss_OID *oid) -{ - OM_uint32 min; - - if (oid && *oid == GSS_C_NULL_OID) - return; - (void) gss_release_oid(&min, oid); - - if (*oid == GSS_C_NULL_OID) - return; /* libgss did own this gss_OID and released it */ - - xfree((*oid)->elements); - xfree(*oid); - *oid = GSS_C_NULL_OID; -} - -struct gss_name { - gss_OID name_type; - gss_buffer_t external_name; - gss_OID mech_type; - void *mech_name; -}; - -/* Delete our context, providing it has been built correctly */ -void -ssh_gssapi_delete_ctx(Gssctxt **ctx) -{ - OM_uint32 ms; - - if ((*ctx) == NULL) - return; - - if ((*ctx)->context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER); -#if 0 - /* XXX */ - if ((*ctx)->desired_mech != GSS_C_NULL_OID) - ssh_gssapi_release_oid(&(*ctx)->desired_mech); -#endif - if ((*ctx)->actual_mech != GSS_C_NULL_OID) - (void) ssh_gssapi_release_oid(&(*ctx)->actual_mech); - if ((*ctx)->desired_name != GSS_C_NO_NAME) - gss_release_name(&ms, &(*ctx)->desired_name); -#if 0 - if ((*ctx)->src_name != GSS_C_NO_NAME) - gss_release_name(&ms, &(*ctx)->src_name); -#endif - if ((*ctx)->dst_name != GSS_C_NO_NAME) - gss_release_name(&ms, &(*ctx)->dst_name); - if ((*ctx)->creds != GSS_C_NO_CREDENTIAL) - gss_release_cred(&ms, &(*ctx)->creds); - if ((*ctx)->deleg_creds != GSS_C_NO_CREDENTIAL) - gss_release_cred(&ms, &(*ctx)->deleg_creds); - - xfree(*ctx); - *ctx = NULL; -} - -/* Create a GSS hostbased service principal name for a given server hostname */ -int -ssh_gssapi_import_name(Gssctxt *ctx, const char *server_host) -{ - gss_buffer_desc name_buf; - int ret; - - /* Build target principal */ - name_buf.length = strlen(SSH_GSS_HOSTBASED_SERVICE) + - strlen(server_host) + 1; /* +1 for '@' */ - name_buf.value = xmalloc(name_buf.length + 1); /* +1 for NUL */ - ret = snprintf(name_buf.value, name_buf.length + 1, "%s@%s", - SSH_GSS_HOSTBASED_SERVICE, server_host); - - debug3("%s: snprintf() returned %d, expected %d", __func__, ret, - name_buf.length); - - ctx->major = gss_import_name(&ctx->minor, &name_buf, - GSS_C_NT_HOSTBASED_SERVICE, &ctx->desired_name); - - if (GSS_ERROR(ctx->major)) { - ssh_gssapi_error(ctx, "calling GSS_Import_name()"); - return (0); - } - - xfree(name_buf.value); - - return (1); -} - -OM_uint32 -ssh_gssapi_get_mic(Gssctxt *ctx, gss_buffer_desc *buffer, gss_buffer_desc *hash) -{ - - ctx->major = gss_get_mic(&ctx->minor, ctx->context, - GSS_C_QOP_DEFAULT, buffer, hash); - if (GSS_ERROR(ctx->major)) - ssh_gssapi_error(ctx, "while getting MIC"); - return (ctx->major); -} - -OM_uint32 -ssh_gssapi_verify_mic(Gssctxt *ctx, gss_buffer_desc *buffer, - gss_buffer_desc *hash) -{ - gss_qop_t qop; - - ctx->major = gss_verify_mic(&ctx->minor, ctx->context, buffer, - hash, &qop); - if (GSS_ERROR(ctx->major)) - ssh_gssapi_error(ctx, "while verifying MIC"); - return (ctx->major); -} -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/libssh/common/ssh-rsa.c b/usr/src/cmd/ssh/libssh/common/ssh-rsa.c deleted file mode 100644 index bc89d41da1..0000000000 --- a/usr/src/cmd/ssh/libssh/common/ssh-rsa.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: ssh-rsa.c,v 1.26 2002/08/27 17:13:56 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/evp.h> -#include <openssl/err.h> - -#include "xmalloc.h" -#include "log.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "ssh-rsa.h" -#include "compat.h" -#include "ssh.h" - -static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int , RSA *); - -/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ -int -ssh_rsa_sign(Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - const EVP_MD *evp_md; - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], *sig; - u_int slen, dlen, len; - int ok, nid; - Buffer b; - - if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { - error("ssh_rsa_sign: no RSA key"); - return -1; - } - nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; - if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); - return -1; - } - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - - slen = RSA_size(key->rsa); - sig = xmalloc(slen); - - ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); - memset(digest, 'd', sizeof(digest)); - - if (ok != 1) { - int ecode = ERR_get_error(); - error("ssh_rsa_sign: RSA_sign failed: %s", - ERR_error_string(ecode, NULL)); - xfree(sig); - return -1; - } - if (len < slen) { - u_int diff = slen - len; - debug("slen %u > len %u", slen, len); - memmove(sig + diff, sig, len); - memset(sig, 0, diff); - } else if (len > slen) { - error("ssh_rsa_sign: slen %u slen2 %u", slen, len); - xfree(sig); - return -1; - } - /* encode signature */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-rsa"); - buffer_put_string(&b, sig, slen); - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; - if (sigp != NULL) { - *sigp = xmalloc(len); - memcpy(*sigp, buffer_ptr(&b), len); - } - buffer_free(&b); - memset(sig, 's', slen); - xfree(sig); - - return 0; -} - -int -ssh_rsa_verify(Key *key, u_char *signature, u_int signaturelen, - u_char *data, u_int datalen) -{ - Buffer b; - const EVP_MD *evp_md; - EVP_MD_CTX md; - char *ktype; - u_char digest[EVP_MAX_MD_SIZE], *sigblob; - u_int len, dlen, modlen; - int rlen, ret, nid; - - if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { - error("ssh_rsa_verify: no RSA key"); - return -1; - } - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", - BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); - return -1; - } - buffer_init(&b); - buffer_append(&b, signature, signaturelen); - ktype = buffer_get_string(&b, NULL); - if (strcmp("ssh-rsa", ktype) != 0) { - error("ssh_rsa_verify: cannot handle type %s", ktype); - buffer_free(&b); - xfree(ktype); - return -1; - } - xfree(ktype); - sigblob = buffer_get_string(&b, &len); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("ssh_rsa_verify: remaining bytes in signature %d", rlen); - xfree(sigblob); - return -1; - } - /* RSA_verify expects a signature of RSA_size */ - modlen = RSA_size(key->rsa); - if (len > modlen) { - error("ssh_rsa_verify: len %u > modlen %u", len, modlen); - xfree(sigblob); - return -1; - } else if (len < modlen) { - u_int diff = modlen - len; - debug("ssh_rsa_verify: add padding: modlen %u > len %u", - modlen, len); - sigblob = xrealloc(sigblob, modlen); - memmove(sigblob + diff, sigblob, len); - memset(sigblob, 0, diff); - len = modlen; - } - nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; - if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); - xfree(sigblob); - return -1; - } - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - - ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); - memset(digest, 'd', sizeof(digest)); - memset(sigblob, 's', len); - xfree(sigblob); - debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); - return ret; -} - -/* - * See: - * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ - * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn - */ -/* - * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) - * oiw(14) secsig(3) algorithms(2) 26 } - */ -static const u_char id_sha1[] = { - 0x30, 0x21, /* type Sequence, length 0x21 (33) */ - 0x30, 0x09, /* type Sequence, length 0x09 */ - 0x06, 0x05, /* type OID, length 0x05 */ - 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ - 0x05, 0x00, /* NULL */ - 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ -}; -/* - * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) - * rsadsi(113549) digestAlgorithm(2) 5 } - */ -static const u_char id_md5[] = { - 0x30, 0x20, /* type Sequence, length 0x20 (32) */ - 0x30, 0x0c, /* type Sequence, length 0x09 */ - 0x06, 0x08, /* type OID, length 0x05 */ - 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */ - 0x05, 0x00, /* NULL */ - 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */ -}; - -static int -openssh_RSA_verify(int type, u_char *hash, u_int hashlen, - u_char *sigbuf, u_int siglen, RSA *rsa) -{ - u_int ret, rsasize, oidlen = 0, hlen = 0; - int len; - const u_char *oid = NULL; - u_char *decrypted = NULL; - - ret = 0; - switch (type) { - case NID_sha1: - oid = id_sha1; - oidlen = sizeof(id_sha1); - hlen = 20; - break; - case NID_md5: - oid = id_md5; - oidlen = sizeof(id_md5); - hlen = 16; - break; - default: - goto done; - break; - } - if (hashlen != hlen) { - error("bad hashlen"); - goto done; - } - rsasize = RSA_size(rsa); - if (siglen == 0 || siglen > rsasize) { - error("bad siglen"); - goto done; - } - decrypted = xmalloc(rsasize); - if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, - RSA_PKCS1_PADDING)) < 0) { - error("RSA_public_decrypt failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto done; - } - if (len != hlen + oidlen) { - error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); - goto done; - } - if (memcmp(decrypted, oid, oidlen) != 0) { - error("oid mismatch"); - goto done; - } - if (memcmp(decrypted + oidlen, hash, hlen) != 0) { - error("hash mismatch"); - goto done; - } - ret = 1; -done: - if (decrypted) - xfree(decrypted); - return ret; -} diff --git a/usr/src/cmd/ssh/libssh/common/tildexpand.c b/usr/src/cmd/ssh/libssh/common/tildexpand.c deleted file mode 100644 index 5fcd07ebe6..0000000000 --- a/usr/src/cmd/ssh/libssh/common/tildexpand.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: tildexpand.c,v 1.13 2002/06/23 03:25:50 deraadt Exp $"); - -#include <libgen.h> - -#include "xmalloc.h" -#include "log.h" -#include "tildexpand.h" - -/* - * Expands tildes in the file name. Returns data allocated by xmalloc. - * Warning: this calls getpw*. - */ -char * -tilde_expand_filename(const char *filename, uid_t my_uid) -{ - const char *cp; - uint_t userlen; - char *expanded; - struct passwd *pw; - char *pw_dir; - char user[100]; - int len; - - /* Return immediately if no tilde. */ - if (filename[0] != '~') - return (xstrdup(filename)); - - /* Skip the tilde. */ - filename++; - - /* Find where the username ends. */ - cp = strchr(filename, '/'); - if (cp) - userlen = cp - filename; /* Something after username. */ - else - userlen = strlen(filename); /* Nothing after username. */ - - /* This is the ~/xyz case with no ~username specification. */ - if (userlen == 0) - pw = getpwuid(my_uid); - else { - /* Tilde refers to someone elses home directory. */ - if (userlen > sizeof (user) - 1) - fatal("User name after tilde too long."); - memcpy(user, filename, userlen); - user[userlen] = 0; - pw = getpwnam(user); - } - - /* Use the HOME variable now. */ - if (pw == NULL) { - debug("User account's password entry not found, trying to use " - "the HOME variable."); - if ((pw_dir = getenv("HOME")) == NULL) { - fatal("User account's password entry not found and " - "the HOME variable not set."); - } - } else { - pw_dir = pw->pw_dir; - } - - /* If referring to someones home directory, return it now. */ - if (cp == NULL) { - /* Only home directory specified */ - return (xstrdup(pw_dir)); - } - - /* Build a path combining the specified directory and path. */ - len = strlen(pw_dir) + strlen(cp + 1) + 2; - if (len > MAXPATHLEN) - fatal("Home directory too long (%d > %d)", len - 1, - MAXPATHLEN - 1); - - expanded = xmalloc(len); - snprintf(expanded, len, "%s%s%s", pw_dir, - strcmp(pw_dir, "/") ? "/" : "", cp + 1); - return (expanded); -} diff --git a/usr/src/cmd/ssh/libssh/common/ttymodes.c b/usr/src/cmd/ssh/libssh/common/ttymodes.c deleted file mode 100644 index b20ab34ff3..0000000000 --- a/usr/src/cmd/ssh/libssh/common/ttymodes.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* - * SSH2 tty modes support by Kevin Steves. - * Copyright (c) 2001 Kevin Steves. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Encoding and decoding of terminal modes in a portable way. - * Much of the format is defined in ttymodes.h; it is included multiple times - * into this file with the appropriate macro definitions to generate the - * suitable code. - */ - -#include "includes.h" -RCSID("$OpenBSD: ttymodes.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $"); - -#include "packet.h" -#include "log.h" -#include "ssh1.h" -#include "compat.h" -#include "buffer.h" -#include "bufaux.h" - -#define TTY_OP_END 0 -/* - * uint32 (u_int) follows speed in SSH1 and SSH2 - */ -#define TTY_OP_ISPEED_PROTO1 192 -#define TTY_OP_OSPEED_PROTO1 193 -#define TTY_OP_ISPEED_PROTO2 128 -#define TTY_OP_OSPEED_PROTO2 129 - -/* - * Converts POSIX speed_t to a baud rate. The values of the - * constants for speed_t are not themselves portable. - */ -static int -speed_to_baud(speed_t speed) -{ - switch (speed) { - case B0: - return 0; - case B50: - return 50; - case B75: - return 75; - case B110: - return 110; - case B134: - return 134; - case B150: - return 150; - case B200: - return 200; - case B300: - return 300; - case B600: - return 600; - case B1200: - return 1200; - case B1800: - return 1800; - case B2400: - return 2400; - case B4800: - return 4800; - case B9600: - return 9600; - -#ifdef B19200 - case B19200: - return 19200; -#else /* B19200 */ -#ifdef EXTA - case EXTA: - return 19200; -#endif /* EXTA */ -#endif /* B19200 */ - -#ifdef B38400 - case B38400: - return 38400; -#else /* B38400 */ -#ifdef EXTB - case EXTB: - return 38400; -#endif /* EXTB */ -#endif /* B38400 */ - -#ifdef B7200 - case B7200: - return 7200; -#endif /* B7200 */ -#ifdef B14400 - case B14400: - return 14400; -#endif /* B14400 */ -#ifdef B28800 - case B28800: - return 28800; -#endif /* B28800 */ -#ifdef B57600 - case B57600: - return 57600; -#endif /* B57600 */ -#ifdef B76800 - case B76800: - return 76800; -#endif /* B76800 */ -#ifdef B115200 - case B115200: - return 115200; -#endif /* B115200 */ -#ifdef B230400 - case B230400: - return 230400; -#endif /* B230400 */ -#ifdef B460800 - case B460800: - return 460800; -#endif /* B460800 */ -#ifdef B921600 - case B921600: - return 921600; -#endif /* B921600 */ - default: - return 9600; - } -} - -/* - * Converts a numeric baud rate to a POSIX speed_t. - */ -static speed_t -baud_to_speed(int baud) -{ - switch (baud) { - case 0: - return B0; - case 50: - return B50; - case 75: - return B75; - case 110: - return B110; - case 134: - return B134; - case 150: - return B150; - case 200: - return B200; - case 300: - return B300; - case 600: - return B600; - case 1200: - return B1200; - case 1800: - return B1800; - case 2400: - return B2400; - case 4800: - return B4800; - case 9600: - return B9600; - -#ifdef B19200 - case 19200: - return B19200; -#else /* B19200 */ -#ifdef EXTA - case 19200: - return EXTA; -#endif /* EXTA */ -#endif /* B19200 */ - -#ifdef B38400 - case 38400: - return B38400; -#else /* B38400 */ -#ifdef EXTB - case 38400: - return EXTB; -#endif /* EXTB */ -#endif /* B38400 */ - -#ifdef B7200 - case 7200: - return B7200; -#endif /* B7200 */ -#ifdef B14400 - case 14400: - return B14400; -#endif /* B14400 */ -#ifdef B28800 - case 28800: - return B28800; -#endif /* B28800 */ -#ifdef B57600 - case 57600: - return B57600; -#endif /* B57600 */ -#ifdef B76800 - case 76800: - return B76800; -#endif /* B76800 */ -#ifdef B115200 - case 115200: - return B115200; -#endif /* B115200 */ -#ifdef B230400 - case 230400: - return B230400; -#endif /* B230400 */ -#ifdef B460800 - case 460800: - return B460800; -#endif /* B460800 */ -#ifdef B921600 - case 921600: - return B921600; -#endif /* B921600 */ - default: - return B9600; - } -} - -/* - * Encodes terminal modes for the terminal referenced by fd - * or tiop in a portable manner, and appends the modes to a packet - * being constructed. - */ -void -tty_make_modes(int fd, struct termios *tiop) -{ - struct termios tio; - int baud; - Buffer buf; - int tty_op_ospeed, tty_op_ispeed; - void (*put_arg)(Buffer *, u_int); - - buffer_init(&buf); - if (compat20) { - tty_op_ospeed = TTY_OP_OSPEED_PROTO2; - tty_op_ispeed = TTY_OP_ISPEED_PROTO2; - put_arg = buffer_put_int; - } else { - tty_op_ospeed = TTY_OP_OSPEED_PROTO1; - tty_op_ispeed = TTY_OP_ISPEED_PROTO1; - put_arg = (void (*)(Buffer *, u_int)) buffer_put_char; - } - - if (tiop == NULL) { - if (tcgetattr(fd, &tio) == -1) { - log("tcgetattr: %.100s", strerror(errno)); - goto end; - } - } else - tio = *tiop; - - /* Store input and output baud rates. */ - baud = speed_to_baud(cfgetospeed(&tio)); - debug3("tty_make_modes: ospeed %d", baud); - buffer_put_char(&buf, tty_op_ospeed); - buffer_put_int(&buf, baud); - baud = speed_to_baud(cfgetispeed(&tio)); - debug3("tty_make_modes: ispeed %d", baud); - buffer_put_char(&buf, tty_op_ispeed); - buffer_put_int(&buf, baud); - - /* Store values of mode flags. */ -#define TTYCHAR(NAME, OP) \ - debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \ - buffer_put_char(&buf, OP); \ - put_arg(&buf, tio.c_cc[NAME]); - -#define TTYMODE(NAME, FIELD, OP) \ - debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \ - buffer_put_char(&buf, OP); \ - put_arg(&buf, ((tio.FIELD & NAME) != 0)); - -#include "ttymodes.h" - -#undef TTYCHAR -#undef TTYMODE - -end: - /* Mark end of mode data. */ - buffer_put_char(&buf, TTY_OP_END); - if (compat20) - packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); - else - packet_put_raw(buffer_ptr(&buf), buffer_len(&buf)); - buffer_free(&buf); -} - -/* - * Decodes terminal modes for the terminal referenced by fd in a portable - * manner from a packet being read. - */ -void -tty_parse_modes(int fd, int *n_bytes_ptr) -{ - struct termios tio; - int opcode, baud; - int n_bytes = 0; - int failure = 0; - u_int (*get_arg)(void); - int arg, arg_size; - - if (compat20) { - *n_bytes_ptr = packet_get_int(); - debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); - if (*n_bytes_ptr == 0) - return; - get_arg = packet_get_int; - arg_size = 4; - } else { - get_arg = packet_get_char; - arg_size = 1; - } - - /* - * Get old attributes for the terminal. We will modify these - * flags. I am hoping that if there are any machine-specific - * modes, they will initially have reasonable values. - */ - if (tcgetattr(fd, &tio) == -1) { - log("tcgetattr: %.100s", strerror(errno)); - failure = -1; - } - - for (;;) { - n_bytes += 1; - opcode = packet_get_char(); - switch (opcode) { - case TTY_OP_END: - goto set; - - /* XXX: future conflict possible */ - case TTY_OP_ISPEED_PROTO1: - case TTY_OP_ISPEED_PROTO2: - n_bytes += 4; - baud = packet_get_int(); - debug3("tty_parse_modes: ispeed %d", baud); - if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) - error("cfsetispeed failed for %d", baud); - break; - - /* XXX: future conflict possible */ - case TTY_OP_OSPEED_PROTO1: - case TTY_OP_OSPEED_PROTO2: - n_bytes += 4; - baud = packet_get_int(); - debug3("tty_parse_modes: ospeed %d", baud); - if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) - error("cfsetospeed failed for %d", baud); - break; - -#define TTYCHAR(NAME, OP) \ - case OP: \ - n_bytes += arg_size; \ - tio.c_cc[NAME] = get_arg(); \ - debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \ - break; -#define TTYMODE(NAME, FIELD, OP) \ - case OP: \ - n_bytes += arg_size; \ - if ((arg = get_arg())) \ - tio.FIELD |= NAME; \ - else \ - tio.FIELD &= ~NAME; \ - debug3("tty_parse_modes: %d %d", OP, arg); \ - break; - -#include "ttymodes.h" - -#undef TTYCHAR -#undef TTYMODE - - default: - debug("Ignoring unsupported tty mode opcode %d (0x%x)", - opcode, opcode); - if (!compat20) { - /* - * SSH1: - * Opcodes 1 to 127 are defined to have - * a one-byte argument. - * Opcodes 128 to 159 are defined to have - * an integer argument. - */ - if (opcode > 0 && opcode < 128) { - n_bytes += 1; - (void) packet_get_char(); - break; - } else if (opcode >= 128 && opcode < 160) { - n_bytes += 4; - (void) packet_get_int(); - break; - } else { - /* - * It is a truly undefined opcode (160 to 255). - * We have no idea about its arguments. So we - * must stop parsing. Note that some data may be - * left in the packet; hopefully there is nothing - * more coming after the mode data. - */ - log("parse_tty_modes: unknown opcode %d", opcode); - goto set; - } - } else { - /* - * SSH2: - * Opcodes 1 to 159 are defined to have - * a uint32 argument. - * Opcodes 160 to 255 are undefined and - * cause parsing to stop. - */ - if (opcode > 0 && opcode < 160) { - n_bytes += 4; - (void) packet_get_int(); - break; - } else { - log("parse_tty_modes: unknown opcode %d", opcode); - goto set; - } - } - } - } - -set: - if (*n_bytes_ptr != n_bytes) { - *n_bytes_ptr = n_bytes; - log("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d", - *n_bytes_ptr, n_bytes); - return; /* Don't process bytes passed */ - } - if (failure == -1) - return; /* Packet parsed ok but tcgetattr() failed */ - - /* Set the new modes for the terminal. */ - if (tcsetattr(fd, TCSANOW, &tio) == -1) - log("Setting tty modes failed: %.100s", strerror(errno)); -} diff --git a/usr/src/cmd/ssh/libssh/common/uidswap.c b/usr/src/cmd/ssh/libssh/common/uidswap.c deleted file mode 100644 index 942b22a749..0000000000 --- a/usr/src/cmd/ssh/libssh/common/uidswap.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Code for uid-swapping. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: uidswap.c,v 1.23 2002/07/15 17:15:31 stevesk Exp $"); - -#include <priv.h> - -#include "log.h" -#include "uidswap.h" -#include "buffer.h" -#include "servconf.h" - -/* - * Note: all these functions must work in all of the following cases: - * 1. euid=0, ruid=0 - * 2. euid=0, ruid!=0 - * 3. euid!=0, ruid!=0 - * Additionally, they must work regardless of whether the system has - * POSIX saved uids or not. - */ - -#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS) -/* Lets assume that posix saved ids also work with seteuid, even though that - is not part of the posix specification. */ -#define SAVED_IDS_WORK -/* Saved effective uid. */ -static uid_t saved_euid = 0; -static gid_t saved_egid = 0; -#endif - -/* Saved effective uid. */ -static int privileged = 0; -static int temporarily_use_uid_effective = 0; -static int ngroups_max = -1; -static gid_t *saved_egroups, *user_groups; -static int saved_egroupslen = -1, user_groupslen = -1; - -/* - * Temporarily changes to the given uid. If the effective user - * id is not root, this does nothing. This call cannot be nested. - */ -void -temporarily_use_uid(struct passwd *pw) -{ - /* Save the current euid, and egroups. */ -#ifdef SAVED_IDS_WORK - saved_euid = geteuid(); - saved_egid = getegid(); - debug("temporarily_use_uid: %u/%u (e=%u/%u)", - (u_int)pw->pw_uid, (u_int)pw->pw_gid, - (u_int)saved_euid, (u_int)saved_egid); - if (saved_euid != 0) { - privileged = 0; - return; - } -#else - if (geteuid() != 0) { - privileged = 0; - return; - } -#endif /* SAVED_IDS_WORK */ - - privileged = 1; - temporarily_use_uid_effective = 1; - - if (ngroups_max < 0) { - ngroups_max = sysconf(_SC_NGROUPS_MAX); - saved_egroups = malloc(ngroups_max * sizeof (gid_t)); - user_groups = malloc(ngroups_max * sizeof (gid_t)); - if (saved_egroups == NULL || user_groups == NULL) - fatal("malloc(gid array): %.100s", strerror(errno)); - } - - saved_egroupslen = getgroups(ngroups_max, saved_egroups); - if (saved_egroupslen < 0) - fatal("getgroups: %.100s", strerror(errno)); - - /* set and save the user's groups */ - if (user_groupslen == -1) { - if (initgroups(pw->pw_name, pw->pw_gid) < 0) - fatal("initgroups: %s: %.100s", pw->pw_name, - strerror(errno)); - user_groupslen = getgroups(ngroups_max, user_groups); - if (user_groupslen < 0) - fatal("getgroups: %.100s", strerror(errno)); - } - /* Set the effective uid to the given (unprivileged) uid. */ - if (setgroups(user_groupslen, user_groups) < 0) - fatal("setgroups: %.100s", strerror(errno)); -#ifdef SAVED_IDS_WORK - /* Set saved gid and set real gid */ - if (setregid(pw->pw_gid, -1) == -1) - debug("setregid(%u, -1): %.100s", (uint_t)pw->pw_gid, strerror(errno)); - /* Set saved uid and set real uid */ - if (setreuid(pw->pw_uid, -1) == -1) - debug("setreuid(%u, -1): %.100s", (uint_t)pw->pw_uid, strerror(errno)); -#else - /* Propagate the privileged gid to all of our gids. */ - if (setgid(getegid()) < 0) - debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno)); - /* Propagate the privileged uid to all of our uids. */ - if (setuid(geteuid()) < 0) - debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno)); -#endif /* SAVED_IDS_WORK */ - /* Set effective gid */ - if (setegid(pw->pw_gid) == -1) - fatal("setegid %u: %.100s", (u_int)pw->pw_uid, - strerror(errno)); - /* Set effective uid */ - if (seteuid(pw->pw_uid) == -1) - fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, - strerror(errno)); - /* - * If saved set ids work then - * - * ruid == euid == pw->pw_uid - * saved uid = previous euid - * rgid == egid == pw->pw_gid - * saved gid = previous egid - */ -} - -/* - * Restores to the original (privileged) uid. - */ -void -restore_uid(void) -{ - /* it's a no-op unless privileged */ - if (!privileged) { - debug("restore_uid: (unprivileged)"); - return; - } - if (!temporarily_use_uid_effective) - fatal("restore_uid: temporarily_use_uid not effective"); - -#ifdef SAVED_IDS_WORK - debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid); - /* Set the effective uid back to the saved privileged uid. */ - if (seteuid(saved_euid) < 0) - fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno)); - if (setuid(saved_euid) < 0) - fatal("setuid %u: %.100s", (u_int)saved_euid, strerror(errno)); - if (setegid(saved_egid) < 0) - fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno)); - if (setgid(saved_egid) < 0) - fatal("setgid %u: %.100s", (u_int)saved_egid, strerror(errno)); -#else /* SAVED_IDS_WORK */ - /* - * We are unable to restore the real uid to its unprivileged value. - * Propagate the real uid (usually more privileged) to effective uid - * as well. - */ - setuid(getuid()); - setgid(getgid()); -#endif /* SAVED_IDS_WORK */ - - if (setgroups(saved_egroupslen, saved_egroups) < 0) - fatal("setgroups: %.100s", strerror(errno)); - temporarily_use_uid_effective = 0; -} - -/* - * Permanently sets all uids to the given uid. This cannot be called while - * temporarily_use_uid is effective. Note that when the ChrootDirectory option - * is in use we keep a few privileges so that we can call chroot(2) later while - * already running under UIDs of a connecting user. - */ -void -permanently_set_uid(struct passwd *pw, char *chroot_directory) -{ - priv_set_t *pset; - - if (temporarily_use_uid_effective) - fatal("%s: temporarily_use_uid effective", __func__); - - debug("%s: %u/%u", __func__, (u_int)pw->pw_uid, (u_int)pw->pw_gid); - - if (initgroups(pw->pw_name, pw->pw_gid) < 0) - fatal("initgroups: %s: %.100s", pw->pw_name, - strerror(errno)); - - if (setgid(pw->pw_gid) < 0) - fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); - - /* - * If root is connecting we are done now. Note that we must have called - * setgid() in case that the SSH server was run under a group other than - * root. - */ - if (pw->pw_uid == 0) - return; - - /* - * This means we will keep all privileges after the UID change. - */ - if (setpflags(PRIV_AWARE, 1) != 0) - fatal("setpflags: %s", strerror(errno)); - - /* Now we are running under UID of the user. */ - if (setuid(pw->pw_uid) < 0) - fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); - - /* - * We will run with the privileges from the Inheritable set as - * we would have after exec(2) if we had stayed in NPA mode - * before setuid(2) call (see privileges(5), user_attr(4), and - * pam_unix_cred(5)). We want to run with P = E = I, with I as - * set by pam_unix_cred(5). We also add PRIV_PROC_CHROOT, - * obviously, and then PRIV_PROC_FORK and PRIV_PROC_EXEC, since - * those two might have been removed from the I set. Note that - * we are expected to finish the login process without them in - * the I set, the important thing is that those not be passed on - * to a shell or a subsystem later if they were not set in - * pam_unix_cred(5). - */ - if ((pset = priv_allocset()) == NULL) - fatal("priv_allocset: %s", strerror(errno)); - if (getppriv(PRIV_INHERITABLE, pset) != 0) - fatal("getppriv: %s", strerror(errno)); - - /* We do not need PRIV_PROC_CHROOT unless chroot()ing. */ - if (chroot_requested(chroot_directory) && - priv_addset(pset, PRIV_PROC_CHROOT) == -1) { - fatal("%s: priv_addset failed", __func__); - } - - if (priv_addset(pset, PRIV_PROC_FORK) == -1 || - priv_addset(pset, PRIV_PROC_EXEC) == -1) { - fatal("%s: priv_addset failed", __func__); - } - - /* Set only P; this will also set E. */ - if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) == -1) - fatal("setppriv: %s", strerror(errno)); - - /* We don't need the PA flag anymore. */ - if (setpflags(PRIV_AWARE, 0) == -1) - fatal("setpflags: %s", strerror(errno)); - - priv_freeset(pset); -} diff --git a/usr/src/cmd/ssh/libssh/common/uuencode.c b/usr/src/cmd/ssh/libssh/common/uuencode.c deleted file mode 100644 index 432f5c4369..0000000000 --- a/usr/src/cmd/ssh/libssh/common/uuencode.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: uuencode.c,v 1.16 2002/09/09 14:54:15 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "xmalloc.h" -#include "uuencode.h" - -int -uuencode(u_char *src, u_int srclength, - char *target, size_t targsize) -{ - return __b64_ntop(src, srclength, target, targsize); -} - -int -uudecode(const char *src, u_char *target, size_t targsize) -{ - int len; - char *encoded, *p; - - /* copy the 'readonly' source */ - encoded = xstrdup(src); - /* skip whitespace and data */ - for (p = encoded; *p == ' ' || *p == '\t'; p++) - ; - for (; *p != '\0' && *p != ' ' && *p != '\t'; p++) - ; - /* and remove trailing whitespace because __b64_pton needs this */ - *p = '\0'; - len = __b64_pton((u_char *) encoded, target, targsize); - xfree(encoded); - return len; -} - -void -dump_base64(FILE *fp, u_char *data, u_int len) -{ - char *buf = xmalloc(2*len); - int i, n; - - n = uuencode(data, len, buf, 2*len); - for (i = 0; i < n; i++) { - fprintf(fp, "%c", buf[i]); - if (i % 70 == 69) - fprintf(fp, "\n"); - } - if (i % 70 != 69) - fprintf(fp, "\n"); - xfree(buf); -} diff --git a/usr/src/cmd/ssh/libssh/common/xlist.c b/usr/src/cmd/ssh/libssh/common/xlist.c deleted file mode 100644 index c44e420eeb..0000000000 --- a/usr/src/cmd/ssh/libssh/common/xlist.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <strings.h> -#include "xmalloc.h" -#include "xlist.h" - -char ** -xsplit(char *list, char sep) -{ - char **a; - char *p, *q; - uint_t n = 0; - - for (n = 0, p = list; p && *p; ) { - while (p && *p && *p == sep) - p++; - if (!*p) - break; - n++; - p = strchr(p, sep); - } - a = (char **)xmalloc(sizeof (char *) * (n + 2)); - for (n = 0, p = list; p && *p; ) { - while (*p == sep) - p++; - if (!*p) - break; - q = strchr(p, sep); - if (!q) - q = p + strlen(p); - a[n] = (char *)xmalloc((q - p + 2)); - (void) strncpy(a[n], p, q - p); - a[n][q - p] = '\0'; - n++; - if (!*q) - break; - p = q + 1; - } - a[n] = NULL; - return (a); -} - -void -xfree_split_list(char **list) -{ - char **p; - for (p = list; p && *p; p++) { - xfree(*p); - } - xfree(list); -} - -char * -xjoin(char **alist, char sep) -{ - char **p; - char *list; - char sep_str[2]; - uint_t n; - - for (n = 1, p = alist; p && *p; p++) { - if (!*p || !**p) - continue; - n += strlen(*p) + 1; - } - list = (char *)xmalloc(n); - *list = '\0'; - - sep_str[0] = sep; - sep_str[1] = '\0'; - for (p = alist; p && *p; p++) { - if (!*p || !**p) - continue; - if (*list != '\0') - (void) strlcat(list, sep_str, n); - (void) strlcat(list, *p, n); - } - return (list); -} diff --git a/usr/src/cmd/ssh/libssh/common/xmalloc.c b/usr/src/cmd/ssh/libssh/common/xmalloc.c deleted file mode 100644 index b9ae011d3c..0000000000 --- a/usr/src/cmd/ssh/libssh/common/xmalloc.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Versions of malloc and friends that check their results, and never return - * failure (they call fatal if they encounter an error). - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "xmalloc.h" -#include "log.h" - -void * -xmalloc(size_t size) -{ - void *ptr; - - if (size == 0) - fatal("xmalloc: zero size"); - ptr = malloc(size); - if (ptr == NULL) - fatal("xmalloc: out of memory (allocating %lu bytes)", (u_long) size); - return ptr; -} - -void * -xcalloc(size_t nmemb, size_t size) -{ - void *ptr; - - if (size == 0 || nmemb == 0) - fatal("xcalloc: zero size"); - if (SIZE_T_MAX / nmemb < size) - fatal("xcalloc: nmemb * size > SIZE_T_MAX"); - ptr = calloc(nmemb, size); - if (ptr == NULL) - fatal("xcalloc: out of memory (allocating %lu bytes)", - (u_long)(size * nmemb)); - return ptr; -} - -void * -xrealloc(void *ptr, size_t new_size) -{ - void *new_ptr; - - if (new_size == 0) - fatal("xrealloc: zero size"); - if (ptr == NULL) - new_ptr = malloc(new_size); - else - new_ptr = realloc(ptr, new_size); - if (new_ptr == NULL) - fatal("xrealloc: out of memory (new_size %lu bytes)", (u_long) new_size); - return new_ptr; -} - -void -xfree(void *ptr) -{ - if (ptr == NULL) - fatal("xfree: NULL pointer given as argument"); - free(ptr); -} - -char * -xstrdup(const char *str) -{ - size_t len; - char *cp; - - len = strlen(str) + 1; - cp = xmalloc(len); - strlcpy(cp, str, len); - return cp; -} diff --git a/usr/src/cmd/ssh/req.flg b/usr/src/cmd/ssh/req.flg deleted file mode 100644 index f02f86c7fe..0000000000 --- a/usr/src/cmd/ssh/req.flg +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#pragma ident "%Z%%M% %I% %E% SMI" - -echo_file usr/src/lib/Makefile.lib -echo_file usr/src/lib/Makefile.targ -echo_file usr/src/cmd/Makefile.cmd diff --git a/usr/src/cmd/ssh/scp/scp.c b/usr/src/cmd/ssh/scp/scp.c deleted file mode 100644 index 2759d952c5..0000000000 --- a/usr/src/cmd/ssh/scp/scp.c +++ /dev/null @@ -1,1341 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * scp - secure remote copy. This is basically patched BSD rcp which - * uses ssh to do the data transfer (instead of using rcmd). - * - * NOTE: This version should NOT be suid root. (This uses ssh to - * do the transfer and ssh has the necessary privileges.) - * - * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi> - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 1999 Theo de Raadt. All rights reserved. - * Copyright (c) 1999 Aaron Campbell. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Parts from: - * - * Copyright (c) 1983, 1990, 1992, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.91 2002/06/19 00:27:55 deraadt Exp $"); - -#include "xmalloc.h" -#include "atomicio.h" -#include "pathnames.h" -#include "log.h" -#include "misc.h" - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -/* For progressmeter() -- number of seconds before xfer considered "stalled" */ -#define STALLTIME 5 -/* alarm() interval for updating progress meter */ -#define PROGRESSTIME 1 - -/* Visual statistics about files as they are transferred. */ -void progressmeter(int); - -/* Returns width of the terminal (for progress meter calculations). */ -int getttywidth(void); -int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, - int argc); - -/* Struct for addargs */ -arglist args; - -/* Time a transfer started. */ -static struct timeval start; - -/* Number of bytes of current file transferred so far. */ -volatile off_t statbytes; - -/* Total size of current file. */ -off_t totalbytes = 0; - -/* Name of current file being transferred. */ -char *curfile; - -/* This is set to non-zero to enable verbose mode. */ -int verbose_mode = 0; - -/* This is set to zero if the progressmeter is not desired. */ -int showprogress = 1; - -/* This is the program to execute for the secured connection. ("ssh" or -S) */ -char *ssh_program = _PATH_SSH_PROGRAM; - -/* This is used to store the pid of ssh_program */ -static pid_t do_cmd_pid = -1; - -static void -killchild(int signo) -{ - if (do_cmd_pid > 1) { - kill(do_cmd_pid, signo ? signo : SIGTERM); - waitpid(do_cmd_pid, NULL, 0); - } - - if (signo) - _exit(1); - exit(1); -} - -/* - * Run a command via fork(2)/exec(2). This can be a local-to-local copy via - * cp(1) or one side of a remote-to-remote copy. We must not use system(3) here - * because we don't want filenames to go through a command expansion in the - * underlying shell. Note that the user can create a filename that is a piece of - * shell code itself and this must not be executed. - */ -static int -do_local_cmd(arglist *a) -{ - uint_t i; - int status; - pid_t pid; - - if (a->num == 0) - fatal("do_local_cmd: no arguments"); - - if (verbose_mode) { - fprintf(stderr, gettext("Executing:")); - for (i = 0; i < a->num; i++) - fprintf(stderr, " %s", a->list[i]); - fprintf(stderr, "\n"); - } - if ((pid = fork()) == -1) - fatal("do_local_cmd: fork: %s", strerror(errno)); - - if (pid == 0) { - execvp(a->list[0], a->list); - perror(a->list[0]); - exit(1); - } - - do_cmd_pid = pid; - signal(SIGTERM, killchild); - signal(SIGINT, killchild); - signal(SIGHUP, killchild); - - while (waitpid(pid, &status, 0) == -1) - if (errno != EINTR) - fatal("do_local_cmd: waitpid: %s", strerror(errno)); - - do_cmd_pid = -1; - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - return (-1); - - return (0); -} - -/* - * This function executes the given command as the specified user on the - * given host. This returns < 0 if execution fails, and >= 0 otherwise. This - * assigns the input and output file descriptors on success. - */ - -int -do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) -{ - int pin[2], pout[2], reserved[2]; - - if (verbose_mode) - fprintf(stderr, - gettext("Executing: program %s host %s, " - "user %s, command %s\n"), - ssh_program, host, - remuser ? remuser : gettext("(unspecified)"), cmd); - - /* - * Reserve two descriptors so that the real pipes won't get - * descriptors 0 and 1 because that will screw up dup2 below. - */ - pipe(reserved); - - /* Create a socket pair for communicating with ssh. */ - if (pipe(pin) < 0) - fatal("pipe: %s", strerror(errno)); - if (pipe(pout) < 0) - fatal("pipe: %s", strerror(errno)); - - /* Free the reserved descriptors. */ - close(reserved[0]); - close(reserved[1]); - - /* For a child to execute the command on the remote host using ssh. */ - if ((do_cmd_pid = fork()) == 0) { - /* Child. */ - close(pin[1]); - close(pout[0]); - dup2(pin[0], 0); - dup2(pout[1], 1); - close(pin[0]); - close(pout[1]); - - args.list[0] = ssh_program; - if (remuser != NULL) - addargs(&args, "-l%s", remuser); - addargs(&args, "%s", host); - addargs(&args, "%s", cmd); - - execvp(ssh_program, args.list); - perror(ssh_program); - exit(1); - } else if (do_cmd_pid == (pid_t)-1) { - /* fork() failed */ - fatal("fork: %s", strerror(errno)); - } - - /* Parent. Close the other side, and return the local side. */ - close(pin[0]); - *fdout = pin[1]; - close(pout[1]); - *fdin = pout[0]; - return (0); -} - -typedef struct { - int cnt; - char *buf; -} BUF; - -BUF *allocbuf(BUF *, int, int); -void lostconn(int); -void nospace(void); -int okname(char *); -void run_err(const char *, ...); -void verifydir(char *); - -struct passwd *pwd; -uid_t userid; -int errs, remin, remout; -int pflag, iamremote, iamrecursive, targetshouldbedirectory; - -#define CMDNEEDS 64 -char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ - -int response(void); -void rsource(char *, struct stat *); -void sink(int, char *[]); -void source(int, char *[]); -void tolocal(int, char *[]); -void toremote(char *, int, char *[]); -void usage(void); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - int ch, fflag, tflag, status; - char *targ; - extern char *optarg; - extern int optind; - - __progname = get_progname(argv[0]); - - g11n_setlocale(LC_ALL, ""); - - args.list = NULL; - addargs(&args, "ssh"); /* overwritten with ssh_program */ - addargs(&args, "-x"); - addargs(&args, "-oForwardAgent no"); - addargs(&args, "-oClearAllForwardings yes"); - - fflag = tflag = 0; - while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) - switch (ch) { - /* User-visible flags. */ - case '4': - case '6': - case 'C': - addargs(&args, "-%c", ch); - break; - case 'o': - case 'c': - case 'i': - case 'F': - addargs(&args, "-%c%s", ch, optarg); - break; - case 'P': - addargs(&args, "-p%s", optarg); - break; - case 'B': - addargs(&args, "-oBatchmode yes"); - break; - case 'p': - pflag = 1; - break; - case 'r': - iamrecursive = 1; - break; - case 'S': - ssh_program = xstrdup(optarg); - break; - case 'v': - addargs(&args, "-v"); - verbose_mode = 1; - break; - case 'q': - showprogress = 0; - break; - - /* Server options. */ - case 'd': - targetshouldbedirectory = 1; - break; - case 'f': /* "from" */ - iamremote = 1; - fflag = 1; - break; - case 't': /* "to" */ - iamremote = 1; - tflag = 1; -#ifdef HAVE_CYGWIN - setmode(0, O_BINARY); -#endif - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - if ((pwd = getpwuid(userid = getuid())) == NULL) - fatal("unknown user %d", (int)userid); - - if (!isatty(STDERR_FILENO)) - showprogress = 0; - - remin = STDIN_FILENO; - remout = STDOUT_FILENO; - - if (fflag) { - /* Follow "protocol", send data. */ - (void) response(); - source(argc, argv); - exit(errs != 0); - } - if (tflag) { - /* Receive data. */ - sink(argc, argv); - exit(errs != 0); - } - if (argc < 2) - usage(); - if (argc > 2) - targetshouldbedirectory = 1; - - remin = remout = -1; - do_cmd_pid = (pid_t)-1; - - /* Command to be executed on remote system using "ssh". */ - (void) snprintf(cmd, sizeof (cmd), "scp%s%s%s%s", - verbose_mode ? " -v" : "", - iamrecursive ? " -r" : "", pflag ? " -p" : "", - targetshouldbedirectory ? " -d" : ""); - - (void) signal(SIGPIPE, lostconn); - - if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ - toremote(targ, argc, argv); - else { - if (targetshouldbedirectory) - verifydir(argv[argc - 1]); - tolocal(argc, argv); /* Dest is local host. */ - } - /* - * Finally check the exit status of the ssh process, if one was forked - * and no error has occurred yet - */ - if (do_cmd_pid != (pid_t)-1 && errs == 0) { - if (remin != -1) { - (void) close(remin); - } - if (remout != -1) { - (void) close(remout); - } - if (waitpid(do_cmd_pid, &status, 0) == -1) { - errs = 1; - } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - errs = 1; - } - } - - return (errs != 0); -} - -void -toremote(targ, argc, argv) - char *targ, *argv[]; - int argc; -{ - int i, len; - char *bp, *host, *src, *suser, *thost, *tuser, *arg; - arglist alist; - - memset(&alist, '\0', sizeof (alist)); - alist.list = NULL; - - *targ++ = 0; - if (*targ == 0) - targ = "."; - - arg = xstrdup(argv[argc - 1]); - if ((thost = strchr(arg, '@'))) { - /* user@host */ - *thost++ = 0; - tuser = arg; - if (*tuser == '\0') - tuser = NULL; - else if (!okname(tuser)) - exit(1); - } else { - thost = arg; - tuser = NULL; - } - - if (tuser != NULL && !okname(tuser)) { - xfree(arg); - return; - } - - for (i = 0; i < argc - 1; i++) { - src = colon(argv[i]); - if (src) { /* remote to remote */ - freeargs(&alist); - addargs(&alist, "%s", ssh_program); - if (verbose_mode) - addargs(&alist, "-v"); - addargs(&alist, "-x"); - addargs(&alist, "-oClearAllForwardings yes"); - addargs(&alist, "-n"); - - *src++ = 0; - if (*src == 0) - src = "."; - host = strchr(argv[i], '@'); - - if (host) { - *host++ = 0; - host = cleanhostname(host); - suser = argv[i]; - if (*suser == '\0') - suser = pwd->pw_name; - else if (!okname(suser)) - continue; - addargs(&alist, "-l"); - addargs(&alist, "%s", suser); - } else { - host = cleanhostname(argv[i]); - } - addargs(&alist, "%s", host); - addargs(&alist, "%s", cmd); - addargs(&alist, "%s", src); - addargs(&alist, "%s%s%s:%s", - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); - if (do_local_cmd(&alist) != 0) - errs = 1; - } else { /* local to remote */ - if (remin == -1) { - len = strlen(targ) + CMDNEEDS + 20; - bp = xmalloc(len); - (void) snprintf(bp, len, "%s -t %s", cmd, targ); - host = cleanhostname(thost); - if (do_cmd(host, tuser, bp, &remin, - &remout, argc) < 0) - exit(1); - if (response() < 0) - exit(1); - (void) xfree(bp); - } - source(1, argv + i); - } - } -} - -void -tolocal(argc, argv) - int argc; - char *argv[]; -{ - int i, len; - char *bp, *host, *src, *suser; - arglist alist; - - memset(&alist, '\0', sizeof (alist)); - alist.list = NULL; - - for (i = 0; i < argc - 1; i++) { - if (!(src = colon(argv[i]))) { /* Local to local. */ - freeargs(&alist); - addargs(&alist, "%s", _PATH_CP); - if (iamrecursive) - addargs(&alist, "-r"); - if (pflag) - addargs(&alist, "-p"); - addargs(&alist, "%s", argv[i]); - addargs(&alist, "%s", argv[argc-1]); - if (do_local_cmd(&alist)) - ++errs; - continue; - } - *src++ = 0; - if (*src == 0) - src = "."; - if ((host = strchr(argv[i], '@')) == NULL) { - host = argv[i]; - suser = NULL; - } else { - *host++ = 0; - suser = argv[i]; - if (*suser == '\0') - suser = pwd->pw_name; - else if (!okname(suser)) - continue; - } - host = cleanhostname(host); - len = strlen(src) + CMDNEEDS + 20; - bp = xmalloc(len); - (void) snprintf(bp, len, "%s -f %s", cmd, src); - if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { - (void) xfree(bp); - ++errs; - continue; - } - xfree(bp); - sink(1, argv + argc - 1); - (void) close(remin); - remin = remout = -1; - } -} - -void -source(argc, argv) - int argc; - char *argv[]; -{ - struct stat stb; - static BUF buffer; - BUF *bp; - off_t i, amt, result; - int fd, haderr, indx; - char *last, *name, buf[2048]; - int len; - - for (indx = 0; indx < argc; ++indx) { - name = argv[indx]; - statbytes = 0; - len = strlen(name); - while (len > 1 && name[len-1] == '/') - name[--len] = '\0'; - if (strchr(name, '\n') != NULL) { - run_err("%s: skipping, filename contains a newline", - name); - goto next; - } - if ((fd = open(name, O_RDONLY, 0)) < 0) - goto syserr; - if (fstat(fd, &stb) < 0) { -syserr: run_err("%s: %s", name, strerror(errno)); - goto next; - } - switch (stb.st_mode & S_IFMT) { - case S_IFREG: - break; - case S_IFDIR: - if (iamrecursive) { - rsource(name, &stb); - goto next; - } - /* FALLTHROUGH */ - default: - run_err("%s: not a regular file", name); - goto next; - } - if ((last = strrchr(name, '/')) == NULL) - last = name; - else - ++last; - curfile = last; - if (pflag) { - /* - * Make it compatible with possible future - * versions expecting microseconds. - */ - (void) snprintf(buf, sizeof (buf), "T%lu 0 %lu 0\n", - (ulong_t)stb.st_mtime, - (ulong_t)stb.st_atime); - (void) atomicio(write, remout, buf, strlen(buf)); - if (response() < 0) - goto next; - } -#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) -#ifdef HAVE_LONG_LONG_INT - snprintf(buf, sizeof (buf), "C%04o %lld %s\n", - (uint_t)(stb.st_mode & FILEMODEMASK), - (long long)stb.st_size, last); -#else - /* XXX: Handle integer overflow? */ - snprintf(buf, sizeof (buf), "C%04o %lu %s\n", - (uint_t)(stb.st_mode & FILEMODEMASK), - (ulong_t)stb.st_size, last); -#endif - if (verbose_mode) { - fprintf(stderr, gettext("Sending file modes: %s"), buf); - fflush(stderr); - } - (void) atomicio(write, remout, buf, strlen(buf)); - if (response() < 0) - goto next; - if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { -next: (void) close(fd); - continue; - } - if (showprogress) { - totalbytes = stb.st_size; - progressmeter(-1); - } - /* Keep writing after an error so that we stay sync'd up. */ - for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { - amt = bp->cnt; - if (i + amt > stb.st_size) - amt = stb.st_size - i; - if (!haderr) { - result = atomicio(read, fd, bp->buf, amt); - if (result != amt) - haderr = result >= 0 ? EIO : errno; - } - if (haderr) - (void) atomicio(write, remout, bp->buf, amt); - else { - result = atomicio(write, remout, bp->buf, amt); - if (result != amt) - haderr = result >= 0 ? EIO : errno; - statbytes += result; - } - } - if (showprogress) - progressmeter(1); - - if (close(fd) < 0 && !haderr) - haderr = errno; - if (!haderr) - (void) atomicio(write, remout, "", 1); - else - run_err("%s: %s", name, strerror(haderr)); - (void) response(); - } -} - -void -rsource(name, statp) - char *name; - struct stat *statp; -{ - DIR *dirp; - struct dirent *dp; - char *last, *vect[1], path[1100]; - - if (!(dirp = opendir(name))) { - run_err("%s: %s", name, strerror(errno)); - return; - } - last = strrchr(name, '/'); - if (last == 0) - last = name; - else - last++; - if (pflag) { - (void) snprintf(path, sizeof (path), "T%lu 0 %lu 0\n", - (ulong_t)statp->st_mtime, - (ulong_t)statp->st_atime); - (void) atomicio(write, remout, path, strlen(path)); - if (response() < 0) { - closedir(dirp); - return; - } - } - (void) snprintf(path, sizeof (path), "D%04o %d %.1024s\n", - (uint_t)(statp->st_mode & FILEMODEMASK), 0, last); - if (verbose_mode) - fprintf(stderr, gettext("Entering directory: %s"), path); - (void) atomicio(write, remout, path, strlen(path)); - if (response() < 0) { - closedir(dirp); - return; - } - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_ino == 0) - continue; - if ((strcmp(dp->d_name, ".") == 0) || - (strcmp(dp->d_name, "..") == 0)) - continue; - if (strlen(name) + 1 + strlen(dp->d_name) >= - sizeof (path) - 1) { - run_err("%s/%s: name too long", name, dp->d_name); - continue; - } - (void) snprintf(path, sizeof (path), "%s/%s", name, dp->d_name); - vect[0] = path; - source(1, vect); - } - (void) closedir(dirp); - (void) atomicio(write, remout, "E\n", 2); - (void) response(); -} - -void -sink(argc, argv) - int argc; - char *argv[]; -{ - static BUF buffer; - struct stat stb; - enum { - YES, NO, DISPLAYED - } wrerr; - BUF *bp; - off_t i, j; - int amt, count, exists, first, mask, mode, ofd, omode; - off_t size; - int setimes, targisdir, wrerrno = 0; - char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; - struct timeval tv[2]; - -#define atime tv[0] -#define mtime tv[1] -#define SCREWUP(str) { why = str; goto screwup; } - - setimes = targisdir = 0; - mask = umask(0); - if (!pflag) - (void) umask(mask); - if (argc != 1) { - run_err("ambiguous target"); - exit(1); - } - targ = *argv; - if (targetshouldbedirectory) - verifydir(targ); - - (void) atomicio(write, remout, "", 1); - if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) - targisdir = 1; - for (first = 1; ; first = 0) { - cp = buf; - if (atomicio(read, remin, cp, 1) <= 0) - return; - if (*cp++ == '\n') - SCREWUP("unexpected <newline>") - do { - if (atomicio(read, remin, &ch, sizeof (ch)) != - sizeof (ch)) - SCREWUP("lost connection") - *cp++ = ch; - } while (cp < &buf[sizeof (buf) - 1] && ch != '\n'); - *cp = 0; - - if (buf[0] == '\01' || buf[0] == '\02') { - if (iamremote == 0) - (void) atomicio(write, STDERR_FILENO, - buf + 1, strlen(buf + 1)); - if (buf[0] == '\02') - exit(1); - ++errs; - continue; - } - if (buf[0] == 'E') { - (void) atomicio(write, remout, "", 1); - return; - } - if (ch == '\n') - *--cp = 0; - - cp = buf; - if (*cp == 'T') { - setimes++; - cp++; - mtime.tv_sec = strtol(cp, &cp, 10); - if (!cp || *cp++ != ' ') - SCREWUP("mtime.sec not delimited") - mtime.tv_usec = strtol(cp, &cp, 10); - if (!cp || *cp++ != ' ') - SCREWUP("mtime.usec not delimited") - atime.tv_sec = strtol(cp, &cp, 10); - if (!cp || *cp++ != ' ') - SCREWUP("atime.sec not delimited") - atime.tv_usec = strtol(cp, &cp, 10); - if (!cp || *cp++ != '\0') - SCREWUP("atime.usec not delimited") - (void) atomicio(write, remout, "", 1); - continue; - } - if (*cp != 'C' && *cp != 'D') { - /* - * Check for the case "rcp remote:foo\* local:bar". - * In this case, the line "No match." can be returned - * by the shell before the rcp command on the remote is - * executed so the ^Aerror_message convention isn't - * followed. - */ - if (first) { - run_err("%s", cp); - exit(1); - } - SCREWUP("expected control record") - } - mode = 0; - for (++cp; cp < buf + 5; cp++) { - if (*cp < '0' || *cp > '7') - SCREWUP("bad mode") - mode = (mode << 3) | (*cp - '0'); - } - if (*cp++ != ' ') - SCREWUP("mode not delimited") - - for (size = 0; isdigit(*cp); ) - size = size * 10 + (*cp++ - '0'); - if (*cp++ != ' ') - SCREWUP("size not delimited") - if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) { - run_err("error: unexpected filename: %s", cp); - exit(1); - } - if (targisdir) { - static char *namebuf; - static int cursize; - size_t need; - - need = strlen(targ) + strlen(cp) + 250; - if (need > cursize) { - if (namebuf) - xfree(namebuf); - namebuf = xmalloc(need); - cursize = need; - } - (void) snprintf(namebuf, need, "%s%s%s", targ, - strcmp(targ, "/") ? "/" : "", cp); - np = namebuf; - } else - np = targ; - curfile = cp; - exists = stat(np, &stb) == 0; - if (buf[0] == 'D') { - int mod_flag = pflag; - if (!iamrecursive) - SCREWUP("received directory without -r"); - if (exists) { - if (!S_ISDIR(stb.st_mode)) { - errno = ENOTDIR; - goto bad; - } - if (pflag) - (void) chmod(np, mode); - } else { - /* - * Handle copying from a read-only - * directory - */ - mod_flag = 1; - if (mkdir(np, mode | S_IRWXU) < 0) - goto bad; - } - vect[0] = xstrdup(np); - sink(1, vect); - if (setimes) { - setimes = 0; - if (utimes(vect[0], tv) < 0) - run_err("%s: set times: %s", - vect[0], strerror(errno)); - } - if (mod_flag) - (void) chmod(vect[0], mode); - if (vect[0]) - xfree(vect[0]); - continue; - } - omode = mode; - mode |= S_IWRITE; - if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { -bad: run_err("%s: %s", np, strerror(errno)); - continue; - } - (void) atomicio(write, remout, "", 1); - if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { - (void) close(ofd); - continue; - } - wrerr = NO; - - if (showprogress) { - totalbytes = size; - progressmeter(-1); - } - statbytes = 0; - for (i = 0; i < size; i += bp->cnt) { - amt = bp->cnt; - cp = bp->buf; - if (i + amt > size) - amt = size - i; - count = amt; - do { - j = read(remin, cp, amt); - if (j == -1 && (errno == EINTR || - errno == EAGAIN)) { - continue; - } else if (j <= 0) { - run_err("%s", j ? strerror(errno) : - "dropped connection"); - exit(1); - } - amt -= j; - cp += j; - statbytes += j; - } while (amt > 0); - /* Keep reading so we stay sync'd up. */ - if (wrerr == NO) { - j = atomicio(write, ofd, bp->buf, - count); - if (j != count) { - wrerr = YES; - wrerrno = j >= 0 ? EIO : errno; - } - } - } - if (showprogress) - progressmeter(1); - if (ftruncate(ofd, size)) { - run_err("%s: truncate: %s", np, strerror(errno)); - wrerr = DISPLAYED; - } - if (pflag) { - if (exists || omode != mode) -#ifdef HAVE_FCHMOD - if (fchmod(ofd, omode)) { -#else /* HAVE_FCHMOD */ - if (chmod(np, omode)) { -#endif /* HAVE_FCHMOD */ - run_err("%s: set mode: %s", - np, strerror(errno)); - wrerr = DISPLAYED; - } - } else { - if (!exists && omode != mode) -#ifdef HAVE_FCHMOD - if (fchmod(ofd, omode & ~mask)) { -#else /* HAVE_FCHMOD */ - if (chmod(np, omode & ~mask)) { -#endif /* HAVE_FCHMOD */ - run_err("%s: set mode: %s", - np, strerror(errno)); - wrerr = DISPLAYED; - } - } - if (close(ofd) == -1) { - wrerr = YES; - wrerrno = errno; - } - (void) response(); - if (setimes && wrerr == NO) { - setimes = 0; - if (utimes(np, tv) < 0) { - run_err("%s: set times: %s", - np, strerror(errno)); - wrerr = DISPLAYED; - } - } - switch (wrerr) { - case YES: - run_err("%s: %s", np, strerror(wrerrno)); - break; - case NO: - (void) atomicio(write, remout, "", 1); - break; - case DISPLAYED: - break; - } - } -screwup: - run_err("protocol error: %s", why); - exit(1); -} - -int -response(void) -{ - char ch, *cp, resp, rbuf[2048]; - - if (atomicio(read, remin, &resp, sizeof (resp)) != sizeof (resp)) - lostconn(0); - - cp = rbuf; - switch (resp) { - case 0: /* ok */ - return (0); - default: - *cp++ = resp; - /* FALLTHROUGH */ - case 1: /* error, followed by error msg */ - case 2: /* fatal error, "" */ - do { - if (atomicio(read, remin, &ch, sizeof (ch)) != - sizeof (ch)) - lostconn(0); - *cp++ = ch; - } while (cp < &rbuf[sizeof (rbuf) - 1] && ch != '\n'); - - if (!iamremote) - (void) atomicio(write, STDERR_FILENO, rbuf, cp - rbuf); - ++errs; - if (resp == 1) - return (-1); - exit(1); - } - /* NOTREACHED */ -} - -void -usage(void) -{ - (void) fprintf(stderr, - gettext( - "Usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" - " [-c cipher] [-i identity] [-o option]\n" - " [[user@]host1:]file1 [...] " - "[[user@]host2:]file2\n")); - exit(1); -} - -/* PRINTFLIKE1 */ -void -run_err(const char *fmt, ...) -{ - static FILE *fp; - va_list ap; - - ++errs; - - if (!iamremote) { - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); - } - - if (fp == NULL && !(fp = fdopen(remout, "w"))) - return; - - (void) fprintf(fp, "%c", 0x01); - (void) fprintf(fp, "scp: "); - va_start(ap, fmt); - (void) vfprintf(fp, fmt, ap); - va_end(ap); - (void) fprintf(fp, "\n"); - (void) fflush(fp); - -} - -void -verifydir(cp) - char *cp; -{ - struct stat stb; - - if (!stat(cp, &stb)) { - if (S_ISDIR(stb.st_mode)) - return; - errno = ENOTDIR; - } - run_err("%s: %s", cp, strerror(errno)); - exit(1); -} - -int -okname(cp0) - char *cp0; -{ - int c; - char *cp; - - cp = cp0; - do { - c = (int)*cp; - if (c & 0200) - goto bad; - if (!isalpha(c) && !isdigit(c)) { - switch (c) { - case '\'': - case '"': - case '`': - case ' ': - case '#': - goto bad; - default: - break; - } - } - } while (*++cp); - return (1); - -bad: fprintf(stderr, gettext("%s: invalid user name\n"), cp0); - return (0); -} - -BUF * -allocbuf(bp, fd, blksize) - BUF *bp; - int fd, blksize; -{ - size_t size; -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - struct stat stb; - - if (fstat(fd, &stb) < 0) { - run_err("fstat: %s", strerror(errno)); - return (0); - } - if (stb.st_blksize == 0) - size = blksize; - else - size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % - stb.st_blksize; -#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ - size = blksize; -#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ - if (bp->cnt >= size) - return (bp); - if (bp->buf == NULL) - bp->buf = xmalloc(size); - else - bp->buf = xrealloc(bp->buf, size); - memset(bp->buf, 0, size); - bp->cnt = size; - return (bp); -} - -void -lostconn(signo) - int signo; -{ - if (!iamremote) - write(STDERR_FILENO, "lost connection\n", 16); - if (signo) - _exit(1); - else - exit(1); -} - -static void -updateprogressmeter(int ignore) -{ - int save_errno = errno; - - progressmeter(0); - signal(SIGALRM, updateprogressmeter); - alarm(PROGRESSTIME); - errno = save_errno; -} - -static int -foregroundproc(void) -{ - static pid_t pgrp = -1; - int ctty_pgrp; - - if (pgrp == -1) - pgrp = getpgrp(); - -#ifdef HAVE_TCGETPGRP - return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 && - ctty_pgrp == pgrp); -#else - return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 && - ctty_pgrp == pgrp)); -#endif -} - -void -progressmeter(int flag) -{ - static const char prefixes[] = " KMGTP"; - static struct timeval lastupdate; - static off_t lastsize; - struct timeval now, td, wait; - off_t cursize, abbrevsize; - double elapsed; - int ratio, barlength, i, remaining; - char buf[512]; - - if (flag == -1) { - (void) gettimeofday(&start, (struct timezone *)0); - lastupdate = start; - lastsize = 0; - } - if (foregroundproc() == 0) - return; - - (void) gettimeofday(&now, (struct timezone *)0); - cursize = statbytes; - if (totalbytes != 0) { - ratio = (int)(100.0 * cursize / totalbytes); - ratio = MAX(ratio, 0); - ratio = MIN(ratio, 100); - } else - ratio = 100; - - snprintf(buf, sizeof (buf), "\r%-20.20s %3d%% ", curfile, ratio); - - barlength = getttywidth() - 51; - if (barlength > 0) { - i = barlength * ratio / 100; - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), - "|%.*s%*s|", i, - "*******************************************************" - "*******************************************************" - "*******************************************************" - "*******************************************************" - "*******************************************************" - "*******************************************************" - "*******************************************************", - barlength - i, ""); - } - i = 0; - abbrevsize = cursize; - while (abbrevsize >= 100000 && i < strlen(prefixes) - 1) { - i++; - abbrevsize >>= 10; - } - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), " %5lu %c%c ", - (unsigned long) abbrevsize, prefixes[i], - prefixes[i] == ' ' ? ' ' : 'B'); - - timersub(&now, &lastupdate, &wait); - if (cursize > lastsize) { - lastupdate = now; - lastsize = cursize; - if (wait.tv_sec >= STALLTIME) { - start.tv_sec += wait.tv_sec; - start.tv_usec += wait.tv_usec; - } - wait.tv_sec = 0; - } - timersub(&now, &start, &td); - elapsed = td.tv_sec + (td.tv_usec / 1000000.0); - - if (flag != 1 && - (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) { - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), - " --:-- ETA"); - } else if (wait.tv_sec >= STALLTIME) { - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), - " - stalled -"); - } else { - if (flag != 1) - remaining = (int)(totalbytes / (statbytes / elapsed) - - elapsed); - else - remaining = (int)elapsed; - - i = remaining / 3600; - if (i) - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), - "%2d:", i); - else - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), - " "); - i = remaining % 3600; - snprintf(buf + strlen(buf), sizeof (buf) - strlen(buf), - "%02d:%02d%s", i / 60, i % 60, - (flag != 1) ? " ETA" : " "); - } - atomicio(write, fileno(stdout), buf, strlen(buf)); - - if (flag == -1) { - mysignal(SIGALRM, updateprogressmeter); - alarm(PROGRESSTIME); - } else if (flag == 1) { - alarm(0); - atomicio(write, fileno(stdout), "\n", 1); - statbytes = 0; - } -} - -int -getttywidth(void) -{ - struct winsize winsize; - - if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) - return (winsize.ws_col ? winsize.ws_col : 80); - else - return (80); -} diff --git a/usr/src/cmd/ssh/sftp-server/Makefile b/usr/src/cmd/ssh/sftp-server/Makefile deleted file mode 100644 index c2bdf26c1e..0000000000 --- a/usr/src/cmd/ssh/sftp-server/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/sftp-server/Makefile - -PROG = sftp-server - -OBJS = sftp-server.o sftp-server-main.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto - -POFILE_DIR = .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -install: all $(ROOTLIBSSHPROG) $(ROOTLIBSSH) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/sftp-server/sftp-server-main.c b/usr/src/cmd/ssh/sftp-server/sftp-server-main.c deleted file mode 100644 index 7b604b7cdc..0000000000 --- a/usr/src/cmd/ssh/sftp-server/sftp-server-main.c +++ /dev/null @@ -1,51 +0,0 @@ -/* $OpenBSD: sftp-server-main.c,v 1.4 2009/02/21 19:32:04 tobias Exp $ */ -/* - * Copyright (c) 2008 Markus Friedl. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include <sys/types.h> -#include <pwd.h> -#include <stdarg.h> -#include <stdio.h> -#include <unistd.h> - -#include "log.h" -#include "sftp.h" -#include "misc.h" - -/* defined in sftp-server.c */ -extern struct passwd *pw; -extern char *client_addr; - -void cleanup_exit(int i); - -int -main(int argc, char **argv) -{ - struct passwd *user_pw; - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); - - if ((user_pw = getpwuid(getuid())) == NULL) { - fprintf(stderr, "No user found for uid %lu\n", - (ulong_t)getuid()); - return (1); - } - - return (sftp_server_main(argc, argv, user_pw)); -} diff --git a/usr/src/cmd/ssh/sftp-server/sftp-server.c b/usr/src/cmd/ssh/sftp-server/sftp-server.c deleted file mode 100644 index 030ed79ac2..0000000000 --- a/usr/src/cmd/ssh/sftp-server/sftp-server.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* $OpenBSD: sftp-server.c,v 1.71 2007/01/03 07:22:36 stevesk Exp $ */ - -#include "includes.h" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <pwd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <pwd.h> -#include <time.h> -#include <unistd.h> -#include <stdarg.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "log.h" -#include "misc.h" -#include "uidswap.h" - -#include "sftp.h" -#include "sftp-common.h" - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -/* helper */ -#define get_int64() buffer_get_int64(&iqueue); -#define get_int() buffer_get_int(&iqueue); -#define get_string(lenp) buffer_get_string(&iqueue, lenp); - -void cleanup_exit(int i); - -/* Our verbosity */ -LogLevel log_level = SYSLOG_LEVEL_ERROR; - -/* Our client */ -struct passwd *pw = NULL; -char *client_addr = NULL; - -/* input and output queue */ -Buffer iqueue; -Buffer oqueue; - -/* Version of client */ -int version; - -/* portable attributes, etc. */ - -typedef struct Stat Stat; - -struct Stat { - char *name; - char *long_name; - Attrib attrib; -}; - -static int -errno_to_portable(int unixerrno) -{ - int ret = 0; - - switch (unixerrno) { - case 0: - ret = SSH2_FX_OK; - break; - case ENOENT: - case ENOTDIR: - case EBADF: - case ELOOP: - ret = SSH2_FX_NO_SUCH_FILE; - break; - case EPERM: - case EACCES: - case EFAULT: - ret = SSH2_FX_PERMISSION_DENIED; - break; - case ENAMETOOLONG: - case EINVAL: - ret = SSH2_FX_BAD_MESSAGE; - break; - default: - ret = SSH2_FX_FAILURE; - break; - } - return ret; -} - -static int -flags_from_portable(int pflags) -{ - int flags = 0; - - if ((pflags & SSH2_FXF_READ) && - (pflags & SSH2_FXF_WRITE)) { - flags = O_RDWR; - } else if (pflags & SSH2_FXF_READ) { - flags = O_RDONLY; - } else if (pflags & SSH2_FXF_WRITE) { - flags = O_WRONLY; - } - if (pflags & SSH2_FXF_CREAT) - flags |= O_CREAT; - if (pflags & SSH2_FXF_TRUNC) - flags |= O_TRUNC; - if (pflags & SSH2_FXF_EXCL) - flags |= O_EXCL; - return flags; -} - -static const char * -string_from_portable(int pflags) -{ - static char ret[128]; - - *ret = '\0'; - -#define PAPPEND(str) { \ - if (*ret != '\0') \ - strlcat(ret, ",", sizeof(ret)); \ - strlcat(ret, str, sizeof(ret)); \ - } - - if (pflags & SSH2_FXF_READ) - PAPPEND("READ") - if (pflags & SSH2_FXF_WRITE) - PAPPEND("WRITE") - if (pflags & SSH2_FXF_CREAT) - PAPPEND("CREATE") - if (pflags & SSH2_FXF_TRUNC) - PAPPEND("TRUNCATE") - if (pflags & SSH2_FXF_EXCL) - PAPPEND("EXCL") - - return ret; -} - -static Attrib * -get_attrib(void) -{ - return decode_attrib(&iqueue); -} - -/* handle handles */ - -typedef struct Handle Handle; -struct Handle { - int use; - DIR *dirp; - int fd; - char *name; - u_int64_t bytes_read, bytes_write; -}; - -enum { - HANDLE_UNUSED, - HANDLE_DIR, - HANDLE_FILE -}; - -Handle handles[100]; - -static void -handle_init(void) -{ - u_int i; - - for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) - handles[i].use = HANDLE_UNUSED; -} - -static int -handle_new(int use, const char *name, int fd, DIR *dirp) -{ - u_int i; - - for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) { - if (handles[i].use == HANDLE_UNUSED) { - handles[i].use = use; - handles[i].dirp = dirp; - handles[i].fd = fd; - handles[i].name = xstrdup(name); - handles[i].bytes_read = handles[i].bytes_write = 0; - return i; - } - } - return -1; -} - -static int -handle_is_ok(int i, int type) -{ - return i >= 0 && (u_int)i < sizeof(handles)/sizeof(Handle) && - handles[i].use == type; -} - -static int -handle_to_string(int handle, char **stringp, int *hlenp) -{ - if (stringp == NULL || hlenp == NULL) - return -1; - *stringp = xmalloc(sizeof(int32_t)); - put_u32(*stringp, handle); - *hlenp = sizeof(int32_t); - return 0; -} - -static int -handle_from_string(const char *handle, u_int hlen) -{ - int val; - - if (hlen != sizeof(int32_t)) - return -1; - val = get_u32(handle); - if (handle_is_ok(val, HANDLE_FILE) || - handle_is_ok(val, HANDLE_DIR)) - return val; - return -1; -} - -static char * -handle_to_name(int handle) -{ - if (handle_is_ok(handle, HANDLE_DIR)|| - handle_is_ok(handle, HANDLE_FILE)) - return handles[handle].name; - return NULL; -} - -static DIR * -handle_to_dir(int handle) -{ - if (handle_is_ok(handle, HANDLE_DIR)) - return handles[handle].dirp; - return NULL; -} - -static int -handle_to_fd(int handle) -{ - if (handle_is_ok(handle, HANDLE_FILE)) - return handles[handle].fd; - return -1; -} - -static void -handle_update_read(int handle, ssize_t bytes) -{ - if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) - handles[handle].bytes_read += bytes; -} - -static void -handle_update_write(int handle, ssize_t bytes) -{ - if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) - handles[handle].bytes_write += bytes; -} - -static u_int64_t -handle_bytes_read(int handle) -{ - if (handle_is_ok(handle, HANDLE_FILE)) - return (handles[handle].bytes_read); - return 0; -} - -static u_int64_t -handle_bytes_write(int handle) -{ - if (handle_is_ok(handle, HANDLE_FILE)) - return (handles[handle].bytes_write); - return 0; -} - -static int -handle_close(int handle) -{ - int ret = -1; - - if (handle_is_ok(handle, HANDLE_FILE)) { - ret = close(handles[handle].fd); - handles[handle].use = HANDLE_UNUSED; - xfree(handles[handle].name); - } else if (handle_is_ok(handle, HANDLE_DIR)) { - ret = closedir(handles[handle].dirp); - handles[handle].use = HANDLE_UNUSED; - xfree(handles[handle].name); - } else { - errno = ENOENT; - } - return ret; -} - -static void -handle_log_close(int handle, char *emsg) -{ - if (handle_is_ok(handle, HANDLE_FILE)) { - log("%s%sclose \"%s\" bytes read %llu written %llu", - emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", - handle_to_name(handle), - (unsigned long long)handle_bytes_read(handle), - (unsigned long long)handle_bytes_write(handle)); - } else { - log("%s%sclosedir \"%s\"", - emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", - handle_to_name(handle)); - } -} - -static void -handle_log_exit(void) -{ - u_int i; - - for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) - if (handles[i].use != HANDLE_UNUSED) - handle_log_close(i, "forced"); -} - -static int -get_handle(void) -{ - char *handle; - int val = -1; - u_int hlen; - - handle = get_string(&hlen); - if (hlen < 256) - val = handle_from_string(handle, hlen); - xfree(handle); - return val; -} - -/* send replies */ - -static void -send_msg(Buffer *m) -{ - int mlen = buffer_len(m); - - buffer_put_int(&oqueue, mlen); - buffer_append(&oqueue, buffer_ptr(m), mlen); - buffer_consume(m, mlen); -} - -static const char * -status_to_message(u_int32_t status) -{ - const char *status_messages[] = { - "Success", /* SSH_FX_OK */ - "End of file", /* SSH_FX_EOF */ - "No such file", /* SSH_FX_NO_SUCH_FILE */ - "Permission denied", /* SSH_FX_PERMISSION_DENIED */ - "Failure", /* SSH_FX_FAILURE */ - "Bad message", /* SSH_FX_BAD_MESSAGE */ - "No connection", /* SSH_FX_NO_CONNECTION */ - "Connection lost", /* SSH_FX_CONNECTION_LOST */ - "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ - "Unknown error" /* Others */ - }; - return (status_messages[MIN(status,SSH2_FX_MAX)]); -} - -static void -send_status(u_int32_t id, u_int32_t status) -{ - Buffer msg; - - debug3("request %u: sent status %u", id, status); - if (log_level > SYSLOG_LEVEL_VERBOSE || - (status != SSH2_FX_OK && status != SSH2_FX_EOF)) - log("sent status %s", status_to_message(status)); - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_STATUS); - buffer_put_int(&msg, id); - buffer_put_int(&msg, status); - if (version >= 3) { - buffer_put_cstring(&msg, status_to_message(status)); - buffer_put_cstring(&msg, ""); - } - send_msg(&msg); - buffer_free(&msg); -} -static void -send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) -{ - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, type); - buffer_put_int(&msg, id); - buffer_put_string(&msg, data, dlen); - send_msg(&msg); - buffer_free(&msg); -} - -static void -send_data(u_int32_t id, const char *data, int dlen) -{ - debug("request %u: sent data len %d", id, dlen); - send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); -} - -static void -send_handle(u_int32_t id, int handle) -{ - char *string; - int hlen; - - handle_to_string(handle, &string, &hlen); - debug("request %u: sent handle handle %d", id, handle); - send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); - xfree(string); -} - -static void -send_names(u_int32_t id, int count, const Stat *stats) -{ - Buffer msg; - int i; - - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_NAME); - buffer_put_int(&msg, id); - buffer_put_int(&msg, count); - debug("request %u: sent names count %d", id, count); - for (i = 0; i < count; i++) { - buffer_put_cstring(&msg, stats[i].name); - buffer_put_cstring(&msg, stats[i].long_name); - encode_attrib(&msg, &stats[i].attrib); - } - send_msg(&msg); - buffer_free(&msg); -} - -static void -send_attrib(u_int32_t id, const Attrib *a) -{ - Buffer msg; - - debug("request %u: sent attrib have 0x%x", id, a->flags); - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_ATTRS); - buffer_put_int(&msg, id); - encode_attrib(&msg, a); - send_msg(&msg); - buffer_free(&msg); -} - -/* parse incoming */ - -static void -process_init(void) -{ - Buffer msg; - - version = get_int(); - verbose("received client version %d", version); - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_VERSION); - buffer_put_int(&msg, SSH2_FILEXFER_VERSION); - send_msg(&msg); - buffer_free(&msg); -} - -static void -process_open(void) -{ - u_int32_t id, pflags; - Attrib *a; - char *name; - int handle, fd, flags, mode, status = SSH2_FX_FAILURE; - - id = get_int(); - name = get_string(NULL); - pflags = get_int(); /* portable flags */ - debug3("request %u: open flags %d", id, pflags); - a = get_attrib(); - flags = flags_from_portable(pflags); - mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; - log("open \"%s\" flags %s mode 0%o", - name, string_from_portable(pflags), mode); - fd = open(name, flags, mode); - if (fd < 0) { - status = errno_to_portable(errno); - } else { - handle = handle_new(HANDLE_FILE, name, fd, NULL); - if (handle < 0) { - close(fd); - } else { - send_handle(id, handle); - status = SSH2_FX_OK; - } - } - if (status != SSH2_FX_OK) - send_status(id, status); - xfree(name); -} - -static void -process_close(void) -{ - u_int32_t id; - int handle, ret, status = SSH2_FX_FAILURE; - - id = get_int(); - handle = get_handle(); - debug3("request %u: close handle %u", id, handle); - handle_log_close(handle, NULL); - ret = handle_close(handle); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - send_status(id, status); -} - -static void -process_read(void) -{ - char buf[64*1024]; - u_int32_t id, len; - int handle, fd, ret, status = SSH2_FX_FAILURE; - u_int64_t off; - - id = get_int(); - handle = get_handle(); - off = get_int64(); - len = get_int(); - - debug("request %u: read \"%s\" (handle %d) off %llu len %d", - id, handle_to_name(handle), handle, (unsigned long long)off, len); - if (len > sizeof buf) { - len = sizeof buf; - debug2("read change len %d", len); - } - fd = handle_to_fd(handle); - if (fd >= 0) { - if (lseek(fd, off, SEEK_SET) < 0) { - error("process_read: seek failed"); - status = errno_to_portable(errno); - } else { - ret = read(fd, buf, len); - if (ret < 0) { - status = errno_to_portable(errno); - } else if (ret == 0) { - status = SSH2_FX_EOF; - } else { - send_data(id, buf, ret); - status = SSH2_FX_OK; - handle_update_read(handle, ret); - } - } - } - if (status != SSH2_FX_OK) - send_status(id, status); -} - -static void -process_write(void) -{ - u_int32_t id; - u_int64_t off; - u_int len; - int handle, fd, ret, status = SSH2_FX_FAILURE; - char *data; - - id = get_int(); - handle = get_handle(); - off = get_int64(); - data = get_string(&len); - - debug("request %u: write \"%s\" (handle %d) off %llu len %d", - id, handle_to_name(handle), handle, (unsigned long long)off, len); - fd = handle_to_fd(handle); - if (fd >= 0) { - if (lseek(fd, off, SEEK_SET) < 0) { - 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"); - status = errno_to_portable(errno); - } else if ((size_t)ret == len) { - status = SSH2_FX_OK; - handle_update_write(handle, ret); - } else { - debug2("nothing at all written"); - } - } - } - send_status(id, status); - xfree(data); -} - -static void -process_do_stat(int do_lstat) -{ - Attrib a; - struct stat st; - u_int32_t id; - char *name; - int ret, status = SSH2_FX_FAILURE; - - id = get_int(); - name = get_string(NULL); - debug3("request %u: %sstat", id, do_lstat ? "l" : ""); - verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); - ret = do_lstat ? lstat(name, &st) : stat(name, &st); - if (ret < 0) { - status = errno_to_portable(errno); - } else { - stat_to_attrib(&st, &a); - send_attrib(id, &a); - status = SSH2_FX_OK; - } - if (status != SSH2_FX_OK) - send_status(id, status); - xfree(name); -} - -static void -process_stat(void) -{ - process_do_stat(0); -} - -static void -process_lstat(void) -{ - process_do_stat(1); -} - -static void -process_fstat(void) -{ - Attrib a; - struct stat st; - u_int32_t id; - int fd, ret, handle, status = SSH2_FX_FAILURE; - - id = get_int(); - handle = get_handle(); - debug("request %u: fstat \"%s\" (handle %u)", - id, handle_to_name(handle), handle); - fd = handle_to_fd(handle); - if (fd >= 0) { - ret = fstat(fd, &st); - if (ret < 0) { - status = errno_to_portable(errno); - } else { - stat_to_attrib(&st, &a); - send_attrib(id, &a); - status = SSH2_FX_OK; - } - } - if (status != SSH2_FX_OK) - send_status(id, status); -} - -static struct timeval * -attrib_to_tv(const Attrib *a) -{ - static struct timeval tv[2]; - - tv[0].tv_sec = a->atime; - tv[0].tv_usec = 0; - tv[1].tv_sec = a->mtime; - tv[1].tv_usec = 0; - return tv; -} - -static void -process_setstat(void) -{ - Attrib *a; - u_int32_t id; - char *name; - int status = SSH2_FX_OK, ret; - - id = get_int(); - name = get_string(NULL); - a = get_attrib(); - debug("request %u: setstat name \"%s\"", id, name); - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { - log("set \"%s\" size %llu", - name, (unsigned long long)a->size); - ret = truncate(name, a->size); - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - log("set \"%s\" mode %04o", name, a->perm); - ret = chmod(name, a->perm & 07777); - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - char buf[64]; - time_t t = a->mtime; - - strftime(buf, sizeof(buf), "%Y" "%m%d-%H:%M:%S", - localtime(&t)); - log("set \"%s\" modtime %s", name, buf); - ret = utimes(name, attrib_to_tv(a)); - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - log("set \"%s\" owner %lu group %lu", name, - (u_long)a->uid, (u_long)a->gid); - ret = chown(name, a->uid, a->gid); - if (ret == -1) - status = errno_to_portable(errno); - } - send_status(id, status); - xfree(name); -} - -static void -process_fsetstat(void) -{ - Attrib *a; - u_int32_t id; - int handle, fd, ret; - int status = SSH2_FX_OK; - - id = get_int(); - handle = get_handle(); - a = get_attrib(); - debug("request %u: fsetstat handle %d", id, handle); - fd = handle_to_fd(handle); - if (fd < 0) { - status = SSH2_FX_FAILURE; - } else { - char *name = handle_to_name(handle); - - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { - log("set \"%s\" size %llu", - name, (unsigned long long)a->size); - ret = ftruncate(fd, a->size); - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - log("set \"%s\" mode %04o", name, a->perm); -#ifdef HAVE_FCHMOD - ret = fchmod(fd, a->perm & 07777); -#else - ret = chmod(name, a->perm & 07777); -#endif - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - char buf[64]; - time_t t = a->mtime; - - strftime(buf, sizeof(buf), "%Y" "%m%d-%H:%M:%S", - localtime(&t)); - log("set \"%s\" modtime %s", name, buf); -#ifdef HAVE_FUTIMES - ret = futimes(fd, attrib_to_tv(a)); -#else - ret = utimes(name, attrib_to_tv(a)); -#endif - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - log("set \"%s\" owner %lu group %lu", name, - (u_long)a->uid, (u_long)a->gid); -#ifdef HAVE_FCHOWN - ret = fchown(fd, a->uid, a->gid); -#else - ret = chown(name, a->uid, a->gid); -#endif - if (ret == -1) - status = errno_to_portable(errno); - } - } - send_status(id, status); -} - -static void -process_opendir(void) -{ - DIR *dirp = NULL; - char *path; - int handle, status = SSH2_FX_FAILURE; - u_int32_t id; - - id = get_int(); - path = get_string(NULL); - debug3("request %u: opendir", id); - log("opendir \"%s\"", path); - dirp = opendir(path); - if (dirp == NULL) { - status = errno_to_portable(errno); - } else { - handle = handle_new(HANDLE_DIR, path, 0, dirp); - if (handle < 0) { - closedir(dirp); - } else { - send_handle(id, handle); - status = SSH2_FX_OK; - } - - } - if (status != SSH2_FX_OK) - send_status(id, status); - xfree(path); -} - -static void -process_readdir(void) -{ - DIR *dirp; - struct dirent *dp; - char *path; - int handle; - u_int32_t id; - - id = get_int(); - handle = get_handle(); - debug("request %u: readdir \"%s\" (handle %d)", id, - handle_to_name(handle), handle); - dirp = handle_to_dir(handle); - path = handle_to_name(handle); - if (dirp == NULL || path == NULL) { - send_status(id, SSH2_FX_FAILURE); - } else { - struct stat st; - char pathname[MAXPATHLEN]; - Stat *stats; - int nstats = 10, count = 0, i; - - stats = xcalloc(nstats, sizeof(Stat)); - while ((dp = readdir(dirp)) != NULL) { - if (count >= nstats) { - nstats *= 2; - stats = xrealloc(stats, nstats * sizeof(Stat)); - } -/* XXX OVERFLOW ? */ - snprintf(pathname, sizeof pathname, "%s%s%s", path, - strcmp(path, "/") ? "/" : "", dp->d_name); - if (lstat(pathname, &st) < 0) - continue; - stat_to_attrib(&st, &(stats[count].attrib)); - stats[count].name = xstrdup(dp->d_name); - stats[count].long_name = ls_file(dp->d_name, &st, 0); - count++; - /* send up to 100 entries in one message */ - /* XXX check packet size instead */ - if (count == 100) - break; - } - if (count > 0) { - send_names(id, count, stats); - for (i = 0; i < count; i++) { - xfree(stats[i].name); - xfree(stats[i].long_name); - } - } else { - send_status(id, SSH2_FX_EOF); - } - xfree(stats); - } -} - -static void -process_remove(void) -{ - char *name; - u_int32_t id; - int status = SSH2_FX_FAILURE; - int ret; - - id = get_int(); - name = get_string(NULL); - debug3("request %u: remove", id); - log("remove name \"%s\"", name); - ret = unlink(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - send_status(id, status); - xfree(name); -} - -static void -process_mkdir(void) -{ - Attrib *a; - u_int32_t id; - char *name; - int ret, mode, status = SSH2_FX_FAILURE; - - id = get_int(); - name = get_string(NULL); - a = get_attrib(); - mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? - a->perm & 0777 : 0777; - debug3("request %u: mkdir", id); - log("mkdir name \"%s\" mode 0%o", name, mode); - ret = mkdir(name, mode); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - send_status(id, status); - xfree(name); -} - -static void -process_rmdir(void) -{ - u_int32_t id; - char *name; - int ret, status; - - id = get_int(); - name = get_string(NULL); - debug3("request %u: rmdir", id); - log("rmdir name \"%s\"", name); - ret = rmdir(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - send_status(id, status); - xfree(name); -} - -static void -process_realpath(void) -{ - char resolvedname[MAXPATHLEN]; - u_int32_t id; - char *path; - - id = get_int(); - path = get_string(NULL); - if (path[0] == '\0') { - xfree(path); - path = xstrdup("."); - } - debug3("request %u: realpath", id); - verbose("realpath \"%s\"", path); - if (realpath(path, resolvedname) == NULL) { - send_status(id, errno_to_portable(errno)); - } else { - Stat s; - attrib_clear(&s.attrib); - s.name = s.long_name = resolvedname; - send_names(id, 1, &s); - } - xfree(path); -} - -static void -process_rename(void) -{ - u_int32_t id; - char *oldpath, *newpath; - int status; - struct stat sb; - - id = get_int(); - oldpath = get_string(NULL); - newpath = get_string(NULL); - debug3("request %u: rename", id); - log("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 -#ifdef LINK_OPNOTSUPP_ERRNO - || errno == LINK_OPNOTSUPP_ERRNO -#endif - ) { - 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 = - errno_to_portable(errno); - else - status = SSH2_FX_OK; - } - } else { - status = errno_to_portable(errno); - } - } else if (unlink(oldpath) == -1) { - status = errno_to_portable(errno); - /* clean spare link */ - unlink(newpath); - } else - status = SSH2_FX_OK; - } else if (stat(newpath, &sb) == -1) { - if (rename(oldpath, newpath) == -1) - status = errno_to_portable(errno); - else - status = SSH2_FX_OK; - } - send_status(id, status); - xfree(oldpath); - xfree(newpath); -} - -static void -process_readlink(void) -{ - u_int32_t id; - int len; - char buf[MAXPATHLEN]; - char *path; - - id = get_int(); - path = get_string(NULL); - 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 { - Stat s; - - buf[len] = '\0'; - attrib_clear(&s.attrib); - s.name = s.long_name = buf; - send_names(id, 1, &s); - } - xfree(path); -} - -static void -process_symlink(void) -{ - u_int32_t id; - char *oldpath, *newpath; - int ret, status; - - id = get_int(); - oldpath = get_string(NULL); - newpath = get_string(NULL); - debug3("request %u: symlink", id); - log("symlink old \"%s\" new \"%s\"", oldpath, newpath); - /* this will fail if 'newpath' exists */ - ret = symlink(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - send_status(id, status); - xfree(oldpath); - xfree(newpath); -} - -static void -process_extended(void) -{ - u_int32_t id; - char *request; - - id = get_int(); - request = get_string(NULL); - send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ - xfree(request); -} - -/* stolen from ssh-agent */ - -static void -process(void) -{ - u_int msg_len; - u_int buf_len; - u_int consumed; - u_int type; - u_char *cp; - - buf_len = buffer_len(&iqueue); - if (buf_len < 5) - return; /* Incomplete message. */ - cp = buffer_ptr(&iqueue); - msg_len = get_u32(cp); - if (msg_len > SFTP_MAX_MSG_LENGTH) { - error("bad message from %s local user %s", - client_addr, pw->pw_name); - cleanup_exit(11); - } - if (buf_len < msg_len + 4) - return; - buffer_consume(&iqueue, 4); - buf_len -= 4; - type = buffer_get_char(&iqueue); - switch (type) { - case SSH2_FXP_INIT: - process_init(); - break; - case SSH2_FXP_OPEN: - process_open(); - break; - case SSH2_FXP_CLOSE: - process_close(); - break; - case SSH2_FXP_READ: - process_read(); - break; - case SSH2_FXP_WRITE: - process_write(); - break; - case SSH2_FXP_LSTAT: - process_lstat(); - break; - case SSH2_FXP_FSTAT: - process_fstat(); - break; - case SSH2_FXP_SETSTAT: - process_setstat(); - break; - case SSH2_FXP_FSETSTAT: - process_fsetstat(); - break; - case SSH2_FXP_OPENDIR: - process_opendir(); - break; - case SSH2_FXP_READDIR: - process_readdir(); - break; - case SSH2_FXP_REMOVE: - process_remove(); - break; - case SSH2_FXP_MKDIR: - process_mkdir(); - break; - case SSH2_FXP_RMDIR: - process_rmdir(); - break; - case SSH2_FXP_REALPATH: - process_realpath(); - break; - case SSH2_FXP_STAT: - process_stat(); - break; - case SSH2_FXP_RENAME: - process_rename(); - break; - case SSH2_FXP_READLINK: - process_readlink(); - break; - case SSH2_FXP_SYMLINK: - process_symlink(); - break; - case SSH2_FXP_EXTENDED: - process_extended(); - break; - default: - error("Unknown message %d", type); - break; - } - /* discard the remaining bytes from the current packet */ - if (buf_len < buffer_len(&iqueue)) - fatal("iqueue grew unexpectedly"); - consumed = buf_len - buffer_len(&iqueue); - if (msg_len < consumed) - fatal("msg_len %d < consumed %d", msg_len, consumed); - if (msg_len > consumed) - buffer_consume(&iqueue, msg_len - consumed); -} - -/* - * Cleanup handler that logs active handles upon normal exit. Not static since - * sftp-server-main.c file needs that as well. - */ -void -cleanup_exit(int i) -{ - if (pw != NULL && client_addr != NULL) { - handle_log_exit(); - log("session closed for local user %s from [%s]", - pw->pw_name, client_addr); - } - _exit(i); -} - -static void -usage(void) -{ - fprintf(stderr, - "Usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname); - exit(1); -} - -int -sftp_server_main(int argc, char **argv, struct passwd *user_pw) -{ - fd_set *rset, *wset; - int in, out, max, ch, skipargs = 0, log_stderr = 0; - ssize_t len, olen, set_size; - SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; - char *cp, buf[4*4096]; - - extern char *optarg; - - __progname = get_progname(argv[0]); - - (void) g11n_setlocale(LC_ALL, ""); - - log_init(__progname, log_level, log_facility, log_stderr); - - while (!skipargs && (ch = getopt(argc, argv, "C:f:l:che")) != -1) { - switch (ch) { - case 'c': - /* - * Ignore all arguments if we are invoked as a - * shell using "sftp-server -c command" - */ - skipargs = 1; - break; - case 'e': - log_stderr = 1; - break; - case 'l': - log_level = log_level_number(optarg); - if (log_level == SYSLOG_LEVEL_NOT_SET) - error("Invalid log level \"%s\"", optarg); - break; - case 'f': - log_facility = log_facility_number(optarg); - if (log_facility == SYSLOG_FACILITY_NOT_SET) - error("Invalid log facility \"%s\"", optarg); - break; - case 'h': - default: - usage(); - } - } - - log_init(__progname, log_level, log_facility, log_stderr); - - if ((cp = getenv("SSH_CONNECTION")) != NULL) { - client_addr = xstrdup(cp); - if ((cp = strchr(client_addr, ' ')) == NULL) - fatal("Malformed SSH_CONNECTION variable: \"%s\"", - getenv("SSH_CONNECTION")); - *cp = '\0'; - } else - client_addr = xstrdup("UNKNOWN"); - - pw = pwcopy(user_pw); - - log("session opened for local user %s from [%s]", - pw->pw_name, client_addr); - - handle_init(); - - in = dup(STDIN_FILENO); - out = dup(STDOUT_FILENO); - -#ifdef HAVE_CYGWIN - setmode(in, O_BINARY); - setmode(out, O_BINARY); -#endif - - max = 0; - if (in > max) - max = in; - if (out > max) - max = out; - - buffer_init(&iqueue); - buffer_init(&oqueue); - - set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); - rset = (fd_set *)xmalloc(set_size); - wset = (fd_set *)xmalloc(set_size); - - for (;;) { - memset(rset, 0, set_size); - memset(wset, 0, set_size); - - /* - * Ensure that we can read a full buffer and handle - * the worst-case length packet it can generate, - * otherwise apply backpressure by stopping reads. - */ - if (buffer_check_alloc(&iqueue, sizeof(buf)) && - buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) - FD_SET(in, rset); - - olen = buffer_len(&oqueue); - if (olen > 0) - FD_SET(out, wset); - - if (select(max+1, rset, wset, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - error("select: %s", strerror(errno)); - cleanup_exit(2); - } - - /* copy stdin to iqueue */ - if (FD_ISSET(in, rset)) { - len = read(in, buf, sizeof buf); - if (len == 0) { - debug("read eof"); - cleanup_exit(0); - } else if (len < 0) { - error("read: %s", strerror(errno)); - cleanup_exit(1); - } else { - buffer_append(&iqueue, buf, len); - } - } - /* send oqueue to stdout */ - if (FD_ISSET(out, wset)) { - len = write(out, buffer_ptr(&oqueue), olen); - if (len < 0) { - error("write: %s", strerror(errno)); - cleanup_exit(1); - } else { - buffer_consume(&oqueue, len); - } - } - - /* - * Process requests from client if we can fit the results - * into the output buffer, otherwise stop processing input - * and let the output queue drain. - */ - if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) - process(); - } - - /* NOTREACHED */ - return (0); -} diff --git a/usr/src/cmd/ssh/sftp/sftp-client.c b/usr/src/cmd/ssh/sftp/sftp-client.c deleted file mode 100644 index f194ccaf2b..0000000000 --- a/usr/src/cmd/ssh/sftp/sftp-client.c +++ /dev/null @@ -1,1184 +0,0 @@ -/* - * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* $OpenBSD: sftp-client.c,v 1.76 2007/01/22 11:32:50 djm Exp $ */ - -/* XXX: memleaks */ -/* XXX: signed vs unsigned */ -/* XXX: remove all logging, only return status codes */ -/* XXX: copy between two remote sites */ - -#include "includes.h" - -#include <sys/types.h> -#include <sys/param.h> -#include "sys-queue.h" -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -#include <sys/uio.h> - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "log.h" -#include "atomicio.h" -#include "progressmeter.h" -#include "misc.h" - -#include "sftp.h" -#include "sftp-common.h" -#include "sftp-client.h" - -extern volatile sig_atomic_t interrupted; -extern int showprogress; - -/* Minimum amount of data to read at a time */ -#define MIN_READ_SIZE 512 - -struct sftp_conn { - int fd_in; - int fd_out; - u_int transfer_buflen; - u_int num_requests; - u_int version; - u_int msg_id; -}; - -static void -send_msg(int fd, Buffer *m) -{ - char mlen[4]; - struct iovec iov[2]; - - if (buffer_len(m) > SFTP_MAX_MSG_LENGTH) - fatal("Outbound message too long %u", buffer_len(m)); - - /* Send length first */ - put_u32(mlen, buffer_len(m)); - iov[0].iov_base = mlen; - iov[0].iov_len = sizeof(mlen); - iov[1].iov_base = buffer_ptr(m); - iov[1].iov_len = buffer_len(m); - - if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen)) - fatal("Couldn't send packet: %s", strerror(errno)); - - buffer_clear(m); -} - -static void -get_msg(int fd, Buffer *m) -{ - u_int msg_len; - - buffer_append_space(m, 4); - if (atomicio(read, fd, buffer_ptr(m), 4) != 4) { - if (errno == EPIPE) - fatal("Connection closed"); - else - fatal("Couldn't read packet: %s", strerror(errno)); - } - - msg_len = buffer_get_int(m); - if (msg_len > SFTP_MAX_MSG_LENGTH) - fatal("Received message too long %u", msg_len); - - buffer_append_space(m, msg_len); - if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) { - if (errno == EPIPE) - fatal("Connection closed"); - else - fatal("Read packet: %s", strerror(errno)); - } -} - -static void -send_string_request(int fd, u_int id, u_int code, char *s, - u_int len) -{ - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, code); - buffer_put_int(&msg, id); - buffer_put_string(&msg, s, len); - send_msg(fd, &msg); - debug3("Sent message fd %d T:%u I:%u", fd, code, id); - buffer_free(&msg); -} - -static void -send_string_attrs_request(int fd, u_int id, u_int code, char *s, - u_int len, Attrib *a) -{ - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, code); - buffer_put_int(&msg, id); - buffer_put_string(&msg, s, len); - encode_attrib(&msg, a); - send_msg(fd, &msg); - debug3("Sent message fd %d T:%u I:%u", fd, code, id); - buffer_free(&msg); -} - -static u_int -get_status(int fd, u_int expected_id) -{ - Buffer msg; - u_int type, id, status; - - buffer_init(&msg); - get_msg(fd, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - - if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); - if (type != SSH2_FXP_STATUS) - fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", - SSH2_FXP_STATUS, type); - - status = buffer_get_int(&msg); - buffer_free(&msg); - - debug3("SSH2_FXP_STATUS %u", status); - - return(status); -} - -static char * -get_handle(int fd, u_int expected_id, u_int *len) -{ - Buffer msg; - u_int type, id; - char *handle; - - buffer_init(&msg); - get_msg(fd, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - - if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); - if (type == SSH2_FXP_STATUS) { - int status = buffer_get_int(&msg); - - error("Couldn't get handle: %s", fx2txt(status)); - buffer_free(&msg); - return(NULL); - } else if (type != SSH2_FXP_HANDLE) - fatal("Expected SSH2_FXP_HANDLE(%u) packet, got %u", - SSH2_FXP_HANDLE, type); - - handle = buffer_get_string(&msg, len); - buffer_free(&msg); - - return(handle); -} - -static Attrib * -get_decode_stat(int fd, u_int expected_id, int quiet) -{ - Buffer msg; - u_int type, id; - Attrib *a; - - buffer_init(&msg); - get_msg(fd, &msg); - - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - - debug3("Received stat reply T:%u I:%u", type, id); - if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); - if (type == SSH2_FXP_STATUS) { - int status = buffer_get_int(&msg); - - if (quiet) - debug("Couldn't stat remote file: %s", fx2txt(status)); - else - error("Couldn't stat remote file: %s", fx2txt(status)); - buffer_free(&msg); - return(NULL); - } else if (type != SSH2_FXP_ATTRS) { - fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", - SSH2_FXP_ATTRS, type); - } - a = decode_attrib(&msg); - buffer_free(&msg); - - return(a); -} - -struct sftp_conn * -do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) -{ - u_int type; - int version; - Buffer msg; - struct sftp_conn *ret; - - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_INIT); - buffer_put_int(&msg, SSH2_FILEXFER_VERSION); - send_msg(fd_out, &msg); - - buffer_clear(&msg); - - get_msg(fd_in, &msg); - - /* Expecting a VERSION reply */ - if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { - error("Invalid packet back from SSH2_FXP_INIT (type %u)", - type); - buffer_free(&msg); - return(NULL); - } - version = buffer_get_int(&msg); - - debug2("Remote version: %d", version); - - /* Check for extensions */ - while (buffer_len(&msg) > 0) { - char *name = buffer_get_string(&msg, NULL); - char *value = buffer_get_string(&msg, NULL); - - debug2("Init extension: \"%s\"", name); - xfree(name); - xfree(value); - } - - buffer_free(&msg); - - ret = xmalloc(sizeof(*ret)); - ret->fd_in = fd_in; - ret->fd_out = fd_out; - ret->transfer_buflen = transfer_buflen; - ret->num_requests = num_requests; - ret->version = version; - ret->msg_id = 1; - - /* Some filexfer v.0 servers don't support large packets */ - if (version == 0) - ret->transfer_buflen = MIN(ret->transfer_buflen, 20480); - - return(ret); -} - -u_int -sftp_proto_version(struct sftp_conn *conn) -{ - return(conn->version); -} - -int -do_close(struct sftp_conn *conn, char *handle, u_int handle_len) -{ - u_int id, status; - Buffer msg; - - buffer_init(&msg); - - id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_CLOSE); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_CLOSE I:%u", id); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't close file: %s", fx2txt(status)); - - buffer_free(&msg); - - return(status); -} - - -static int -do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, - SFTP_DIRENT ***dir) -{ - Buffer msg; - u_int count, type, id, handle_len, i, expected_id, ents = 0; - char *handle; - - id = conn->msg_id++; - - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_OPENDIR); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, path); - send_msg(conn->fd_out, &msg); - - buffer_clear(&msg); - - handle = get_handle(conn->fd_in, id, &handle_len); - if (handle == NULL) - return(-1); - - if (dir) { - ents = 0; - *dir = xmalloc(sizeof(**dir)); - (*dir)[0] = NULL; - } - - for (; !interrupted;) { - id = expected_id = conn->msg_id++; - - debug3("Sending SSH2_FXP_READDIR I:%u", id); - - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_READDIR); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - send_msg(conn->fd_out, &msg); - - buffer_clear(&msg); - - get_msg(conn->fd_in, &msg); - - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - - debug3("Received reply T:%u I:%u", type, id); - - if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); - - if (type == SSH2_FXP_STATUS) { - int status = buffer_get_int(&msg); - - debug3("Received SSH2_FXP_STATUS %d", status); - - if (status == SSH2_FX_EOF) { - break; - } else { - error("Couldn't read directory: %s", - fx2txt(status)); - do_close(conn, handle, handle_len); - xfree(handle); - return(status); - } - } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", - SSH2_FXP_NAME, type); - - count = buffer_get_int(&msg); - if (count == 0) - break; - debug3("Received %d SSH2_FXP_NAME responses", count); - for (i = 0; i < count; i++) { - char *filename, *longname; - Attrib *a; - - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); - a = decode_attrib(&msg); - - if (printflag) - printf("%s\n", longname); - - if (dir) { - *dir = xrealloc(*dir, (ents + 2) * sizeof(**dir)); - (*dir)[ents] = xmalloc(sizeof(***dir)); - (*dir)[ents]->filename = xstrdup(filename); - (*dir)[ents]->longname = xstrdup(longname); - memcpy(&(*dir)[ents]->a, a, sizeof(*a)); - (*dir)[++ents] = NULL; - } - - xfree(filename); - xfree(longname); - } - } - - buffer_free(&msg); - do_close(conn, handle, handle_len); - xfree(handle); - - /* Don't return partial matches on interrupt */ - if (interrupted && dir != NULL && *dir != NULL) { - free_sftp_dirents(*dir); - *dir = xmalloc(sizeof(**dir)); - **dir = NULL; - } - - return(0); -} - -int -do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) -{ - return(do_lsreaddir(conn, path, 0, dir)); -} - -void free_sftp_dirents(SFTP_DIRENT **s) -{ - int i; - - for (i = 0; s[i]; i++) { - xfree(s[i]->filename); - xfree(s[i]->longname); - xfree(s[i]); - } - xfree(s); -} - -int -do_rm(struct sftp_conn *conn, char *path) -{ - u_int status, id; - - debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); - - id = conn->msg_id++; - send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, - strlen(path)); - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't delete file: %s", fx2txt(status)); - return(status); -} - -int -do_mkdir(struct sftp_conn *conn, char *path, Attrib *a) -{ - u_int status, id; - - id = conn->msg_id++; - send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path, - strlen(path), a); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't create directory: %s", fx2txt(status)); - - return(status); -} - -int -do_rmdir(struct sftp_conn *conn, char *path) -{ - u_int status, id; - - id = conn->msg_id++; - send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path, - strlen(path)); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't remove directory: %s", fx2txt(status)); - - return(status); -} - -Attrib * -do_stat(struct sftp_conn *conn, char *path, int quiet) -{ - u_int id; - - id = conn->msg_id++; - - send_string_request(conn->fd_out, id, - conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, - path, strlen(path)); - - return(get_decode_stat(conn->fd_in, id, quiet)); -} - -Attrib * -do_lstat(struct sftp_conn *conn, char *path, int quiet) -{ - u_int id; - - if (conn->version == 0) { - if (quiet) - debug("Server version does not support lstat operation"); - else - log("Server version does not support lstat operation"); - return(do_stat(conn, path, quiet)); - } - - id = conn->msg_id++; - send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path, - strlen(path)); - - return(get_decode_stat(conn->fd_in, id, quiet)); -} - -/* this is never used so hush the lint */ -#if 0 -Attrib * -do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) -{ - u_int id; - - id = conn->msg_id++; - send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle, - handle_len); - - return(get_decode_stat(conn->fd_in, id, quiet)); -} -#endif - -int -do_setstat(struct sftp_conn *conn, char *path, Attrib *a) -{ - u_int status, id; - - id = conn->msg_id++; - send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path, - strlen(path), a); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't setstat on \"%s\": %s", path, - fx2txt(status)); - - return(status); -} - -int -do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, - Attrib *a) -{ - u_int status, id; - - id = conn->msg_id++; - send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle, - handle_len, a); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't fsetstat: %s", fx2txt(status)); - - return(status); -} - -char * -do_realpath(struct sftp_conn *conn, char *path) -{ - Buffer msg; - u_int type, expected_id, count, id; - char *filename, *longname; - /* LINTED */ - Attrib *a; - - expected_id = id = conn->msg_id++; - send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path, - strlen(path)); - - buffer_init(&msg); - - get_msg(conn->fd_in, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - - if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); - - if (type == SSH2_FXP_STATUS) { - u_int status = buffer_get_int(&msg); - - error("Couldn't canonicalise: %s", fx2txt(status)); - return(NULL); - } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", - SSH2_FXP_NAME, type); - - count = buffer_get_int(&msg); - if (count != 1) - fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); - - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); - a = decode_attrib(&msg); - - debug3("SSH_FXP_REALPATH %s -> %s", path, filename); - - xfree(longname); - - buffer_free(&msg); - - return(filename); -} - -int -do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) -{ - Buffer msg; - u_int status, id; - - buffer_init(&msg); - - /* Send rename request */ - id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_RENAME); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, oldpath); - buffer_put_cstring(&msg, newpath); - send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath, - newpath); - buffer_free(&msg); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, - newpath, fx2txt(status)); - - return(status); -} - -int -do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) -{ - Buffer msg; - u_int status, id; - - if (conn->version < 3) { - error("This server does not support the symlink operation"); - return(SSH2_FX_OP_UNSUPPORTED); - } - - buffer_init(&msg); - - /* Send symlink request */ - id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_SYMLINK); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, oldpath); - buffer_put_cstring(&msg, newpath); - send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, - newpath); - buffer_free(&msg); - - status = get_status(conn->fd_in, id); - if (status != SSH2_FX_OK) - error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, - newpath, fx2txt(status)); - - return(status); -} - -/* this is never used so hush the lint */ -#if 0 -char * -do_readlink(struct sftp_conn *conn, char *path) -{ - Buffer msg; - u_int type, expected_id, count, id; - char *filename, *longname; - Attrib *a; - - expected_id = id = conn->msg_id++; - send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path, - strlen(path)); - - buffer_init(&msg); - - get_msg(conn->fd_in, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - - if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); - - if (type == SSH2_FXP_STATUS) { - u_int status = buffer_get_int(&msg); - - error("Couldn't readlink: %s", fx2txt(status)); - return(NULL); - } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", - SSH2_FXP_NAME, type); - - count = buffer_get_int(&msg); - if (count != 1) - fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); - - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); - a = decode_attrib(&msg); - - debug3("SSH_FXP_READLINK %s -> %s", path, filename); - - xfree(longname); - - buffer_free(&msg); - - return(filename); -} -#endif - -static void -send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, - char *handle, u_int handle_len) -{ - Buffer msg; - - buffer_init(&msg); - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_READ); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - buffer_put_int64(&msg, offset); - buffer_put_int(&msg, len); - send_msg(fd_out, &msg); - buffer_free(&msg); -} - -int -do_download(struct sftp_conn *conn, char *remote_path, char *local_path, - int pflag) -{ - Attrib junk, *a; - Buffer msg; - char *handle; - int local_fd, status = 0, write_error; - int read_error, write_errno; - u_int64_t offset, size; - u_int handle_len, mode, type, id, buflen, num_req, max_req; - off_t progress_counter; - struct request { - u_int id; - u_int len; - u_int64_t offset; - TAILQ_ENTRY(request) tq; - }; - TAILQ_HEAD(reqhead, request) requests; - struct request *req; - - TAILQ_INIT(&requests); - - a = do_stat(conn, remote_path, 0); - if (a == NULL) - return(-1); - - /* Do not preserve set[ug]id here, as we do not preserve ownership */ - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - mode = a->perm & 0777; - else - mode = 0666; - - if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && - (!S_ISREG(a->perm))) { - error("Cannot download non-regular file: %s", remote_path); - return(-1); - } - - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) - size = a->size; - else - size = 0; - - buflen = conn->transfer_buflen; - buffer_init(&msg); - - /* Send open request */ - id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_OPEN); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, remote_path); - buffer_put_int(&msg, SSH2_FXF_READ); - attrib_clear(&junk); /* Send empty attributes */ - encode_attrib(&msg, &junk); - send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); - - handle = get_handle(conn->fd_in, id, &handle_len); - if (handle == NULL) { - buffer_free(&msg); - return(-1); - } - - local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, - mode | S_IWRITE); - if (local_fd == -1) { - error("Couldn't open local file \"%s\" for writing: %s", - local_path, strerror(errno)); - buffer_free(&msg); - xfree(handle); - return(-1); - } - - /* Read from remote and write to local */ - write_error = read_error = write_errno = num_req = offset = 0; - max_req = 1; - progress_counter = 0; - - if (showprogress && size != 0) - start_progress_meter(remote_path, size, &progress_counter); - - while (num_req > 0 || max_req > 0) { - char *data; - u_int len; - - /* - * Simulate EOF on interrupt: stop sending new requests and - * allow outstanding requests to drain gracefully - */ - if (interrupted) { - if (num_req == 0) /* If we haven't started yet... */ - break; - max_req = 0; - } - - /* Send some more requests */ - while (num_req < max_req) { - debug3("Request range %llu -> %llu (%d/%d)", - (unsigned long long)offset, - (unsigned long long)offset + buflen - 1, - num_req, max_req); - req = xmalloc(sizeof(*req)); - req->id = conn->msg_id++; - req->len = buflen; - req->offset = offset; - offset += buflen; - num_req++; - TAILQ_INSERT_TAIL(&requests, req, tq); - send_read_request(conn->fd_out, req->id, req->offset, - req->len, handle, handle_len); - } - - buffer_clear(&msg); - get_msg(conn->fd_in, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); - debug3("Received reply T:%u I:%u R:%d", type, id, max_req); - - /* Find the request in our queue */ - for (req = TAILQ_FIRST(&requests); - req != NULL && req->id != id; - req = TAILQ_NEXT(req, tq)) - ; - if (req == NULL) - fatal("Unexpected reply %u", id); - - switch (type) { - case SSH2_FXP_STATUS: - status = buffer_get_int(&msg); - if (status != SSH2_FX_EOF) - read_error = 1; - max_req = 0; - TAILQ_REMOVE(&requests, req, tq); - xfree(req); - num_req--; - break; - case SSH2_FXP_DATA: - data = buffer_get_string(&msg, &len); - debug3("Received data %llu -> %llu", - (unsigned long long)req->offset, - (unsigned long long)req->offset + len - 1); - if (len > req->len) - fatal("Received more data than asked for " - "%u > %u", len, req->len); - if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || - atomicio(vwrite, local_fd, data, len) != len) && - !write_error) { - write_errno = errno; - write_error = 1; - max_req = 0; - } - progress_counter += len; - xfree(data); - - if (len == req->len) { - TAILQ_REMOVE(&requests, req, tq); - xfree(req); - num_req--; - } else { - /* Resend the request for the missing data */ - debug3("Short data block, re-requesting " - "%llu -> %llu (%2d)", - (unsigned long long)req->offset + len, - (unsigned long long)req->offset + - req->len - 1, num_req); - req->id = conn->msg_id++; - req->len -= len; - req->offset += len; - send_read_request(conn->fd_out, req->id, - req->offset, req->len, handle, handle_len); - /* Reduce the request size */ - if (len < buflen) - buflen = MAX(MIN_READ_SIZE, len); - } - if (max_req > 0) { /* max_req = 0 iff EOF received */ - if (size > 0 && offset > size) { - /* Only one request at a time - * after the expected EOF */ - debug3("Finish at %llu (%2d)", - (unsigned long long)offset, - num_req); - max_req = 1; - } else if (max_req <= conn->num_requests) { - ++max_req; - } - } - break; - default: - fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", - SSH2_FXP_DATA, type); - } - } - - if (showprogress && size) - stop_progress_meter(); - - /* Sanity check */ - if (TAILQ_FIRST(&requests) != NULL) - fatal("Transfer complete, but requests still in queue"); - - if (read_error) { - error("Couldn't read from remote file \"%s\" : %s", - remote_path, fx2txt(status)); - do_close(conn, handle, handle_len); - } else if (write_error) { - error("Couldn't write to \"%s\": %s", local_path, - strerror(write_errno)); - status = -1; - do_close(conn, handle, handle_len); - } else { - status = do_close(conn, handle, handle_len); - - /* Override umask and utimes if asked */ -#ifdef HAVE_FCHMOD - if (pflag && fchmod(local_fd, mode) == -1) -#else - if (pflag && chmod(local_path, mode) == -1) -#endif /* HAVE_FCHMOD */ - error("Couldn't set mode on \"%s\": %s", local_path, - strerror(errno)); - if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { - struct timeval tv[2]; - tv[0].tv_sec = a->atime; - tv[1].tv_sec = a->mtime; - tv[0].tv_usec = tv[1].tv_usec = 0; - if (utimes(local_path, tv) == -1) - error("Can't set times on \"%s\": %s", - local_path, strerror(errno)); - } - } - close(local_fd); - buffer_free(&msg); - xfree(handle); - - return(status); -} - -int -do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, - int pflag) -{ - int local_fd, status; - u_int handle_len, id, type; - u_int64_t offset; - char *handle, *data; - Buffer msg; - struct stat sb; - Attrib a; - u_int32_t startid; - u_int32_t ackid; - struct outstanding_ack { - u_int id; - u_int len; - u_int64_t offset; - TAILQ_ENTRY(outstanding_ack) tq; - }; - TAILQ_HEAD(ackhead, outstanding_ack) acks; - struct outstanding_ack *ack = NULL; - - TAILQ_INIT(&acks); - - if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { - error("Couldn't open local file \"%s\" for reading: %s", - local_path, strerror(errno)); - return(-1); - } - if (fstat(local_fd, &sb) == -1) { - error("Couldn't fstat local file \"%s\": %s", - local_path, strerror(errno)); - close(local_fd); - return(-1); - } - if (!S_ISREG(sb.st_mode)) { - error("%s is not a regular file", local_path); - close(local_fd); - return(-1); - } - stat_to_attrib(&sb, &a); - - a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; - a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; - a.perm &= 0777; - if (!pflag) - a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; - - buffer_init(&msg); - - /* Send open request */ - id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_OPEN); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, remote_path); - buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); - encode_attrib(&msg, &a); - send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); - - buffer_clear(&msg); - - handle = get_handle(conn->fd_in, id, &handle_len); - if (handle == NULL) { - close(local_fd); - buffer_free(&msg); - return(-1); - } - - startid = ackid = id + 1; - data = xmalloc(conn->transfer_buflen); - - /* Read from local and write to remote */ - offset = 0; - if (showprogress) - start_progress_meter(local_path, sb.st_size, (off_t *)&offset); - - for (;;) { - int len; - - /* - * Can't use atomicio here because it returns 0 on EOF, - * thus losing the last block of the file. - * Simulate an EOF on interrupt, allowing ACKs from the - * server to drain. - */ - if (interrupted) - len = 0; - else do - len = read(local_fd, data, conn->transfer_buflen); - while ((len == -1) && (errno == EINTR || errno == EAGAIN)); - - if (len == -1) - fatal("Couldn't read from \"%s\": %s", local_path, - strerror(errno)); - - if (len != 0) { - ack = xmalloc(sizeof(*ack)); - ack->id = ++id; - ack->offset = offset; - ack->len = len; - TAILQ_INSERT_TAIL(&acks, ack, tq); - - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_WRITE); - buffer_put_int(&msg, ack->id); - buffer_put_string(&msg, handle, handle_len); - buffer_put_int64(&msg, offset); - buffer_put_string(&msg, data, len); - send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", - id, (unsigned long long)offset, len); - } else if (TAILQ_FIRST(&acks) == NULL) - break; - - if (ack == NULL) - fatal("Unexpected ACK %u", id); - - if (id == startid || len == 0 || - id - ackid >= conn->num_requests) { - u_int r_id; - - buffer_clear(&msg); - get_msg(conn->fd_in, &msg); - type = buffer_get_char(&msg); - r_id = buffer_get_int(&msg); - - if (type != SSH2_FXP_STATUS) - fatal("Expected SSH2_FXP_STATUS(%d) packet, " - "got %d", SSH2_FXP_STATUS, type); - - status = buffer_get_int(&msg); - debug3("SSH2_FXP_STATUS %d", status); - - /* Find the request in our queue */ - for (ack = TAILQ_FIRST(&acks); - ack != NULL && ack->id != r_id; - ack = TAILQ_NEXT(ack, tq)) - ; - if (ack == NULL) - fatal("Can't find request for ID %u", r_id); - TAILQ_REMOVE(&acks, ack, tq); - - if (status != SSH2_FX_OK) { - error("Couldn't write to remote file \"%s\": %s", - remote_path, fx2txt(status)); - if (showprogress) - stop_progress_meter(); - do_close(conn, handle, handle_len); - close(local_fd); - xfree(data); - xfree(ack); - status = -1; - goto done; - } - debug3("In write loop, ack for %u %u bytes at %llu", - ack->id, ack->len, (unsigned long long)ack->offset); - ++ackid; - xfree(ack); - } - offset += len; - } - if (showprogress) - stop_progress_meter(); - xfree(data); - - if (close(local_fd) == -1) { - error("Couldn't close local file \"%s\": %s", local_path, - strerror(errno)); - do_close(conn, handle, handle_len); - status = -1; - goto done; - } - - /* Override umask and utimes if asked */ - if (pflag) - do_fsetstat(conn, handle, handle_len, &a); - - status = do_close(conn, handle, handle_len); - -done: - xfree(handle); - buffer_free(&msg); - return(status); -} diff --git a/usr/src/cmd/ssh/sftp/sftp-glob.c b/usr/src/cmd/ssh/sftp/sftp-glob.c deleted file mode 100644 index 626e80922a..0000000000 --- a/usr/src/cmd/ssh/sftp/sftp-glob.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */ - -#include "includes.h" - -#include <sys/types.h> -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif - -#include <dirent.h> -#include <string.h> - -#include "xmalloc.h" -#include "sftp.h" -#include "buffer.h" -#include "sftp-common.h" -#include "sftp-client.h" - -int remote_glob(struct sftp_conn *, const char *, int, - int (*)(const char *, int), glob_t *); - -struct SFTP_OPENDIR { - SFTP_DIRENT **dir; - int offset; -}; - -static struct { - struct sftp_conn *conn; -} cur; - -static void * -fudge_opendir(const char *path) -{ - struct SFTP_OPENDIR *r; - - r = xmalloc(sizeof(*r)); - - if (do_readdir(cur.conn, (char *)path, &r->dir)) { - xfree(r); - return(NULL); - } - - r->offset = 0; - - return((void *)r); -} - -static struct dirent * -fudge_readdir(struct SFTP_OPENDIR *od) -{ - /* Solaris needs sizeof(dirent) + path length (see below) */ - static union { - char buf_chars[sizeof (struct dirent) + MAXPATHLEN]; - struct dirent buf_dirent; - } buf; - struct dirent *ret = &buf.buf_dirent; -#ifdef __GNU_LIBRARY__ - static int inum = 1; -#endif /* __GNU_LIBRARY__ */ - - if (od->dir[od->offset] == NULL) - return(NULL); - - memset(buf.buf_chars, 0, sizeof (buf.buf_chars)); - - /* - * Solaris defines dirent->d_name as a one byte array and expects - * you to hack around it. - */ -#ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME - strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); -#else - strlcpy(ret->d_name, od->dir[od->offset++]->filename, - sizeof(ret->d_name)); -#endif -#ifdef __GNU_LIBRARY__ - /* - * Idiot glibc uses extensions to struct dirent for readdir with - * ALTDIRFUNCs. Not that this is documented anywhere but the - * source... Fake an inode number to appease it. - */ - ret->d_ino = inum++; - if (!inum) - inum = 1; -#endif /* __GNU_LIBRARY__ */ - - return(ret); -} - -static void -fudge_closedir(struct SFTP_OPENDIR *od) -{ - free_sftp_dirents(od->dir); - xfree(od); -} - -static int -fudge_lstat(const char *path, struct stat *st) -{ - Attrib *a; - - if (!(a = do_lstat(cur.conn, (char *)path, 0))) - return(-1); - - attrib_to_stat(a, st); - - return(0); -} - -static int -fudge_stat(const char *path, struct stat *st) -{ - Attrib *a; - - if (!(a = do_stat(cur.conn, (char *)path, 0))) - return(-1); - - attrib_to_stat(a, st); - - return(0); -} - -int -remote_glob(struct sftp_conn *conn, const char *pattern, int flags, - int (*errfunc)(const char *, int), glob_t *pglob) -{ - pglob->gl_opendir = fudge_opendir; - pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; - pglob->gl_closedir = (void (*)(void *))fudge_closedir; - pglob->gl_lstat = fudge_lstat; - pglob->gl_stat = fudge_stat; - - memset(&cur, 0, sizeof(cur)); - cur.conn = conn; - - return(glob(pattern, flags|GLOB_LIMIT|GLOB_ALTDIRFUNC, errfunc, pglob)); -} diff --git a/usr/src/cmd/ssh/sftp/sftp.c b/usr/src/cmd/ssh/sftp/sftp.c deleted file mode 100644 index 10b971f02c..0000000000 --- a/usr/src/cmd/ssh/sftp/sftp.c +++ /dev/null @@ -1,1690 +0,0 @@ -/* - * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* $OpenBSD: sftp.c,v 1.96 2007/01/03 04:09:15 stevesk Exp $ */ - -#include "includes.h" - -#include <sys/types.h> -#include <sys/ioctl.h> -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/wait.h> - -#include <errno.h> - -#ifdef HAVE_PATHS_H -# include <paths.h> -#endif - -#ifdef USE_LIBEDIT -#include <histedit.h> -#else -#ifdef USE_LIBTECLA -#include <libtecla.h> -#define MAX_LINE_LEN 2048 -#define MAX_CMD_HIST 10000 -#endif /* USE_LIBTECLA */ -#endif /* USE_LIBEDIT */ - -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdarg.h> - -#include "xmalloc.h" -#include "log.h" -#include "pathnames.h" -#include "misc.h" - -#include "sftp.h" -#include "buffer.h" -#include "sftp-common.h" -#include "sftp-client.h" - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - - -/* File to read commands from */ -FILE* infile; - -/* Are we in batchfile mode? */ -int batchmode = 0; - -/* Size of buffer used when copying files */ -size_t copy_buffer_len = 32768; - -/* Number of concurrent outstanding requests */ -size_t num_requests = 16; - -/* PID of ssh transport process */ -static pid_t sshpid = -1; - -/* This is set to 0 if the progressmeter is not desired. */ -int showprogress = 1; - -/* SIGINT received during command processing */ -volatile sig_atomic_t interrupted = 0; - -/* I wish qsort() took a separate ctx for the comparison function...*/ -int sort_flag; - -int remote_glob(struct sftp_conn *, const char *, int, - int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ - -/* Separators for interactive commands */ -#define WHITESPACE " \t\r\n" - -/* ls flags */ -#define LS_LONG_VIEW 0x01 /* Full view ala ls -l */ -#define LS_SHORT_VIEW 0x02 /* Single row view ala ls -1 */ -#define LS_NUMERIC_VIEW 0x04 /* Long view with numeric uid/gid */ -#define LS_NAME_SORT 0x08 /* Sort by name (default) */ -#define LS_TIME_SORT 0x10 /* Sort by mtime */ -#define LS_SIZE_SORT 0x20 /* Sort by file size */ -#define LS_REVERSE_SORT 0x40 /* Reverse sort order */ -#define LS_SHOW_ALL 0x80 /* Don't skip filenames starting with '.' */ - -#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW) -#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT) - -/* Commands for interactive mode */ -#define I_CHDIR 1 -#define I_CHGRP 2 -#define I_CHMOD 3 -#define I_CHOWN 4 -#define I_GET 5 -#define I_HELP 6 -#define I_LCHDIR 7 -#define I_LLS 8 -#define I_LMKDIR 9 -#define I_LPWD 10 -#define I_LS 11 -#define I_LUMASK 12 -#define I_MKDIR 13 -#define I_PUT 14 -#define I_PWD 15 -#define I_QUIT 16 -#define I_RENAME 17 -#define I_RM 18 -#define I_RMDIR 19 -#define I_SHELL 20 -#define I_SYMLINK 21 -#define I_VERSION 22 -#define I_PROGRESS 23 - -struct CMD { - const char *c; - const int n; -}; - -static const struct CMD cmds[] = { - { "bye", I_QUIT }, - { "cd", I_CHDIR }, - { "chdir", I_CHDIR }, - { "chgrp", I_CHGRP }, - { "chmod", I_CHMOD }, - { "chown", I_CHOWN }, - { "dir", I_LS }, - { "exit", I_QUIT }, - { "get", I_GET }, - { "mget", I_GET }, - { "help", I_HELP }, - { "lcd", I_LCHDIR }, - { "lchdir", I_LCHDIR }, - { "lls", I_LLS }, - { "lmkdir", I_LMKDIR }, - { "ln", I_SYMLINK }, - { "lpwd", I_LPWD }, - { "ls", I_LS }, - { "lumask", I_LUMASK }, - { "mkdir", I_MKDIR }, - { "progress", I_PROGRESS }, - { "put", I_PUT }, - { "mput", I_PUT }, - { "pwd", I_PWD }, - { "quit", I_QUIT }, - { "rename", I_RENAME }, - { "rm", I_RM }, - { "rmdir", I_RMDIR }, - { "symlink", I_SYMLINK }, - { "version", I_VERSION }, - { "!", I_SHELL }, - { "?", I_HELP }, - { NULL, -1} -}; - -int interactive_loop(int fd_in, int fd_out, char *file1, char *file2); - -/* ARGSUSED */ -static void -killchild(int signo) -{ - if (sshpid > 1) { - kill(sshpid, SIGTERM); - waitpid(sshpid, NULL, 0); - } - - _exit(1); -} - -/* ARGSUSED */ -static void -cmd_interrupt(int signo) -{ - const char msg[] = "\rInterrupt \n"; - int olderrno = errno; - - write(STDERR_FILENO, msg, sizeof(msg) - 1); - interrupted = 1; - errno = olderrno; -} - -static void -help(void) -{ - printf(gettext("Available commands:\n" - "cd path Change remote directory to 'path'\n" - "lcd path Change local directory to 'path'\n" - "chgrp grp path Change group of file 'path' to 'grp'\n" - "chmod mode path Change permissions of file 'path' to 'mode'\n" - "chown own path Change owner of file 'path' to 'own'\n" - "help Display this help text\n" - "get remote-path [local-path] Download file\n" - "lls [ls-options [path]] Display local directory listing\n" - "ln oldpath newpath Symlink remote file\n" - "lmkdir path Create local directory\n" - "lpwd Print local working directory\n" - "ls [path] Display remote directory listing\n" - "lumask umask Set local umask to 'umask'\n" - "mkdir path Create remote directory\n" - "progress Toggle display of progress meter\n" - "put local-path [remote-path] Upload file\n" - "pwd Display remote working directory\n" - "exit Quit sftp\n" - "quit Quit sftp\n" - "rename oldpath newpath Rename remote file\n" - "rmdir path Remove remote directory\n" - "rm path Delete remote file\n" - "symlink oldpath newpath Symlink remote file\n" - "version Show SFTP version\n" - "!command Execute 'command' in local shell\n" - "! Escape to local shell\n" - "? Synonym for help\n")); -} - -static void -local_do_shell(const char *args) -{ - int status; - char *shell; - pid_t pid; - - if (!*args) - args = NULL; - - if ((shell = getenv("SHELL")) == NULL) - shell = _PATH_BSHELL; - - if ((pid = fork()) == -1) - fatal("Couldn't fork: %s", strerror(errno)); - - if (pid == 0) { - /* XXX: child has pipe fds to ssh subproc open - issue? */ - if (args) { - debug3("Executing %s -c \"%s\"", shell, args); - execl(shell, shell, "-c", args, (char *)NULL); - } else { - debug3("Executing %s", shell); - execl(shell, shell, (char *)NULL); - } - fprintf(stderr, gettext("Couldn't execute \"%s\": %s\n"), shell, - strerror(errno)); - _exit(1); - } - while (waitpid(pid, &status, 0) == -1) - if (errno != EINTR) - fatal("Couldn't wait for child: %s", strerror(errno)); - if (!WIFEXITED(status)) - error("Shell exited abnormally"); - else if (WEXITSTATUS(status)) - error("Shell exited with status %d", WEXITSTATUS(status)); -} - -static void -local_do_ls(const char *args) -{ - if (!args || !*args) - local_do_shell(_PATH_LS); - else { - int len = strlen(_PATH_LS " ") + strlen(args) + 1; - char *buf = xmalloc(len); - - /* XXX: quoting - rip quoting code from ftp? */ - snprintf(buf, len, _PATH_LS " %s", args); - local_do_shell(buf); - xfree(buf); - } -} - -/* Strip one path (usually the pwd) from the start of another */ -static char * -path_strip(char *path, char *strip) -{ - size_t len; - - if (strip == NULL) - return (xstrdup(path)); - - len = strlen(strip); - if (strncmp(path, strip, len) == 0) { - if (strip[len - 1] != '/' && path[len] == '/') - len++; - return (xstrdup(path + len)); - } - - return (xstrdup(path)); -} - -static char * -path_append(char *p1, char *p2) -{ - char *ret; - size_t len = strlen(p1) + strlen(p2) + 2; - - ret = xmalloc(len); - strlcpy(ret, p1, len); - if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') - strlcat(ret, "/", len); - strlcat(ret, p2, len); - - return(ret); -} - -static char * -make_absolute(char *p, char *pwd) -{ - char *abs_str; - - /* Derelativise */ - if (p && p[0] != '/') { - abs_str = path_append(pwd, p); - xfree(p); - return(abs_str); - } else - return(p); -} - -static int -infer_path(const char *p, char **ifp) -{ - char *cp; - - cp = strrchr(p, '/'); - if (cp == NULL) { - *ifp = xstrdup(p); - return(0); - } - - if (!cp[1]) { - error("Invalid path"); - return(-1); - } - - *ifp = xstrdup(cp + 1); - return(0); -} - -static int -parse_getput_flags(const char **cpp, int *pflag) -{ - const char *cp = *cpp; - - /* Check for flags */ - if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) { - switch (cp[1]) { - case 'p': - case 'P': - *pflag = 1; - break; - default: - error("Invalid flag -%c", cp[1]); - return(-1); - } - cp += 2; - *cpp = cp + strspn(cp, WHITESPACE); - } - - return(0); -} - -static int -parse_ls_flags(const char **cpp, int *lflag) -{ - const char *cp = *cpp; - - /* Defaults */ - *lflag = LS_NAME_SORT; - - /* Check for flags */ - if (cp++[0] == '-') { - for (; strchr(WHITESPACE, *cp) == NULL; cp++) { - switch (*cp) { - case 'l': - *lflag &= ~VIEW_FLAGS; - *lflag |= LS_LONG_VIEW; - break; - case '1': - *lflag &= ~VIEW_FLAGS; - *lflag |= LS_SHORT_VIEW; - break; - case 'n': - *lflag &= ~VIEW_FLAGS; - *lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW; - break; - case 'S': - *lflag &= ~SORT_FLAGS; - *lflag |= LS_SIZE_SORT; - break; - case 't': - *lflag &= ~SORT_FLAGS; - *lflag |= LS_TIME_SORT; - break; - case 'r': - *lflag |= LS_REVERSE_SORT; - break; - case 'f': - *lflag &= ~SORT_FLAGS; - break; - case 'a': - *lflag |= LS_SHOW_ALL; - break; - default: - error("Invalid flag -%c", *cp); - return(-1); - } - } - *cpp = cp + strspn(cp, WHITESPACE); - } - - return(0); -} - -static int -get_pathname(const char **cpp, char **path) -{ - const char *cp = *cpp, *end; - char quot; - u_int i, j; - - cp += strspn(cp, WHITESPACE); - if (!*cp) { - *cpp = cp; - *path = NULL; - return (0); - } - - *path = xmalloc(strlen(cp) + 1); - - /* Check for quoted filenames */ - if (*cp == '\"' || *cp == '\'') { - quot = *cp++; - - /* Search for terminating quote, unescape some chars */ - for (i = j = 0; i <= strlen(cp); i++) { - if (cp[i] == quot) { /* Found quote */ - i++; - (*path)[j] = '\0'; - break; - } - if (cp[i] == '\0') { /* End of string */ - error("Unterminated quote"); - goto fail; - } - if (cp[i] == '\\') { /* Escaped characters */ - i++; - if (cp[i] != '\'' && cp[i] != '\"' && - cp[i] != '\\') { - error("Bad escaped character '\\%c'", - cp[i]); - goto fail; - } - } - (*path)[j++] = cp[i]; - } - - if (j == 0) { - error("Empty quotes"); - goto fail; - } - *cpp = cp + i + strspn(cp + i, WHITESPACE); - } else { - /* Read to end of filename */ - end = strpbrk(cp, WHITESPACE); - if (end == NULL) - end = strchr(cp, '\0'); - *cpp = end + strspn(end, WHITESPACE); - - memcpy(*path, cp, end - cp); - (*path)[end - cp] = '\0'; - } - return (0); - - fail: - xfree(*path); - *path = NULL; - return (-1); -} - -static int -is_dir(char *path) -{ - struct stat sb; - - /* XXX: report errors? */ - if (stat(path, &sb) == -1) - return(0); - - return(S_ISDIR(sb.st_mode)); -} - -static int -is_reg(char *path) -{ - struct stat sb; - - if (stat(path, &sb) == -1) - fatal("stat %s: %s", path, strerror(errno)); - - return(S_ISREG(sb.st_mode)); -} - -static int -remote_is_dir(struct sftp_conn *conn, char *path) -{ - Attrib *a; - - /* XXX: report errors? */ - if ((a = do_stat(conn, path, 1)) == NULL) - return(0); - if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) - return(0); - return(S_ISDIR(a->perm)); -} - -static int -process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) -{ - char *abs_src = NULL; - char *abs_dst = NULL; - char *tmp; - glob_t g; - int err = 0; - int i; - - abs_src = xstrdup(src); - abs_src = make_absolute(abs_src, pwd); - - memset(&g, 0, sizeof(g)); - debug3("Looking up %s", abs_src); - if (remote_glob(conn, abs_src, 0, NULL, &g)) { - error("File \"%s\" not found.", abs_src); - err = -1; - goto out; - } - - /* If multiple matches, dst must be a directory or unspecified */ - if (g.gl_matchc > 1 && dst && !is_dir(dst)) { - error("Multiple files match, but \"%s\" is not a directory", - dst); - err = -1; - goto out; - } - - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - if (infer_path(g.gl_pathv[i], &tmp)) { - err = -1; - goto out; - } - - if (g.gl_matchc == 1 && dst) { - /* If directory specified, append filename */ - xfree(tmp); - if (is_dir(dst)) { - if (infer_path(g.gl_pathv[0], &tmp)) { - err = 1; - goto out; - } - abs_dst = path_append(dst, tmp); - xfree(tmp); - } else - abs_dst = xstrdup(dst); - } else if (dst) { - abs_dst = path_append(dst, tmp); - xfree(tmp); - } else - abs_dst = tmp; - - printf(gettext("Fetching %s to %s\n"), g.gl_pathv[i], abs_dst); - if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1) - err = -1; - xfree(abs_dst); - abs_dst = NULL; - } - -out: - xfree(abs_src); - globfree(&g); - return(err); -} - -static int -process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) -{ - char *tmp_dst = NULL; - char *abs_dst = NULL; - char *tmp; - glob_t g; - int err = 0; - int i; - - if (dst) { - tmp_dst = xstrdup(dst); - tmp_dst = make_absolute(tmp_dst, pwd); - } - - memset(&g, 0, sizeof(g)); - debug3("Looking up %s", src); - if (glob(src, GLOB_LIMIT, NULL, &g)) { - error("File \"%s\" not found.", src); - err = -1; - goto out; - } - - /* If multiple matches, dst may be directory or unspecified */ - if (g.gl_matchc > 1 && tmp_dst && !remote_is_dir(conn, tmp_dst)) { - error("Multiple files match, but \"%s\" is not a directory", - tmp_dst); - err = -1; - goto out; - } - - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - if (!is_reg(g.gl_pathv[i])) { - error("skipping non-regular file %s", - g.gl_pathv[i]); - continue; - } - if (infer_path(g.gl_pathv[i], &tmp)) { - err = -1; - goto out; - } - - if (g.gl_matchc == 1 && tmp_dst) { - /* If directory specified, append filename */ - if (remote_is_dir(conn, tmp_dst)) { - if (infer_path(g.gl_pathv[0], &tmp)) { - err = 1; - goto out; - } - abs_dst = path_append(tmp_dst, tmp); - xfree(tmp); - } else - abs_dst = xstrdup(tmp_dst); - - } else if (tmp_dst) { - abs_dst = path_append(tmp_dst, tmp); - xfree(tmp); - } else - abs_dst = make_absolute(tmp, pwd); - - printf(gettext("Uploading %s to %s\n"), g.gl_pathv[i], abs_dst); - if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1) - err = -1; - } - -out: - if (abs_dst) - xfree(abs_dst); - if (tmp_dst) - xfree(tmp_dst); - globfree(&g); - return(err); -} - -static int -sdirent_comp(const void *aa, const void *bb) -{ - SFTP_DIRENT *a = *(SFTP_DIRENT **)aa; - SFTP_DIRENT *b = *(SFTP_DIRENT **)bb; - int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; - -#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) - if (sort_flag & LS_NAME_SORT) - return (rmul * strcmp(a->filename, b->filename)); - else if (sort_flag & LS_TIME_SORT) - return (rmul * NCMP(a->a.mtime, b->a.mtime)); - else if (sort_flag & LS_SIZE_SORT) - return (rmul * NCMP(a->a.size, b->a.size)); - - fatal("Unknown ls sort type"); - - /* NOTREACHED */ - return (0); -} - -/* sftp ls.1 replacement for directories */ -static int -do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) -{ - int n; - u_int c = 1, colspace = 0, columns = 1; - SFTP_DIRENT **d; - - if ((n = do_readdir(conn, path, &d)) != 0) - return (n); - - if (!(lflag & LS_SHORT_VIEW)) { - u_int m = 0, width = 80; - struct winsize ws; - char *tmp; - - /* Count entries for sort and find longest filename */ - for (n = 0; d[n] != NULL; n++) { - if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL)) - m = MAX(m, strlen(d[n]->filename)); - } - - /* Add any subpath that also needs to be counted */ - tmp = path_strip(path, strip_path); - m += strlen(tmp); - xfree(tmp); - - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) - width = ws.ws_col; - - columns = width / (m + 2); - columns = MAX(columns, 1); - colspace = width / columns; - colspace = MIN(colspace, width); - } - - if (lflag & SORT_FLAGS) { - for (n = 0; d[n] != NULL; n++) - ; /* count entries */ - sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); - qsort(d, n, sizeof(*d), sdirent_comp); - } - - for (n = 0; d[n] != NULL && !interrupted; n++) { - char *tmp, *fname; - - if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL)) - continue; - - tmp = path_append(path, d[n]->filename); - fname = path_strip(tmp, strip_path); - xfree(tmp); - - if (lflag & LS_LONG_VIEW) { - if (lflag & LS_NUMERIC_VIEW) { - char *lname; - struct stat sb; - - memset(&sb, 0, sizeof(sb)); - attrib_to_stat(&d[n]->a, &sb); - lname = ls_file(fname, &sb, 1); - printf("%s\n", lname); - xfree(lname); - } else - printf("%s\n", d[n]->longname); - } else { - printf("%-*s", colspace, fname); - if (c >= columns) { - printf("\n"); - c = 1; - } else - c++; - } - - xfree(fname); - } - - if (!(lflag & LS_LONG_VIEW) && (c != 1)) - printf("\n"); - - free_sftp_dirents(d); - return (0); -} - -/* sftp ls.1 replacement which handles path globs */ -static int -do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, - int lflag) -{ - glob_t g; - u_int i, c = 1, colspace = 0, columns = 1; - Attrib *a = NULL; - - memset(&g, 0, sizeof(g)); - - if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE, - NULL, &g) || (g.gl_pathc && !g.gl_matchc)) { - if (g.gl_pathc) - globfree(&g); - error("Can't ls: \"%s\" not found", path); - return (-1); - } - - if (interrupted) - goto out; - - /* - * If the glob returns a single match and it is a directory, - * then just list its contents. - */ - if (g.gl_matchc == 1) { - if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) { - globfree(&g); - return (-1); - } - if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && - S_ISDIR(a->perm)) { - int err; - - err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag); - globfree(&g); - return (err); - } - } - - if (!(lflag & LS_SHORT_VIEW)) { - u_int m = 0, width = 80; - struct winsize ws; - - /* Count entries for sort and find longest filename */ - for (i = 0; g.gl_pathv[i]; i++) - m = MAX(m, strlen(g.gl_pathv[i])); - - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) - width = ws.ws_col; - - columns = width / (m + 2); - columns = MAX(columns, 1); - colspace = width / columns; - } - - for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) { - char *fname; - - fname = path_strip(g.gl_pathv[i], strip_path); - - if (lflag & LS_LONG_VIEW) { - char *lname; - struct stat sb; - - /* - * XXX: this is slow - 1 roundtrip per path - * A solution to this is to fork glob() and - * build a sftp specific version which keeps the - * attribs (which currently get thrown away) - * that the server returns as well as the filenames. - */ - memset(&sb, 0, sizeof(sb)); - if (a == NULL) - a = do_lstat(conn, g.gl_pathv[i], 1); - if (a != NULL) - attrib_to_stat(a, &sb); - lname = ls_file(fname, &sb, 1); - printf("%s\n", lname); - xfree(lname); - } else { - printf("%-*s", colspace, fname); - if (c >= columns) { - printf("\n"); - c = 1; - } else - c++; - } - xfree(fname); - } - - if (!(lflag & LS_LONG_VIEW) && (c != 1)) - printf("\n"); - - out: - if (g.gl_pathc) - globfree(&g); - - return (0); -} - -static int -parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, - unsigned long *n_arg, char **path1, char **path2) -{ - const char *cmd, *cp = *cpp; - char *cp2; - int base = 0; - long l; - int i, cmdnum; - - /* Skip leading whitespace */ - cp = cp + strspn(cp, WHITESPACE); - - /* Ignore blank lines and lines which begin with comment '#' char */ - if (*cp == '\0' || *cp == '#') - return (0); - - /* Check for leading '-' (disable error processing) */ - *iflag = 0; - if (*cp == '-') { - *iflag = 1; - cp++; - } - - /* Figure out which command we have */ - for (i = 0; cmds[i].c; i++) { - int cmdlen = strlen(cmds[i].c); - - /* Check for command followed by whitespace */ - if (!strncasecmp(cp, cmds[i].c, cmdlen) && - strchr(WHITESPACE, cp[cmdlen])) { - cp += cmdlen; - cp = cp + strspn(cp, WHITESPACE); - break; - } - } - cmdnum = cmds[i].n; - cmd = cmds[i].c; - - /* Special case */ - if (*cp == '!') { - cp++; - cmdnum = I_SHELL; - } else if (cmdnum == -1) { - error("Invalid command."); - return (-1); - } - - /* Get arguments and parse flags */ - *lflag = *pflag = *n_arg = 0; - *path1 = *path2 = NULL; - switch (cmdnum) { - case I_GET: - case I_PUT: - if (parse_getput_flags(&cp, pflag)) - return(-1); - /* Get first pathname (mandatory) */ - if (get_pathname(&cp, path1)) - return(-1); - if (*path1 == NULL) { - error("You must specify at least one path after a " - "%s command.", cmd); - return(-1); - } - /* Try to get second pathname (optional) */ - if (get_pathname(&cp, path2)) - return(-1); - break; - case I_RENAME: - case I_SYMLINK: - if (get_pathname(&cp, path1)) - return(-1); - if (get_pathname(&cp, path2)) - return(-1); - if (!*path1 || !*path2) { - error("You must specify two paths after a %s " - "command.", cmd); - return(-1); - } - break; - case I_RM: - case I_MKDIR: - case I_RMDIR: - case I_CHDIR: - case I_LCHDIR: - case I_LMKDIR: - /* Get pathname (mandatory) */ - if (get_pathname(&cp, path1)) - return(-1); - if (*path1 == NULL) { - error("You must specify a path after a %s command.", - cmd); - return(-1); - } - break; - case I_LS: - if (parse_ls_flags(&cp, lflag)) - return(-1); - /* Path is optional */ - if (get_pathname(&cp, path1)) - return(-1); - break; - case I_LLS: - case I_SHELL: - /* Uses the rest of the line */ - break; - case I_LUMASK: - base = 8; - /* FALLTHRU */ - case I_CHMOD: - base = 8; - /* FALLTHRU */ - case I_CHOWN: - case I_CHGRP: - /* Get numeric arg (mandatory) */ - errno = 0; - l = strtol(cp, &cp2, base); - if (cp2 == cp || ((l == LONG_MIN || l == LONG_MAX) && - errno == ERANGE) || l < 0) { - error("You must supply a numeric argument " - "to the %s command.", cmd); - return(-1); - } - cp = cp2; - *n_arg = l; - if (cmdnum == I_LUMASK && strchr(WHITESPACE, *cp)) - break; - if (cmdnum == I_LUMASK || !strchr(WHITESPACE, *cp)) { - error("You must supply a numeric argument " - "to the %s command.", cmd); - return(-1); - } - cp += strspn(cp, WHITESPACE); - - /* Get pathname (mandatory) */ - if (get_pathname(&cp, path1)) - return(-1); - if (*path1 == NULL) { - error("You must specify a path after a %s command.", - cmd); - return(-1); - } - break; - case I_QUIT: - case I_PWD: - case I_LPWD: - case I_HELP: - case I_VERSION: - case I_PROGRESS: - break; - default: - fatal("Command not implemented"); - } - - *cpp = cp; - return(cmdnum); -} - -static int -parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, - int err_abort) -{ - char *path1, *path2, *tmp; - int pflag, lflag, iflag, cmdnum, i; - unsigned long n_arg; - Attrib a, *aa; - char path_buf[MAXPATHLEN]; - int err = 0; - glob_t g; - - path1 = path2 = NULL; - cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg, - &path1, &path2); - - if (iflag != 0) - err_abort = 0; - - memset(&g, 0, sizeof(g)); - - /* Perform command */ - switch (cmdnum) { - case 0: - /* Blank line */ - break; - case -1: - /* Unrecognized command */ - err = -1; - break; - case I_GET: - err = process_get(conn, path1, path2, *pwd, pflag); - break; - case I_PUT: - err = process_put(conn, path1, path2, *pwd, pflag); - break; - case I_RENAME: - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = do_rename(conn, path1, path2); - break; - case I_SYMLINK: - path2 = make_absolute(path2, *pwd); - err = do_symlink(conn, path1, path2); - break; - case I_RM: - path1 = make_absolute(path1, *pwd); - remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - printf(gettext("Removing %s\n"), g.gl_pathv[i]); - err = do_rm(conn, g.gl_pathv[i]); - if (err != 0 && err_abort) - break; - } - break; - case I_MKDIR: - path1 = make_absolute(path1, *pwd); - attrib_clear(&a); - a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; - a.perm = 0777; - err = do_mkdir(conn, path1, &a); - break; - case I_RMDIR: - path1 = make_absolute(path1, *pwd); - err = do_rmdir(conn, path1); - break; - case I_CHDIR: - path1 = make_absolute(path1, *pwd); - if ((tmp = do_realpath(conn, path1)) == NULL) { - err = 1; - break; - } - if ((aa = do_stat(conn, tmp, 0)) == NULL) { - xfree(tmp); - err = 1; - break; - } - if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { - error("Can't change directory: Can't check target"); - xfree(tmp); - err = 1; - break; - } - if (!S_ISDIR(aa->perm)) { - error("Can't change directory: \"%s\" is not " - "a directory", tmp); - xfree(tmp); - err = 1; - break; - } - xfree(*pwd); - *pwd = tmp; - break; - case I_LS: - if (!path1) { - do_globbed_ls(conn, *pwd, *pwd, lflag); - break; - } - - /* Strip pwd off beginning of non-absolute paths */ - tmp = NULL; - if (*path1 != '/') - tmp = *pwd; - - path1 = make_absolute(path1, *pwd); - err = do_globbed_ls(conn, path1, tmp, lflag); - break; - case I_LCHDIR: - if (chdir(path1) == -1) { - error("Couldn't change local directory to " - "\"%s\": %s", path1, strerror(errno)); - err = 1; - } - break; - case I_LMKDIR: - if (mkdir(path1, 0777) == -1) { - error("Couldn't create local directory " - "\"%s\": %s", path1, strerror(errno)); - err = 1; - } - break; - case I_LLS: - local_do_ls(cmd); - break; - case I_SHELL: - local_do_shell(cmd); - break; - case I_LUMASK: - umask(n_arg); - printf(gettext("Local umask: %03lo\n"), n_arg); - break; - case I_CHMOD: - path1 = make_absolute(path1, *pwd); - attrib_clear(&a); - a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; - a.perm = n_arg; - remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - printf(gettext("Changing mode on %s\n"), g.gl_pathv[i]); - err = do_setstat(conn, g.gl_pathv[i], &a); - if (err != 0 && err_abort) - break; - } - break; - case I_CHOWN: - case I_CHGRP: - 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))) { - if (err != 0 && err_abort) - break; - else - continue; - } - if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { - error("Can't get current ownership of " - "remote file \"%s\"", g.gl_pathv[i]); - if (err != 0 && err_abort) - break; - else - continue; - } - aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; - if (cmdnum == I_CHOWN) { - printf(gettext("Changing owner on %s\n"), g.gl_pathv[i]); - aa->uid = n_arg; - } else { - printf(gettext("Changing group on %s\n"), g.gl_pathv[i]); - aa->gid = n_arg; - } - err = do_setstat(conn, g.gl_pathv[i], aa); - if (err != 0 && err_abort) - break; - } - break; - case I_PWD: - printf(gettext("Remote working directory: %s\n"), *pwd); - break; - case I_LPWD: - if (!getcwd(path_buf, sizeof(path_buf))) { - error("Couldn't get local cwd: %s", strerror(errno)); - err = -1; - break; - } - printf(gettext("Local working directory: %s\n"), path_buf); - break; - case I_QUIT: - /* Processed below */ - break; - case I_HELP: - help(); - break; - case I_VERSION: - printf(gettext("SFTP protocol version %u\n"), sftp_proto_version(conn)); - break; - case I_PROGRESS: - showprogress = !showprogress; - if (showprogress) - printf("Progress meter enabled\n"); - else - printf("Progress meter disabled\n"); - break; - default: - fatal("%d is not implemented", cmdnum); - } - - if (g.gl_pathc) - globfree(&g); - if (path1) - xfree(path1); - if (path2) - xfree(path2); - - /* If an unignored error occurs in batch mode we should abort. */ - if (err_abort && err != 0) - return (-1); - else if (cmdnum == I_QUIT) - return (1); - - return (0); -} - -#ifdef USE_LIBEDIT -static char * -prompt(EditLine *el) -{ - return ("sftp> "); -} -#else -#ifdef USE_LIBTECLA -/* - * Disable default TAB completion for filenames, because it displays local - * files for every commands, which is not desirable. - */ -static -CPL_MATCH_FN(nomatch) -{ - return (0); -} -#endif /* USE_LIBTECLA */ -#endif /* USE_LIBEDIT */ - -int -interactive_loop(int fd_in, int fd_out, char *file1, char *file2) -{ - char *pwd; - char *dir = NULL; - char cmd[2048]; - struct sftp_conn *conn; - int err, interactive; - void *il = NULL; - -#ifdef USE_LIBEDIT - EditLine *el = NULL; - History *hl = NULL; - HistEvent hev; - - if (!batchmode && isatty(STDIN_FILENO)) { - if ((il = el = el_init(__progname, stdin, stdout, stderr)) == NULL) - fatal("Couldn't initialise editline"); - if ((hl = history_init()) == NULL) - fatal("Couldn't initialise editline history"); - history(hl, &hev, H_SETSIZE, 100); - el_set(el, EL_HIST, history, hl); - - el_set(el, EL_PROMPT, prompt); - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_TERMINAL, NULL); - el_set(el, EL_SIGNAL, 1); - el_source(el, NULL); - } -#else -#ifdef USE_LIBTECLA - GetLine *gl = NULL; - - if (!batchmode && isatty(STDIN_FILENO)) { - if ((il = gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) - fatal("Couldn't initialize GetLine"); - if (gl_customize_completion(gl, NULL, nomatch) != 0) { - (void) del_GetLine(gl); - fatal("Couldn't register completion function"); - } - } -#endif /* USE_LIBTECLA */ -#endif /* USE_LIBEDIT */ - - conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); - if (conn == NULL) - fatal("Couldn't initialise connection to server"); - - pwd = do_realpath(conn, "."); - if (pwd == NULL) - fatal("Need cwd"); - - if (file1 != NULL) { - dir = xstrdup(file1); - dir = make_absolute(dir, pwd); - - if (remote_is_dir(conn, dir) && file2 == NULL) { - printf(gettext("Changing to: %s\n"), dir); - snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); - if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) { - xfree(dir); - xfree(pwd); - xfree(conn); - return (-1); - } - } else { - if (file2 == NULL) - snprintf(cmd, sizeof cmd, "get %s", dir); - else - snprintf(cmd, sizeof cmd, "get %s %s", dir, - file2); - - err = parse_dispatch_command(conn, cmd, &pwd, 1); - xfree(dir); - xfree(pwd); - xfree(conn); - return (err); - } - xfree(dir); - } - -#if defined(HAVE_SETVBUF) && !defined(BROKEN_SETVBUF) - setvbuf(stdout, NULL, _IOLBF, 0); - setvbuf(infile, NULL, _IOLBF, 0); -#else - setlinebuf(stdout); - setlinebuf(infile); -#endif - - interactive = !batchmode && isatty(STDIN_FILENO); - err = 0; - for (;;) { - char *cp; - - signal(SIGINT, SIG_IGN); - - if (il == NULL) { - if (interactive) - printf("sftp> "); - if (fgets(cmd, sizeof(cmd), infile) == NULL) { - if (interactive) - printf("\n"); - break; - } - if (!interactive) { /* Echo command */ - printf("sftp> %s", cmd); - if (strlen(cmd) > 0 && - cmd[strlen(cmd) - 1] != '\n') - printf("\n"); - } - } -#ifdef USE_LIBEDIT - else { - const char *line; - int count = 0; - - if ((line = el_gets(el, &count)) == NULL || count <= 0) { - printf("\n"); - break; - } - history(hl, &hev, H_ENTER, line); - if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) { - fprintf(stderr, gettext("Error: input line too long\n")); - continue; - } - } -#else -#ifdef USE_LIBTECLA - else { - const char *line; - - line = gl_get_line(gl, "sftp> ", NULL, -1); - if (line != NULL) { - if (strlcpy(cmd, line, sizeof(cmd)) >= - sizeof(cmd)) { - fprintf(stderr, gettext( - "Error: input line too long\n")); - continue; - } - } else { - GlReturnStatus rtn; - - rtn = gl_return_status(gl); - if (rtn == GLR_SIGNAL) { - gl_abandon_line(gl); - continue; - } else if (rtn == GLR_ERROR) { - fprintf(stderr, gettext( - "Error reading terminal: %s/\n"), - gl_error_message(gl, NULL, 0)); - } - break; - } - } -#endif /* USE_LIBTECLA */ -#endif /* USE_LIBEDIT */ - - cp = strrchr(cmd, '\n'); - if (cp) - *cp = '\0'; - - /* Handle user interrupts gracefully during commands */ - interrupted = 0; - signal(SIGINT, cmd_interrupt); - - err = parse_dispatch_command(conn, cmd, &pwd, batchmode); - if (err != 0) - break; - } - xfree(pwd); - xfree(conn); - -#ifdef USE_LIBEDIT - if (el != NULL) - el_end(el); -#else -#ifdef USE_LIBTECLA - if (gl != NULL) - (void) del_GetLine(gl); -#endif /* USE_LIBTECLA */ -#endif /* USE_LIBEDIT */ - - /* err == 1 signifies normal "quit" exit */ - return (err >= 0 ? 0 : -1); -} - -static void -connect_to_server(char *path, char **args, int *in, int *out) -{ - int c_in, c_out; - - 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]; - - 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 - */ - signal(SIGINT, SIG_IGN); - execvp(path, args); - fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); - _exit(1); - } - - signal(SIGTERM, killchild); - signal(SIGINT, killchild); - signal(SIGHUP, killchild); - close(c_in); - close(c_out); -} - -static void -usage(void) -{ - fprintf(stderr, - gettext("Usage: %s [-1Cv] [-b batchfile] [-B buffer_size]\n" - " [-F ssh_config] [-o ssh_option] [-P sftp_server_path]\n" - " [-R num_requests] [-s subsystem | sftp_server]\n" - " [-S program] [user@]host[:dir[/] | :file [file]]\n"), - __progname, __progname, __progname, __progname); - exit(1); -} - -int -main(int argc, char **argv) -{ - int in, out, ch, err; - char *host, *userhost, *cp, *file2 = NULL; - int debug_level = 0, sshver = 2; - char *file1 = NULL, *sftp_server = NULL; - char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; - LogLevel ll = SYSLOG_LEVEL_INFO; - arglist args; - extern int optind; - extern char *optarg; - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); - - __progname = get_progname(argv[0]); - - (void) g11n_setlocale(LC_ALL, ""); - - memset(&args, '\0', sizeof(args)); - args.list = NULL; - addargs(&args, "%s", ssh_program); - addargs(&args, "-oForwardX11 no"); - addargs(&args, "-oForwardAgent no"); - addargs(&args, "-oClearAllForwardings yes"); - - ll = SYSLOG_LEVEL_INFO; - infile = stdin; - - while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { - switch (ch) { - case 'C': - addargs(&args, "-C"); - break; - case 'v': - if (debug_level < 3) { - addargs(&args, "-v"); - ll = SYSLOG_LEVEL_DEBUG1 + debug_level; - } - debug_level++; - break; - case 'F': - case 'o': - addargs(&args, "-%c%s", ch, optarg); - break; - case '1': - sshver = 1; - if (sftp_server == NULL) - sftp_server = _PATH_SFTP_SERVER; - break; - case 's': - sftp_server = optarg; - break; - case 'S': - ssh_program = optarg; - replacearg(&args, 0, "%s", ssh_program); - break; - case 'b': - if (batchmode) - fatal("Batch file already specified."); - - /* Allow "-" as stdin */ - if (strcmp(optarg, "-") != 0 && - (infile = fopen(optarg, "r")) == NULL) - fatal("%s (%s).", strerror(errno), optarg); - showprogress = 0; - batchmode = 1; - addargs(&args, "-obatchmode yes"); - break; - case 'P': - sftp_direct = optarg; - break; - case 'B': - copy_buffer_len = strtol(optarg, &cp, 10); - if (copy_buffer_len == 0 || *cp != '\0') - fatal("Invalid buffer size \"%s\"", optarg); - break; - case 'R': - num_requests = strtol(optarg, &cp, 10); - if (num_requests == 0 || *cp != '\0') - fatal("Invalid number of requests \"%s\"", - optarg); - break; - case 'h': - default: - usage(); - } - } - - if (!isatty(STDERR_FILENO)) - showprogress = 0; - - log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); - - if (sftp_direct == NULL) { - if (optind == argc || argc > (optind + 2)) - usage(); - - userhost = xstrdup(argv[optind]); - file2 = argv[optind+1]; - - if ((host = strrchr(userhost, '@')) == NULL) - host = userhost; - else { - *host++ = '\0'; - if (!userhost[0]) { - fprintf(stderr, gettext("Missing username\n")); - usage(); - } - addargs(&args, "-l%s", userhost); - } - - if ((cp = colon(host)) != NULL) { - *cp++ = '\0'; - file1 = cp; - } - - host = cleanhostname(host); - if (!*host) { - fprintf(stderr, gettext("Missing hostname\n")); - usage(); - } - - addargs(&args, "-oProtocol %d", sshver); - - /* no subsystem if the server-spec contains a '/' */ - if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) - addargs(&args, "-s"); - - addargs(&args, "%s", host); - addargs(&args, "%s", (sftp_server != NULL ? - sftp_server : "sftp")); - - if (!batchmode) - fprintf(stderr, gettext("Connecting to %s...\n"), host); - connect_to_server(ssh_program, args.list, &in, &out); - } else { - args.list = NULL; - addargs(&args, "sftp-server"); - - if (!batchmode) - fprintf(stderr, gettext("Attaching to %s...\n"), sftp_direct); - connect_to_server(sftp_direct, args.list, &in, &out); - } - freeargs(&args); - - err = interactive_loop(in, out, file1, file2); - - shutdown(in, SHUT_RDWR); - shutdown(out, SHUT_RDWR); - - close(in); - close(out); - if (batchmode) - fclose(infile); - - while (waitpid(sshpid, NULL, 0) == -1) - if (errno != EINTR) - fatal("Couldn't wait for ssh process: %s", - strerror(errno)); - - return (err == 0 ? 0 : 1); -} diff --git a/usr/src/cmd/ssh/ssh-add/Makefile b/usr/src/cmd/ssh/ssh-add/Makefile deleted file mode 100644 index 1fb132f741..0000000000 --- a/usr/src/cmd/ssh/ssh-add/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# 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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/ssh-add/Makefile - -PROG= ssh-add - -OBJS = \ - ssh-add.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -install: all $(ROOTPROG) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/ssh-add/ssh-add.c b/usr/src/cmd/ssh/ssh-add/ssh-add.c deleted file mode 100644 index cfa1ce320e..0000000000 --- a/usr/src/cmd/ssh/ssh-add/ssh-add.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Adds an identity to the authentication server, or removes an identity. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * SSH2 implementation, - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: ssh-add.c,v 1.63 2002/09/19 15:51:23 markus Exp $"); - -#include <openssl/evp.h> - -#include "ssh.h" -#include "rsa.h" -#include "log.h" -#include "xmalloc.h" -#include "key.h" -#include "authfd.h" -#include "authfile.h" -#include "pathnames.h" -#include "readpass.h" -#include "misc.h" - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -/* argv0 */ -extern char *__progname; - -/* Default files to add */ -static char *default_files[] = { - _PATH_SSH_CLIENT_ID_RSA, - _PATH_SSH_CLIENT_ID_DSA, - _PATH_SSH_CLIENT_IDENTITY, - NULL -}; - -/* Default lifetime (0 == forever) */ -static int lifetime = 0; - -/* we keep a cache of one passphrases */ -static char *pass = NULL; -static void -clear_pass(void) -{ - if (pass) { - memset(pass, 0, strlen(pass)); - xfree(pass); - pass = NULL; - } -} - -static int -delete_file(AuthenticationConnection *ac, const char *filename) -{ - Key *public; - char *comment = NULL; - int ret = -1; - - public = key_load_public(filename, &comment); - if (public == NULL) { - printf(gettext("Bad key file %s\n"), filename); - return -1; - } - if (ssh_remove_identity(ac, public)) { - fprintf(stderr, gettext("Identity removed: %s (%s)\n"), - filename, comment); - ret = 0; - } else - fprintf(stderr, gettext("Could not remove identity: %s\n"), - filename); - - key_free(public); - xfree(comment); - - return ret; -} - -/* Send a request to remove all identities. */ -static int -delete_all(AuthenticationConnection *ac) -{ - int ret = -1; - - if (ssh_remove_all_identities(ac, 1)) - ret = 0; - /* ignore error-code for ssh2 */ - ssh_remove_all_identities(ac, 2); - - if (ret == 0) - fprintf(stderr, gettext("All identities removed.\n")); - else - fprintf(stderr, gettext("Failed to remove all identities.\n")); - - return ret; -} - -static int -add_file(AuthenticationConnection *ac, const char *filename) -{ - struct stat st; - Key *private; - char *comment = NULL; - char msg[1024]; - int ret = -1; - - if (stat(filename, &st) < 0) { - perror(filename); - return -1; - } - /* At first, try empty passphrase */ - private = key_load_private(filename, "", &comment); - if (comment == NULL) - comment = xstrdup(filename); - /* try last */ - if (private == NULL && pass != NULL) - private = key_load_private(filename, pass, NULL); - if (private == NULL) { - /* clear passphrase since it did not work */ - clear_pass(); - snprintf(msg, sizeof msg, - gettext("Enter passphrase for %.200s: "), comment); - for (;;) { - pass = read_passphrase(msg, RP_ALLOW_STDIN); - if (strcmp(pass, "") == 0) { - clear_pass(); - xfree(comment); - return -1; - } - private = key_load_private(filename, pass, &comment); - if (private != NULL) - break; - clear_pass(); - strlcpy(msg, gettext("Bad passphrase, try again: "), - sizeof msg); - } - } - - if (ssh_add_identity_constrained(ac, private, comment, lifetime)) { - fprintf(stderr, gettext("Identity added: %s (%s)\n"), - filename, comment); - ret = 0; - if (lifetime != 0) - fprintf(stderr, - gettext("Lifetime set to %d seconds\n"), lifetime); - } else if (ssh_add_identity(ac, private, comment)) { - fprintf(stderr, gettext("Identity added: %s (%s)\n"), - filename, comment); - ret = 0; - } else { - fprintf(stderr, gettext("Could not add identity: %s\n"), - filename); - } - - xfree(comment); - key_free(private); - - return ret; -} - -static int -list_identities(AuthenticationConnection *ac, int do_fp) -{ - Key *key; - char *comment, *fp; - int had_identities = 0; - int version; - - for (version = 1; version <= 2; version++) { - for (key = ssh_get_first_identity(ac, &comment, version); - key != NULL; - key = ssh_get_next_identity(ac, &comment, version)) { - had_identities = 1; - if (do_fp) { - fp = key_fingerprint(key, SSH_FP_MD5, - SSH_FP_HEX); - printf("%d %s %s (%s)\n", - key_size(key), fp, comment, key_type(key)); - xfree(fp); - } else { - if (!key_write(key, stdout)) - fprintf(stderr, - gettext("key_write failed")); - fprintf(stdout, " %s\n", comment); - } - key_free(key); - xfree(comment); - } - } - if (!had_identities) { - printf(gettext("The agent has no identities.\n")); - return -1; - } - return 0; -} - -static int -lock_agent(AuthenticationConnection *ac, int lock) -{ - char prompt[100], *p1, *p2; - int passok = 1, ret = -1; - - strlcpy(prompt, "Enter lock password: ", sizeof(prompt)); - p1 = read_passphrase(prompt, RP_ALLOW_STDIN); - if (lock) { - strlcpy(prompt, "Again: ", sizeof prompt); - p2 = read_passphrase(prompt, RP_ALLOW_STDIN); - if (strcmp(p1, p2) != 0) { - fprintf(stderr, gettext("Passwords do not match.\n")); - passok = 0; - } - memset(p2, 0, strlen(p2)); - xfree(p2); - } - if (passok && ssh_lock_agent(ac, lock, p1)) { - if (lock) - fprintf(stderr, gettext("Agent locked.\n")); - else - fprintf(stderr, gettext("Agent unlocked.\n")); - ret = 0; - } else { - if (lock) - fprintf(stderr, gettext("Failed to lock agent.\n")); - else - fprintf(stderr, gettext("Failed to unlock agent.\n")); - } - memset(p1, 0, strlen(p1)); - xfree(p1); - return (ret); -} - -static int -do_file(AuthenticationConnection *ac, int deleting, char *file) -{ - if (deleting) { - if (delete_file(ac, file) == -1) - return -1; - } else { - if (add_file(ac, file) == -1) - return -1; - } - return 0; -} - -static void -usage(void) -{ - fprintf(stderr, - gettext( "Usage: %s [options]\n" - "Options:\n" - " -l List fingerprints of all identities.\n" - " -L List public key parameters of all identities.\n" - " -d Delete identity.\n" - " -D Delete all identities.\n" - " -x Lock agent.\n" - " -X Unlock agent.\n" - " -t life Set lifetime (seconds) when adding identities.\n" - ), __progname); -} - -int -main(int argc, char **argv) -{ - extern char *optarg; - extern int optind; - AuthenticationConnection *ac = NULL; - int i, ch, deleting = 0, ret = 0; - - __progname = get_progname(argv[0]); - - (void) g11n_setlocale(LC_ALL, ""); - - init_rng(); - seed_rng(); - - SSLeay_add_all_algorithms(); - - /* At first, get a connection to the authentication agent. */ - ac = ssh_get_authentication_connection(); - if (ac == NULL) { - fprintf(stderr, gettext("Could not open a connection " - "to your authentication agent.\n")); - exit(2); - } - while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) { - switch (ch) { - case 'l': - case 'L': - if (list_identities(ac, ch == 'l' ? 1 : 0) == -1) - ret = 1; - goto done; - break; - case 'x': - case 'X': - if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1) - ret = 1; - goto done; - break; - case 'd': - deleting = 1; - break; - case 'D': - if (delete_all(ac) == -1) - ret = 1; - goto done; - break; - case 't': - if ((lifetime = convtime(optarg)) == -1) { - fprintf(stderr, gettext("Invalid lifetime\n")); - ret = 1; - goto done; - } - break; - default: - usage(); - ret = 1; - goto done; - } - } - argc -= optind; - argv += optind; - if (argc == 0) { - char buf[MAXPATHLEN]; - struct passwd *pw; - struct stat st; - int count = 0; - - if ((pw = getpwuid(getuid())) == NULL) { - fprintf(stderr, gettext("No user found with uid %u\n"), - (u_int)getuid()); - ret = 1; - goto done; - } - - for(i = 0; default_files[i]; i++) { - snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, - default_files[i]); - if (stat(buf, &st) < 0) - continue; - if (do_file(ac, deleting, buf) == -1) - ret = 1; - else - count++; - } - if (count == 0) - ret = 1; - } else { - for(i = 0; i < argc; i++) { - if (do_file(ac, deleting, argv[i]) == -1) - ret = 1; - } - } - clear_pass(); - -done: - ssh_close_authentication_connection(ac); - return ret; -} diff --git a/usr/src/cmd/ssh/ssh-agent/Makefile b/usr/src/cmd/ssh/ssh-agent/Makefile deleted file mode 100644 index 3d4a366c17..0000000000 --- a/usr/src/cmd/ssh/ssh-agent/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# 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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/ssh-agent/Makefile - -PROG= ssh-agent - -OBJS = \ - ssh-agent.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -install: all $(ROOTPROG) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/ssh-agent/ssh-agent.c b/usr/src/cmd/ssh/ssh-agent/ssh-agent.c deleted file mode 100644 index 1ac5f4030d..0000000000 --- a/usr/src/cmd/ssh/ssh-agent/ssh-agent.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * The authentication agent program. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#include "sys-queue.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.159 2008/06/28 14:05:15 djm Exp $"); - -#ifdef HAVE_SOLARIS_PRIVILEGE -#include <priv.h> -#endif /* HAVE_SOLARIS_PRIVILEGE */ - -#include <openssl/evp.h> -#include <openssl/md5.h> - -#include "ssh.h" -#include "rsa.h" -#include "buffer.h" -#include "bufaux.h" -#include "xmalloc.h" -#include "key.h" -#include "authfd.h" -#include "compat.h" -#include "log.h" -#include "readpass.h" -#include "misc.h" - -typedef enum { - AUTH_UNUSED, - AUTH_SOCKET, - AUTH_CONNECTION -} sock_type; - -typedef struct { - int fd; - sock_type type; - Buffer input; - Buffer output; - Buffer request; -} SocketEntry; - -u_int sockets_alloc = 0; -SocketEntry *sockets = NULL; - -typedef struct identity { - TAILQ_ENTRY(identity) next; - Key *key; - char *comment; - u_int death; - u_int confirm; -} Identity; - -typedef struct { - int nentries; - TAILQ_HEAD(idqueue, identity) idlist; -} Idtab; - -/* private key table, one per protocol version */ -Idtab idtable[3]; - -int max_fd = 0; - -/* pid of shell == parent of agent */ -pid_t parent_pid = -1; -u_int parent_alive_interval = 0; - -/* pathname and directory for AUTH_SOCKET */ -char socket_name[MAXPATHLEN]; -char socket_dir[MAXPATHLEN]; - -/* locking */ -int locked = 0; -char *lock_passwd = NULL; - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -/* Default lifetime (0 == forever) */ -static int lifetime = 0; - -static void -close_socket(SocketEntry *e) -{ - close(e->fd); - e->fd = -1; - e->type = AUTH_UNUSED; - buffer_free(&e->input); - buffer_free(&e->output); - buffer_free(&e->request); -} - -static void -idtab_init(void) -{ - int i; - - for (i = 0; i <=2; i++) { - TAILQ_INIT(&idtable[i].idlist); - idtable[i].nentries = 0; - } -} - -/* return private key table for requested protocol version */ -static Idtab * -idtab_lookup(int version) -{ - if (version < 1 || version > 2) - fatal("internal error, bad protocol version %d", version); - return &idtable[version]; -} - -static void -free_identity(Identity *id) -{ - key_free(id->key); - xfree(id->comment); - xfree(id); -} - -/* return matching private key for given public key */ -static Identity * -lookup_identity(Key *key, int version) -{ - Identity *id; - - Idtab *tab = idtab_lookup(version); - TAILQ_FOREACH(id, &tab->idlist, next) { - if (key_equal(key, id->key)) - return (id); - } - return (NULL); -} - -/* Check confirmation of keysign request */ -static int -confirm_key(Identity *id) -{ - char *p; - int ret = -1; - - p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); - if (ask_permission( - gettext("Allow use of key %s?\nKey fingerprint %s."), - id->comment, p)) - ret = 0; - xfree(p); - - return (ret); -} - -/* send list of supported public keys to 'client' */ -static void -process_request_identities(SocketEntry *e, int version) -{ - Idtab *tab = idtab_lookup(version); - Identity *id; - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, (version == 1) ? - SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); - buffer_put_int(&msg, tab->nentries); - TAILQ_FOREACH(id, &tab->idlist, next) { - if (id->key->type == KEY_RSA1) { - buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); - buffer_put_bignum(&msg, id->key->rsa->e); - buffer_put_bignum(&msg, id->key->rsa->n); - } else { - u_char *blob; - u_int blen; - key_to_blob(id->key, &blob, &blen); - buffer_put_string(&msg, blob, blen); - xfree(blob); - } - buffer_put_cstring(&msg, id->comment); - } - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); - buffer_free(&msg); -} - -/* ssh1 only */ -static void -process_authentication_challenge1(SocketEntry *e) -{ - u_char buf[32], mdbuf[16], session_id[16]; - u_int response_type; - BIGNUM *challenge; - Identity *id; - int i, len; - Buffer msg; - MD5_CTX md; - Key *key; - - buffer_init(&msg); - key = key_new(KEY_RSA1); - if ((challenge = BN_new()) == NULL) - fatal("process_authentication_challenge1: BN_new failed"); - - (void) buffer_get_int(&e->request); /* ignored */ - buffer_get_bignum(&e->request, key->rsa->e); - buffer_get_bignum(&e->request, key->rsa->n); - buffer_get_bignum(&e->request, challenge); - - /* Only protocol 1.1 is supported */ - if (buffer_len(&e->request) == 0) - goto failure; - buffer_get(&e->request, session_id, 16); - response_type = buffer_get_int(&e->request); - if (response_type != 1) - goto failure; - - id = lookup_identity(key, 1); - if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { - Key *private = id->key; - /* Decrypt the challenge using the private key. */ - if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) - goto failure; - - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > 32) { - log("process_authentication_challenge: bad challenge length %d", len); - goto failure; - } - memset(buf, 0, 32); - BN_bn2bin(challenge, buf + 32 - len); - MD5_Init(&md); - MD5_Update(&md, buf, 32); - MD5_Update(&md, session_id, 16); - MD5_Final(mdbuf, &md); - - /* Send the response. */ - buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); - for (i = 0; i < 16; i++) - buffer_put_char(&msg, mdbuf[i]); - goto send; - } - -failure: - /* Unknown identity or protocol error. Send failure. */ - buffer_put_char(&msg, SSH_AGENT_FAILURE); -send: - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); - key_free(key); - BN_clear_free(challenge); - buffer_free(&msg); -} - -/* ssh2 only */ -static void -process_sign_request2(SocketEntry *e) -{ - u_char *blob, *data, *signature = NULL; - u_int blen, dlen, slen = 0; - extern uint32_t datafellows; - int odatafellows; - int ok = -1, flags; - Buffer msg; - Key *key; - - datafellows = 0; - - blob = buffer_get_string(&e->request, &blen); - data = buffer_get_string(&e->request, &dlen); - - flags = buffer_get_int(&e->request); - odatafellows = datafellows; - if (flags & SSH_AGENT_OLD_SIGNATURE) - datafellows = SSH_BUG_SIGBLOB; - - key = key_from_blob(blob, blen); - if (key != NULL) { - Identity *id = lookup_identity(key, 2); - if (id != NULL && (!id->confirm || confirm_key(id) == 0)) - ok = key_sign(id->key, &signature, &slen, data, dlen); - key_free(key); - } - buffer_init(&msg); - if (ok == 0) { - buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); - buffer_put_string(&msg, signature, slen); - } else { - buffer_put_char(&msg, SSH_AGENT_FAILURE); - } - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), - buffer_len(&msg)); - buffer_free(&msg); - xfree(data); - xfree(blob); - if (signature != NULL) - xfree(signature); - datafellows = odatafellows; -} - -/* shared */ -static void -process_remove_identity(SocketEntry *e, int version) -{ - u_int blen, bits; - int success = 0; - Key *key = NULL; - u_char *blob; - - switch (version) { - case 1: - key = key_new(KEY_RSA1); - bits = buffer_get_int(&e->request); - buffer_get_bignum(&e->request, key->rsa->e); - buffer_get_bignum(&e->request, key->rsa->n); - - if (bits != key_size(key)) - log("Warning: identity keysize mismatch: actual %u, announced %u", - key_size(key), bits); - break; - case 2: - blob = buffer_get_string(&e->request, &blen); - key = key_from_blob(blob, blen); - xfree(blob); - break; - } - if (key != NULL) { - Identity *id = lookup_identity(key, version); - if (id != NULL) { - /* - * We have this key. Free the old key. Since we - * don't want to leave empty slots in the middle of - * the array, we actually free the key there and move - * all the entries between the empty slot and the end - * of the array. - */ - Idtab *tab = idtab_lookup(version); - if (tab->nentries < 1) - fatal("process_remove_identity: " - "internal error: tab->nentries %d", - tab->nentries); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - tab->nentries--; - success = 1; - } - key_free(key); - } - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); -} - -static void -process_remove_all_identities(SocketEntry *e, int version) -{ - Idtab *tab = idtab_lookup(version); - Identity *id; - - /* Loop over all identities and clear the keys. */ - for (id = TAILQ_FIRST(&tab->idlist); id; - id = TAILQ_FIRST(&tab->idlist)) { - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - } - - /* Mark that there are no identities. */ - tab->nentries = 0; - - /* Send success. */ - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, SSH_AGENT_SUCCESS); -} - -/* removes expired keys and returns number of seconds until the next expiry */ -static u_int -reaper(void) -{ - u_int deadline = 0, now = time(NULL); - Identity *id, *nxt; - int version; - Idtab *tab; - - for (version = 1; version < 3; version++) { - tab = idtab_lookup(version); - for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { - nxt = TAILQ_NEXT(id, next); - if (id->death == 0) - continue; - if (now >= id->death) { - debug("expiring key '%s'", id->comment); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - tab->nentries--; - } else - deadline = (deadline == 0) ? id->death : - MIN(deadline, id->death); - } - } - if (deadline == 0 || deadline <= now) - return 0; - else - return (deadline - now); -} - -static void -process_add_identity(SocketEntry *e, int version) -{ - Idtab *tab = idtab_lookup(version); - Identity *id; - int type, success = 0, death = 0, confirm = 0; - char *type_name, *comment; - Key *k = NULL; - - switch (version) { - case 1: - k = key_new_private(KEY_RSA1); - (void) buffer_get_int(&e->request); /* ignored */ - buffer_get_bignum(&e->request, k->rsa->n); - buffer_get_bignum(&e->request, k->rsa->e); - buffer_get_bignum(&e->request, k->rsa->d); - buffer_get_bignum(&e->request, k->rsa->iqmp); - - /* SSH and SSL have p and q swapped */ - buffer_get_bignum(&e->request, k->rsa->q); /* p */ - buffer_get_bignum(&e->request, k->rsa->p); /* q */ - - /* Generate additional parameters */ - rsa_generate_additional_parameters(k->rsa); - break; - case 2: - type_name = buffer_get_string(&e->request, NULL); - type = key_type_from_name(type_name); - xfree(type_name); - switch (type) { - case KEY_DSA: - k = key_new_private(type); - buffer_get_bignum2(&e->request, k->dsa->p); - buffer_get_bignum2(&e->request, k->dsa->q); - buffer_get_bignum2(&e->request, k->dsa->g); - buffer_get_bignum2(&e->request, k->dsa->pub_key); - buffer_get_bignum2(&e->request, k->dsa->priv_key); - break; - case KEY_RSA: - k = key_new_private(type); - buffer_get_bignum2(&e->request, k->rsa->n); - buffer_get_bignum2(&e->request, k->rsa->e); - buffer_get_bignum2(&e->request, k->rsa->d); - buffer_get_bignum2(&e->request, k->rsa->iqmp); - buffer_get_bignum2(&e->request, k->rsa->p); - buffer_get_bignum2(&e->request, k->rsa->q); - - /* Generate additional parameters */ - rsa_generate_additional_parameters(k->rsa); - break; - default: - buffer_clear(&e->request); - goto send; - } - break; - } - /* enable blinding */ - switch (k->type) { - case KEY_RSA: - case KEY_RSA1: - if (RSA_blinding_on(k->rsa, NULL) != 1) { - error("process_add_identity: RSA_blinding_on failed"); - key_free(k); - goto send; - } - break; - } - comment = buffer_get_string(&e->request, NULL); - if (k == NULL) { - xfree(comment); - goto send; - } - while (buffer_len(&e->request)) { - switch ((type = buffer_get_char(&e->request))) { - case SSH_AGENT_CONSTRAIN_LIFETIME: - death = time(NULL) + buffer_get_int(&e->request); - break; - case SSH_AGENT_CONSTRAIN_CONFIRM: - confirm = 1; - break; - default: - error("process_add_identity: " - "Unknown constraint type %d", type); - xfree(comment); - key_free(k); - goto send; - } - } - success = 1; - if (lifetime && !death) - death = time(NULL) + lifetime; - if ((id = lookup_identity(k, version)) == NULL) { - id = xmalloc(sizeof(Identity)); - id->key = k; - TAILQ_INSERT_TAIL(&tab->idlist, id, next); - /* Increment the number of identities. */ - tab->nentries++; - } else { - key_free(k); - xfree(id->comment); - } - id->comment = comment; - id->death = death; - id->confirm = confirm; -send: - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); -} - -/* XXX todo: encrypt sensitive data with passphrase */ -static void -process_lock_agent(SocketEntry *e, int lock) -{ - int success = 0; - char *passwd; - - passwd = buffer_get_string(&e->request, NULL); - if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { - locked = 0; - memset(lock_passwd, 0, strlen(lock_passwd)); - xfree(lock_passwd); - lock_passwd = NULL; - success = 1; - } else if (!locked && lock) { - locked = 1; - lock_passwd = xstrdup(passwd); - success = 1; - } - memset(passwd, 0, strlen(passwd)); - xfree(passwd); - - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); -} - -static void -no_identities(SocketEntry *e, u_int type) -{ - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, - (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? - SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); - buffer_put_int(&msg, 0); - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); - buffer_free(&msg); -} - -/* dispatch incoming messages */ - -static void -process_message(SocketEntry *e) -{ - u_int msg_len, type; - u_char *cp; - - if (buffer_len(&e->input) < 5) - return; /* Incomplete message. */ - cp = buffer_ptr(&e->input); - msg_len = get_u32(cp); - if (msg_len > 256 * 1024) { - close_socket(e); - return; - } - if (buffer_len(&e->input) < msg_len + 4) - return; - - /* move the current input to e->request */ - buffer_consume(&e->input, 4); - buffer_clear(&e->request); - buffer_append(&e->request, buffer_ptr(&e->input), msg_len); - buffer_consume(&e->input, msg_len); - type = buffer_get_char(&e->request); - - /* check wheter agent is locked */ - if (locked && type != SSH_AGENTC_UNLOCK) { - buffer_clear(&e->request); - switch (type) { - case SSH_AGENTC_REQUEST_RSA_IDENTITIES: - case SSH2_AGENTC_REQUEST_IDENTITIES: - /* send empty lists */ - no_identities(e, type); - break; - default: - /* send a fail message for all other request types */ - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, SSH_AGENT_FAILURE); - } - return; - } - - debug("type %d", type); - switch (type) { - case SSH_AGENTC_LOCK: - case SSH_AGENTC_UNLOCK: - process_lock_agent(e, type == SSH_AGENTC_LOCK); - break; - /* ssh1 */ - case SSH_AGENTC_RSA_CHALLENGE: - process_authentication_challenge1(e); - break; - case SSH_AGENTC_REQUEST_RSA_IDENTITIES: - process_request_identities(e, 1); - break; - case SSH_AGENTC_ADD_RSA_IDENTITY: - case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED: - process_add_identity(e, 1); - break; - case SSH_AGENTC_REMOVE_RSA_IDENTITY: - process_remove_identity(e, 1); - break; - case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: - process_remove_all_identities(e, 1); - break; - /* ssh2 */ - case SSH2_AGENTC_SIGN_REQUEST: - process_sign_request2(e); - break; - case SSH2_AGENTC_REQUEST_IDENTITIES: - process_request_identities(e, 2); - break; - case SSH2_AGENTC_ADD_IDENTITY: - case SSH2_AGENTC_ADD_ID_CONSTRAINED: - process_add_identity(e, 2); - break; - case SSH2_AGENTC_REMOVE_IDENTITY: - process_remove_identity(e, 2); - break; - case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: - process_remove_all_identities(e, 2); - break; - default: - /* Unknown message. Respond with failure. */ - error("Unknown message %d", type); - buffer_clear(&e->request); - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, SSH_AGENT_FAILURE); - break; - } -} - -static void -new_socket(sock_type type, int fd) -{ - u_int i, old_alloc, new_alloc; - - set_nonblock(fd); - - if (fd > max_fd) - max_fd = fd; - - for (i = 0; i < sockets_alloc; i++) - if (sockets[i].type == AUTH_UNUSED) { - sockets[i].fd = fd; - buffer_init(&sockets[i].input); - buffer_init(&sockets[i].output); - buffer_init(&sockets[i].request); - sockets[i].type = type; - return; - } - old_alloc = sockets_alloc; - new_alloc = sockets_alloc + 10; - sockets = xrealloc(sockets, new_alloc * sizeof(sockets[0])); - for (i = old_alloc; i < new_alloc; i++) - sockets[i].type = AUTH_UNUSED; - sockets_alloc = new_alloc; - sockets[old_alloc].fd = fd; - buffer_init(&sockets[old_alloc].input); - buffer_init(&sockets[old_alloc].output); - buffer_init(&sockets[old_alloc].request); - sockets[old_alloc].type = type; -} - -static int -prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, - struct timeval **tvpp) -{ - u_int i, sz, deadline; - int n = 0; - static struct timeval tv; - - for (i = 0; i < sockets_alloc; i++) { - switch (sockets[i].type) { - case AUTH_SOCKET: - case AUTH_CONNECTION: - n = MAX(n, sockets[i].fd); - break; - case AUTH_UNUSED: - break; - default: - fatal("Unknown socket type %d", sockets[i].type); - break; - } - } - - sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); - if (*fdrp == NULL || sz > *nallocp) { - if (*fdrp) - xfree(*fdrp); - if (*fdwp) - xfree(*fdwp); - *fdrp = xmalloc(sz); - *fdwp = xmalloc(sz); - *nallocp = sz; - } - if (n < *fdl) - debug("XXX shrink: %d < %d", n, *fdl); - *fdl = n; - memset(*fdrp, 0, sz); - memset(*fdwp, 0, sz); - - for (i = 0; i < sockets_alloc; i++) { - switch (sockets[i].type) { - case AUTH_SOCKET: - case AUTH_CONNECTION: - FD_SET(sockets[i].fd, *fdrp); - if (buffer_len(&sockets[i].output) > 0) - FD_SET(sockets[i].fd, *fdwp); - break; - default: - break; - } - } - deadline = reaper(); - if (parent_alive_interval != 0) - deadline = (deadline == 0) ? parent_alive_interval : - MIN(deadline, parent_alive_interval); - if (deadline == 0) { - *tvpp = NULL; - } else { - tv.tv_sec = deadline; - tv.tv_usec = 0; - *tvpp = &tv; - } - return (1); -} - -static void -after_select(fd_set *readset, fd_set *writeset) -{ - struct sockaddr_un sunaddr; - socklen_t slen; - char buf[1024]; - int len, sock; - u_int i; - uid_t euid; - gid_t egid; - - for (i = 0; i < sockets_alloc; i++) - switch (sockets[i].type) { - case AUTH_UNUSED: - break; - case AUTH_SOCKET: - if (FD_ISSET(sockets[i].fd, readset)) { - slen = sizeof(sunaddr); - sock = accept(sockets[i].fd, - (struct sockaddr *)&sunaddr, &slen); - if (sock < 0) { - error("accept from AUTH_SOCKET: %s", - strerror(errno)); - break; - } - if (getpeereid(sock, &euid, &egid) < 0) { - error("getpeereid %d failed: %s", - sock, strerror(errno)); - close(sock); - break; - } - if ((euid != 0) && (getuid() != euid)) { - error("uid mismatch: " - "peer euid %u != uid %u", - (u_int) euid, (u_int) getuid()); - close(sock); - break; - } - new_socket(AUTH_CONNECTION, sock); - } - break; - case AUTH_CONNECTION: - if (buffer_len(&sockets[i].output) > 0 && - FD_ISSET(sockets[i].fd, writeset)) { - do { - len = write(sockets[i].fd, - buffer_ptr(&sockets[i].output), - buffer_len(&sockets[i].output)); - if (len == -1 && (errno == EAGAIN || - errno == EINTR || - errno == EWOULDBLOCK)) - continue; - break; - } while (1); - if (len <= 0) { - close_socket(&sockets[i]); - break; - } - buffer_consume(&sockets[i].output, len); - } - if (FD_ISSET(sockets[i].fd, readset)) { - do { - len = read(sockets[i].fd, buf, sizeof(buf)); - if (len == -1 && (errno == EAGAIN || - errno == EINTR || - errno == EWOULDBLOCK)) - continue; - break; - } while (1); - if (len <= 0) { - close_socket(&sockets[i]); - break; - } - buffer_append(&sockets[i].input, buf, len); - process_message(&sockets[i]); - } - break; - default: - fatal("Unknown type %d", sockets[i].type); - } -} - -static void -cleanup_socket(void) -{ - if (socket_name[0]) - unlink(socket_name); - if (socket_dir[0]) - rmdir(socket_dir); -} - -void -cleanup_exit(int i) -{ - cleanup_socket(); - _exit(i); -} - -/*ARGSUSED*/ -static void -cleanup_handler(int sig) -{ - cleanup_socket(); - _exit(2); -} - -static void -check_parent_exists(void) -{ -#ifdef HAVE_SOLARIS_PRIVILEGE - /* - * We can not simply use "kill(ppid, 0) < 0" to detect if the parent - * has exited when the child process no longer has the - * PRIV_PROC_SESSION privilege. - */ - if (parent_pid != -1 && getppid() != parent_pid) { -#else - if (parent_pid != -1 && kill(parent_pid, 0) < 0) { - -#endif - /* printf("Parent has died - Authentication agent exiting.\n"); */ - cleanup_socket(); - _exit(2); - } -} - -static void -usage(void) -{ - fprintf(stderr, - gettext("Usage: %s [options] [command [args ...]]\n" - "Options:\n" - " -c Generate C-shell commands on stdout.\n" - " -s Generate Bourne shell commands on stdout.\n" - " -k Kill the current agent.\n" - " -d Debug mode.\n" - " -a socket Bind agent socket to given name.\n" - " -t life Default identity lifetime (seconds).\n"), - __progname); - exit(1); -} - -int -main(int ac, char **av) -{ - int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; - int sock, fd, ch, result, saved_errno; - u_int nalloc; - char *shell, *pidstr, *agentsocket = NULL; - const char *format; - fd_set *readsetp = NULL, *writesetp = NULL; - struct sockaddr_un sunaddr; -#ifdef HAVE_SETRLIMIT - struct rlimit rlim; -#endif - int prev_mask; - extern int optind; - extern char *optarg; - pid_t pid; - char pidstrbuf[1 + 3 * sizeof pid]; - struct timeval *tvp = NULL; -#ifdef HAVE_SOLARIS_PRIVILEGE - priv_set_t *myprivs; -#endif /* HAVE_SOLARIS_PRIVILEGE */ - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); - - /* drop */ - setegid(getgid()); - setgid(getgid()); - - SSLeay_add_all_algorithms(); - - __progname = get_progname(av[0]); - init_rng(); - seed_rng(); - - while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { - switch (ch) { - case 'c': - if (s_flag) - usage(); - c_flag++; - break; - case 'k': - k_flag++; - break; - case 's': - if (c_flag) - usage(); - s_flag++; - break; - case 'd': - if (d_flag) - usage(); - d_flag++; - break; - case 'a': - agentsocket = optarg; - break; - case 't': - if ((lifetime = convtime(optarg)) == -1) { - fprintf(stderr, gettext("Invalid lifetime\n")); - usage(); - } - break; - default: - usage(); - } - } - ac -= optind; - av += optind; - - if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) - usage(); - - if (ac == 0 && !c_flag && !s_flag) { - shell = getenv("SHELL"); - if (shell != NULL && - strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) - c_flag = 1; - } - if (k_flag) { - pidstr = getenv(SSH_AGENTPID_ENV_NAME); - if (pidstr == NULL) { - fprintf(stderr, - gettext("%s not set, cannot kill agent\n"), - SSH_AGENTPID_ENV_NAME); - exit(1); - } - pid = atoi(pidstr); - if (pid < 1) { - fprintf(stderr, - gettext("%s not set, cannot kill agent\n"), - SSH_AGENTPID_ENV_NAME); - exit(1); - } - if (kill(pid, SIGTERM) == -1) { - perror("kill"); - exit(1); - } - format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; - printf(format, SSH_AUTHSOCKET_ENV_NAME); - printf(format, SSH_AGENTPID_ENV_NAME); - printf("echo "); - printf(gettext("Agent pid %ld killed;\n"), (long)pid); - exit(0); - } - parent_pid = getpid(); - - if (agentsocket == NULL) { - /* Create private directory for agent socket */ - strlcpy(socket_dir, "/tmp/ssh-XXXXXXXXXX", sizeof socket_dir); - if (mkdtemp(socket_dir) == NULL) { - perror("mkdtemp: private socket dir"); - exit(1); - } - snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, - (long)parent_pid); - } else { - /* Try to use specified agent socket */ - socket_dir[0] = '\0'; - strlcpy(socket_name, agentsocket, sizeof socket_name); - } - - /* - * Create socket early so it will exist before command gets run from - * the parent. - */ - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("socket"); - *socket_name = '\0'; /* Don't unlink any existing file */ - cleanup_exit(1); - } - memset(&sunaddr, 0, sizeof(sunaddr)); - sunaddr.sun_family = AF_UNIX; - strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); - prev_mask = umask(0177); - if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { - perror("bind"); - *socket_name = '\0'; /* Don't unlink any existing file */ - umask(prev_mask); - cleanup_exit(1); - } - umask(prev_mask); - if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { - perror("listen"); - cleanup_exit(1); - } - - /* - * Fork, and have the parent execute the command, if any, or present - * the socket data. The child continues as the authentication agent. - */ - if (d_flag) { - log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); - format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; - printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, - SSH_AUTHSOCKET_ENV_NAME); - printf("echo "); - printf(gettext("Agent pid %ld;\n"), (long)parent_pid); - goto skip; - } - pid = fork(); - if (pid == -1) { - perror("fork"); - cleanup_exit(1); - } - if (pid != 0) { /* Parent - execute the given command. */ - close(sock); - snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); - if (ac == 0) { - format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; - printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, - SSH_AUTHSOCKET_ENV_NAME); - printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, - SSH_AGENTPID_ENV_NAME); - printf("echo "); - printf(gettext("Agent pid %ld;\n"), (long)pid); - exit(0); - } - if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || - setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { - perror("setenv"); - exit(1); - } - execvp(av[0], av); - perror(av[0]); - exit(1); - } - /* child */ - log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); - -#ifdef HAVE_SOLARIS_PRIVILEGE - /* - * Drop unneeded privs, including basic ones like fork/exec. - * - * Idiom: remove from 'basic' privs we know we don't want, - * invert the result and remove the resulting set from P. - * - * None of the priv_delset() calls below, nor the setppriv call - * below can fail, so their return values are not checked. - */ - if ((myprivs = priv_str_to_set("basic", ",", NULL)) == NULL) - fatal("priv_str_to_set failed: %m"); - (void) priv_delset(myprivs, PRIV_PROC_EXEC); - (void) priv_delset(myprivs, PRIV_PROC_FORK); - (void) priv_delset(myprivs, PRIV_FILE_LINK_ANY); - (void) priv_delset(myprivs, PRIV_PROC_INFO); - (void) priv_delset(myprivs, PRIV_PROC_SESSION); - priv_inverse(myprivs); - (void) setppriv(PRIV_OFF, PRIV_PERMITTED, myprivs); - (void) priv_freeset(myprivs); -#endif /* HAVE_SOLARIS_PRIVILEGE */ - - if (setsid() == -1) { - error("setsid: %s", strerror(errno)); - cleanup_exit(1); - } - - (void)chdir("/"); - if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { - /* XXX might close listen socket */ - (void)dup2(fd, STDIN_FILENO); - (void)dup2(fd, STDOUT_FILENO); - (void)dup2(fd, STDERR_FILENO); - if (fd > 2) - close(fd); - } - -#ifdef HAVE_SETRLIMIT - /* deny core dumps, since memory contains unencrypted private keys */ - rlim.rlim_cur = rlim.rlim_max = 0; - if (setrlimit(RLIMIT_CORE, &rlim) < 0) { - error("setrlimit RLIMIT_CORE: %s", strerror(errno)); - cleanup_exit(1); - } -#endif - -skip: - new_socket(AUTH_SOCKET, sock); - if (ac > 0) - parent_alive_interval = 10; - idtab_init(); - if (!d_flag) - signal(SIGINT, SIG_IGN); - signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, cleanup_handler); - signal(SIGTERM, cleanup_handler); - nalloc = 0; - - while (1) { - prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); - result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); - saved_errno = errno; - if (parent_alive_interval != 0) - check_parent_exists(); - (void) reaper(); /* remove expired keys */ - if (result < 0) { - if (saved_errno == EINTR) - continue; - fatal("select: %s", strerror(saved_errno)); - } else if (result > 0) - after_select(readsetp, writesetp); - } - /* NOTREACHED */ - return (0); /* keep lint happy */ -} diff --git a/usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c b/usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c deleted file mode 100644 index 33182730ae..0000000000 --- a/usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (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 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * An http client that let's users 'ssh' to the - * outside of the firewall by opening up a connection - * through the http proxy. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <netdb.h> -#include <strings.h> -#include <unistd.h> -#include <inttypes.h> -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <locale.h> -#include <libintl.h> -#include <netinet/in.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <sys/time.h> -#include <sys/stropts.h> -#include <sys/stat.h> -#include <sys/varargs.h> -#include "proxy-io.h" - -#define DEFAULT_HTTPPROXYPORT "80" -#define CONNECT_STRLEN 256 - -static int debug_flag = 0; - -static void -usage(void) -{ - (void) fprintf(stderr, gettext("Usage: ssh-http-proxy-connect " - "[-h http_proxy_host] [-p http_proxy_port]\n" - "remote_host remote_port\n")); - exit(1); -} - -/* PRINTFLIKE1 */ -static void -debug(const char *format, ...) -{ - char fmtbuf[BUFFER_SIZ]; - va_list args; - - if (debug_flag == 0) { - return; - } - va_start(args, format); - (void) snprintf(fmtbuf, sizeof (fmtbuf), - "ssh-http-proxy: %s\n", format); - (void) vfprintf(stderr, fmtbuf, args); - va_end(args); -} - -static void -signal_handler(int sig) -{ - exit(0); -} - -int -main(int argc, char **argv) -{ - extern char *optarg; - extern int optind; - int retval, err_code, sock, ssh_port; - int version, ret_code; - char *httpproxy = NULL; - char *temp, *httpproxyport = NULL; - char *ssh_host; - char connect_str[CONNECT_STRLEN], connect_reply[BUFFER_SIZ]; - char *ret_string; - struct addrinfo hints, *ai; - struct pollfd fds[2]; - - /* Initialization for variables, set locale and textdomain */ - - (void) setlocale(LC_ALL, ""); - -#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ -#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ -#endif - (void) textdomain(TEXT_DOMAIN); - - /* Set up the signal handler */ - (void) signal(SIGINT, signal_handler); - (void) signal(SIGPIPE, signal_handler); - (void) signal(SIGPOLL, signal_handler); - - while ((retval = getopt(argc, argv, "dp:h:")) != -1) { - switch (retval) { - case 'h': - httpproxy = optarg; - break; - case 'p': - httpproxyport = optarg; - break; - case 'd': - debug_flag = 1; - break; - default: - break; - } - } - - if (optind != argc - 2) { - usage(); - } - - ssh_host = argv[optind++]; - ssh_port = atoi(argv[optind]); - - /* - * If the name of the http proxy were not - * passed on the command line, try the - * user's environment. First try HTTPPROXY. - * If it's not set, try http_proxy. - * Check the url specified for http_proxy - * for errors. - */ - if (httpproxy == NULL) { - if ((httpproxy = getenv("HTTPPROXY")) == NULL) { - /* Try the other environment variable http_proxy */ - if ((temp = getenv("http_proxy")) != NULL) { - temp += strlen("http://"); - if (strpbrk(temp, ":") == NULL) { - /* Malformed url */ - (void) fprintf(stderr, gettext("ssh-http-proxy: " - "Incorrect url specified for http_proxy " - "environment variable\n")); - exit(1); - } - httpproxy = strtok(temp, ":"); - httpproxyport = strtok(NULL, "/"); - } else { - (void) fprintf(stderr, - gettext("ssh-http-proxy: http proxy not specified\n")); - exit(1); - } - } - } - - /* - * Extract the proxy port number from the user's environment. - * Ignored if HTTPPROXY is not set. - */ - if ((httpproxy != NULL) && (httpproxyport == NULL)) { - if ((httpproxyport = getenv("HTTPPROXYPORT")) == NULL) { - httpproxyport = DEFAULT_HTTPPROXYPORT; - } - } - - debug("HTTPPROXY = %s", httpproxy); - debug("HTTPPROXYPORT = %s", httpproxyport); - - bzero(&hints, sizeof (struct addrinfo)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - if ((err_code = getaddrinfo(httpproxy, httpproxyport, &hints, &ai)) - != 0) { - (void) fprintf(stderr, "ssh-http-proxy: Unable to " - "perform name lookup\n"); - (void) fprintf(stderr, "%s: %s\n", httpproxy, - gai_strerror(err_code)); - exit(1); - } - - if ((sock = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) { - perror("socket"); - exit(1); - } - - /* Connect to the http proxy */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { - (void) fprintf(stderr, gettext("ssh-http-proxy: Unable to connect" - " to %s: %s\n"), httpproxy, strerror(errno)); - (void) close(sock); - exit(1); - } else { - /* Successful connection. */ - (void) snprintf(connect_str, sizeof (connect_str), - "CONNECT %s:%d HTTP/1.1\r\n\r\n", ssh_host, ssh_port); - if (write(sock, &connect_str, strlen(connect_str)) < 0) { - perror("write"); - (void) close(sock); - exit(1); - } - - if (read(sock, connect_reply, sizeof (connect_reply)) == -1) { - perror("read"); - (void) close(sock); - exit(1); - } - - if (sscanf(connect_reply, "HTTP/1.%d %d", - &version, &ret_code) != 2) { - (void) fprintf(stderr, - gettext("ssh-http-proxy: HTTP reply not understood\n")); - (void) close(sock); - exit(1); - } - - ret_string = strtok(connect_reply, "\n"); - - /* If the return error code is not 200, print an error and quit. */ - if (ret_code != 200) { - (void) fprintf(stderr, "%s\n", ret_string); - (void) close(sock); - exit(1); - } else { - debug("%s", ret_string); - } - } - - fds[0].fd = STDIN_FILENO; /* Poll stdin for data. */ - fds[1].fd = sock; /* Poll the socket for data. */ - fds[0].events = fds[1].events = POLLIN; - - for (;;) { - if (poll(fds, 2, INFTIM) == -1) { - perror("poll"); - (void) close(sock); - exit(1); - } - - /* Data arrived on stdin, write it to the socket */ - if (fds[0].revents & POLLIN) { - if (proxy_read_write_loop(STDIN_FILENO, sock) == 0) { - (void) close(sock); - exit(1); - } - } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - (void) close(sock); - exit(1); - } - - /* Data arrived on the socket, write it to stdout */ - if (fds[1].revents & POLLIN) { - if (proxy_read_write_loop(sock, STDOUT_FILENO) == 0) { - (void) close(sock); - exit(1); - } - } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { - (void) close(sock); - exit(1); - } - } - - /* NOTREACHED */ - return (0); -} diff --git a/usr/src/cmd/ssh/ssh-keygen/Makefile b/usr/src/cmd/ssh/ssh-keygen/Makefile deleted file mode 100644 index f92c437045..0000000000 --- a/usr/src/cmd/ssh/ssh-keygen/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# 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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/ssh-keygen/Makefile - -PROG= ssh-keygen - -OBJS = \ - ssh-keygen.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lcrypto -lsocket - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -install: all $(ROOTPROG) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c b/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c deleted file mode 100644 index ebad79b0f8..0000000000 --- a/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c +++ /dev/null @@ -1,1208 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Identity and host key generation and maintenance. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* $OpenBSD: ssh-keygen.c,v 1.160 2007/01/21 01:41:54 stevesk Exp $ */ - -#include "includes.h" -#include <openssl/evp.h> -#include <openssl/pem.h> - -#include "xmalloc.h" -#include "key.h" -#include "rsa.h" -#include "authfile.h" -#include "uuencode.h" -#include "buffer.h" -#include "bufaux.h" -#include "pathnames.h" -#include "log.h" -#include "readpass.h" -#include "misc.h" -#include <langinfo.h> -#include "match.h" -#include "hostfile.h" -#include "tildexpand.h" - -/* Number of bits in the RSA/DSA key. This value can be set on the command line. */ -#define DEFAULT_BITS_RSA 2048 -#define DEFAULT_BITS_DSA 1024 -u_int32_t bits = 0; - -/* - * Flag indicating that we just want to change the passphrase. This can be - * set on the command line. - */ -int change_passphrase = 0; - -/* - * Flag indicating that we just want to change the comment. This can be set - * on the command line. - */ -int change_comment = 0; - -int quiet = 0; - -/* Flag indicating that we want to hash a known_hosts file */ -int hash_hosts = 0; -/* Flag indicating that we want to lookup a host in known_hosts file */ -int find_host = 0; -/* Flag indicating that we want to delete a host from a known_hosts file */ -int delete_host = 0; - -/* Flag indicating that we just want to see the key fingerprint */ -int print_fingerprint = 0; -int print_bubblebabble = 0; - -/* The identity file name, given on the command line or entered by the user. */ -char identity_file[1024]; -int have_identity = 0; - -/* This is set to the passphrase if given on the command line. */ -char *identity_passphrase = NULL; - -/* This is set to the new passphrase if given on the command line. */ -char *identity_new_passphrase = NULL; - -/* This is set to the new comment if given on the command line. */ -char *identity_comment = NULL; - -/* Dump public key file in format used by real and the original SSH 2 */ -int convert_to_ssh2 = 0; -int convert_from_ssh2 = 0; -int print_public = 0; - -char *key_type_name = NULL; - -/* argv0 */ -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -char hostname[MAXHOSTNAMELEN]; - -static void -ask_filename(struct passwd *pw, const char *prompt) -{ - char buf[1024]; - char *name = NULL; - - if (key_type_name == NULL) - name = _PATH_SSH_CLIENT_ID_RSA; - else { - switch (key_type_from_name(key_type_name)) { - case KEY_RSA1: - name = _PATH_SSH_CLIENT_IDENTITY; - break; - case KEY_DSA: - name = _PATH_SSH_CLIENT_ID_DSA; - break; - case KEY_RSA: - name = _PATH_SSH_CLIENT_ID_RSA; - break; - default: - fprintf(stderr, gettext("bad key type")); - exit(1); - break; - } - } - snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); - fprintf(stderr, "%s (%s): ", gettext(prompt), identity_file); - if (fgets(buf, sizeof(buf), stdin) == NULL) - exit(1); - if (strchr(buf, '\n')) - *strchr(buf, '\n') = 0; - if (strcmp(buf, "") != 0) - strlcpy(identity_file, buf, sizeof(identity_file)); - have_identity = 1; -} - -static Key * -load_identity(char *filename) -{ - char *pass; - Key *prv; - - prv = key_load_private(filename, "", NULL); - if (prv == NULL) { - if (identity_passphrase) - pass = xstrdup(identity_passphrase); - else - pass = read_passphrase(gettext("Enter passphrase: "), - RP_ALLOW_STDIN); - prv = key_load_private(filename, pass, NULL); - memset(pass, 0, strlen(pass)); - xfree(pass); - } - return prv; -} - -#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----" -#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----" -#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" -#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb - -static void -do_convert_to_ssh2(struct passwd *pw) -{ - Key *k; - u_int len; - u_char *blob; - struct stat st; - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - if ((k = key_load_public(identity_file, NULL)) == NULL) { - if ((k = load_identity(identity_file)) == NULL) { - fprintf(stderr, gettext("load failed\n")); - exit(1); - } - } - if (key_to_blob(k, &blob, &len) <= 0) { - fprintf(stderr, gettext("key_to_blob failed\n")); - exit(1); - } - fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); - fprintf(stdout, gettext( - "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n"), - key_size(k), key_type(k), - pw->pw_name, hostname); - dump_base64(stdout, blob, len); - fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); - key_free(k); - xfree(blob); - exit(0); -} - -static void -buffer_get_bignum_bits(Buffer *b, BIGNUM *value) -{ - u_int bignum_bits = buffer_get_int(b); - u_int bytes = (bignum_bits + 7) / 8; - - if (buffer_len(b) < bytes) - fatal("buffer_get_bignum_bits: input buffer too small: " - "need %d have %d", bytes, buffer_len(b)); - if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL) - fatal("buffer_get_bignum_bits: BN_bin2bn failed"); - buffer_consume(b, bytes); -} - -static Key * -do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) -{ - Buffer b; - Key *key = NULL; - char *type, *cipher; - u_char *sig, data[] = "abcde12345"; - int magic, rlen, ktype, i1, i2, i3, i4; - u_int slen; - u_long e; - - buffer_init(&b); - buffer_append(&b, blob, blen); - - magic = buffer_get_int(&b); - if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { - error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); - buffer_free(&b); - return NULL; - } - i1 = buffer_get_int(&b); - type = buffer_get_string(&b, NULL); - cipher = buffer_get_string(&b, NULL); - i2 = buffer_get_int(&b); - i3 = buffer_get_int(&b); - i4 = buffer_get_int(&b); - debug("ignore (%d %d %d %d)", i1, i2, i3, i4); - if (strcmp(cipher, "none") != 0) { - error("unsupported cipher %s", cipher); - xfree(cipher); - buffer_free(&b); - xfree(type); - return NULL; - } - xfree(cipher); - - if (strstr(type, "dsa")) { - ktype = KEY_DSA; - } else if (strstr(type, "rsa")) { - ktype = KEY_RSA; - } else { - buffer_free(&b); - xfree(type); - return NULL; - } - key = key_new_private(ktype); - xfree(type); - - switch (key->type) { - case KEY_DSA: - buffer_get_bignum_bits(&b, key->dsa->p); - buffer_get_bignum_bits(&b, key->dsa->g); - buffer_get_bignum_bits(&b, key->dsa->q); - buffer_get_bignum_bits(&b, key->dsa->pub_key); - buffer_get_bignum_bits(&b, key->dsa->priv_key); - break; - case KEY_RSA: - e = buffer_get_char(&b); - debug("e %lx", e); - if (e < 30) { - e <<= 8; - e += buffer_get_char(&b); - debug("e %lx", e); - e <<= 8; - e += buffer_get_char(&b); - debug("e %lx", e); - } - if (!BN_set_word(key->rsa->e, e)) { - buffer_free(&b); - key_free(key); - return NULL; - } - buffer_get_bignum_bits(&b, key->rsa->d); - buffer_get_bignum_bits(&b, key->rsa->n); - buffer_get_bignum_bits(&b, key->rsa->iqmp); - buffer_get_bignum_bits(&b, key->rsa->q); - buffer_get_bignum_bits(&b, key->rsa->p); - rsa_generate_additional_parameters(key->rsa); - break; - } - rlen = buffer_len(&b); - if (rlen != 0) - error("do_convert_private_ssh2_from_blob: " - "remaining bytes in key blob %d", rlen); - buffer_free(&b); - - /* try the key */ - key_sign(key, &sig, &slen, data, sizeof(data)); - key_verify(key, sig, slen, data, sizeof(data)); - xfree(sig); - return key; -} - -static int -get_line(FILE *fp, char *line, size_t len) -{ - int c; - size_t pos = 0; - - line[0] = '\0'; - while ((c = fgetc(fp)) != EOF) { - if (pos >= len - 1) { - fprintf(stderr, "input line too long.\n"); - exit(1); - } - switch (c) { - case '\r': - c = fgetc(fp); - if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) { - fprintf(stderr, "unget: %s\n", strerror(errno)); - exit(1); - } - return pos; - case '\n': - return pos; - } - line[pos++] = c; - line[pos] = '\0'; - } - /* We reached EOF */ - return -1; -} - -static void -do_convert_from_ssh2(struct passwd *pw) -{ - Key *k; - int blen; - u_int len; - char line[1024]; - u_char blob[8096]; - char encoded[8096]; - struct stat st; - int escaped = 0, private = 0, ok; - FILE *fp; - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - fp = fopen(identity_file, "r"); - if (fp == NULL) { - perror(identity_file); - exit(1); - } - encoded[0] = '\0'; - while ((blen = get_line(fp, line, sizeof(line))) != -1) { - if (line[blen - 1] == '\\') - escaped++; - if (strncmp(line, "----", 4) == 0 || - strstr(line, ": ") != NULL) { - if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) - private = 1; - if (strstr(line, " END ") != NULL) { - break; - } - /* fprintf(stderr, "ignore: %s", line); */ - continue; - } - if (escaped) { - escaped--; - /* fprintf(stderr, "escaped: %s", line); */ - continue; - } - strlcat(encoded, line, sizeof(encoded)); - } - len = strlen(encoded); - if (((len % 4) == 3) && - (encoded[len-1] == '=') && - (encoded[len-2] == '=') && - (encoded[len-3] == '=')) - encoded[len-3] = '\0'; - blen = uudecode(encoded, blob, sizeof(blob)); - if (blen < 0) { - fprintf(stderr, gettext("uudecode failed.\n")); - exit(1); - } - k = private ? - do_convert_private_ssh2_from_blob(blob, blen) : - key_from_blob(blob, blen); - if (k == NULL) { - fprintf(stderr, gettext("decode blob failed.\n")); - exit(1); - } - ok = private ? - (k->type == KEY_DSA ? - PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : - PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : - key_write(k, stdout); - if (!ok) { - fprintf(stderr, gettext("key write failed")); - exit(1); - } - key_free(k); - if (!private) - fprintf(stdout, "\n"); - fclose(fp); - exit(0); -} - -static void -do_print_public(struct passwd *pw) -{ - Key *prv; - struct stat st; - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - prv = load_identity(identity_file); - if (prv == NULL) { - fprintf(stderr, gettext("load failed\n")); - exit(1); - } - if (!key_write(prv, stdout)) - fprintf(stderr, gettext("key_write failed")); - key_free(prv); - fprintf(stdout, "\n"); - exit(0); -} - -static void -do_fingerprint(struct passwd *pw) -{ - FILE *f; - Key *public; - char *comment = NULL, *cp, *ep, line[16*1024], *fp; - int i, skip = 0, num = 1, invalid = 1; - enum fp_rep rep; - enum fp_type fptype; - struct stat st; - - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - public = key_load_public(identity_file, &comment); - if (public != NULL) { - fp = key_fingerprint(public, fptype, rep); - printf("%u %s %s\n", key_size(public), fp, comment); - key_free(public); - xfree(comment); - xfree(fp); - exit(0); - } - if (comment) { - xfree(comment); - comment = NULL; - } - - f = fopen(identity_file, "r"); - if (f != NULL) { - while (fgets(line, sizeof(line), f)) { - i = strlen(line) - 1; - if (line[i] != '\n') { - error("line %d too long: %.40s...", num, line); - skip = 1; - continue; - } - num++; - if (skip) { - skip = 0; - continue; - } - line[i] = '\0'; - - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; - i = strtol(cp, &ep, 10); - if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { - int quoted = 0; - comment = cp; - for (; *cp && (quoted || (*cp != ' ' && - *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - if (!*cp) - continue; - *cp++ = '\0'; - } - ep = cp; - public = key_new(KEY_RSA1); - if (key_read(public, &cp) != 1) { - cp = ep; - key_free(public); - public = key_new(KEY_UNSPEC); - if (key_read(public, &cp) != 1) { - key_free(public); - continue; - } - } - comment = *cp ? cp : comment; - fp = key_fingerprint(public, fptype, rep); - printf("%u %s %s\n", key_size(public), fp, - comment ? comment : gettext("no comment")); - xfree(fp); - key_free(public); - invalid = 0; - } - fclose(f); - } - if (invalid) { - printf(gettext("%s is not a public key file.\n"), - identity_file); - exit(1); - } - exit(0); -} - -static void -print_host(FILE *f, const char *name, Key *public, int hash) -{ - if (hash && (name = host_hash(name, NULL, 0)) == NULL) - fatal("hash_host failed"); - fprintf(f, "%s ", name); - if (!key_write(public, f)) - fatal("key_write failed"); - fprintf(f, "\n"); -} - -static void -do_known_hosts(struct passwd *pw, const char *name) -{ - FILE *in, *out = stdout; - Key *public; - char *cp, *cp2, *kp, *kp2; - char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; - int c, i, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; - - if (!have_identity) { - cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); - if (strlcpy(identity_file, cp, sizeof(identity_file)) >= - sizeof(identity_file)) - fatal("Specified known hosts path too long"); - xfree(cp); - have_identity = 1; - } - if ((in = fopen(identity_file, "r")) == NULL) - fatal("fopen: %s", strerror(errno)); - - /* - * Find hosts goes to stdout, hash and deletions happen in-place - * A corner case is ssh-keygen -HF foo, which should go to stdout - */ - if (!find_host && (hash_hosts || delete_host)) { - if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) || - strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) || - strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) || - strlcat(old, ".old", sizeof(old)) >= sizeof(old)) - fatal("known_hosts path too long"); - umask(077); - if ((c = mkstemp(tmp)) == -1) - fatal("mkstemp: %s", strerror(errno)); - if ((out = fdopen(c, "w")) == NULL) { - c = errno; - unlink(tmp); - fatal("fdopen: %s", strerror(c)); - } - inplace = 1; - } - - while (fgets(line, sizeof(line), in)) { - num++; - i = strlen(line) - 1; - if (line[i] != '\n') { - error("line %d too long: %.40s...", num, line); - skip = 1; - invalid = 1; - continue; - } - if (skip) { - skip = 0; - continue; - } - line[i] = '\0'; - - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') { - if (inplace) - fprintf(out, "%s\n", cp); - continue; - } - /* Find the end of the host name portion. */ - for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) - ; - if (*kp == '\0' || *(kp + 1) == '\0') { - error("line %d missing key: %.40s...", - num, line); - invalid = 1; - continue; - } - *kp++ = '\0'; - kp2 = kp; - - public = key_new(KEY_RSA1); - if (key_read(public, &kp) != 1) { - kp = kp2; - key_free(public); - public = key_new(KEY_UNSPEC); - if (key_read(public, &kp) != 1) { - error("line %d invalid key: %.40s...", - num, line); - key_free(public); - invalid = 1; - continue; - } - } - - if (*cp == HASH_DELIM) { - if (find_host || delete_host) { - cp2 = host_hash(name, cp, strlen(cp)); - if (cp2 == NULL) { - error("line %d: invalid hashed " - "name: %.64s...", num, line); - invalid = 1; - continue; - } - c = (strcmp(cp2, cp) == 0); - if (find_host && c) { - printf(gettext("# Host %s found: " - "line %d type %s\n"), name, - num, key_type(public)); - print_host(out, cp, public, 0); - } - if (delete_host && !c) - print_host(out, cp, public, 0); - } else if (hash_hosts) - print_host(out, cp, public, 0); - } else { - if (find_host || delete_host) { - c = (match_hostname(name, cp, - strlen(cp)) == 1); - if (find_host && c) { - printf(gettext("# Host %s found: " - "line %d type %s\n"), name, - num, key_type(public)); - print_host(out, name, public, hash_hosts); - } - if (delete_host && !c) - print_host(out, cp, public, 0); - } else if (hash_hosts) { - for (cp2 = strsep(&cp, ","); - cp2 != NULL && *cp2 != '\0'; - cp2 = strsep(&cp, ",")) { - if (strcspn(cp2, "*?!") != strlen(cp2)) - fprintf(stderr, gettext("Warning: " - "ignoring host name with " - "metacharacters: %.64s\n"), - cp2); - else - print_host(out, cp2, public, 1); - } - has_unhashed = 1; - } - } - key_free(public); - } - fclose(in); - - if (invalid) { - fprintf(stderr, gettext("%s is not a valid known_host file.\n"), - identity_file); - if (inplace) { - fprintf(stderr, gettext("Not replacing existing known_hosts " - "file because of errors\n")); - fclose(out); - unlink(tmp); - } - exit(1); - } - - if (inplace) { - fclose(out); - - /* Backup existing file */ - if (unlink(old) == -1 && errno != ENOENT) - fatal("unlink %.100s: %s", old, strerror(errno)); - if (link(identity_file, old) == -1) - fatal("link %.100s to %.100s: %s", identity_file, old, - strerror(errno)); - /* Move new one into place */ - if (rename(tmp, identity_file) == -1) { - error("rename\"%s\" to \"%s\": %s", tmp, identity_file, - strerror(errno)); - unlink(tmp); - unlink(old); - exit(1); - } - - fprintf(stderr, gettext("%s updated.\n"), identity_file); - fprintf(stderr, gettext("Original contents retained as %s\n"), old); - if (has_unhashed) { - fprintf(stderr, gettext("WARNING: %s contains unhashed " - "entries\n"), old); - fprintf(stderr, gettext("Delete this file to ensure privacy " - "of hostnames\n")); - } - } - - exit(0); -} - -/* - * Perform changing a passphrase. The argument is the passwd structure - * for the current user. - */ -static void -do_change_passphrase(struct passwd *pw) -{ - char *comment; - char *old_passphrase, *passphrase1, *passphrase2; - struct stat st; - Key *private; - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - /* Try to load the file with empty passphrase. */ - private = key_load_private(identity_file, "", &comment); - if (private == NULL) { - if (identity_passphrase) - old_passphrase = xstrdup(identity_passphrase); - else - old_passphrase = - read_passphrase(gettext("Enter old passphrase: "), - RP_ALLOW_STDIN); - private = key_load_private(identity_file, old_passphrase, - &comment); - memset(old_passphrase, 0, strlen(old_passphrase)); - xfree(old_passphrase); - if (private == NULL) { - printf(gettext("Bad passphrase.\n")); - exit(1); - } - } - printf(gettext("Key has comment '%s'\n"), comment); - - /* Ask the new passphrase (twice). */ - if (identity_new_passphrase) { - passphrase1 = xstrdup(identity_new_passphrase); - passphrase2 = NULL; - } else { - passphrase1 = - read_passphrase(gettext("Enter new passphrase (empty" - " for no passphrase): "), RP_ALLOW_STDIN); - passphrase2 = read_passphrase(gettext("Enter same " - "passphrase again: "), RP_ALLOW_STDIN); - - /* Verify that they are the same. */ - if (strcmp(passphrase1, passphrase2) != 0) { - memset(passphrase1, 0, strlen(passphrase1)); - memset(passphrase2, 0, strlen(passphrase2)); - xfree(passphrase1); - xfree(passphrase2); - printf(gettext("Pass phrases do not match. Try " - "again.\n")); - exit(1); - } - /* Destroy the other copy. */ - memset(passphrase2, 0, strlen(passphrase2)); - xfree(passphrase2); - } - - /* Save the file using the new passphrase. */ - if (!key_save_private(private, identity_file, passphrase1, comment)) { - printf(gettext("Saving the key failed: %s.\n"), identity_file); - memset(passphrase1, 0, strlen(passphrase1)); - xfree(passphrase1); - key_free(private); - xfree(comment); - exit(1); - } - /* Destroy the passphrase and the copy of the key in memory. */ - memset(passphrase1, 0, strlen(passphrase1)); - xfree(passphrase1); - key_free(private); /* Destroys contents */ - xfree(comment); - - printf(gettext("Your identification has been saved with the new " - "passphrase.\n")); - exit(0); -} - -/* - * Change the comment of a private key file. - */ -static void -do_change_comment(struct passwd *pw) -{ - char new_comment[1024], *comment, *passphrase; - Key *private; - Key *public; - struct stat st; - FILE *f; - int fd; - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - private = key_load_private(identity_file, "", &comment); - if (private == NULL) { - if (identity_passphrase) - passphrase = xstrdup(identity_passphrase); - else if (identity_new_passphrase) - passphrase = xstrdup(identity_new_passphrase); - else - passphrase = - read_passphrase(gettext("Enter passphrase: "), - RP_ALLOW_STDIN); - /* Try to load using the passphrase. */ - private = key_load_private(identity_file, passphrase, &comment); - if (private == NULL) { - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); - printf(gettext("Bad passphrase.\n")); - exit(1); - } - } else { - passphrase = xstrdup(""); - } - if (private->type != KEY_RSA1) { - fprintf(stderr, gettext("Comments are only supported for " - "RSA1 keys.\n")); - key_free(private); - exit(1); - } - printf(gettext("Key now has comment '%s'\n"), comment); - - if (identity_comment) { - strlcpy(new_comment, identity_comment, sizeof(new_comment)); - } else { - printf(gettext("Enter new comment: ")); - fflush(stdout); - if (!fgets(new_comment, sizeof(new_comment), stdin)) { - memset(passphrase, 0, strlen(passphrase)); - key_free(private); - exit(1); - } - if (strchr(new_comment, '\n')) - *strchr(new_comment, '\n') = 0; - } - - /* Save the file using the new passphrase. */ - if (!key_save_private(private, identity_file, passphrase, new_comment)) { - printf(gettext("Saving the key failed: %s.\n"), identity_file); - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); - key_free(private); - xfree(comment); - exit(1); - } - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); - public = key_from_private(private); - key_free(private); - - strlcat(identity_file, ".pub", sizeof(identity_file)); - fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - printf(gettext("Could not save your public key in %s\n"), - identity_file); - exit(1); - } - f = fdopen(fd, "w"); - if (f == NULL) { - printf(gettext("fdopen %s failed"), identity_file); - exit(1); - } - if (!key_write(public, f)) - fprintf(stderr, gettext("write key failed")); - key_free(public); - fprintf(f, " %s\n", new_comment); - fclose(f); - - xfree(comment); - - printf(gettext("The comment in your key file has been changed.\n")); - exit(0); -} - -static void -usage(void) -{ - fprintf(stderr, gettext( - "Usage: %s [options]\n" - "Options:\n" - " -b bits Number of bits in the key to create.\n" - " -B Show bubblebabble digest of key file.\n" - " -c Change comment in private and public key files.\n" - " -C comment Provide new comment.\n" - " -e Convert OpenSSH to IETF SECSH key file.\n" - " -f filename Filename of the key file.\n" - " -F hostname Find hostname in known hosts file.\n" - " -H Hash names in known_hosts file.\n" - " -i Convert IETF SECSH to OpenSSH key file.\n" - " -l Show fingerprint of key file.\n" - " -N phrase Provide new passphrase.\n" - " -p Change passphrase of private key file.\n" - " -P phrase Provide old passphrase.\n" - " -q Quiet.\n" - " -R hostname Remove host from known_hosts file.\n" - " -t type Specify type of key to create.\n" - " -y Read private key file and print public key.\n" - ), __progname); - - exit(1); -} - -/* - * Main program for key management. - */ -int -main(int argc, char **argv) -{ - char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; - char *rr_hostname = NULL; - Key *private, *public; - struct passwd *pw; - struct stat st; - int opt, type, fd; - FILE *f; - - extern int optind; - extern char *optarg; - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); - - __progname = get_progname(argv[0]); - - g11n_setlocale(LC_ALL, ""); - - SSLeay_add_all_algorithms(); - init_rng(); - seed_rng(); - - /* we need this for the home * directory. */ - pw = getpwuid(getuid()); - if (!pw) { - printf(gettext("You don't exist, go away!\n")); - exit(1); - } - if (gethostname(hostname, sizeof(hostname)) < 0) { - perror("gethostname"); - exit(1); - } - -#define GETOPT_ARGS "BcdeHilpqxXyb:C:f:F:N:P:R:t:" - - while ((opt = getopt(argc, argv, GETOPT_ARGS)) != -1) { - switch (opt) { - case 'b': - bits = atoi(optarg); - if (bits < 512 || bits > 32768) { - printf(gettext("Bits has bad value.\n")); - exit(1); - } - break; - case 'F': - find_host = 1; - rr_hostname = optarg; - break; - case 'H': - hash_hosts = 1; - break; - case 'R': - delete_host = 1; - rr_hostname = optarg; - break; - case 'l': - print_fingerprint = 1; - break; - case 'B': - print_bubblebabble = 1; - break; - case 'p': - change_passphrase = 1; - break; - case 'c': - change_comment = 1; - break; - case 'f': - strlcpy(identity_file, optarg, sizeof(identity_file)); - have_identity = 1; - break; - case 'P': - identity_passphrase = optarg; - break; - case 'N': - identity_new_passphrase = optarg; - break; - case 'C': - identity_comment = optarg; - break; - case 'q': - quiet = 1; - break; - case 'e': - case 'x': - /* export key */ - convert_to_ssh2 = 1; - break; - case 'i': - case 'X': - /* import key */ - convert_from_ssh2 = 1; - break; - case 'y': - print_public = 1; - break; - case 'd': - key_type_name = "dsa"; - break; - case 't': - key_type_name = optarg; - break; - case '?': - default: - usage(); - } - } - if (optind < argc) { - printf(gettext("Too many arguments.\n")); - usage(); - } - if (change_passphrase && change_comment) { - printf(gettext("Can only have one of -p and -c.\n")); - usage(); - } - if (delete_host || hash_hosts || find_host) - do_known_hosts(pw, rr_hostname); - if (print_fingerprint || print_bubblebabble) - do_fingerprint(pw); - if (change_passphrase) - do_change_passphrase(pw); - if (change_comment) - do_change_comment(pw); - if (convert_to_ssh2) - do_convert_to_ssh2(pw); - if (convert_from_ssh2) - do_convert_from_ssh2(pw); - if (print_public) - do_print_public(pw); - - arc4random_stir(); - - if (key_type_name == NULL) { - printf(gettext("You must specify a key type (-t).\n")); - usage(); - } - type = key_type_from_name(key_type_name); - if (type == KEY_UNSPEC) { - fprintf(stderr, gettext("unknown key type %s\n"), - key_type_name); - exit(1); - } - if (bits == 0) - bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS_RSA; - - if (!quiet) - printf(gettext("Generating public/private %s key pair.\n"), - key_type_name); - private = key_generate(type, bits); - if (private == NULL) { - fprintf(stderr, gettext("key_generate failed")); - exit(1); - } - public = key_from_private(private); - - if (!have_identity) - ask_filename(pw, gettext("Enter file in which to save the key")); - - /* Create ~/.ssh directory if it doesn't already exist. */ - snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR); - if (strstr(identity_file, dotsshdir) != NULL && - stat(dotsshdir, &st) < 0) { - if (mkdir(dotsshdir, 0700) < 0) - error("Could not create directory '%s'.", dotsshdir); - else if (!quiet) - printf(gettext("Created directory '%s'.\n"), dotsshdir); - } - /* If the file already exists, ask the user to confirm. */ - if (stat(identity_file, &st) >= 0) { - char yesno[128]; - printf(gettext("%s already exists.\n"), identity_file); - printf(gettext("Overwrite (%s/%s)? "), - nl_langinfo(YESSTR), nl_langinfo(NOSTR)); - fflush(stdout); - if (fgets(yesno, sizeof(yesno), stdin) == NULL) - exit(1); - if (strcasecmp(chop(yesno), nl_langinfo(YESSTR)) != 0) - exit(1); - } - /* Ask for a passphrase (twice). */ - if (identity_passphrase) - passphrase1 = xstrdup(identity_passphrase); - else if (identity_new_passphrase) - passphrase1 = xstrdup(identity_new_passphrase); - else { -passphrase_again: - passphrase1 = - read_passphrase(gettext("Enter passphrase (empty " - "for no passphrase): "), RP_ALLOW_STDIN); - passphrase2 = read_passphrase(gettext("Enter same " - "passphrase again: "), RP_ALLOW_STDIN); - if (strcmp(passphrase1, passphrase2) != 0) { - /* - * The passphrases do not match. Clear them and - * retry. - */ - memset(passphrase1, 0, strlen(passphrase1)); - memset(passphrase2, 0, strlen(passphrase2)); - xfree(passphrase1); - xfree(passphrase2); - printf(gettext("Passphrases do not match. Try " - "again.\n")); - goto passphrase_again; - } - /* Clear the other copy of the passphrase. */ - memset(passphrase2, 0, strlen(passphrase2)); - xfree(passphrase2); - } - - if (identity_comment) { - strlcpy(comment, identity_comment, sizeof(comment)); - } else { - /* Create default commend field for the passphrase. */ - snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); - } - - /* Save the key with the given passphrase and comment. */ - if (!key_save_private(private, identity_file, passphrase1, comment)) { - printf(gettext("Saving the key failed: %s.\n"), identity_file); - memset(passphrase1, 0, strlen(passphrase1)); - xfree(passphrase1); - exit(1); - } - /* Clear the passphrase. */ - memset(passphrase1, 0, strlen(passphrase1)); - xfree(passphrase1); - - /* Clear the private key and the random number generator. */ - key_free(private); - arc4random_stir(); - - if (!quiet) - printf(gettext("Your identification has been saved in %s.\n"), - identity_file); - - strlcat(identity_file, ".pub", sizeof(identity_file)); - fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - printf(gettext("Could not save your public key in %s\n"), - identity_file); - exit(1); - } - f = fdopen(fd, "w"); - if (f == NULL) { - printf(gettext("fdopen %s failed"), identity_file); - exit(1); - } - if (!key_write(public, f)) - fprintf(stderr, gettext("write key failed")); - fprintf(f, " %s\n", comment); - fclose(f); - - if (!quiet) { - char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); - printf(gettext("Your public key has been saved in %s.\n"), - identity_file); - printf(gettext("The key fingerprint is:\n")); - printf("%s %s\n", fp, comment); - xfree(fp); - } - - key_free(public); - return(0); - /* NOTREACHED */ -} diff --git a/usr/src/cmd/ssh/ssh-keyscan/Makefile b/usr/src/cmd/ssh/ssh-keyscan/Makefile deleted file mode 100644 index 9e2fd17160..0000000000 --- a/usr/src/cmd/ssh/ssh-keyscan/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# 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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/ssh-keyscan/Makefile - -PROG= ssh-keyscan - -OBJS = \ - ssh-keyscan.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lnsl -lz -lcrypto - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ - -install: all $(ROOTPROG) diff --git a/usr/src/cmd/ssh/ssh-keyscan/ssh-keyscan.c b/usr/src/cmd/ssh/ssh-keyscan/ssh-keyscan.c deleted file mode 100644 index 8879289088..0000000000 --- a/usr/src/cmd/ssh/ssh-keyscan/ssh-keyscan.c +++ /dev/null @@ -1,832 +0,0 @@ -/* - * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. - * - * Modification and redistribution in source and binary forms is - * permitted provided that due credit is given to the author and the - * OpenBSD project by leaving this copyright notice intact. - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: ssh-keyscan.c,v 1.40 2002/07/06 17:47:58 stevesk Exp $"); - -#include "sys-queue.h" - -#include <openssl/bn.h> - -#include <setjmp.h> -#include "xmalloc.h" -#include "ssh.h" -#include "ssh1.h" -#include "key.h" -#include "kex.h" -#include "compat.h" -#include "myproposal.h" -#include "packet.h" -#include "dispatch.h" -#include "buffer.h" -#include "bufaux.h" -#include "log.h" -#include "atomicio.h" -#include "misc.h" - -/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. - Default value is AF_UNSPEC means both IPv4 and IPv6. */ -#ifdef IPV4_DEFAULT -int IPv4or6 = AF_INET; -#else -int IPv4or6 = AF_UNSPEC; -#endif - -int ssh_port = SSH_DEFAULT_PORT; - -#define KT_RSA1 1 -#define KT_DSA 2 -#define KT_RSA 4 - -int get_keytypes = KT_RSA1; /* Get only RSA1 keys by default */ - -#define MAXMAXFD 256 - -/* The number of seconds after which to give up on a TCP connection */ -int timeout = 5; - -int maxfd; -#define MAXCON (maxfd - 10) - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif -fd_set *read_wait; -size_t read_wait_size; -int ncon; -int nonfatal_fatal = 0; -jmp_buf kexjmp; -Key *kexjmp_key; - -/* - * Keep a connection structure for each file descriptor. The state - * associated with file descriptor n is held in fdcon[n]. - */ -typedef struct Connection { - u_char c_status; /* State of connection on this file desc. */ -#define CS_UNUSED 0 /* File descriptor unused */ -#define CS_CON 1 /* Waiting to connect/read greeting */ -#define CS_SIZE 2 /* Waiting to read initial packet size */ -#define CS_KEYS 3 /* Waiting to read public key packet */ - int c_fd; /* Quick lookup: c->c_fd == c - fdcon */ - int c_plen; /* Packet length field for ssh packet */ - int c_len; /* Total bytes which must be read. */ - int c_off; /* Length of data read so far. */ - int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ - char *c_namebase; /* Address to free for c_name and c_namelist */ - char *c_name; /* Hostname of connection for errors */ - char *c_namelist; /* Pointer to other possible addresses */ - char *c_output_name; /* Hostname of connection for output */ - char *c_data; /* Data read from this fd */ - Kex *c_kex; /* The key-exchange struct for ssh2 */ - struct timeval c_tv; /* Time at which connection gets aborted */ - TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */ -} con; - -TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */ -con *fdcon; - -/* - * This is just a wrapper around fgets() to make it usable. - */ - -/* Stress-test. Increase this later. */ -#define LINEBUF_SIZE 16 - -typedef struct { - char *buf; - u_int size; - int lineno; - const char *filename; - FILE *stream; - void (*errfun) (const char *,...); -} Linebuf; - -static Linebuf * -Linebuf_alloc(const char *filename, void (*errfun) (const char *,...)) -{ - Linebuf *lb; - - if (!(lb = malloc(sizeof(*lb)))) { - if (errfun) - (*errfun) ("linebuf (%s): malloc failed\n", - filename ? filename : "(stdin)"); - return (NULL); - } - if (filename) { - lb->filename = filename; - if (!(lb->stream = fopen(filename, "r"))) { - xfree(lb); - if (errfun) - (*errfun) ("%s: %s\n", filename, strerror(errno)); - return (NULL); - } - } else { - lb->filename = "(stdin)"; - lb->stream = stdin; - } - - if (!(lb->buf = malloc(lb->size = LINEBUF_SIZE))) { - if (errfun) - (*errfun) ("linebuf (%s): malloc failed\n", lb->filename); - xfree(lb); - return (NULL); - } - lb->errfun = errfun; - lb->lineno = 0; - return (lb); -} - -static void -Linebuf_free(Linebuf * lb) -{ - fclose(lb->stream); - xfree(lb->buf); - xfree(lb); -} - -#if 0 -static void -Linebuf_restart(Linebuf * lb) -{ - clearerr(lb->stream); - rewind(lb->stream); - lb->lineno = 0; -} - -static int -Linebuf_lineno(Linebuf * lb) -{ - return (lb->lineno); -} -#endif - -static char * -Linebuf_getline(Linebuf * lb) -{ - int n = 0; - void *p; - - lb->lineno++; - for (;;) { - /* Read a line */ - if (!fgets(&lb->buf[n], lb->size - n, lb->stream)) { - if (ferror(lb->stream) && lb->errfun) - (*lb->errfun)("%s: %s\n", lb->filename, - strerror(errno)); - return (NULL); - } - n = strlen(lb->buf); - - /* Return it or an error if it fits */ - if (n > 0 && lb->buf[n - 1] == '\n') { - lb->buf[n - 1] = '\0'; - return (lb->buf); - } - if (n != lb->size - 1) { - if (lb->errfun) - (*lb->errfun)("%s: skipping incomplete last line\n", - lb->filename); - return (NULL); - } - /* Double the buffer if we need more space */ - lb->size *= 2; - if ((p = realloc(lb->buf, lb->size)) == NULL) { - lb->size /= 2; - if (lb->errfun) - (*lb->errfun)("linebuf (%s): realloc failed\n", - lb->filename); - return (NULL); - } - lb->buf = p; - } -} - -static int -fdlim_get(int hard) -{ -#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) - struct rlimit rlfd; - - if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0) - return (-1); - if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY) - return 10000; - else - return hard ? rlfd.rlim_max : rlfd.rlim_cur; -#elif defined (HAVE_SYSCONF) - return sysconf (_SC_OPEN_MAX); -#else - return 10000; -#endif -} - -static int -fdlim_set(int lim) -{ -#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) - struct rlimit rlfd; -#endif - - if (lim <= 0) - return (-1); -#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) - if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0) - return (-1); - rlfd.rlim_cur = lim; - if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0) - return (-1); -#elif defined (HAVE_SETDTABLESIZE) - setdtablesize(lim); -#endif - return (0); -} - -/* - * This is an strsep function that returns a null field for adjacent - * separators. This is the same as the 4.4BSD strsep, but different from the - * one in the GNU libc. - */ -static char * -xstrsep(char **str, const char *delim) -{ - char *s, *e; - - if (!**str) - return (NULL); - - s = *str; - e = s + strcspn(s, delim); - - if (*e != '\0') - *e++ = '\0'; - *str = e; - - return (s); -} - -/* - * Get the next non-null token (like GNU strsep). Strsep() will return a - * null token for two adjacent separators, so we may have to loop. - */ -static char * -strnnsep(char **stringp, char *delim) -{ - char *tok; - - do { - tok = xstrsep(stringp, delim); - } while (tok && *tok == '\0'); - return (tok); -} - -static Key * -keygrab_ssh1(con *c) -{ - static Key *rsa; - static Buffer msg; - - if (rsa == NULL) { - buffer_init(&msg); - rsa = key_new(KEY_RSA1); - } - buffer_append(&msg, c->c_data, c->c_plen); - buffer_consume(&msg, 8 - (c->c_plen & 7)); /* padding */ - if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) { - error("%s: invalid packet type", c->c_name); - buffer_clear(&msg); - return NULL; - } - buffer_consume(&msg, 8); /* cookie */ - - /* server key */ - (void) buffer_get_int(&msg); - buffer_get_bignum(&msg, rsa->rsa->e); - buffer_get_bignum(&msg, rsa->rsa->n); - - /* host key */ - (void) buffer_get_int(&msg); - buffer_get_bignum(&msg, rsa->rsa->e); - buffer_get_bignum(&msg, rsa->rsa->n); - - buffer_clear(&msg); - - return (rsa); -} - -static int -hostjump(Key *hostkey) -{ - kexjmp_key = hostkey; - longjmp(kexjmp, 1); - /* NOTREACHED */ - return (0); -} - -static int -ssh2_capable(int remote_major, int remote_minor) -{ - switch (remote_major) { - case 1: - if (remote_minor == 99) - return 1; - break; - case 2: - return 1; - default: - break; - } - return 0; -} - -static Key * -keygrab_ssh2(con *c) -{ - int j; - - packet_set_connection(c->c_fd, c->c_fd); - enable_compat20(); - my_clnt_proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - c->c_keytype == KT_DSA? "ssh-dss": "ssh-rsa"; - c->c_kex = kex_setup(c->c_name, my_clnt_proposal, NULL); - kex_start(c->c_kex); - c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - c->c_kex->verify_host_key = hostjump; - - if (!(j = setjmp(kexjmp))) { - nonfatal_fatal = 1; - dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, c->c_kex); - fprintf(stderr, "Impossible! dispatch_run() returned!\n"); - exit(1); - } - nonfatal_fatal = 0; - xfree(c->c_kex); - c->c_kex = NULL; - packet_close(); - - return j < 0? NULL : kexjmp_key; -} - -static void -keyprint(con *c, Key *key) -{ - if (!key) - return; - - fprintf(stdout, "%s ", c->c_output_name ? c->c_output_name : c->c_name); - key_write(key, stdout); - fputs("\n", stdout); -} - -static int -tcpconnect(char *host) -{ - struct addrinfo hints, *ai, *aitop; - char strport[NI_MAXSERV]; - int gaierr, s = -1; - - snprintf(strport, sizeof strport, "%d", ssh_port); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_socktype = SOCK_STREAM; - if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) - fatal("getaddrinfo %s: %s", host, gai_strerror(gaierr)); - for (ai = aitop; ai; ai = ai->ai_next) { - s = socket(ai->ai_family, SOCK_STREAM, 0); - if (s < 0) { - error("socket: %s", strerror(errno)); - continue; - } - if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) - fatal("F_SETFL: %s", strerror(errno)); - if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 && - errno != EINPROGRESS) - error("connect (`%s'): %s", host, strerror(errno)); - else - break; - close(s); - s = -1; - } - freeaddrinfo(aitop); - return s; -} - -static int -conalloc(char *iname, char *oname, int keytype) -{ - char *namebase, *name, *namelist; - int s; - - namebase = namelist = xstrdup(iname); - - do { - name = xstrsep(&namelist, ","); - if (!name) { - xfree(namebase); - return (-1); - } - } while ((s = tcpconnect(name)) < 0); - - if (s >= maxfd) - fatal("conalloc: fdno %d too high", s); - if (fdcon[s].c_status) - fatal("conalloc: attempt to reuse fdno %d", s); - - fdcon[s].c_fd = s; - fdcon[s].c_status = CS_CON; - fdcon[s].c_namebase = namebase; - fdcon[s].c_name = name; - fdcon[s].c_namelist = namelist; - fdcon[s].c_output_name = xstrdup(oname); - fdcon[s].c_data = (char *) &fdcon[s].c_plen; - fdcon[s].c_len = 4; - fdcon[s].c_off = 0; - fdcon[s].c_keytype = keytype; - gettimeofday(&fdcon[s].c_tv, NULL); - fdcon[s].c_tv.tv_sec += timeout; - TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); - FD_SET(s, read_wait); - ncon++; - return (s); -} - -static void -confree(int s) -{ - if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) - fatal("confree: attempt to free bad fdno %d", s); - close(s); - xfree(fdcon[s].c_namebase); - xfree(fdcon[s].c_output_name); - if (fdcon[s].c_status == CS_KEYS) - xfree(fdcon[s].c_data); - fdcon[s].c_status = CS_UNUSED; - fdcon[s].c_keytype = 0; - TAILQ_REMOVE(&tq, &fdcon[s], c_link); - FD_CLR(s, read_wait); - ncon--; -} - -static void -contouch(int s) -{ - TAILQ_REMOVE(&tq, &fdcon[s], c_link); - gettimeofday(&fdcon[s].c_tv, NULL); - fdcon[s].c_tv.tv_sec += timeout; - TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); -} - -static int -conrecycle(int s) -{ - con *c = &fdcon[s]; - int ret; - - ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); - confree(s); - return (ret); -} - -static void -congreet(int s) -{ - int remote_major, remote_minor, n = 0; - char buf[256], *cp; - char remote_version[sizeof buf]; - size_t bufsiz; - con *c = &fdcon[s]; - - bufsiz = sizeof(buf); - cp = buf; - while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n') { - if (*cp == '\r') - *cp = '\n'; - cp++; - } - if (n < 0) { - if (errno != ECONNREFUSED) - error("read (%s): %s", c->c_name, strerror(errno)); - conrecycle(s); - return; - } - if (n == 0) { - error("%s: Connection closed by remote host", c->c_name); - conrecycle(s); - return; - } - if (*cp != '\n' && *cp != '\r') { - error("%s: bad greeting", c->c_name); - confree(s); - return; - } - *cp = '\0'; - if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) == 3) - compat_datafellows(remote_version); - else - datafellows = 0; - if (c->c_keytype != KT_RSA1) { - if (!ssh2_capable(remote_major, remote_minor)) { - debug("%s doesn't support ssh2", c->c_name); - confree(s); - return; - } - } else if (remote_major != 1) { - debug("%s doesn't support ssh1", c->c_name); - confree(s); - return; - } - fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); - n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", - c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, - c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); - if (atomicio(write, s, buf, n) != n) { - error("write (%s): %s", c->c_name, strerror(errno)); - confree(s); - return; - } - if (c->c_keytype != KT_RSA1) { - keyprint(c, keygrab_ssh2(c)); - confree(s); - return; - } - c->c_status = CS_SIZE; - contouch(s); -} - -static void -conread(int s) -{ - con *c = &fdcon[s]; - int n; - - if (c->c_status == CS_CON) { - congreet(s); - return; - } - n = read(s, c->c_data + c->c_off, c->c_len - c->c_off); - if (n < 0) { - error("read (%s): %s", c->c_name, strerror(errno)); - confree(s); - return; - } - c->c_off += n; - - if (c->c_off == c->c_len) - switch (c->c_status) { - case CS_SIZE: - c->c_plen = htonl(c->c_plen); - c->c_len = c->c_plen + 8 - (c->c_plen & 7); - c->c_off = 0; - c->c_data = xmalloc(c->c_len); - c->c_status = CS_KEYS; - break; - case CS_KEYS: - keyprint(c, keygrab_ssh1(c)); - confree(s); - return; - break; - default: - fatal("conread: invalid status %d", c->c_status); - break; - } - - contouch(s); -} - -static void -conloop(void) -{ - struct timeval seltime, now; - fd_set *r, *e; - con *c; - int i; - - gettimeofday(&now, NULL); - c = TAILQ_FIRST(&tq); - - if (c && (c->c_tv.tv_sec > now.tv_sec || - (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) { - seltime = c->c_tv; - seltime.tv_sec -= now.tv_sec; - seltime.tv_usec -= now.tv_usec; - if (seltime.tv_usec < 0) { - seltime.tv_usec += 1000000; - seltime.tv_sec--; - } - } else - seltime.tv_sec = seltime.tv_usec = 0; - - r = xmalloc(read_wait_size); - memcpy(r, read_wait, read_wait_size); - e = xmalloc(read_wait_size); - memcpy(e, read_wait, read_wait_size); - - while (select(maxfd, r, NULL, e, &seltime) == -1 && - (errno == EAGAIN || errno == EINTR)) - ; - - for (i = 0; i < maxfd; i++) { - if (FD_ISSET(i, e)) { - error("%s: exception!", fdcon[i].c_name); - confree(i); - } else if (FD_ISSET(i, r)) - conread(i); - } - xfree(r); - xfree(e); - - c = TAILQ_FIRST(&tq); - while (c && (c->c_tv.tv_sec < now.tv_sec || - (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { - int s = c->c_fd; - - c = TAILQ_NEXT(c, c_link); - conrecycle(s); - } -} - -static void -do_host(char *host) -{ - char *name = strnnsep(&host, " \t\n"); - int j; - - if (name == NULL) - return; - for (j = KT_RSA1; j <= KT_RSA; j *= 2) { - if (get_keytypes & j) { - while (ncon >= MAXCON) - conloop(); - conalloc(name, *host ? host : name, j); - } - } -} - -void -fatal(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); - va_end(args); - if (nonfatal_fatal) - longjmp(kexjmp, -1); - else - fatal_cleanup(); -} - -static void -usage(void) -{ - fprintf(stderr, - gettext("Usage: %s [-v46] [-p port] [-T timeout] [-f file]\n" - "\t\t [host | addrlist namelist] [...]\n"), - __progname); - exit(1); -} - -int -main(int argc, char **argv) -{ - int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO; - int opt, fopt_count = 0; - char *tname; - - extern int optind; - extern char *optarg; - - __progname = get_progname(argv[0]); - - (void) g11n_setlocale(LC_ALL, ""); - - init_rng(); - seed_rng(); - TAILQ_INIT(&tq); - - if (argc <= 1) - usage(); - - while ((opt = getopt(argc, argv, "v46p:T:t:f:")) != -1) { - switch (opt) { - case 'p': - ssh_port = a2port(optarg); - if (ssh_port == 0) { - fprintf(stderr, gettext("Bad port '%s'\n"), - optarg); - exit(1); - } - break; - case 'T': - timeout = convtime(optarg); - if (timeout == -1 || timeout == 0) { - fprintf(stderr, gettext("Bad timeout '%s'\n"), - optarg); - usage(); - } - break; - case 'v': - if (!debug_flag) { - debug_flag = 1; - log_level = SYSLOG_LEVEL_DEBUG1; - } - else if (log_level < SYSLOG_LEVEL_DEBUG3) - log_level++; - else - fatal("Too high debugging level."); - break; - case 'f': - if (strcmp(optarg, "-") == 0) - optarg = NULL; - argv[fopt_count++] = optarg; - break; - case 't': - get_keytypes = 0; - tname = strtok(optarg, ","); - while (tname) { - int type = key_type_from_name(tname); - switch (type) { - case KEY_RSA1: - get_keytypes |= KT_RSA1; - break; - case KEY_DSA: - get_keytypes |= KT_DSA; - break; - case KEY_RSA: - get_keytypes |= KT_RSA; - break; - case KEY_UNSPEC: - fatal("unknown key type %s", tname); - } - tname = strtok(NULL, ","); - } - break; - case '4': - IPv4or6 = AF_INET; - break; - case '6': - IPv4or6 = AF_INET6; - break; - case '?': - default: - usage(); - } - } - if (optind == argc && !fopt_count) - usage(); - - log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); - - maxfd = fdlim_get(1); - if (maxfd < 0) - fatal("%s: fdlim_get: bad value", __progname); - if (maxfd > MAXMAXFD) - maxfd = MAXMAXFD; - if (MAXCON <= 0) - fatal("%s: not enough file descriptors", __progname); - if (maxfd > fdlim_get(0)) - fdlim_set(maxfd); - fdcon = xmalloc(maxfd * sizeof(con)); - memset(fdcon, 0, maxfd * sizeof(con)); - - read_wait_size = howmany(maxfd, NFDBITS) * sizeof(fd_mask); - read_wait = xmalloc(read_wait_size); - memset(read_wait, 0, read_wait_size); - - if (fopt_count) { - Linebuf *lb; - char *line; - int j; - - for (j = 0; j < fopt_count; j++) { - lb = Linebuf_alloc(argv[j], error); - if (!lb) - continue; - while ((line = Linebuf_getline(lb)) != NULL) - do_host(line); - Linebuf_free(lb); - } - } - - while (optind < argc) - do_host(argv[optind++]); - - while (ncon > 0) - conloop(); - - return (0); -} diff --git a/usr/src/cmd/ssh/ssh-keysign/Makefile b/usr/src/cmd/ssh/ssh-keysign/Makefile deleted file mode 100644 index e31ae681a1..0000000000 --- a/usr/src/cmd/ssh/ssh-keysign/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/ssh-keysign/Makefile - -PROG= ssh-keysign - -DIRS= $(ROOTLIBSSH) - - -OBJS = ssh-keysign.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -FILEMODE= 04555 - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lnsl -lz -lcrypto - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ - -install: all $(DIRS) $(ROOTLIBSSHPROG) $(ROOTLIBSSH) - - -$(ROOTLIBSSHPROG)/%: % - $(INS.file) - -$(DIRS): - $(INS.dir) diff --git a/usr/src/cmd/ssh/ssh-keysign/ssh-keysign.c b/usr/src/cmd/ssh/ssh-keysign/ssh-keysign.c deleted file mode 100644 index 66f6fde586..0000000000 --- a/usr/src/cmd/ssh/ssh-keysign/ssh-keysign.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 2002 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: ssh-keysign.c,v 1.7 2002/07/03 14:21:05 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <unistd.h> - -#include <openssl/evp.h> -#include <openssl/rand.h> -#include <openssl/rsa.h> - -#include "log.h" -#include "key.h" -#include "ssh.h" -#include "ssh2.h" -#include "misc.h" -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "authfile.h" -#include "msg.h" -#include "canohost.h" -#include "pathnames.h" -#include "readconf.h" - -uid_t original_real_uid; /* XXX readconf.c needs this */ - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -#ifndef lint -char *__progname; -#endif /* lint */ -#endif - -static int -valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, - u_int datalen) -{ - Buffer b; - Key *key; - u_char *pkblob; - u_int blen, len; - char *pkalg, *p; - int pktype, fail; - - fail = 0; - - buffer_init(&b); - buffer_append(&b, data, datalen); - - /* session id, currently limited to SHA1 (20 bytes) */ - p = buffer_get_string(&b, &len); - if (len != 20) - fail++; - xfree(p); - - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - - /* server user */ - buffer_skip_string(&b); - - /* service */ - p = buffer_get_string(&b, NULL); - if (strcmp("ssh-connection", p) != 0) - fail++; - xfree(p); - - /* method */ - p = buffer_get_string(&b, NULL); - if (strcmp("hostbased", p) != 0) - fail++; - xfree(p); - - /* pubkey */ - pkalg = buffer_get_string(&b, NULL); - pkblob = buffer_get_string(&b, &blen); - - pktype = key_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) - fail++; - else if ((key = key_from_blob(pkblob, blen)) == NULL) - fail++; - else if (key->type != pktype) - fail++; - xfree(pkalg); - xfree(pkblob); - - /* client host name, handle trailing dot */ - p = buffer_get_string(&b, &len); - debug2("valid_request: check expect chost %s got %s", host, p); - if (strlen(host) != len - 1) - fail++; - else if (p[len - 1] != '.') - fail++; - else if (strncasecmp(host, p, len - 1) != 0) - fail++; - xfree(p); - - /* local user */ - p = buffer_get_string(&b, NULL); - - if (strcmp(pw->pw_name, p) != 0) - fail++; - xfree(p); - - /* end of message */ - if (buffer_len(&b) != 0) - fail++; - - debug3("valid_request: fail %d", fail); - - if (fail && key != NULL) - key_free(key); - else - *ret = key; - - return (fail ? -1 : 0); -} - -int -main(int argc, char **argv) -{ - Buffer b; - Options options; - Key *keys[2], *key; - struct passwd *pw; - int key_fd[2], i, found, version = 2, fd; - u_char *signature, *data; - char *host; - u_int slen, dlen; - u_int32_t rnd[256]; - - /* - * Since these two open()s are all that's done here before - * dropping privileges with setreuid(), and since having been - * privileged protects ssh-keysign from core dumps and tracing, - * there's no need to use Least Privilege interfaces like - * setppriv(2). - */ - key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); - key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); - - (void) setreuid(getuid(), getuid()); - - (void) g11n_setlocale(LC_ALL, ""); - - init_rng(); - seed_rng(); - arc4random_stir(); - -#ifdef DEBUG_SSH_KEYSIGN - log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); -#endif - - /* verify that ssh-keysign is enabled by the admin */ - original_real_uid = getuid(); /* XXX readconf.c needs this */ - initialize_options(&options); - (void)read_config_file(_PATH_HOST_CONFIG_FILE, "", &options); - fill_default_options(&options); - if (options.hostbased_authentication != 1) - fatal("Hostbased authentication not enabled in %s", - _PATH_HOST_CONFIG_FILE); - - if (key_fd[0] == -1 && key_fd[1] == -1) - fatal("could not open any host key"); - - if ((pw = getpwuid(getuid())) == NULL) - fatal("getpwuid failed"); - pw = pwcopy(pw); - - SSLeay_add_all_algorithms(); - for (i = 0; i < 256; i++) - rnd[i] = arc4random(); - RAND_seed(rnd, sizeof(rnd)); - - found = 0; - for (i = 0; i < 2; i++) { - keys[i] = NULL; - if (key_fd[i] == -1) - continue; - keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, - NULL, NULL); - (void) close(key_fd[i]); - if (keys[i] != NULL && keys[i]->type == KEY_RSA) { - if (RSA_blinding_on(keys[i]->rsa, NULL) != 1) { - error("RSA_blinding_on failed"); - key_free(keys[i]); - keys[i] = NULL; - } - } - if (keys[i] != NULL) - found = 1; - } - if (!found) - fatal("no hostkey found"); - - buffer_init(&b); - if (ssh_msg_recv(STDIN_FILENO, &b) < 0) - fatal("ssh_msg_recv failed"); - if (buffer_get_char(&b) != version) - fatal("bad version"); - fd = buffer_get_int(&b); - if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO)) - fatal("bad fd"); - if ((host = get_local_name(fd)) == NULL) - fatal("cannot get sockname for fd"); - - data = buffer_get_string(&b, &dlen); - if (valid_request(pw, host, &key, data, dlen) < 0) - fatal("not a valid request"); - xfree(host); - - found = 0; - for (i = 0; i < 2; i++) { - if (keys[i] != NULL && - key_equal(key, keys[i])) { - found = 1; - break; - } - } - if (!found) - fatal("no matching hostkey found"); - - if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) - fatal("key_sign failed"); - xfree(data); - - /* send reply */ - buffer_clear(&b); - buffer_put_string(&b, signature, slen); - ssh_msg_send(STDOUT_FILENO, version, &b); - - return (0); -} diff --git a/usr/src/cmd/ssh/ssh-socks5-proxy-connect/ssh-socks5-proxy-connect.c b/usr/src/cmd/ssh/ssh-socks5-proxy-connect/ssh-socks5-proxy-connect.c deleted file mode 100644 index 131eb73fcc..0000000000 --- a/usr/src/cmd/ssh/ssh-socks5-proxy-connect/ssh-socks5-proxy-connect.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * 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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * A SOCKS client that let's users 'ssh' to the - * outside of the firewall by opening up a connection - * through the SOCKS server. Supports only SOCKS v5. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <netdb.h> -#include <strings.h> -#include <unistd.h> -#include <inttypes.h> -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <locale.h> -#include <libintl.h> -#include <netinet/in.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <sys/time.h> -#include <sys/stropts.h> -#include <sys/stat.h> -#include <sys/varargs.h> -#include "proxy-io.h" - -#define DEFAULT_SOCKS5_PORT "1080" - -static int debug_flag = 0; - -static void -usage(void) -{ - (void) fprintf(stderr, gettext("Usage: ssh-socks5-proxy-connect " - "[-h socks5_proxy_host] [-p socks5_proxy_port] \n" - "remote_host remote_port\n")); - exit(1); -} - -/* PRINTFLIKE1 */ -static void -debug(const char *format, ...) -{ - char fmtbuf[BUFFER_SIZ]; - va_list args; - - if (debug_flag == 0) { - return; - } - va_start(args, format); - (void) snprintf(fmtbuf, sizeof (fmtbuf), - "ssh-socks5-proxy: %s\n", format); - (void) vfprintf(stderr, fmtbuf, args); - va_end(args); -} - -static void -signal_handler(int sig) -{ - exit(0); -} - -static int -do_version_exchange(int sockfd) -{ - char buffer[3], recv_buf[2]; - - buffer[0] = 0x05; /* VER */ - buffer[1] = 0x01; /* NMETHODS */ - buffer[2] = 0x00; /* METHODS */ - - if (write(sockfd, &buffer, sizeof (buffer)) < 0) { - perror("write"); - return (0); - } - - if (read(sockfd, &recv_buf, sizeof (recv_buf)) == -1) { - perror("read"); - return (0); - } - - /* - * No need to check the server's version as per - * the protocol spec. Check the method supported - * by the server. Currently if the server does not - * support NO AUTH, we disconnect. - */ - if (recv_buf[1] != 0x00) { - debug("Unsupported Authentication Method"); - return (0); - } - - /* Return success. */ - return (1); -} - -static void -send_request( - int sockfd, - const char *ssh_host, - uchar_t ssh_host_len, - uint16_t *ssh_port) -{ - int failure = 1; - char *buffer, *temp, recv_buf[BUFFER_SIZ]; - uchar_t version = 0x05, cmd = 0x01, rsv = 0x00, atyp = 0x03; - - buffer = malloc(strlen(ssh_host) + 7); - - temp = buffer; - - /* Assemble the request packet */ - (void) memcpy(temp, &version, sizeof (version)); - temp += sizeof (version); - (void) memcpy(temp, &cmd, sizeof (cmd)); - temp += sizeof (cmd); - (void) memcpy(temp, &rsv, sizeof (rsv)); - temp += sizeof (rsv); - (void) memcpy(temp, &atyp, sizeof (atyp)); - temp += sizeof (atyp); - (void) memcpy(temp, &ssh_host_len, sizeof (ssh_host_len)); - temp += sizeof (ssh_host_len); - (void) memcpy(temp, ssh_host, strlen(ssh_host)); - temp += strlen(ssh_host); - (void) memcpy(temp, ssh_port, sizeof (*ssh_port)); - temp += sizeof (*ssh_port); - - if (write(sockfd, buffer, temp - buffer) == -1) { - perror("write"); - exit(1); - } - - /* - * The maximum size of the protocol message we are waiting for is 10 - * bytes -- VER[1], REP[1], RSV[1], ATYP[1], BND.ADDR[4] and - * BND.PORT[2]; see RFC 1928, section "6. Replies" for more details. - * Everything else is already a part of the data we are supposed to - * deliver to the requester. We know that BND.ADDR is exactly 4 bytes - * since as you can see below, we accept only ATYP == 1 which specifies - * that the IPv4 address is in a binary format. - */ - if (read(sockfd, &recv_buf, 10) == -1) { - perror("read"); - exit(1); - } - - /* temp now points to the recieve buffer. */ - temp = recv_buf; - - /* Check the server's version. */ - if (*temp++ != 0x05) { - (void) fprintf(stderr, gettext("Unsupported SOCKS version: %x\n"), - recv_buf[0]); - exit(1); - } - - /* Check server's reply */ - switch (*temp++) { - case 0x00: - failure = 0; - debug("CONNECT command Succeeded."); - break; - case 0x01: - debug("General SOCKS server failure."); - break; - case 0x02: - debug("Connection not allowed by ruleset."); - break; - case 0x03: - debug("Network Unreachable."); - break; - case 0x04: - debug("Host unreachable."); - break; - case 0x05: - debug("Connection refused."); - break; - case 0x06: - debug("TTL expired."); - break; - case 0x07: - debug("Command not supported"); - break; - case 0x08: - debug("Address type not supported."); - break; - default: - (void) fprintf(stderr, gettext("ssh-socks5-proxy: " - "SOCKS Server reply not understood\n")); - } - - if (failure == 1) { - exit(1); - } - - /* Parse the rest of the packet */ - - /* Ignore RSV */ - temp++; - - /* Check ATYP */ - if (*temp != 0x01) { - (void) fprintf(stderr, gettext("ssh-socks5-proxy: " - "Address type not supported: %u\n"), *temp); - exit(1); - } - - free(buffer); -} - -int -main(int argc, char **argv) -{ - extern char *optarg; - extern int optind; - int retval, err_code, sock; - uint16_t ssh_port; - uchar_t ssh_host_len; - char *socks_server = NULL, *socks_port = NULL; - char *ssh_host; - struct addrinfo hints, *ai; - struct pollfd fds[2]; - - /* Initialization for variables, set locale and textdomain */ - - (void) setlocale(LC_ALL, ""); - -#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ -#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ -#endif - (void) textdomain(TEXT_DOMAIN); - - /* Set up the signal handler */ - (void) signal(SIGINT, signal_handler); - (void) signal(SIGPIPE, signal_handler); - (void) signal(SIGPOLL, signal_handler); - - while ((retval = getopt(argc, argv, "dp:h:")) != -1) { - switch (retval) { - case 'h': - socks_server = optarg; - break; - case 'p': - socks_port = optarg; - break; - case 'd': - debug_flag = 1; - break; - default: - break; - } - } - - if (optind != argc - 2) { - usage(); - } - - ssh_host = argv[optind++]; - ssh_host_len = (uchar_t)strlen(ssh_host); - ssh_port = htons(atoi(argv[optind])); - - /* - * If the name and/or port number of the - * socks server were not passed on the - * command line, try the user's environment. - */ - if (socks_server == NULL) { - if ((socks_server = getenv("SOCKS5_SERVER")) == NULL) { - (void) fprintf(stderr, gettext("ssh-socks5-proxy: " - "SOCKS5 SERVER not specified\n")); - exit(1); - } - } - if (socks_port == NULL) { - if ((socks_port = getenv("SOCKS5_PORT")) == NULL) { - socks_port = DEFAULT_SOCKS5_PORT; - } - } - - debug("SOCKS5_SERVER = %s", socks_server); - debug("SOCKS5_PORT = %s", socks_port); - - bzero(&hints, sizeof (struct addrinfo)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - if ((err_code = getaddrinfo(socks_server, socks_port, &hints, &ai)) - != 0) { - (void) fprintf(stderr, "%s: %s\n", socks_server, - gai_strerror(err_code)); - exit(1); - } - - if ((sock = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) { - perror("socket"); - exit(1); - } - - /* Connect to the SOCKS server */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) == 0) { - debug("Connected to the SOCKS server"); - /* Do the SOCKS v5 communication with the server. */ - if (do_version_exchange(sock) > 0) { - debug("Done version exchange"); - send_request(sock, ssh_host, ssh_host_len, &ssh_port); - } else { - (void) fprintf(stderr, gettext("ssh-socks5-proxy: Client and " - "Server versions differ.\n")); - (void) close(sock); - exit(1); - } - } else { - perror("connect"); - (void) close(sock); - exit(1); - } - - fds[0].fd = STDIN_FILENO; /* Poll stdin for data. */ - fds[1].fd = sock; /* Poll the socket for data. */ - fds[0].events = fds[1].events = POLLIN; - - for (;;) { - if (poll(fds, 2, INFTIM) == -1) { - perror("poll"); - (void) close(sock); - exit(1); - } - - /* Data arrived on stdin, write it to the socket */ - if (fds[0].revents & POLLIN) { - if (proxy_read_write_loop(STDIN_FILENO, sock) == 0) { - (void) close(sock); - exit(1); - } - } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - (void) close(sock); - exit(1); - } - - /* Data arrived on the socket, write it to stdout */ - if (fds[1].revents & POLLIN) { - if (proxy_read_write_loop(sock, STDOUT_FILENO) == 0) { - (void) close(sock); - exit(1); - } - } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { - (void) close(sock); - exit(1); - } - } - - /* NOTREACHED */ - return (0); -} diff --git a/usr/src/cmd/ssh/ssh/Makefile b/usr/src/cmd/ssh/ssh/Makefile deleted file mode 100644 index 7bdd4f6be5..0000000000 --- a/usr/src/cmd/ssh/ssh/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/ssh/Makefile - -PROG= ssh - -OBJS = ssh.o \ - sshconnect.o \ - sshconnect1.o \ - sshconnect2.o \ - sshtty.o \ - clientloop.o \ - gss-clnt.o -SRCS = $(OBJS:.o=.c) - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket \ - -lnsl \ - -lz \ - -lcrypto \ - -lgss - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -install: all $(ROOTPROG) - -clean: - $(RM) -f $(OBJS) $(PROG) - -lint: lint_SRCS - -include ../Makefile.msg.targ - -XGETFLAGS += --keyword=log -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/ssh/clientloop.c b/usr/src/cmd/ssh/ssh/clientloop.c deleted file mode 100644 index 8a9985c632..0000000000 --- a/usr/src/cmd/ssh/ssh/clientloop.c +++ /dev/null @@ -1,1626 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * The main loop for the interactive session (client side). - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 1999 Theo de Raadt. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * SSH2 support added by Markus Friedl. - * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.104 2002/08/22 19:38:42 stevesk Exp $"); - -#include "ssh.h" -#include "ssh1.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "packet.h" -#include "buffer.h" -#include "compat.h" -#include "channels.h" -#include "dispatch.h" -#include "buffer.h" -#include "bufaux.h" -#include "key.h" -#include "kex.h" -#include "log.h" -#include "readconf.h" -#include "clientloop.h" -#include "authfd.h" -#include "atomicio.h" -#include "sshtty.h" -#include "misc.h" -#include "readpass.h" - -/* import options */ -extern Options options; - -/* Flag indicating that stdin should be redirected from /dev/null. */ -extern int stdin_null_flag; - -/* - * Name of the host we are connecting to. This is the name given on the - * command line, or the HostName specified for the user-supplied name in a - * configuration file. - */ -extern char *host; - -/* - * Flag to indicate that we have received a window change signal which has - * not yet been processed. This will cause a message indicating the new - * window size to be sent to the server a little later. This is volatile - * because this is updated in a signal handler. - */ -static volatile sig_atomic_t received_window_change_signal = 0; -static volatile sig_atomic_t received_signal = 0; - -/* Flag indicating whether the user's terminal is in non-blocking mode. */ -static int in_non_blocking_mode = 0; - -/* Common data for the client loop code. */ -static int quit_pending; /* Set to non-zero to quit the client loop. */ -static int escape_char; /* Escape character. */ -static int escape_pending; /* Last character was the escape character */ -static int last_was_cr; /* Last character was a newline. */ -static int exit_status; /* Used to store the exit status of the command. */ -static int stdin_eof; /* EOF has been encountered on standard error. */ -static Buffer stdin_buffer; /* Buffer for stdin data. */ -static Buffer stdout_buffer; /* Buffer for stdout data. */ -static Buffer stderr_buffer; /* Buffer for stderr data. */ -static u_long stdin_bytes, stdout_bytes, stderr_bytes; -static u_int buffer_high; /* Soft max buffer size. */ -static int connection_in; /* Connection to server (input). */ -static int connection_out; /* Connection to server (output). */ -static int need_rekeying; /* Set to non-zero if rekeying is requested. */ -static int session_closed = 0; /* In SSH2: login session closed. */ -static int server_alive_timeouts = 0; /* Number of outstanding alive packets. */ - -static void client_init_dispatch(void); -int session_ident = -1; - -/*XXX*/ -extern Kex *xxx_kex; - -extern int will_daemonize; - -/* Restores stdin to blocking mode. */ - -static void -leave_non_blocking(void) -{ - if (in_non_blocking_mode) { - (void) fcntl(fileno(stdin), F_SETFL, 0); - in_non_blocking_mode = 0; - fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL); - } -} - -/* Puts stdin terminal in non-blocking mode. */ - -static void -enter_non_blocking(void) -{ - in_non_blocking_mode = 1; - (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); - fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL); -} - -/* - * Signal handler for the window change signal (SIGWINCH). This just sets a - * flag indicating that the window has changed. - */ - -static void -window_change_handler(int sig) -{ - received_window_change_signal = 1; - signal(SIGWINCH, window_change_handler); -} - -/* - * Signal handler for signals that cause the program to terminate. These - * signals must be trapped to restore terminal modes. - */ - -static void -signal_handler(int sig) -{ - received_signal = sig; - quit_pending = 1; -} - -/* - * Returns current time in seconds from Jan 1, 1970 with the maximum - * available resolution. - */ - -static double -get_current_time(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; -} - -#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" -void -client_x11_get_proto(const char *display, const char *xauth_path, - u_int trusted, char **_proto, char **_data) -{ - char cmd[1024]; - char line[512]; - char xdisplay[512]; - static char proto[512], data[512]; - FILE *f; - int got_data = 0, generated = 0, do_unlink = 0, i; - char *xauthdir, *xauthfile; - struct stat st; - - xauthdir = xauthfile = NULL; - *_proto = proto; - *_data = data; - proto[0] = data[0] = '\0'; - - if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { - debug("No xauth program."); - } else { - if (display == NULL) { - debug("x11_get_proto: DISPLAY not set"); - return; - } - /* - * Handle FamilyLocal case where $DISPLAY does - * not match an authorization entry. For this we - * just try "xauth list unix:displaynum.screennum". - * XXX: "localhost" match to determine FamilyLocal - * is not perfect. - */ - if (strncmp(display, "localhost:", 10) == 0) { - snprintf(xdisplay, sizeof(xdisplay), "unix:%s", - display + 10); - display = xdisplay; - } - if (trusted == 0) { - xauthdir = xmalloc(MAXPATHLEN); - xauthfile = xmalloc(MAXPATHLEN); - strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN); - if (mkdtemp(xauthdir) != NULL) { - do_unlink = 1; - snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile", - xauthdir); - snprintf(cmd, sizeof(cmd), - "%s -f %s generate %s " SSH_X11_PROTO - " untrusted timeout 1200 2>" _PATH_DEVNULL, - xauth_path, xauthfile, display); - debug2("x11_get_proto: %s", cmd); - if (system(cmd) == 0) - generated = 1; - } - } - - /* - * When in untrusted mode, we read the cookie only if it was - * successfully generated as an untrusted one in the step - * above. - */ - if (trusted || generated) { - snprintf(cmd, sizeof(cmd), - "%s %s%s list %s 2>" _PATH_DEVNULL, - xauth_path, - generated ? "-f " : "" , - generated ? xauthfile : "", - display); - debug2("x11_get_proto: %s", cmd); - f = popen(cmd, "r"); - if (f && fgets(line, sizeof(line), f) && - sscanf(line, "%*s %511s %511s", proto, data) == 2) - got_data = 1; - if (f) - pclose(f); - } - else - error("Warning: untrusted X11 forwarding setup failed: " - "xauth key data not generated"); - } - - if (do_unlink) { - unlink(xauthfile); - rmdir(xauthdir); - } - if (xauthdir) - xfree(xauthdir); - if (xauthfile) - xfree(xauthfile); - - /* - * If we didn't get authentication data, just make up some - * data. The forwarding code will check the validity of the - * response anyway, and substitute this data. The X11 - * server, however, will ignore this fake data and use - * whatever authentication mechanisms it was using otherwise - * for the local connection. - */ - if (!got_data) { - u_int32_t rnd = 0; - - log("Warning: No xauth data; " - "using fake authentication data for X11 forwarding."); - strlcpy(proto, SSH_X11_PROTO, sizeof proto); - for (i = 0; i < 16; i++) { - if (i % 4 == 0) - rnd = arc4random(); - snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", - rnd & 0xff); - rnd >>= 8; - } - } -} - -/* - * This is called when the interactive is entered. This checks if there is - * an EOF coming on stdin. We must check this explicitly, as select() does - * not appear to wake up when redirecting from /dev/null. - */ - -static void -client_check_initial_eof_on_stdin(void) -{ - int len; - char buf[1]; - - /* - * If standard input is to be "redirected from /dev/null", we simply - * mark that we have seen an EOF and send an EOF message to the - * server. Otherwise, we try to read a single character; it appears - * that for some files, such /dev/null, select() never wakes up for - * read for this descriptor, which means that we never get EOF. This - * way we will get the EOF if stdin comes from /dev/null or similar. - */ - if (stdin_null_flag) { - /* Fake EOF on stdin. */ - debug("Sending eof."); - stdin_eof = 1; - packet_start(SSH_CMSG_EOF); - packet_send(); - } else { - enter_non_blocking(); - - /* Check for immediate EOF on stdin. */ - len = read(fileno(stdin), buf, 1); - if (len == 0) { - /* EOF. Record that we have seen it and send EOF to server. */ - debug("Sending eof."); - stdin_eof = 1; - packet_start(SSH_CMSG_EOF); - packet_send(); - } else if (len > 0) { - /* - * Got data. We must store the data in the buffer, - * and also process it as an escape character if - * appropriate. - */ - if ((u_char) buf[0] == escape_char) - escape_pending = 1; - else - buffer_append(&stdin_buffer, buf, 1); - } - leave_non_blocking(); - } -} - - -/* - * Make packets from buffered stdin data, and buffer them for sending to the - * connection. - */ - -static void -client_make_packets_from_stdin_data(void) -{ - u_int len; - - /* Send buffered stdin data to the server. */ - while (buffer_len(&stdin_buffer) > 0 && - packet_not_very_much_data_to_write()) { - len = buffer_len(&stdin_buffer); - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()) - len = packet_get_maxsize(); - packet_start(SSH_CMSG_STDIN_DATA); - packet_put_string(buffer_ptr(&stdin_buffer), len); - packet_send(); - buffer_consume(&stdin_buffer, len); - stdin_bytes += len; - /* If we have a pending EOF, send it now. */ - if (stdin_eof && buffer_len(&stdin_buffer) == 0) { - packet_start(SSH_CMSG_EOF); - packet_send(); - } - } -} - -/* - * Checks if the client window has changed, and sends a packet about it to - * the server if so. The actual change is detected elsewhere (by a software - * interrupt on Unix); this just checks the flag and sends a message if - * appropriate. - */ - -static void -client_check_window_change(void) -{ - struct winsize ws; - Channel *c; - - if (! received_window_change_signal) - return; - - /* - * We want to send a window-change request only when a session is - * already established and alive. - * - * Note: During session handshake we cannot send window-change request, - * because we do not know the remote channel ID yet. We have to store - * the information about signals which have arrived and send the - * window-change request when the channel and the session are fully - * established. - */ - if (compat20) { - if (session_ident == -1 || session_closed) - return; - c = channel_lookup(session_ident); - if (c == NULL || c->type != SSH_CHANNEL_OPEN || - c->remote_id == -1) - return; - } - - received_window_change_signal = 0; - - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) - return; - - debug2("client_check_window_change: changed"); - - if (compat20) { - channel_request_start(session_ident, "window-change", 0); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - packet_send(); - } else { - packet_start(SSH_CMSG_WINDOW_SIZE); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - packet_send(); - } -} - -static void -client_global_request_reply(int type, u_int32_t seq, void *ctxt) -{ - server_alive_timeouts = 0; - client_global_request_reply_fwd(type, seq, ctxt); -} - -static void -server_alive_check(void) -{ - if (++server_alive_timeouts > options.server_alive_count_max) { - log("Timeout, server not responding."); - fatal_cleanup(); - } - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("keepalive@openssh.com"); - packet_put_char(1); /* boolean: want reply */ - packet_send(); -} - -/* - * Waits until the client can do something (some data becomes available on - * one of the file descriptors). - */ - -static void -client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, - int *maxfdp, int *nallocp, int rekeying) -{ - struct timeval tv, *tvp; - int ret; - - /* Add any selections by the channel mechanism. */ - channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying); - - if (!compat20) { - /* Read from the connection, unless our buffers are full. */ - if (buffer_len(&stdout_buffer) < buffer_high && - buffer_len(&stderr_buffer) < buffer_high && - channel_not_very_much_buffered_data()) - FD_SET(connection_in, *readsetp); - /* - * Read from stdin, unless we have seen EOF or have very much - * buffered data to send to the server. - */ - if (!stdin_eof && packet_not_very_much_data_to_write()) - FD_SET(fileno(stdin), *readsetp); - - /* Select stdout/stderr if have data in buffer. */ - if (buffer_len(&stdout_buffer) > 0) - FD_SET(fileno(stdout), *writesetp); - if (buffer_len(&stderr_buffer) > 0) - FD_SET(fileno(stderr), *writesetp); - } else { - /* channel_prepare_select could have closed the last channel */ - if (session_closed && !channel_still_open() && - !packet_have_data_to_write()) { - /* clear mask since we did not call select() */ - memset(*readsetp, 0, *nallocp); - memset(*writesetp, 0, *nallocp); - return; - } else { - FD_SET(connection_in, *readsetp); - } - } - - /* Select server connection if have data to write to the server. */ - if (packet_have_data_to_write()) - FD_SET(connection_out, *writesetp); - - /* - * Wait for something to happen. This will suspend the process until - * some selected descriptor can be read, written, or has some other - * event pending. - */ - - if (options.server_alive_interval == 0 || !compat20) - tvp = NULL; - else { - tv.tv_sec = options.server_alive_interval; - tv.tv_usec = 0; - tvp = &tv; - } - ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); - if (ret < 0) { - char buf[100]; - - /* - * We have to clear the select masks, because we return. - * We have to return, because the mainloop checks for the flags - * set by the signal handlers. - */ - memset(*readsetp, 0, *nallocp); - memset(*writesetp, 0, *nallocp); - - if (errno == EINTR) - return; - /* Note: we might still have data in the buffers. */ - snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); - buffer_append(&stderr_buffer, buf, strlen(buf)); - quit_pending = 1; - } else if (ret == 0) - server_alive_check(); -} - -static void -client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) -{ - struct winsize oldws, newws; - - /* Flush stdout and stderr buffers. */ - if (buffer_len(bout) > 0) - atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); - if (buffer_len(berr) > 0) - atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); - - leave_raw_mode(); - - /* - * Free (and clear) the buffer to reduce the amount of data that gets - * written to swap. - */ - buffer_free(bin); - buffer_free(bout); - buffer_free(berr); - - /* Save old window size. */ - ioctl(fileno(stdin), TIOCGWINSZ, &oldws); - - /* Send the suspend signal to the program itself. */ - kill(getpid(), SIGTSTP); - - /* Check if the window size has changed. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && - (oldws.ws_row != newws.ws_row || - oldws.ws_col != newws.ws_col || - oldws.ws_xpixel != newws.ws_xpixel || - oldws.ws_ypixel != newws.ws_ypixel)) - received_window_change_signal = 1; - - /* OK, we have been continued by the user. Reinitialize buffers. */ - buffer_init(bin); - buffer_init(bout); - buffer_init(berr); - - enter_raw_mode(); -} - -static void -client_process_net_input(fd_set * readset) -{ - int len; - char buf[8192]; - - /* - * Read input from the server, and add any such data to the buffer of - * the packet subsystem. - */ - if (FD_ISSET(connection_in, readset)) { - /* Read as much as possible. */ - len = read(connection_in, buf, sizeof(buf)); - if (len == 0) { - /* Received EOF. The remote host has closed the connection. */ - snprintf(buf, sizeof buf, - gettext("Connection to %.300s closed " - "by remote host.\n"), - host); - buffer_append(&stderr_buffer, buf, strlen(buf)); - quit_pending = 1; - return; - } - /* - * There is a kernel bug on Solaris that causes select to - * sometimes wake up even though there is no data available. - */ - if (len < 0 && (errno == EAGAIN || errno == EINTR)) - len = 0; - - if (len < 0) { - /* An error has encountered. Perhaps there is a network problem. */ - snprintf(buf, sizeof buf, - gettext("Read from remote host " - "%.300s: %.100s\n"), - host, strerror(errno)); - buffer_append(&stderr_buffer, buf, strlen(buf)); - quit_pending = 1; - return; - } - packet_process_incoming(buf, len); - } -} - -static void -process_cmdline(void) -{ - void (*handler)(int); - char *s, *cmd; - int delete = 0; - int local = 0; - Forward fwd; - - memset(&fwd, 0, sizeof(fwd)); - - leave_raw_mode(); - handler = signal(SIGINT, SIG_IGN); - cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); - if (s == NULL) - goto out; - while (isspace(*s)) - s++; - if (*s == '-') - s++; /* Skip cmdline '-', if any */ - if (*s == '\0') - goto out; - - if (*s == 'h' || *s == 'H' || *s == '?') { - log("Commands:"); - log(" -L[bind_address:]port:host:hostport " - "Request local forward"); - log(" -R[bind_address:]port:host:hostport " - "Request remote forward"); - log(" -KR[bind_address:]port " - "Cancel remote forward"); - goto out; - } - - if (*s == 'K') { - delete = 1; - s++; - } - if (*s != 'L' && *s != 'R') { - log("Invalid command."); - goto out; - } - if (*s == 'L') - local = 1; - if (local && delete) { - log("Not supported."); - goto out; - } - if ((!local || delete) && !compat20) { - log("Not supported for SSH protocol version 1."); - goto out; - } - - while (isspace(*++s)) - ; - - if (delete) { - if (parse_forward(0, &fwd, s) == 0) { - log("Bad forwarding close port"); - goto out; - } - channel_request_rforward_cancel(fwd.listen_host, fwd.listen_port); - } else { - if (parse_forward(1, &fwd, s) == 0) { - log("Bad forwarding specification."); - goto out; - } - if (local) { - if (channel_setup_local_fwd_listener(fwd.listen_host, - fwd.listen_port, fwd.connect_host, - fwd.connect_port, options.gateway_ports) < 0) { - log("Port forwarding failed."); - goto out; - } - } else { - if (channel_request_remote_forwarding(fwd.listen_host, - fwd.listen_port, fwd.connect_host, - fwd.connect_port) < 0) { - log("Port forwarding failed."); - goto out; - } - } - - log("Forwarding port."); - } - -out: - signal(SIGINT, handler); - enter_raw_mode(); - if (cmd != NULL) - xfree(cmd); - if (fwd.listen_host != NULL) - xfree(fwd.listen_host); - if (fwd.connect_host != NULL) - xfree(fwd.connect_host); -} - -/* - * If we are using the engine we must not fork until we do key reexchange. See - * PKCS#11 spec for more information on fork safety and packet.c for information - * about forking with the engine. - */ -void -client_daemonize(void) -{ - if (compat20 == 1 && options.use_openssl_engine == 1) { - will_daemonize = 1; - debug("must rekey before daemonizing"); - kex_send_kexinit(xxx_kex); - need_rekeying = 0; - } - else { - if (daemon(1, 1) < 0) { - fatal("daemon() failed: %.200s", - strerror(errno)); - } - } -} - -/* process the characters one by one */ -static int -process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) -{ - char string[1536]; - int bytes = 0; - u_int i; - u_char ch; - char *s; - - for (i = 0; i < len; i++) { - /* Get one character at a time. */ - ch = buf[i]; - - if (escape_pending) { - /* We have previously seen an escape character. */ - /* Clear the flag now. */ - escape_pending = 0; - - /* Process the escaped character. */ - switch (ch) { - case '.': - /* Terminate the connection. */ - snprintf(string, sizeof string, "%c.\r\n", escape_char); - buffer_append(berr, string, strlen(string)); - - quit_pending = 1; - return -1; - - case 'Z' - 64: - /* Suspend the program. */ - /* Print a message to that effect to the user. */ - snprintf(string, sizeof string, - gettext("%c^Z [suspend ssh]\n"), - escape_char); - buffer_append(berr, string, strlen(string)); - - /* Restore terminal modes and suspend. */ - client_suspend_self(bin, bout, berr); - - /* We have been continued. */ - continue; - - case 'B': - if (compat20) { - snprintf(string, sizeof string, - gettext("%cB [sent break]\n"), - escape_char); - buffer_append(berr, string, - strlen(string)); - channel_request_start(session_ident, - "break", 0); - packet_put_int(1000); - packet_send(); - } - continue; - - case 'R': - if (compat20) { - if (datafellows & SSH_BUG_NOREKEY) - log("Server does not support re-keying"); - else - need_rekeying = 1; - } - continue; - - case '&': - /* - * Detach the program (continue to serve connections, - * but put in background and no more new connections). - */ - /* Restore tty modes. */ - leave_raw_mode(); - - /* Stop listening for new connections. */ - channel_stop_listening(); - - snprintf(string, sizeof string, - gettext("%c& [backgrounded]\n"), - escape_char); - buffer_append(berr, string, strlen(string)); - - client_daemonize(); - - /* The child continues serving connections. */ - if (compat20) { - buffer_append(bin, "\004", 1); - /* fake EOF on stdin */ - return -1; - } else if (!stdin_eof) { - /* - * Sending SSH_CMSG_EOF alone does not always appear - * to be enough. So we try to send an EOF character - * first. - */ - packet_start(SSH_CMSG_STDIN_DATA); - packet_put_string("\004", 1); - packet_send(); - /* Close stdin. */ - stdin_eof = 1; - if (buffer_len(bin) == 0) { - packet_start(SSH_CMSG_EOF); - packet_send(); - } - } - continue; - - case '?': - snprintf(string, sizeof string, gettext( -"%c?\n\ -Supported escape sequences:\n\ -%c. - terminate connection\n\ -%cB - send break (SSH protocol 2 only)\n\ -%cC - open a command line\n\ -%cR - Request rekey (SSH protocol 2 only)\n\ -%c^Z - suspend ssh\n\ -%c# - list forwarded connections\n\ -%c& - background ssh (when waiting for connections to terminate)\n\ -%c? - this message\n\ -%c%c - send the escape character by typing it twice\n\ -(Note that escapes are only recognized immediately after newline.)\n"), - escape_char, escape_char, escape_char, escape_char, - escape_char, escape_char, escape_char, escape_char, - escape_char, escape_char); - buffer_append(berr, string, strlen(string)); - continue; - - case '#': - snprintf(string, sizeof string, "%c#\r\n", escape_char); - buffer_append(berr, string, strlen(string)); - s = channel_open_message(); - buffer_append(berr, s, strlen(s)); - xfree(s); - continue; - - case 'C': - process_cmdline(); - continue; - - default: - if (ch != escape_char) { - buffer_put_char(bin, escape_char); - bytes++; - } - /* Escaped characters fall through here */ - break; - } - } else { - /* - * The previous character was not an escape char. Check if this - * is an escape. - */ - if (last_was_cr && ch == escape_char) { - /* It is. Set the flag and continue to next character. */ - escape_pending = 1; - continue; - } - } - - /* - * Normal character. Record whether it was a newline, - * and append it to the buffer. - */ - last_was_cr = (ch == '\r' || ch == '\n'); - buffer_put_char(bin, ch); - bytes++; - } - return bytes; -} - -static void -client_process_input(fd_set * readset) -{ - int len; - char buf[8192]; - - /* Read input from stdin. */ - if (FD_ISSET(fileno(stdin), readset)) { - /* Read as much as possible. */ - len = read(fileno(stdin), buf, sizeof(buf)); - if (len < 0 && (errno == EAGAIN || errno == EINTR)) - return; /* we'll try again later */ - if (len <= 0) { - /* - * Received EOF or error. They are treated - * similarly, except that an error message is printed - * if it was an error condition. - */ - if (len < 0) { - snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); - buffer_append(&stderr_buffer, buf, strlen(buf)); - } - /* Mark that we have seen EOF. */ - stdin_eof = 1; - /* - * Send an EOF message to the server unless there is - * data in the buffer. If there is data in the - * buffer, no message will be sent now. Code - * elsewhere will send the EOF when the buffer - * becomes empty if stdin_eof is set. - */ - if (buffer_len(&stdin_buffer) == 0) { - packet_start(SSH_CMSG_EOF); - packet_send(); - } - } else if (escape_char == SSH_ESCAPECHAR_NONE) { - /* - * Normal successful read, and no escape character. - * Just append the data to buffer. - */ - buffer_append(&stdin_buffer, buf, len); - } else { - /* - * Normal, successful read. But we have an escape character - * and have to process the characters one by one. - */ - if (process_escapes(&stdin_buffer, &stdout_buffer, - &stderr_buffer, buf, len) == -1) - return; - } - } -} - -static void -client_process_output(fd_set * writeset) -{ - int len; - char buf[100]; - - /* Write buffered output to stdout. */ - if (FD_ISSET(fileno(stdout), writeset)) { - /* Write as much data as possible. */ - len = write(fileno(stdout), buffer_ptr(&stdout_buffer), - buffer_len(&stdout_buffer)); - if (len <= 0) { - if (errno == EINTR || errno == EAGAIN) - len = 0; - else { - /* - * An error or EOF was encountered. Put an - * error message to stderr buffer. - */ - snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); - buffer_append(&stderr_buffer, buf, strlen(buf)); - quit_pending = 1; - return; - } - } - /* Consume printed data from the buffer. */ - buffer_consume(&stdout_buffer, len); - stdout_bytes += len; - } - /* Write buffered output to stderr. */ - if (FD_ISSET(fileno(stderr), writeset)) { - /* Write as much data as possible. */ - len = write(fileno(stderr), buffer_ptr(&stderr_buffer), - buffer_len(&stderr_buffer)); - if (len <= 0) { - if (errno == EINTR || errno == EAGAIN) - len = 0; - else { - /* EOF or error, but can't even print error message. */ - quit_pending = 1; - return; - } - } - /* Consume printed characters from the buffer. */ - buffer_consume(&stderr_buffer, len); - stderr_bytes += len; - } -} - -/* - * Get packets from the connection input buffer, and process them as long as - * there are packets available. - * - * Any unknown packets received during the actual - * session cause the session to terminate. This is - * intended to make debugging easier since no - * confirmations are sent. Any compatible protocol - * extensions must be negotiated during the - * preparatory phase. - */ - -static void -client_process_buffered_input_packets(void) -{ - dispatch_run(DISPATCH_NONBLOCK, &quit_pending, compat20 ? xxx_kex : NULL); -} - -/* scan buf[] for '~' before sending data to the peer */ - -static int -simple_escape_filter(Channel *c, char *buf, int len) -{ - /* XXX we assume c->extended is writeable */ - return process_escapes(&c->input, &c->output, &c->extended, buf, len); -} - -static void -client_channel_closed(int id, void *arg) -{ - if (id != session_ident) - error("client_channel_closed: id %d != session_ident %d", - id, session_ident); - channel_cancel_cleanup(id); - session_closed = 1; - if (in_raw_mode()) - leave_raw_mode(); -} - -/* - * Implements the interactive session with the server. This is called after - * the user has been authenticated, and a command has been started on the - * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character - * used as an escape character for terminating or suspending the session. - */ - -int -client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) -{ - fd_set *readset = NULL, *writeset = NULL; - double start_time, total_time; - int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; - char buf[100]; - - debug("Entering interactive session."); - - start_time = get_current_time(); - - /* Initialize variables. */ - escape_pending = 0; - last_was_cr = 1; - exit_status = -1; - stdin_eof = 0; - buffer_high = 64 * 1024; - connection_in = packet_get_connection_in(); - connection_out = packet_get_connection_out(); - max_fd = MAX(connection_in, connection_out); - - if (!compat20) { - /* enable nonblocking unless tty */ - if (!isatty(fileno(stdin))) - set_nonblock(fileno(stdin)); - if (!isatty(fileno(stdout))) - set_nonblock(fileno(stdout)); - if (!isatty(fileno(stderr))) - set_nonblock(fileno(stderr)); - max_fd = MAX(max_fd, fileno(stdin)); - max_fd = MAX(max_fd, fileno(stdout)); - max_fd = MAX(max_fd, fileno(stderr)); - } - stdin_bytes = 0; - stdout_bytes = 0; - stderr_bytes = 0; - quit_pending = 0; - escape_char = escape_char_arg; - - /* Initialize buffers. */ - buffer_init(&stdin_buffer); - buffer_init(&stdout_buffer); - buffer_init(&stderr_buffer); - - client_init_dispatch(); - - /* - * Set signal handlers to restore non-blocking mode, but - * don't overwrite SIG_IGN - matches behavious from rsh(1). - */ - if (signal(SIGINT, SIG_IGN) != SIG_IGN) - signal(SIGINT, signal_handler); - if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) - signal(SIGQUIT, signal_handler); - if (signal(SIGTERM, SIG_IGN) != SIG_IGN) - signal(SIGTERM, signal_handler); - if (have_pty) - signal(SIGWINCH, window_change_handler); - - if (have_pty) - enter_raw_mode(); - - if (compat20) { - session_ident = ssh2_chan_id; - if (escape_char != SSH_ESCAPECHAR_NONE) - channel_register_filter(session_ident, - simple_escape_filter); - if (session_ident != -1) - channel_register_cleanup(session_ident, - client_channel_closed); - } else { - /* Check if we should immediately send eof on stdin. */ - client_check_initial_eof_on_stdin(); - } - - /* Main loop of the client for the interactive session mode. */ - while (!quit_pending) { - - /* Process buffered packets sent by the server. */ - client_process_buffered_input_packets(); - - if (compat20 && session_closed && !channel_still_open()) - break; - - rekeying = (xxx_kex != NULL && !xxx_kex->done); - - if (rekeying) { - debug("rekeying in progress"); - } else { - /* - * Make packets of buffered stdin data, and buffer - * them for sending to the server. - */ - if (!compat20) - client_make_packets_from_stdin_data(); - - /* - * Make packets from buffered channel data, and - * enqueue them for sending to the server. - */ - if (packet_not_very_much_data_to_write()) - channel_output_poll(); - - /* - * Check if the window size has changed, and buffer a - * message about it to the server if so. - */ - client_check_window_change(); - - if (quit_pending) - break; - } - /* - * Wait until we have something to do (something becomes - * available on one of the descriptors). - */ - max_fd2 = max_fd; - client_wait_until_can_do_something(&readset, &writeset, - &max_fd2, &nalloc, rekeying); - - if (quit_pending) - break; - - /* Do channel operations unless rekeying in progress. */ - if (!rekeying) { - channel_after_select(readset, writeset); - if (need_rekeying || packet_need_rekeying()) { - debug("rekey limit reached, need rekeying"); - kex_send_kexinit(xxx_kex); - need_rekeying = 0; - } - } - - /* Buffer input from the connection. */ - client_process_net_input(readset); - - if (quit_pending) - break; - - if (!compat20) { - /* Buffer data from stdin */ - client_process_input(readset); - /* - * Process output to stdout and stderr. Output to - * the connection is processed elsewhere (above). - */ - client_process_output(writeset); - } - - /* Send as much buffered packet data as possible to the sender. */ - if (FD_ISSET(connection_out, writeset)) - packet_write_poll(); - } - if (readset) - xfree(readset); - if (writeset) - xfree(writeset); - - /* Terminate the session. */ - - /* Stop watching for window change. */ - if (have_pty) - signal(SIGWINCH, SIG_DFL); - - channel_free_all(); - - if (have_pty) - leave_raw_mode(); - - /* restore blocking io */ - if (!isatty(fileno(stdin))) - unset_nonblock(fileno(stdin)); - if (!isatty(fileno(stdout))) - unset_nonblock(fileno(stdout)); - if (!isatty(fileno(stderr))) - unset_nonblock(fileno(stderr)); - - if (received_signal) { - if (in_non_blocking_mode) /* XXX */ - leave_non_blocking(); - fatal("Killed by signal %d.", (int) received_signal); - } - - /* - * In interactive mode (with pseudo tty) display a message indicating - * that the connection has been closed. - */ - if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { - snprintf(buf, sizeof buf, - gettext("Connection to %.64s closed.\n"), - host); - buffer_append(&stderr_buffer, buf, strlen(buf)); - } - - /* Output any buffered data for stdout. */ - while (buffer_len(&stdout_buffer) > 0) { - len = write(fileno(stdout), buffer_ptr(&stdout_buffer), - buffer_len(&stdout_buffer)); - if (len <= 0) { - error("Write failed flushing stdout buffer."); - break; - } - buffer_consume(&stdout_buffer, len); - stdout_bytes += len; - } - - /* Output any buffered data for stderr. */ - while (buffer_len(&stderr_buffer) > 0) { - len = write(fileno(stderr), buffer_ptr(&stderr_buffer), - buffer_len(&stderr_buffer)); - if (len <= 0) { - error("Write failed flushing stderr buffer."); - break; - } - buffer_consume(&stderr_buffer, len); - stderr_bytes += len; - } - - /* Clear and free any buffers. */ - memset(buf, 0, sizeof(buf)); - buffer_free(&stdin_buffer); - buffer_free(&stdout_buffer); - buffer_free(&stderr_buffer); - - /* Report bytes transferred, and transfer rates. */ - total_time = get_current_time() - start_time; - debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", - stdin_bytes, stdout_bytes, stderr_bytes, total_time); - if (total_time > 0) - debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", - stdin_bytes / total_time, stdout_bytes / total_time, - stderr_bytes / total_time); - - /* Return the exit status of the program. */ - debug("Exit status %d", exit_status); - return exit_status; -} - -/*********/ - -static void -client_input_stdout_data(int type, u_int32_t seq, void *ctxt) -{ - u_int data_len; - char *data = packet_get_string(&data_len); - packet_check_eom(); - buffer_append(&stdout_buffer, data, data_len); - memset(data, 0, data_len); - xfree(data); -} -static void -client_input_stderr_data(int type, u_int32_t seq, void *ctxt) -{ - u_int data_len; - char *data = packet_get_string(&data_len); - packet_check_eom(); - buffer_append(&stderr_buffer, data, data_len); - memset(data, 0, data_len); - xfree(data); -} -static void -client_input_exit_status(int type, u_int32_t seq, void *ctxt) -{ - exit_status = packet_get_int(); - packet_check_eom(); - /* Acknowledge the exit. */ - packet_start(SSH_CMSG_EXIT_CONFIRMATION); - packet_send(); - /* - * Must wait for packet to be sent since we are - * exiting the loop. - */ - packet_write_wait(); - /* Flag that we want to exit. */ - quit_pending = 1; -} - -static Channel * -client_request_forwarded_tcpip(const char *request_type, int rchan) -{ - Channel *c = NULL; - char *listen_address, *originator_address; - int listen_port, originator_port; - int sock; - - /* Get rest of the packet */ - listen_address = packet_get_string(NULL); - listen_port = packet_get_int(); - originator_address = packet_get_string(NULL); - originator_port = packet_get_int(); - packet_check_eom(); - - debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", - listen_address, listen_port, originator_address, originator_port); - - sock = channel_connect_by_listen_address(listen_port); - if (sock < 0) { - xfree(originator_address); - xfree(listen_address); - return NULL; - } - c = channel_new("forwarded-tcpip", - SSH_CHANNEL_CONNECTING, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - xstrdup(originator_address), 1); - xfree(originator_address); - xfree(listen_address); - return c; -} - -static Channel * -client_request_x11(const char *request_type, int rchan) -{ - Channel *c = NULL; - char *originator; - int originator_port; - int sock; - - if (!options.forward_x11) { - error("Warning: ssh server tried X11 forwarding."); - error("Warning: this is probably a break in attempt by a malicious server."); - return NULL; - } - originator = packet_get_string(NULL); - if (datafellows & SSH_BUG_X11FWD) { - debug2("buggy server: x11 request w/o originator_port"); - originator_port = 0; - } else { - originator_port = packet_get_int(); - } - packet_check_eom(); - /* XXX check permission */ - debug("client_request_x11: request from %s %d", originator, - originator_port); - xfree(originator); - sock = x11_connect_display(); - if (sock < 0) - return NULL; - c = channel_new("x11", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, - xstrdup("x11"), 1); - c->force_drain = 1; - return c; -} - -static Channel * -client_request_agent(const char *request_type, int rchan) -{ - Channel *c = NULL; - int sock; - - if (!options.forward_agent) { - error("Warning: ssh server tried agent forwarding."); - error("Warning: this is probably a break in attempt by a malicious server."); - return NULL; - } - sock = ssh_get_authentication_socket(); - if (sock < 0) - return NULL; - c = channel_new("authentication agent connection", - SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - xstrdup("authentication agent connection"), 1); - c->force_drain = 1; - return c; -} - -/* XXXX move to generic input handler */ -static void -client_input_channel_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - char *ctype; - int rchan; - u_int rmaxpack, rwindow, len; - - ctype = packet_get_string(&len); - rchan = packet_get_int(); - rwindow = packet_get_int(); - rmaxpack = packet_get_int(); - - debug("client_input_channel_open: ctype %s rchan %d win %d max %d", - ctype, rchan, rwindow, rmaxpack); - - if (strcmp(ctype, "forwarded-tcpip") == 0) { - c = client_request_forwarded_tcpip(ctype, rchan); - } else if (strcmp(ctype, "x11") == 0) { - c = client_request_x11(ctype, rchan); - } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { - c = client_request_agent(ctype, rchan); - } -/* XXX duplicate : */ - if (c != NULL) { - debug("confirm %s", ctype); - c->remote_id = rchan; - c->remote_window = rwindow; - c->remote_maxpacket = rmaxpack; - if (c->type != SSH_CHANNEL_CONNECTING) { - packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - packet_send(); - } - } else { - debug("failure %s", ctype); - packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(rchan); - packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); - if (!(datafellows & SSH_BUG_OPENFAILURE)) { - packet_put_utf8_cstring("open failed"); - packet_put_cstring(""); - } - packet_send(); - } - xfree(ctype); -} - -static void -client_input_channel_req(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - int id, reply, success = 0; - char *rtype; - - id = packet_get_int(); - rtype = packet_get_string(NULL); - reply = packet_get_char(); - - debug("client_input_channel_req: channel %d rtype %s reply %d", - id, rtype, reply); - - if (session_ident == -1) { - error("client_input_channel_req: no channel %d", session_ident); - } else if (id != session_ident) { - error("client_input_channel_req: channel %d: wrong channel: %d", - session_ident, id); - } - c = channel_lookup(id); - if (c == NULL) { - error("client_input_channel_req: channel %d: unknown channel", id); - } else if (strcmp(rtype, "eow@openssh.com") == 0) { - packet_check_eom(); - chan_rcvd_eow(c); - } else if (strcmp(rtype, "exit-status") == 0) { - success = 1; - exit_status = packet_get_int(); - packet_check_eom(); - } - if (reply) { - packet_start(success ? - SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(c->remote_id); - packet_send(); - } - xfree(rtype); -} - -static void -client_input_global_request(int type, u_int32_t seq, void *ctxt) -{ - char *rtype; - int want_reply; - int success = 0; - - rtype = packet_get_string(NULL); - want_reply = packet_get_char(); - debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply); - if (want_reply) { - packet_start(success ? - SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); - packet_send(); - packet_write_wait(); - } - xfree(rtype); -} - -static void -client_init_dispatch_20(void) -{ - dispatch_init(&dispatch_protocol_error); - - dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); - dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); - dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); - dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open); - dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); - dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); - dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); - dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); - - /* rekeying */ - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); - - /* global request reply messages */ - dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); - dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); -} - -static void -client_init_dispatch_13(void) -{ - dispatch_init(NULL); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); - dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); - dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); - dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status); - dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data); - dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data); - - dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ? - &auth_input_open_request : &deny_input_open); - dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? - &x11_input_open : &deny_input_open); -} - -static void -client_init_dispatch_15(void) -{ - client_init_dispatch_13(); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); -} - -static void -client_init_dispatch(void) -{ - if (compat20) - client_init_dispatch_20(); - else if (compat13) - client_init_dispatch_13(); - else - client_init_dispatch_15(); -} diff --git a/usr/src/cmd/ssh/ssh/gss-clnt.c b/usr/src/cmd/ssh/ssh/gss-clnt.c deleted file mode 100644 index 05cd358217..0000000000 --- a/usr/src/cmd/ssh/ssh/gss-clnt.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -#ifdef GSSAPI - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "ssh.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "packet.h" -#include "compat.h" -#include <openssl/evp.h> -#include "cipher.h" -#include "kex.h" -#include "log.h" -#include "compat.h" - -#include <netdb.h> - -#include "ssh-gss.h" - -void -ssh_gssapi_client_kex_hook(Kex *kex, char **proposal) -{ - gss_OID_set mechs = GSS_C_NULL_OID_SET; - - if (kex == NULL || kex->serverhost == NULL) - fatal("INTERNAL ERROR (%s)", __func__); - - ssh_gssapi_client_mechs(kex->serverhost, &mechs); - ssh_gssapi_modify_kex(kex, mechs, proposal); -} - -void -ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) -{ - gss_OID_set indicated = GSS_C_NULL_OID_SET; - gss_OID_set acquired, supported; - gss_OID mech; - gss_cred_id_t creds; - Gssctxt *ctxt = NULL; - gss_buffer_desc tok; - OM_uint32 maj, min; - int i; - char *errmsg; - - if (!mechs) - return; - *mechs = GSS_C_NULL_OID_SET; - - maj = gss_indicate_mechs(&min, &indicated); - if (GSS_ERROR(maj)) { - debug("No GSS-API mechanisms are installed"); - return; - } - - maj = gss_create_empty_oid_set(&min, &supported); - if (GSS_ERROR(maj)) { - errmsg = ssh_gssapi_last_error(NULL, &maj, &min); - debug("Failed to allocate resources (%s) for GSS-API", errmsg); - xfree(errmsg); - (void) gss_release_oid_set(&min, &indicated); - return; - } - maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated, - GSS_C_INITIATE, &creds, &acquired, NULL); - - if (GSS_ERROR(maj)) { - errmsg = ssh_gssapi_last_error(NULL, &maj, &min); - debug("Failed to acquire GSS-API credentials for any " - "mechanisms (%s)", errmsg); - xfree(errmsg); - (void) gss_release_oid_set(&min, &indicated); - (void) gss_release_oid_set(&min, &supported); - return; - } - (void) gss_release_cred(&min, &creds); - - for (i = 0; i < acquired->count; i++) { - mech = &acquired->elements[i]; - - if (ssh_gssapi_is_spnego(mech)) - continue; - - ssh_gssapi_build_ctx(&ctxt, 1, mech); - if (!ctxt) - continue; - - /* - * This is useful for mechs like Kerberos, which can - * detect unknown target princs here, but not for - * mechs like SPKM, which cannot detect unknown princs - * until context tokens are actually exchanged. - * - * 'Twould be useful to have a test that could save us - * the bother of trying this for SPKM and the such... - */ - maj = ssh_gssapi_init_ctx(ctxt, server_host, 0, NULL, &tok); - if (GSS_ERROR(maj)) { - errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL); - debug("Skipping GSS-API mechanism %s (%s)", - ssh_gssapi_oid_to_name(mech), errmsg); - xfree(errmsg); - continue; - } - - (void) gss_release_buffer(&min, &tok); - - maj = gss_add_oid_set_member(&min, mech, &supported); - if (GSS_ERROR(maj)) { - errmsg = ssh_gssapi_last_error(NULL, &maj, &min); - debug("Failed to allocate resources (%s) for GSS-API", - errmsg); - xfree(errmsg); - } - } - - *mechs = supported; -} - - -/* - * Wrapper to init_sec_context. Requires that the context contains: - * - * oid - * server name (from ssh_gssapi_import_name) - */ -OM_uint32 -ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, int deleg_creds, - gss_buffer_t recv_tok, gss_buffer_t send_tok) -{ - int flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; - - debug("%s(%p, %s, %d, %p, %p)", __func__, ctx, server_host, - deleg_creds, recv_tok, send_tok); - - if (deleg_creds) { - flags |= GSS_C_DELEG_FLAG; - debug("Delegating GSS-API credentials"); - } - - /* Build target principal */ - if (ctx->desired_name == GSS_C_NO_NAME && - !ssh_gssapi_import_name(ctx, server_host)) { - return (ctx->major); - } - - ctx->major = gss_init_sec_context(&ctx->minor, GSS_C_NO_CREDENTIAL, - &ctx->context, ctx->desired_name, ctx->desired_mech, flags, - 0, /* default lifetime */ - NULL, /* no channel bindings */ - recv_tok, - NULL, /* actual mech type */ - send_tok, &ctx->flags, - NULL); /* actual lifetime */ - - if (GSS_ERROR(ctx->major)) - ssh_gssapi_error(ctx, "calling GSS_Init_sec_context()"); - - return (ctx->major); -} -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/ssh/ssh.c b/usr/src/cmd/ssh/ssh/ssh.c deleted file mode 100644 index d122875470..0000000000 --- a/usr/src/cmd/ssh/ssh/ssh.c +++ /dev/null @@ -1,1245 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Ssh client program. This program can be used to log into a remote machine. - * The software supports strong authentication, encryption, and forwarding - * of X11, TCP/IP, and authentication connections. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * Copyright (c) 1999 Niels Provos. All rights reserved. - * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. - * - * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> - * in Canada (German citizen). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.186 2002/09/19 01:58:18 djm Exp $"); - -#include <openssl/err.h> - -#include "ssh.h" -#include "ssh1.h" -#include "ssh2.h" -#include "compat.h" -#include "cipher.h" -#include "xmalloc.h" -#include "packet.h" -#include "buffer.h" -#include "channels.h" -#include "key.h" -#include "authfd.h" -#include "authfile.h" -#include "pathnames.h" -#include "clientloop.h" -#include "log.h" -#include "readconf.h" -#include "sshconnect.h" -#include "tildexpand.h" -#include "dispatch.h" -#include "misc.h" -#include "kex.h" -#include "mac.h" -#include "sshtty.h" - -#include "g11n.h" - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. - Default value is AF_UNSPEC means both IPv4 and IPv6. */ -#ifdef IPV4_DEFAULT -int IPv4or6 = AF_INET; -#else -int IPv4or6 = AF_UNSPEC; -#endif - -/* Flag indicating whether debug mode is on. This can be set on the command line. */ -int debug_flag = 0; - -/* Flag indicating whether a tty should be allocated */ -int tty_flag = 0; -int no_tty_flag = 0; -int force_tty_flag = 0; - -/* don't exec a shell */ -int no_shell_flag = 0; - -/* - * Flag indicating that nothing should be read from stdin. This can be set - * on the command line. - */ -int stdin_null_flag = 0; - -/* - * Flag indicating that ssh should fork after authentication. This is useful - * so that the passphrase can be entered manually, and then ssh goes to the - * background. - */ -int fork_after_authentication_flag = 0; - -/* - * General data structure for command line options and options configurable - * in configuration files. See readconf.h. - */ -Options options; - -/* optional user configfile */ -char *config = NULL; - -/* - * Name of the host we are connecting to. This is the name given on the - * command line, or the HostName specified for the user-supplied name in a - * configuration file. - */ -char *host; - -/* socket address the host resolves to */ -struct sockaddr_storage hostaddr; - -/* Private host keys. */ -Sensitive sensitive_data; - -/* Original real UID. */ -uid_t original_real_uid; -uid_t original_effective_uid; - -/* command to be executed */ -Buffer command; - -/* Should we execute a command or invoke a subsystem? */ -int subsystem_flag = 0; - -/* # of replies received for global requests */ -static int client_global_request_id = 0; - -/* pid of proxycommand child process */ -pid_t proxy_command_pid = 0; - -/* Prints a help message to the user. This function never returns. */ - -static void -usage(void) -{ - fprintf(stderr, - gettext("Usage: %s [options] host [command]\n" - "Options:\n" - " -l user Log in using this user name.\n" - " -n Redirect input from /dev/null.\n" - " -F config Config file (default: ~/%s).\n" - " -A Enable authentication agent forwarding.\n" - " -a Disable authentication agent forwarding " - "(default).\n" -#ifdef AFS - " -k Disable Kerberos ticket and AFS token " - "forwarding.\n" -#endif /* AFS */ - " -X Enable X11 connection forwarding.\n" - " -x Disable X11 connection forwarding (default).\n" - " -i file Identity for public key authentication " - "(default: ~/.ssh/identity)\n" - " -t Tty; allocate a tty even if command is given.\n" - " -T Do not allocate a tty.\n" - " -v Verbose; display verbose debugging messages.\n" - " Multiple -v increases verbosity.\n" - " -V Display version number only.\n" - " -q Quiet; don't display any warning messages.\n" - " -f Fork into background after authentication.\n" - " -e char Set escape character; ``none'' = disable " - "(default: ~).\n" - " -c cipher Select encryption algorithm\n" - " -m macs Specify MAC algorithms for protocol version 2.\n" - " -p port Connect to this port. Server must be " - "on the same port.\n" - " -L listen-port:host:port Forward local port to " - "remote address\n" - " -R listen-port:host:port Forward remote port to " - "local address\n" - " These cause %s to listen for connections " - "on a port, and\n" - " forward them to the other side by " - "connecting to host:port.\n" - " -D port Enable dynamic application-level " - "port forwarding.\n" - " -C Enable compression.\n" - " -N Do not execute a shell or command.\n" - " -g Allow remote hosts to connect to forwarded " - "ports.\n" - " -1 Force protocol version 1.\n" - " -2 Force protocol version 2.\n" - " -4 Use IPv4 only.\n" - " -6 Use IPv6 only.\n" - " -o 'option' Process the option as if it was read " - "from a configuration file.\n" - " -s Invoke command (mandatory) as SSH2 subsystem.\n" - " -b addr Local IP address.\n"), - __progname, _PATH_SSH_USER_CONFFILE, __progname); - exit(1); -} - -static int ssh_session(void); -static int ssh_session2(void); -static void load_public_identity_files(void); -static void rsh_connect(char *host, char *user, Buffer * command); - -/* - * Main program for the ssh client. - */ -int -main(int ac, char **av) -{ - int i, opt, exit_status; - char *p, *cp, buf[256], *pw_name, *pw_dir; - struct stat st; - struct passwd *pw; - int dummy; - extern int optind, optreset; - extern char *optarg; - Forward fwd; - - __progname = get_progname(av[0]); - - (void) g11n_setlocale(LC_ALL, ""); - - init_rng(); - - /* - * Save the original real uid. It will be needed later (uid-swapping - * may clobber the real uid). - */ - original_real_uid = getuid(); - original_effective_uid = geteuid(); - - /* - * Use uid-swapping to give up root privileges for the duration of - * option processing. We will re-instantiate the rights when we are - * ready to create the privileged port, and will permanently drop - * them when the port has been created (actually, when the connection - * has been made, as we may need to create the port several times). - */ - PRIV_END; - -#ifdef HAVE_SETRLIMIT - /* If we are installed setuid root be careful to not drop core. */ - if (original_real_uid != original_effective_uid) { - struct rlimit rlim; - rlim.rlim_cur = rlim.rlim_max = 0; - if (setrlimit(RLIMIT_CORE, &rlim) < 0) - fatal("setrlimit failed: %.100s", strerror(errno)); - } -#endif - /* - * Get user data. It may happen that NIS or LDAP connection breaks down - * during the user's session. We should try to do our best and use the - * HOME and LOGNAME variables. Remember that the SSH client might be the - * only tool available to fix the problem with the naming services. - */ - pw = getpwuid(original_real_uid); - if (pw == NULL) { - if ((pw_dir = getenv("HOME")) == NULL) { - log("User account's password entry not found and HOME " - "not set. Set it manually and try again. " - "Exiting."); - exit(1); - } - log("User account's password entry not found, using " - "the HOME variable."); - - if ((pw_name = getenv("LOGNAME")) == NULL) { - log("Need a local user name but LOGNAME is not set. " - "Set it manually and try again. Exiting."); - exit(1); - } - log("Local user name '%s' set from the LOGNAME variable.", - pw_name); - - pw_dir = xstrdup(pw_dir); - pw_name = xstrdup(pw_name); - } else { - pw_name = xstrdup(pw->pw_name); - pw_dir = xstrdup(pw->pw_dir); - } - - /* - * Set our umask to something reasonable, as some files are created - * with the default umask. This will make them world-readable but - * writable only by the owner, which is ok for all files for which we - * don't set the modes explicitly. - */ - umask(022); - - /* Initialize option structure to indicate that no values have been set. */ - initialize_options(&options); - - /* Parse command-line arguments. */ - host = NULL; - -again: - while ((opt = getopt(ac, av, - "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) { - switch (opt) { - case '1': - options.protocol = SSH_PROTO_1; - break; - case '2': - options.protocol = SSH_PROTO_2; - break; - case '4': - IPv4or6 = AF_INET; - break; - case '6': - IPv4or6 = AF_INET6; - break; - case 'n': - stdin_null_flag = 1; - break; - case 'f': - fork_after_authentication_flag = 1; - stdin_null_flag = 1; - break; - case 'x': - options.forward_x11 = 0; - break; - case 'X': - options.forward_x11 = 1; - break; - case 'g': - options.gateway_ports = 1; - break; - case 'P': /* deprecated */ - fprintf(stderr, gettext("Warning: Option -P has " - "been deprecated\n")); - options.use_privileged_port = 0; - break; - case 'a': - options.forward_agent = 0; - break; - case 'A': - options.forward_agent = 1; - break; -#ifdef AFS - case 'k': - options.kerberos_tgt_passing = 0; - options.afs_token_passing = 0; - break; -#endif - case 'i': - if (stat(optarg, &st) < 0) { - fprintf(stderr, - gettext("Warning: Identity file %s " - "does not exist.\n"), optarg); - break; - } - if (options.num_identity_files >= - SSH_MAX_IDENTITY_FILES) - fatal("Too many identity files specified " - "(max %d)", SSH_MAX_IDENTITY_FILES); - options.identity_files[options.num_identity_files++] = - xstrdup(optarg); - break; - case 'I': - fprintf(stderr, "no support for smartcards.\n"); - break; - case 't': - if (tty_flag) - force_tty_flag = 1; - tty_flag = 1; - break; - case 'v': - if (0 == debug_flag) { - debug_flag = 1; - options.log_level = SYSLOG_LEVEL_DEBUG1; - } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { - options.log_level++; - break; - } else - fatal("Too high debugging level."); - /* FALLTHROUGH */ - case 'V': - fprintf(stderr, - gettext("%s, SSH protocols %d.%d/%d.%d, " - "OpenSSL 0x%8.8lx\n"), - SSH_VERSION, - PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1, - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, - SSLeay()); - if (opt == 'V') - exit(0); - break; - case 'q': - options.log_level = SYSLOG_LEVEL_QUIET; - break; - case 'e': - if (optarg[0] == '^' && optarg[2] == 0 && - (u_char) optarg[1] >= 64 && - (u_char) optarg[1] < 128) - options.escape_char = (u_char) optarg[1] & 31; - else if (strlen(optarg) == 1) - options.escape_char = (u_char) optarg[0]; - else if (strcmp(optarg, "none") == 0) - options.escape_char = SSH_ESCAPECHAR_NONE; - else { - fprintf(stderr, - gettext("Bad escape character '%s'.\n"), - optarg); - exit(1); - } - break; - case 'c': - if (ciphers_valid(optarg)) { - /* SSH2 only */ - options.ciphers = xstrdup(optarg); - options.cipher = SSH_CIPHER_ILLEGAL; - } else { - /* SSH1 only */ - options.cipher = cipher_number(optarg); - if (options.cipher == -1) { - fprintf(stderr, - gettext("Unknown cipher " - "type '%s'\n"), - optarg); - exit(1); - } - if (options.cipher == SSH_CIPHER_3DES) - options.ciphers = "3des-cbc"; - else if (options.cipher == SSH_CIPHER_BLOWFISH) - options.ciphers = "blowfish-cbc"; - else - options.ciphers = (char *)-1; - } - break; - case 'm': - if (mac_valid(optarg)) - options.macs = xstrdup(optarg); - else { - fprintf(stderr, - gettext("Unknown mac type '%s'\n"), - optarg); - exit(1); - } - break; - case 'p': - options.port = a2port(optarg); - if (options.port == 0) { - fprintf(stderr, gettext("Bad port '%s'\n"), - optarg); - exit(1); - } - break; - case 'l': - options.user = optarg; - break; - - case 'L': - if (parse_forward(1, &fwd, optarg)) - add_local_forward(&options, &fwd); - else - fatal("Bad local forwarding specification " - "'%s'\n", optarg); - break; - - case 'R': - if (parse_forward(1, &fwd, optarg)) - add_remote_forward(&options, &fwd); - else - fatal("Bad remote forwarding specification " - "'%s'\n", optarg); - break; - - case 'D': - if (parse_forward(0, &fwd, optarg) == 0) - fatal("Bad dynamic forwarding specification " - "'%s'\n", optarg); - fwd.connect_host = "socks"; - add_local_forward(&options, &fwd); - break; - - case 'C': - options.compression = 1; - break; - case 'N': - no_shell_flag = 1; - no_tty_flag = 1; - break; - case 'T': - no_tty_flag = 1; - break; - case 'o': - dummy = 1; - if (process_config_line(&options, host ? host : "", - optarg, "command-line", 0, &dummy) != 0) - exit(1); - break; - case 's': - subsystem_flag = 1; - break; - case 'b': - options.bind_address = optarg; - break; - case 'F': - config = optarg; - break; - default: - usage(); - } - } - - ac -= optind; - av += optind; - - if (ac > 0 && !host && **av != '-') { - if (strchr(*av, '@')) { - p = xstrdup(*av); - cp = strchr(p, '@'); - if (cp == NULL || cp == p) - usage(); - options.user = p; - *cp = '\0'; - host = ++cp; - } else - host = *av; - ac--, av++; - if (ac > 0) { - optind = 0; - optreset = 1; - goto again; - } - } - - /* Check that we got a host name. */ - if (!host) - usage(); - - SSLeay_add_all_algorithms(); - ERR_load_crypto_strings(); - channel_set_af(IPv4or6); - - /* Initialize the command to execute on remote host. */ - buffer_init(&command); - - /* - * Save the command to execute on the remote host in a buffer. There - * is no limit on the length of the command, except by the maximum - * packet size. Also sets the tty flag if there is no command. - */ - if (!ac) { - /* No command specified - execute shell on a tty. */ - tty_flag = 1; - if (subsystem_flag) { - fprintf(stderr, - gettext("You must specify a subsystem " - "to invoke.\n")); - usage(); - } - } else { - /* A command has been specified. Store it into the buffer. */ - for (i = 0; i < ac; i++) { - if (i) - buffer_append(&command, " ", 1); - buffer_append(&command, av[i], strlen(av[i])); - } - } - - /* Cannot fork to background if no command. */ - if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag) - fatal("Cannot fork into background without a command to execute."); - - /* Allocate a tty by default if no command specified. */ - if (buffer_len(&command) == 0) - tty_flag = 1; - - /* Force no tty */ - if (no_tty_flag) - tty_flag = 0; - /* Do not allocate a tty if stdin is not a tty. */ - if (!isatty(fileno(stdin)) && !force_tty_flag) { - if (tty_flag) - log("Pseudo-terminal will not be allocated because stdin is not a terminal."); - tty_flag = 0; - } - - /* - * Initialize "log" output. Since we are the client all output - * actually goes to stderr. - */ - log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, - SYSLOG_FACILITY_USER, 1); - - /* - * Read per-user configuration file. Ignore the system wide config - * file if the user specifies a config file on the command line. - */ - if (config != NULL) { - if (!read_config_file(config, host, &options)) - fatal("Can't open user config file %.100s: " - "%.100s", config, strerror(errno)); - } else { - snprintf(buf, sizeof buf, "%.100s/%.100s", pw_dir, - _PATH_SSH_USER_CONFFILE); - (void)read_config_file(buf, host, &options); - - /* Read systemwide configuration file after use config. */ - (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); - } - - process_unknown_options(&options); - - /* Fill configuration defaults. */ - fill_default_options(&options); - - /* reinit */ - log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); - - seed_rng(); - - if (options.user == NULL) - options.user = xstrdup(pw_name); - - if (options.hostname != NULL) - host = options.hostname; - - /* Disable rhosts authentication if not running as root. */ -#ifdef HAVE_CYGWIN - /* Ignore uid if running under Windows */ - if (!options.use_privileged_port) { -#else - if (original_effective_uid != 0 || !options.use_privileged_port) { -#endif - debug("Rhosts Authentication disabled, " - "originating port will not be trusted."); - options.rhosts_authentication = 0; - } - /* Open a connection to the remote host. */ - - /* XXX OpenSSH has deprecated UseRsh */ - if (options.use_rsh) { - seteuid(original_real_uid); - setuid(original_real_uid); - rsh_connect(host, options.user, &command); - fatal("rsh_connect returned"); - } - - if (ssh_connect(host, &hostaddr, options.port, IPv4or6, - options.connection_attempts, -#ifdef HAVE_CYGWIN - options.use_privileged_port, -#else - original_effective_uid == 0 && options.use_privileged_port, -#endif - options.proxy_command) != 0) { - /* XXX OpenSSH has deprecated FallbackToRsh */ - if (options.fallback_to_rsh) { - seteuid(original_real_uid); - setuid(original_real_uid); - rsh_connect(host, options.user, &command); - fatal("rsh_connect returned"); - } - exit(1); - } - - /* - * If we successfully made the connection, load the host private key - * in case we will need it later for combined rsa-rhosts - * authentication. This must be done before releasing extra - * privileges, because the file is only readable by root. - * If we cannot access the private keys, load the public keys - * instead and try to execute the ssh-keysign helper instead. - */ - sensitive_data.nkeys = 0; - sensitive_data.keys = NULL; - sensitive_data.external_keysign = 0; - if (options.rhosts_rsa_authentication || - options.hostbased_authentication) { - sensitive_data.nkeys = 3; - sensitive_data.keys = xmalloc(sensitive_data.nkeys * - sizeof(Key)); - - PRIV_START; - sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, - _PATH_HOST_KEY_FILE, "", NULL); - sensitive_data.keys[1] = key_load_private_type(KEY_DSA, - _PATH_HOST_DSA_KEY_FILE, "", NULL); - sensitive_data.keys[2] = key_load_private_type(KEY_RSA, - _PATH_HOST_RSA_KEY_FILE, "", NULL); - PRIV_END; - - if (options.hostbased_authentication == 1 && - sensitive_data.keys[0] == NULL && - sensitive_data.keys[1] == NULL && - sensitive_data.keys[2] == NULL) { - sensitive_data.keys[1] = key_load_public( - _PATH_HOST_DSA_KEY_FILE, NULL); - sensitive_data.keys[2] = key_load_public( - _PATH_HOST_RSA_KEY_FILE, NULL); - sensitive_data.external_keysign = 1; - } - } - /* - * Get rid of any extra privileges that we may have. We will no - * longer need them. Also, extra privileges could make it very hard - * to read identity files and other non-world-readable files from the - * user's home directory if it happens to be on a NFS volume where - * root is mapped to nobody. - */ - seteuid(original_real_uid); - setuid(original_real_uid); - - /* - * Now that we are back to our own permissions, create ~/.ssh - * directory if it doesn\'t already exist. - */ - snprintf(buf, sizeof buf, "%.100s%s%.100s", pw_dir, - strcmp(pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); - xfree(pw_dir); - if (stat(buf, &st) < 0) - if (mkdir(buf, 0700) < 0) - error("Could not create directory '%.200s'.", buf); - - /* load options.identity_files */ - load_public_identity_files(); - - /* Expand ~ in known host file names. */ - /* XXX mem-leaks: */ - options.system_hostfile = - tilde_expand_filename(options.system_hostfile, original_real_uid); - options.user_hostfile = - tilde_expand_filename(options.user_hostfile, original_real_uid); - options.system_hostfile2 = - tilde_expand_filename(options.system_hostfile2, original_real_uid); - options.user_hostfile2 = - tilde_expand_filename(options.user_hostfile2, original_real_uid); - - signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ - - /* Log into the remote system. This never returns if the login fails. */ - ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw_name); - xfree(pw_name); - - /* We no longer need the private host keys. Clear them now. */ - if (sensitive_data.nkeys != 0) { - for (i = 0; i < sensitive_data.nkeys; i++) { - if (sensitive_data.keys[i] != NULL) { - /* Destroys contents safely */ - debug3("clear hostkey %d", i); - key_free(sensitive_data.keys[i]); - sensitive_data.keys[i] = NULL; - } - } - xfree(sensitive_data.keys); - } - for (i = 0; i < options.num_identity_files; i++) { - if (options.identity_files[i]) { - xfree(options.identity_files[i]); - options.identity_files[i] = NULL; - } - if (options.identity_keys[i]) { - key_free(options.identity_keys[i]); - options.identity_keys[i] = NULL; - } - } - - exit_status = compat20 ? ssh_session2() : ssh_session(); - packet_close(); - - /* - * Send SIGHUP to proxy command if used. We don't wait() in - * case it hangs and instead rely on init to reap the child - */ - if (proxy_command_pid > 1) - kill(proxy_command_pid, SIGHUP); - - return exit_status; -} - -static void -ssh_init_forwarding(void) -{ - int success = 0; - int i; - - /* Initiate local TCP/IP port forwardings. */ - for (i = 0; i < options.num_local_forwards; i++) { - debug("Local connections to %.200s:%d forwarded to remote " - "address %.200s:%d", - (options.local_forwards[i].listen_host == NULL) ? - (options.gateway_ports ? "*" : "LOCALHOST") : - options.local_forwards[i].listen_host, - options.local_forwards[i].listen_port, - options.local_forwards[i].connect_host, - options.local_forwards[i].connect_port); - success += channel_setup_local_fwd_listener( - options.local_forwards[i].listen_host, - options.local_forwards[i].listen_port, - options.local_forwards[i].connect_host, - options.local_forwards[i].connect_port, - options.gateway_ports); - } - if (i > 0 && success == 0) - error("Could not request local forwarding."); - - /* Initiate remote TCP/IP port forwardings. */ - for (i = 0; i < options.num_remote_forwards; i++) { - debug("Remote connections from %.200s:%d forwarded to " - "local address %.200s:%d", - (options.remote_forwards[i].listen_host == NULL) ? - "LOCALHOST" : options.remote_forwards[i].listen_host, - options.remote_forwards[i].listen_port, - options.remote_forwards[i].connect_host, - options.remote_forwards[i].connect_port); - if (channel_request_remote_forwarding( - options.remote_forwards[i].listen_host, - options.remote_forwards[i].listen_port, - options.remote_forwards[i].connect_host, - options.remote_forwards[i].connect_port) < 0) { - log("Warning: Could not request remote forwarding."); - } - } -} - -static void -check_agent_present(void) -{ - if (options.forward_agent) { - /* Clear agent forwarding if we don't have an agent. */ - if (!ssh_agent_present()) - options.forward_agent = 0; - } -} - -static int -ssh_session(void) -{ - int type; - int interactive = 0; - int have_tty = 0; - struct winsize ws; - char *cp; - const char *display; - - /* Enable compression if requested. */ - if (options.compression) { - debug("Requesting compression at level %d.", options.compression_level); - - if (options.compression_level < 1 || options.compression_level > 9) - fatal("Compression level must be from 1 (fast) to 9 (slow, best)."); - - /* Send the request. */ - packet_start(SSH_CMSG_REQUEST_COMPRESSION); - packet_put_int(options.compression_level); - packet_send(); - packet_write_wait(); - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - packet_start_compression(options.compression_level); - else if (type == SSH_SMSG_FAILURE) - log("Warning: Remote host refused compression."); - else - packet_disconnect("Protocol error waiting for compression response."); - } - /* Allocate a pseudo tty if appropriate. */ - if (tty_flag) { - debug("Requesting pty."); - - /* Start the packet. */ - packet_start(SSH_CMSG_REQUEST_PTY); - - /* Store TERM in the packet. There is no limit on the - length of the string. */ - cp = getenv("TERM"); - if (!cp) - cp = ""; - packet_put_cstring(cp); - - /* Store window size in the packet. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) - memset(&ws, 0, sizeof(ws)); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - - /* Store tty modes in the packet. */ - tty_make_modes(fileno(stdin), NULL); - - /* Send the packet, and wait for it to leave. */ - packet_send(); - packet_write_wait(); - - /* Read response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - interactive = 1; - have_tty = 1; - } else if (type == SSH_SMSG_FAILURE) - log("Warning: Remote host failed or refused to allocate a pseudo tty."); - else - packet_disconnect("Protocol error waiting for pty request response."); - } - /* Request X11 forwarding if enabled and DISPLAY is set. */ - display = getenv("DISPLAY"); - if (options.forward_x11 && display != NULL) { - char *proto, *data; - /* Get reasonable local authentication information. */ - client_x11_get_proto(display, options.xauth_location, - options.forward_x11_trusted, &proto, &data); - /* Request forwarding with authentication spoofing. */ - debug("Requesting X11 forwarding with authentication spoofing."); - x11_request_forwarding_with_spoofing(0, display, proto, data); - - /* Read response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - interactive = 1; - } else if (type == SSH_SMSG_FAILURE) { - log("Warning: Remote host denied X11 forwarding."); - } else { - packet_disconnect("Protocol error waiting for X11 forwarding"); - } - } - /* Tell the packet module whether this is an interactive session. */ - packet_set_interactive(interactive); - - /* Request authentication agent forwarding if appropriate. */ - check_agent_present(); - - if (options.forward_agent) { - debug("Requesting authentication agent forwarding."); - auth_request_forwarding(); - - /* Read response from the server. */ - type = packet_read(); - packet_check_eom(); - if (type != SSH_SMSG_SUCCESS) - log("Warning: Remote host denied authentication agent forwarding."); - } - - /* Initiate port forwardings. */ - ssh_init_forwarding(); - - /* If requested, let ssh continue in the background. */ - if (fork_after_authentication_flag) - if (daemon(1, 1) < 0) - fatal("daemon() failed: %.200s", strerror(errno)); - - /* - * If a command was specified on the command line, execute the - * command now. Otherwise request the server to start a shell. - */ - if (buffer_len(&command) > 0) { - int len = buffer_len(&command); - if (len > 900) - len = 900; - debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); - packet_start(SSH_CMSG_EXEC_CMD); - packet_put_string(buffer_ptr(&command), buffer_len(&command)); - packet_send(); - packet_write_wait(); - } else { - debug("Requesting shell."); - packet_start(SSH_CMSG_EXEC_SHELL); - packet_send(); - packet_write_wait(); - } - - /* Enter the interactive session. */ - return client_loop(have_tty, tty_flag ? - options.escape_char : SSH_ESCAPECHAR_NONE, 0); -} - -static void -client_subsystem_reply(int type, u_int32_t seq, void *ctxt) -{ - int id, len; - - id = packet_get_int(); - len = buffer_len(&command); - if (len > 900) - len = 900; - packet_check_eom(); - if (type == SSH2_MSG_CHANNEL_FAILURE) - fatal("Request for subsystem '%.*s' failed on channel %d", - len, (u_char *)buffer_ptr(&command), id); -} - -void -client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt) -{ - int i; - - i = client_global_request_id++; - if (i >= options.num_remote_forwards) - return; - debug("remote forward %s for: listen %d, connect %s:%d", - type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", - options.remote_forwards[i].listen_port, - options.remote_forwards[i].connect_host, - options.remote_forwards[i].connect_port); - if (type == SSH2_MSG_REQUEST_FAILURE) - log("Warning: remote port forwarding failed for listen port %d", - options.remote_forwards[i].listen_port); -} - -static -void -ssh_session2_setlocale(int id) -{ - char *loc; - -#define remote_setlocale(envvar) \ - if ((loc = getenv(envvar)) != NULL) {\ - channel_request_start(id, "env", 0);\ - debug2("Sent request for environment variable %s=%s", envvar, \ - loc); \ - packet_put_cstring(envvar);\ - packet_put_cstring(loc);\ - packet_send();\ - } - - remote_setlocale("LANG") - - remote_setlocale("LC_CTYPE") - remote_setlocale("LC_COLLATE") - remote_setlocale("LC_TIME") - remote_setlocale("LC_NUMERIC") - remote_setlocale("LC_MONETARY") - remote_setlocale("LC_MESSAGES") - - remote_setlocale("LC_ALL") -} - -/* request pty/x11/agent/tcpfwd/shell for channel */ -static void -ssh_session2_setup(int id, void *arg) -{ - int len; - const char *display; - int interactive = 0; - struct termios tio; - - debug("ssh_session2_setup: id %d", id); - - ssh_session2_setlocale(id); - - if (tty_flag) { - struct winsize ws; - char *cp; - cp = getenv("TERM"); - if (!cp) - cp = ""; - /* Store window size in the packet. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) - memset(&ws, 0, sizeof(ws)); - - channel_request_start(id, "pty-req", 0); - packet_put_cstring(cp); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - tio = get_saved_tio(); - tty_make_modes(/*ignored*/ 0, &tio); - packet_send(); - interactive = 1; - /* XXX wait for reply */ - } - - display = getenv("DISPLAY"); - if (options.forward_x11 && display != NULL) { - char *proto, *data; - /* Get reasonable local authentication information. */ - client_x11_get_proto(display, options.xauth_location, - options.forward_x11_trusted, &proto, &data); - /* Request forwarding with authentication spoofing. */ - debug("Requesting X11 forwarding with authentication spoofing."); - x11_request_forwarding_with_spoofing(id, display, proto, data); - interactive = 1; - /* XXX wait for reply */ - } - - check_agent_present(); - if (options.forward_agent) { - debug("Requesting authentication agent forwarding."); - channel_request_start(id, "auth-agent-req@openssh.com", 0); - packet_send(); - } - - len = buffer_len(&command); - if (len > 0) { - if (len > 900) - len = 900; - if (subsystem_flag) { - debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command)); - channel_request_start(id, "subsystem", /*want reply*/ 1); - /* register callback for reply */ - /* XXX we assume that client_loop has already been called */ - dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply); - dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply); - } else { - debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); - channel_request_start(id, "exec", 0); - } - packet_put_string(buffer_ptr(&command), buffer_len(&command)); - packet_send(); - } else { - channel_request_start(id, "shell", 0); - packet_send(); - } - - packet_set_interactive(interactive); -} - -/* open new channel for a session */ -static int -ssh_session2_open(void) -{ - Channel *c; - int window, packetmax, in, out, err; - - if (stdin_null_flag) { - in = open(_PATH_DEVNULL, O_RDONLY); - } else { - in = dup(STDIN_FILENO); - } - out = dup(STDOUT_FILENO); - err = dup(STDERR_FILENO); - - if (in < 0 || out < 0 || err < 0) - fatal("dup() in/out/err failed"); - - /* enable nonblocking unless tty */ - if (!isatty(in)) - set_nonblock(in); - if (!isatty(out)) - set_nonblock(out); - if (!isatty(err)) - set_nonblock(err); - - window = CHAN_SES_WINDOW_DEFAULT; - packetmax = CHAN_SES_PACKET_DEFAULT; - if (tty_flag) { - window >>= 1; - packetmax >>= 1; - } - c = channel_new( - "session", SSH_CHANNEL_OPENING, in, out, err, - window, packetmax, CHAN_EXTENDED_WRITE, - xstrdup("client-session"), /*nonblock*/0); - - debug3("ssh_session2_open: channel_new: %d", c->self); - - channel_send_open(c->self); - if (!no_shell_flag) - channel_register_confirm(c->self, ssh_session2_setup); - - return c->self; -} - -static int -ssh_session2(void) -{ - int id = -1; - - /* XXX should be pre-session */ - ssh_init_forwarding(); - - if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) - id = ssh_session2_open(); - - /* If requested, let ssh continue in the background. */ - if (fork_after_authentication_flag) - client_daemonize(); - - return (client_loop(tty_flag, tty_flag ? - options.escape_char : SSH_ESCAPECHAR_NONE, id)); -} - -static void -load_public_identity_files(void) -{ - char *filename; - int i = 0; - Key *public; - - for (; i < options.num_identity_files; i++) { - filename = tilde_expand_filename(options.identity_files[i], - original_real_uid); - public = key_load_public(filename, NULL); - debug("identity file %s type %d", filename, - public ? public->type : -1); - xfree(options.identity_files[i]); - options.identity_files[i] = filename; - options.identity_keys[i] = public; - } -} - -/* - * Connects to the given host using rsh(or prints an error message and exits - * if rsh is not available). This function never returns. - */ -static void -rsh_connect(char *host, char *user, Buffer * command) -{ - char *args[10]; - int i; - - log("Using rsh. WARNING: Connection will not be encrypted."); - /* Build argument list for rsh. */ - i = 0; - args[i++] = _PATH_RSH; - /* host may have to come after user on some systems */ - args[i++] = host; - if (user) { - args[i++] = "-l"; - args[i++] = user; - } - if (buffer_len(command) > 0) { - buffer_append(command, "\0", 1); - args[i++] = buffer_ptr(command); - } - args[i++] = NULL; - if (debug_flag) { - for (i = 0; args[i]; i++) { - if (i != 0) - (void) fprintf(stderr, " "); - (void) fprintf(stderr, "%s", args[i]); - } - (void) fprintf(stderr, "\n"); - } - (void) execv(_PATH_RSH, args); - perror(_PATH_RSH); - exit(1); -} diff --git a/usr/src/cmd/ssh/ssh/sshconnect.c b/usr/src/cmd/ssh/ssh/sshconnect.c deleted file mode 100644 index 74c3b6fa26..0000000000 --- a/usr/src/cmd/ssh/ssh/sshconnect.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Code to connect to a remote host, and to perform the client side of the - * login (authentication) dialog. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.135 2002/09/19 01:58:18 djm Exp $"); - -#include <openssl/bn.h> - -#include "ssh.h" -#include "xmalloc.h" -#include "rsa.h" -#include "buffer.h" -#include "packet.h" -#include "uidswap.h" -#include "compat.h" -#include "key.h" -#include "sshconnect.h" -#include "hostfile.h" -#include "log.h" -#include "readconf.h" -#include "atomicio.h" -#include "misc.h" -#include "readpass.h" -#include <langinfo.h> -#include <regex.h> -#include <err.h> -#include "engine.h" - -char *client_version_string = NULL; -char *server_version_string = NULL; - -/* import */ -extern Options options; -extern char *__progname; -extern uid_t original_real_uid; -extern uid_t original_effective_uid; -extern pid_t proxy_command_pid; -extern ENGINE *e; - -#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ -#define INET6_ADDRSTRLEN 46 -#endif - -static int show_other_keys(const char *, Key *); - -/* - * Connect to the given ssh server using a proxy command. - */ -static int -ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) -{ - Buffer command; - const char *cp; - char *command_string; - int pin[2], pout[2]; - pid_t pid; - char strport[NI_MAXSERV]; - - /* Convert the port number into a string. */ - snprintf(strport, sizeof strport, "%hu", port); - - /* - * Build the final command string in the buffer by making the - * appropriate substitutions to the given proxy command. - * - * Use "exec" to avoid "sh -c" processes on some platforms - * (e.g. Solaris) - */ - buffer_init(&command); - -#define EXECLEN (sizeof ("exec") - 1) - for (cp = proxy_command; *cp && isspace(*cp) ; cp++) - ; - if (strncmp(cp, "exec", EXECLEN) != 0 || - (strlen(cp) >= EXECLEN && !isspace(*(cp + EXECLEN)))) - buffer_append(&command, "exec ", EXECLEN + 1); -#undef EXECLEN - - for (cp = proxy_command; *cp; cp++) { - if (cp[0] == '%' && cp[1] == '%') { - buffer_append(&command, "%", 1); - cp++; - continue; - } - if (cp[0] == '%' && cp[1] == 'h') { - buffer_append(&command, host, strlen(host)); - cp++; - continue; - } - if (cp[0] == '%' && cp[1] == 'p') { - buffer_append(&command, strport, strlen(strport)); - cp++; - continue; - } - buffer_append(&command, cp, 1); - } - buffer_append(&command, "\0", 1); - - /* Get the final command string. */ - command_string = buffer_ptr(&command); - - /* Create pipes for communicating with the proxy. */ - if (pipe(pin) < 0 || pipe(pout) < 0) - fatal("Could not create pipes to communicate with the proxy: %.100s", - strerror(errno)); - - debug("Executing proxy command: %.500s", command_string); - - /* Fork and execute the proxy command. */ - if ((pid = fork()) == 0) { - char *argv[10]; - - /* Child. Permanently give up superuser privileges. */ - seteuid(original_real_uid); - setuid(original_real_uid); - - /* Redirect stdin and stdout. */ - close(pin[1]); - if (pin[0] != 0) { - if (dup2(pin[0], 0) < 0) - perror("dup2 stdin"); - close(pin[0]); - } - close(pout[0]); - if (dup2(pout[1], 1) < 0) - perror("dup2 stdout"); - /* Cannot be 1 because pin allocated two descriptors. */ - close(pout[1]); - - /* Stderr is left as it is so that error messages get - printed on the user's terminal. */ - argv[0] = _PATH_BSHELL; - argv[1] = "-c"; - argv[2] = command_string; - argv[3] = NULL; - - /* Execute the proxy command. Note that we gave up any - extra privileges above. */ - execv(argv[0], argv); - perror(argv[0]); - exit(1); - } - /* Parent. */ - if (pid < 0) - fatal("fork failed: %.100s", strerror(errno)); - else - proxy_command_pid = pid; /* save pid to clean up later */ - - /* Close child side of the descriptors. */ - close(pin[0]); - close(pout[1]); - - /* Free the command name. */ - buffer_free(&command); - - /* Set the connection file descriptors. */ - packet_set_connection(pout[0], pin[1]); - - /* Indicate OK return */ - return 0; -} - -/* - * Creates a (possibly privileged) socket for use as the ssh connection. - */ -static int -ssh_create_socket(int privileged, int family) -{ - int sock, gaierr; - struct addrinfo hints, *res; - - /* - * If we are running as root and want to connect to a privileged - * port, bind our own socket to a privileged port. - */ - if (privileged) { - int p = IPPORT_RESERVED - 1; - PRIV_START; - sock = rresvport_af(&p, family); - PRIV_END; - if (sock < 0) - error("rresvport: af=%d %.100s", family, strerror(errno)); - else - debug("Allocated local port %d.", p); - return sock; - } - sock = socket(family, SOCK_STREAM, 0); - if (sock < 0) - error("socket: %.100s", strerror(errno)); - - /* Bind the socket to an alternative local IP address */ - if (options.bind_address == NULL) - return sock; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - gaierr = getaddrinfo(options.bind_address, "0", &hints, &res); - if (gaierr) { - error("getaddrinfo: %s: %s", options.bind_address, - gai_strerror(gaierr)); - close(sock); - return -1; - } - if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { - error("bind: %s: %s", options.bind_address, strerror(errno)); - close(sock); - freeaddrinfo(res); - return -1; - } - freeaddrinfo(res); - return sock; -} - -/* - * Connect with timeout. Implements ConnectTimeout option. - */ -static int -timeout_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, int timeout) -{ - fd_set *fdset; - struct timeval tv; - socklen_t optlen; - int optval, rc, result = -1; - - if (timeout <= 0) - return (connect(sockfd, serv_addr, addrlen)); - - set_nonblock(sockfd); - rc = connect(sockfd, serv_addr, addrlen); - if (rc == 0) { - unset_nonblock(sockfd); - return (0); - } - if (errno != EINPROGRESS) - return (-1); - - fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), - sizeof(fd_mask)); - FD_SET(sockfd, fdset); - tv.tv_sec = timeout; - tv.tv_usec = 0; - - for (;;) { - rc = select(sockfd + 1, NULL, fdset, NULL, &tv); - if (rc != -1 || errno != EINTR) - break; - } - - switch (rc) { - case 0: - /* Timed out */ - errno = ETIMEDOUT; - break; - case -1: - /* Select error */ - debug("select: %s", strerror(errno)); - break; - case 1: - /* Completed or failed */ - optval = 0; - optlen = sizeof(optval); - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, - &optlen) == -1) { - debug("getsockopt: %s", strerror(errno)); - break; - } - if (optval != 0) { - errno = optval; - break; - } - result = 0; - unset_nonblock(sockfd); - break; - default: - /* Should not occur */ - fatal("Bogus return (%d) from select()", rc); - } - - xfree(fdset); - return (result); -} - -/* - * Opens a TCP/IP connection to the remote server on the given host. - * The address of the remote host will be returned in hostaddr. - * If port is 0, the default port will be used. If needpriv is true, - * a privileged port will be allocated to make the connection. - * This requires super-user privileges if needpriv is true. - * Connection_attempts specifies the maximum number of tries (one per - * second). If proxy_command is non-NULL, it specifies the command (with %h - * and %p substituted for host and port, respectively) to use to contact - * the daemon. - * Return values: - * 0 for OK - * ECONNREFUSED if we got a "Connection Refused" by the peer on any address - * ECONNABORTED if we failed without a "Connection refused" - * Suitable error messages for the connection failure will already have been - * printed. - */ -int -ssh_connect(const char *host, struct sockaddr_storage * hostaddr, - ushort_t port, int family, int connection_attempts, - int needpriv, const char *proxy_command) -{ - int gaierr; - int on = 1; - int sock = -1, attempt; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; - struct addrinfo hints, *ai, *aitop; - struct servent *sp; - /* - * Did we get only other errors than "Connection refused" (which - * should block fallback to rsh and similar), or did we get at least - * one "Connection refused"? - */ - int full_failure = 1; - - debug("ssh_connect: needpriv %d", needpriv); - - /* Get default port if port has not been set. */ - if (port == 0) { - sp = getservbyname(SSH_SERVICE_NAME, "tcp"); - if (sp) - port = ntohs(sp->s_port); - else - port = SSH_DEFAULT_PORT; - } - /* If a proxy command is given, connect using it. */ - if (proxy_command != NULL) - return ssh_proxy_connect(host, port, proxy_command); - - /* No proxy command. */ - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%u", port); - if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) - fatal("%s: %.100s: %s", __progname, host, - gai_strerror(gaierr)); - - /* - * Try to connect several times. On some machines, the first time - * will sometimes fail. In general socket code appears to behave - * quite magically on many machines. - */ - for (attempt = 0; ;) { - if (attempt > 0) - debug("Trying again..."); - - /* Loop through addresses for this host, and try each one in - sequence until the connection succeeds. */ - for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) - continue; - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, - ntop, sizeof(ntop), strport, sizeof(strport), - NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("ssh_connect: getnameinfo failed"); - continue; - } - debug("Connecting to %.200s [%.100s] port %s.", - host, ntop, strport); - - /* Create a socket for connecting. */ - sock = ssh_create_socket(needpriv, ai->ai_family); - if (sock < 0) - /* Any error is already output */ - continue; - - if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, - options.connection_timeout) >= 0) { - /* Successful connection. */ - memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); - break; - } else { - if (errno == ECONNREFUSED) - full_failure = 0; - debug("connect to address %s port %s: %s", - ntop, strport, strerror(errno)); - /* - * Close the failed socket; there appear to - * be some problems when reusing a socket for - * which connect() has already returned an - * error. - */ - close(sock); - } - } - if (ai) - break; /* Successful connection. */ - - attempt++; - if (attempt >= connection_attempts) - break; - /* Sleep a moment before retrying. */ - sleep(1); - } - - freeaddrinfo(aitop); - - /* Return failure if we didn't get a successful connection. */ - if (attempt >= connection_attempts) { - log("ssh: connect to host %s port %s: %s", - host, strport, strerror(errno)); - return full_failure ? ECONNABORTED : ECONNREFUSED; - } - - debug("Connection established."); - - /* Set keepalives if requested. */ - if (options.keepalives && - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, - sizeof(on)) < 0) - debug2("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); - - /* Set the connection. */ - packet_set_connection(sock, sock); - - return 0; -} - -/* - * Waits for the server identification string, and sends our own - * identification string. - */ -static void -ssh_exchange_identification(void) -{ - char buf[256], remote_version[256]; /* must be same size! */ - int remote_major, remote_minor, i, mismatch; - int connection_in = packet_get_connection_in(); - int connection_out = packet_get_connection_out(); - int minor1 = PROTOCOL_MINOR_1; - - /* Read other side\'s version identification. */ - for (;;) { - for (i = 0; i < sizeof(buf) - 1; i++) { - int len = atomicio(read, connection_in, &buf[i], 1); - if (len < 0) - fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); - if (len != 1) - fatal("ssh_exchange_identification: Connection closed by remote host"); - if (buf[i] == '\r') { - buf[i] = '\n'; - buf[i + 1] = 0; - continue; /**XXX wait for \n */ - } - if (buf[i] == '\n') { - buf[i + 1] = 0; - break; - } - } - buf[sizeof(buf) - 1] = 0; - if (strncmp(buf, "SSH-", 4) == 0) - break; - debug("ssh_exchange_identification: %s", buf); - } - server_version_string = xstrdup(buf); - - /* - * Check that the versions match. In future this might accept - * several versions and set appropriate flags to handle them. - */ - if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) != 3) - fatal("Bad remote protocol version identification: '%.100s'", buf); - debug("Remote protocol version %d.%d, remote software version %.100s", - remote_major, remote_minor, remote_version); - - compat_datafellows(remote_version); - mismatch = 0; - - switch (remote_major) { - case 1: - if (remote_minor == 99 && - (options.protocol & SSH_PROTO_2) && - !(options.protocol & SSH_PROTO_1_PREFERRED)) { - enable_compat20(); - break; - } - if (!(options.protocol & SSH_PROTO_1)) { - mismatch = 1; - break; - } - if (remote_minor < 3) { - fatal("Remote machine has too old SSH software version."); - } else if (remote_minor == 3 || remote_minor == 4) { - /* We speak 1.3, too. */ - enable_compat13(); - minor1 = 3; - if (options.forward_agent) { - log("Agent forwarding disabled for protocol 1.3"); - options.forward_agent = 0; - } - } - break; - case 2: - if (options.protocol & SSH_PROTO_2) { - enable_compat20(); - break; - } - /* FALLTHROUGH */ - default: - mismatch = 1; - break; - } - if (mismatch) - fatal("Protocol major versions differ: %d vs. %d", - (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, - remote_major); - /* Send our own protocol version identification. */ - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", - compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, - compat20 ? PROTOCOL_MINOR_2 : minor1, - SSH_VERSION); - if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) - fatal("write: %.100s", strerror(errno)); - client_version_string = xstrdup(buf); - chop(client_version_string); - chop(server_version_string); - debug("Local version string %.100s", client_version_string); -} - -/* defaults to 'no' */ -static int -confirm(const char *prompt) -{ - const char *msg; - char *p, *again = NULL; - int n, ret = -1; - regex_t yesre, nore; - char *errstr; - int rerr, errlen; - - if (options.batch_mode) - return 0; - n = snprintf(NULL, 0, gettext("Please type '%s' or '%s': "), - nl_langinfo(YESSTR), nl_langinfo(NOSTR)); - again = xmalloc(n + 1); - (void) snprintf(again, n + 1, gettext("Please type '%s' or '%s': "), - nl_langinfo(YESSTR), nl_langinfo(NOSTR)); - - if ((rerr = regcomp(&yesre, nl_langinfo(YESEXPR), REG_EXTENDED)) != 0) { - errlen = regerror(rerr, &yesre, NULL, 0); - if ((errstr = malloc(errlen)) == NULL) - err(1, "malloc"); - regerror(rerr, &yesre, errstr, errlen); - errx(1, "YESEXPR: %s: %s", nl_langinfo(YESEXPR), errstr); - } - - if ((rerr = regcomp(&nore, nl_langinfo(NOEXPR), REG_EXTENDED)) != 0) { - errlen = regerror(rerr, &nore, NULL, 0); - if ((errstr = malloc(errlen)) == NULL) - err(1, "malloc"); - regerror(rerr, &nore, errstr, errlen); - errx(1, "NOEXPR: %s: %s", nl_langinfo(NOEXPR), errstr); - } - - for (msg = prompt;;msg = again) { - p = read_passphrase(msg, RP_ECHO); - if (p == NULL || (p[0] == '\0') || (p[0] == '\n') || - regexec(&nore, p, 0, NULL, 0) == 0) - ret = 0; - if (p && regexec(&yesre, p, 0, NULL, 0) == 0) - ret = 1; - if (p) - xfree(p); - if (ret != -1) { - regfree(&yesre); - regfree(&nore); - return ret; - } - } -} - -/* - * check whether the supplied host key is valid, return -1 if the key - * is not valid. the user_hostfile will not be updated if 'readonly' is true. - */ -static int -check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, int - validated, int readonly, const char *user_hostfile, const char - *system_hostfile) -{ - Key *file_key; - char *type = key_type(host_key); - char *ip = NULL; - char hostline[1000], *hostp, *fp; - HostStatus host_status; - HostStatus ip_status; - int r, local = 0, host_ip_differ = 0; - int salen; - char ntop[NI_MAXHOST]; - char msg[1024]; - int len, host_line, ip_line, has_keys; - const char *host_file = NULL, *ip_file = NULL; - - /* - * Force accepting of the host key for loopback/localhost. The - * problem is that if the home directory is NFS-mounted to multiple - * machines, localhost will refer to a different machine in each of - * them, and the user will get bogus HOST_CHANGED warnings. This - * essentially disables host authentication for localhost; however, - * this is probably not a real problem. - */ - /** hostaddr == 0! */ - switch (hostaddr->sa_family) { - case AF_INET: - /* LINTED */ - local = (ntohl(((struct sockaddr_in *)hostaddr)-> - sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; - salen = sizeof(struct sockaddr_in); - break; - case AF_INET6: - /* LINTED */ - local = IN6_IS_ADDR_LOOPBACK( - &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); - salen = sizeof(struct sockaddr_in6); - break; - default: - local = 0; - salen = sizeof(struct sockaddr_storage); - break; - } - if (options.no_host_authentication_for_localhost == 1 && local && - options.host_key_alias == NULL) { - debug("Forcing accepting of host key for " - "loopback/localhost."); - return 0; - } - - /* - * We don't have the remote ip-address for connections - * using a proxy command - */ - if (options.proxy_command == NULL) { - if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), - NULL, 0, NI_NUMERICHOST) != 0) - fatal("check_host_key: getnameinfo failed"); - ip = xstrdup(ntop); - } else { - ip = xstrdup("<no hostip for proxy command>"); - } - /* - * Turn off check_host_ip if the connection is to localhost, via proxy - * command or if we don't have a hostname to compare with - */ - if (options.check_host_ip && - (local || strcmp(host, ip) == 0 || options.proxy_command != NULL)) - options.check_host_ip = 0; - - /* - * Allow the user to record the key under a different name. This is - * useful for ssh tunneling over forwarded connections or if you run - * multiple sshd's on different ports on the same machine. - */ - if (options.host_key_alias != NULL) { - host = options.host_key_alias; - debug("using hostkeyalias: %s", host); - } - - /* - * Store the host key from the known host file in here so that we can - * compare it with the key for the IP address. - */ - file_key = key_new(host_key->type); - - /* - * Check if the host key is present in the user's list of known - * hosts or in the systemwide list. - */ - host_file = user_hostfile; - host_status = check_host_in_hostfile(host_file, host, host_key, - file_key, &host_line); - if (host_status == HOST_NEW) { - host_file = system_hostfile; - host_status = check_host_in_hostfile(host_file, host, host_key, - file_key, &host_line); - } - /* - * Also perform check for the ip address, skip the check if we are - * localhost or the hostname was an ip address to begin with - */ - if (options.check_host_ip) { - Key *ip_key = key_new(host_key->type); - - ip_file = user_hostfile; - ip_status = check_host_in_hostfile(ip_file, ip, host_key, - ip_key, &ip_line); - if (ip_status == HOST_NEW) { - ip_file = system_hostfile; - ip_status = check_host_in_hostfile(ip_file, ip, - host_key, ip_key, &ip_line); - } - if (host_status == HOST_CHANGED && - (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) - host_ip_differ = 1; - - key_free(ip_key); - } else - ip_status = host_status; - - key_free(file_key); - - switch (host_status) { - case HOST_OK: - /* The host is known and the key matches. */ - if (validated) - debug("Host '%.200s' is known and matches the %s host key.", - host, type); - else - debug("Host '%.200s' is known and matches the %s host " - "key.", host, type); - debug("Found key in %s:%d", host_file, host_line); - if (options.check_host_ip && ip_status == HOST_NEW) { - if (readonly) - log("%s host key for IP address " - "'%.128s' not in list of known hosts.", - type, ip); - else if (!add_host_to_hostfile(user_hostfile, ip, - host_key, options.hash_known_hosts)) - log("Failed to add the %s host key for IP " - "address '%.128s' to the list of known " - "hosts (%.30s).", type, ip, user_hostfile); - else - log("Warning: Permanently added the %s host " - "key for IP address '%.128s' to the list " - "of known hosts.", type, ip); - } - break; - case HOST_NEW: - if (readonly) - goto fail; - /* The host is new. */ - if (!validated && options.strict_host_key_checking == 1) { - /* - * User has requested strict host key checking. We - * will not add the host key automatically. The only - * alternative left is to abort. - */ - error("No %s host key is known for %.200s and you " - "have requested strict checking.", type, host); - goto fail; - } else if (!validated && - options.strict_host_key_checking == 2) { - has_keys = show_other_keys(host, host_key); - /* The default */ - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - snprintf(msg, sizeof(msg), - gettext("The authenticity of host '%.200s (%s)' " - "can't be established%s\n%s key fingerprint " - "is %s.\n" - "Are you sure you want to continue connecting " - "(%s/%s)? "), - host, ip, - has_keys ? gettext(",\nbut keys of different type " - "are already known for this host.") : ".", - type, fp, nl_langinfo(YESSTR), nl_langinfo(NOSTR)); - xfree(fp); - if (!confirm(msg)) - goto fail; - } - /* - * If not in strict mode, add the key automatically to the - * local known_hosts file. - */ - if (options.check_host_ip && ip_status == HOST_NEW) { - snprintf(hostline, sizeof(hostline), "%s,%s", - host, ip); - hostp = hostline; - if (options.hash_known_hosts) { - /* Add hash of host and IP separately */ - r = add_host_to_hostfile(user_hostfile, host, - host_key, options.hash_known_hosts) && - add_host_to_hostfile(user_hostfile, ip, - host_key, options.hash_known_hosts); - } else { - /* Add unhashed "host,ip" */ - r = add_host_to_hostfile(user_hostfile, - hostline, host_key, - options.hash_known_hosts); - } - } else { - r = add_host_to_hostfile(user_hostfile, host, host_key, - options.hash_known_hosts); - hostp = host; - } - - if (!r) - log("Failed to add the host to the list of known " - "hosts (%.500s).", user_hostfile); - else - log("Warning: Permanently added '%.200s' (%s) to the " - "list of known hosts.", hostp, type); - break; - case HOST_CHANGED: - if (validated) { - log("Warning: The host key for host %s has changed; " - "please update your known hosts file(s) " - "(%s:%d)", host, host_file, host_line); - if (options.check_host_ip && host_ip_differ) { - log("Warning: The host key for host %s has " - "changed; please update your known " - "hosts file(s) (%s:%d)", ip, host_file, - host_line); - - } - break; - } - if (options.check_host_ip && host_ip_differ) { - char *msg; - if (ip_status == HOST_NEW) - msg = "is unknown"; - else if (ip_status == HOST_OK) - msg = "is unchanged"; - else - msg = "has a different value"; - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" - "@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @\n" - "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" - "The %s host key for %s has changed,\n" - "and the key for the according IP address %s\n" - "%s. This could either mean that\n" - "DNS SPOOFING is happening or the IP address for the host\n" - "and its host key have changed at the same time.\n", - type, host, ip, msg); - if (ip_status != HOST_NEW) - error("Offending key for IP in %s:%d", ip_file, ip_line); - } - /* The host key has changed. */ - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" - "@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\n" - "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" - "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n" - "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n" - "It is also possible that the %s host key has just been changed.\n" - "The fingerprint for the %s key sent by the remote host is\n%s.\n" - "Please contact your system administrator.\n" - "Add correct host key in %.100s to get rid of this message.\n" - "Offending key in %s:%d\n", - type, type, fp, user_hostfile, host_file, host_line); - xfree(fp); - - /* - * If strict host key checking is in use, the user will have - * to edit the key manually and we can only abort. - */ - if (options.strict_host_key_checking) { - error("%s host key for %.200s has changed and you have " - "requested strict checking.", type, host); - goto fail; - } - - /* - * If strict host key checking has not been requested, allow - * the connection but without password authentication or - * agent forwarding. - */ - if (options.password_authentication) { - error("Password authentication is disabled to avoid " - "man-in-the-middle attacks."); - options.password_authentication = 0; - } - if (options.forward_agent) { - error("Agent forwarding is disabled to avoid " - "man-in-the-middle attacks."); - options.forward_agent = 0; - } - if (options.forward_x11) { - error("X11 forwarding is disabled to avoid " - "man-in-the-middle attacks."); - options.forward_x11 = 0; - } - if (options.num_local_forwards > 0 || - options.num_remote_forwards > 0) { - error("Port forwarding is disabled to avoid " - "man-in-the-middle attacks."); - options.num_local_forwards = - options.num_remote_forwards = 0; - } - /* - * XXX Should permit the user to change to use the new id. - * This could be done by converting the host key to an - * identifying sentence, tell that the host identifies itself - * by that sentence, and ask the user if he/she whishes to - * accept the authentication. - */ - break; - case HOST_FOUND: - fatal("internal error"); - break; - } - - if (options.check_host_ip && host_status != HOST_CHANGED && - ip_status == HOST_CHANGED) { - snprintf(msg, sizeof(msg), - gettext("Warning: the %s host key for '%.200s' " - "differs from the key for the IP address '%.128s'" - "\nOffending key for IP in %s:%d"), - type, host, ip, ip_file, ip_line); - if (host_status == HOST_OK) { - len = strlen(msg); - snprintf(msg + len, sizeof(msg) - len, - "\nMatching host key in %s:%d", - host_file, host_line); - } - if (!validated && options.strict_host_key_checking == 1) { - log(msg); - error("Exiting, you have requested strict checking."); - goto fail; - } else if (!validated && - options.strict_host_key_checking == 2) { - snprintf(msg + strlen(msg), sizeof(msg) - strlen(msg), - gettext("\nAre you sure you want to continue " - "connecting (%s/%s)"), - nl_langinfo(YESSTR), nl_langinfo(NOSTR)); - if (!confirm(msg)) - goto fail; - } else { - log(msg); - } - } - - xfree(ip); - return 0; - -fail: - xfree(ip); - return -1; -} - -int -verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) -{ - struct stat st; - - /* return ok if the key can be found in an old keyfile */ - if (stat(options.system_hostfile2, &st) == 0 || - stat(options.user_hostfile2, &st) == 0) { - if (check_host_key(host, hostaddr, host_key, 0, /*readonly*/ 1, - options.user_hostfile2, options.system_hostfile2) == 0) - return 0; - } - return check_host_key(host, hostaddr, host_key, 0, /*readonly*/ 0, - options.user_hostfile, options.system_hostfile); -} - -int -accept_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) -{ - struct stat st; - - /* return ok if the key can be found in an old keyfile */ - if (stat(options.system_hostfile2, &st) == 0 || - stat(options.user_hostfile2, &st) == 0) { - if (check_host_key(host, hostaddr, host_key, 1, /*readonly*/ 1, - options.user_hostfile2, options.system_hostfile2) == 0) - return 0; - } - return check_host_key(host, hostaddr, host_key, 1, /*readonly*/ 0, - options.user_hostfile, options.system_hostfile); -} -/* - * Starts a dialog with the server, and authenticates the current user on the - * server. This does not need any extra privileges. The basic connection - * to the server must already have been established before this is called. - * If login fails, this function prints an error and never returns. - * This function does not require super-user privileges. - */ -void -ssh_login(Sensitive *sensitive, const char *orighost, - struct sockaddr *hostaddr, char *pw_name) -{ - char *host, *cp; - char *server_user, *local_user; - - local_user = xstrdup(pw_name); - server_user = options.user ? options.user : local_user; - - /* Convert the user-supplied hostname into all lowercase. */ - host = xstrdup(orighost); - for (cp = host; *cp; cp++) - if (isupper(*cp)) - *cp = tolower(*cp); - - /* Exchange protocol version identification strings with the server. */ - ssh_exchange_identification(); - - /* - * See comment at definition of will_daemonize for information why we - * don't support the PKCS#11 engine with protocol 1. - */ - if (compat20 == 1 && options.use_openssl_engine == 1) { - /* - * If this fails then 'e' will be NULL which means we do not use - * the engine, as if UseOpenSSLEngine was set to "no". This is - * important in case we go to the background after the - * authentication. - */ - e = pkcs11_engine_load(options.use_openssl_engine); - } - - /* Put the connection into non-blocking mode. */ - packet_set_nonblocking(); - - /* key exchange */ - /* authenticate user */ - if (compat20) { - /* - * Note that the host pointer is saved in ssh_kex2() for later - * use during the key re-exchanges so we must not xfree() it. - */ - ssh_kex2(host, hostaddr); - ssh_userauth2(local_user, server_user, host, sensitive); - } else { - ssh_kex(host, hostaddr); - ssh_userauth1(local_user, server_user, host, sensitive); - } - - xfree(local_user); -} - -void -ssh_put_password(char *password) -{ - int size; - char *padded; - - if (datafellows & SSH_BUG_PASSWORDPAD) { - packet_put_cstring(password); - return; - } - size = roundup(strlen(password) + 1, 32); - padded = xmalloc(size); - memset(padded, 0, size); - strlcpy(padded, password, size); - packet_put_string(padded, size); - memset(padded, 0, size); - xfree(padded); -} - -static int -show_key_from_file(const char *file, const char *host, int keytype) -{ - Key *found; - char *fp; - int line, ret; - - found = key_new(keytype); - if ((ret = lookup_key_in_hostfile_by_type(file, host, - keytype, found, &line))) { - fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); - log("WARNING: %s key found for host %s\n" - "in %s:%d\n" - "%s key fingerprint %s.", - key_type(found), host, file, line, - key_type(found), fp); - xfree(fp); - } - key_free(found); - return (ret); -} - -/* print all known host keys for a given host, but skip keys of given type */ -static int -show_other_keys(const char *host, Key *key) -{ - int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1}; - int i, found = 0; - - for (i = 0; type[i] != -1; i++) { - if (type[i] == key->type) - continue; - if (type[i] != KEY_RSA1 && - show_key_from_file(options.user_hostfile2, host, type[i])) { - found = 1; - continue; - } - if (type[i] != KEY_RSA1 && - show_key_from_file(options.system_hostfile2, host, type[i])) { - found = 1; - continue; - } - if (show_key_from_file(options.user_hostfile, host, type[i])) { - found = 1; - continue; - } - if (show_key_from_file(options.system_hostfile, host, type[i])) { - found = 1; - continue; - } - debug2("no key of type %d for host %s", type[i], host); - } - return (found); -} diff --git a/usr/src/cmd/ssh/ssh/sshconnect1.c b/usr/src/cmd/ssh/ssh/sshconnect1.c deleted file mode 100644 index 19cdd84cb6..0000000000 --- a/usr/src/cmd/ssh/ssh/sshconnect1.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Code to connect to a remote host, and to perform the client side of the - * login (authentication) dialog. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.52 2002/08/08 13:50:23 aaron Exp $"); - -#include <openssl/bn.h> -#include <openssl/md5.h> - -#ifdef KRB4 -#include <krb.h> -#endif -#ifdef KRB5 -#include <krb5.h> -#ifndef HEIMDAL -#define krb5_get_err_text(context,code) error_message(code) -#endif /* !HEIMDAL */ -#endif -#ifdef AFS -#include <kafs.h> -#include "radix.h" -#endif - -#include "ssh.h" -#include "ssh1.h" -#include "xmalloc.h" -#include "rsa.h" -#include "buffer.h" -#include "packet.h" -#include "mpaux.h" -#include "uidswap.h" -#include "log.h" -#include "readconf.h" -#include "key.h" -#include "authfd.h" -#include "sshconnect.h" -#include "authfile.h" -#include "readpass.h" -#include "cipher.h" -#include "canohost.h" -#include "auth.h" - -/* Session id for the current session. */ -u_char session_id[16]; -u_int supported_authentications = 0; - -extern Options options; -extern char *__progname; - -/* - * Checks if the user has an authentication agent, and if so, tries to - * authenticate using the agent. - */ -static int -try_agent_authentication(void) -{ - int type; - char *comment; - AuthenticationConnection *auth; - u_char response[16]; - u_int i; - Key *key; - BIGNUM *challenge; - - /* Get connection to the agent. */ - auth = ssh_get_authentication_connection(); - if (!auth) - return 0; - - if ((challenge = BN_new()) == NULL) - fatal("try_agent_authentication: BN_new failed"); - /* Loop through identities served by the agent. */ - for (key = ssh_get_first_identity(auth, &comment, 1); - key != NULL; - key = ssh_get_next_identity(auth, &comment, 1)) { - - /* Try this identity. */ - debug("Trying RSA authentication via agent with '%.100s'", comment); - xfree(comment); - - /* Tell the server that we are willing to authenticate using this key. */ - packet_start(SSH_CMSG_AUTH_RSA); - packet_put_bignum(key->rsa->n); - packet_send(); - packet_write_wait(); - - /* Wait for server's response. */ - type = packet_read(); - - /* The server sends failure if it doesn\'t like our key or - does not support RSA authentication. */ - if (type == SSH_SMSG_FAILURE) { - debug("Server refused our key."); - key_free(key); - continue; - } - /* Otherwise it should have sent a challenge. */ - if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) - packet_disconnect("Protocol error during RSA authentication: %d", - type); - - packet_get_bignum(challenge); - packet_check_eom(); - - debug("Received RSA challenge from server."); - - /* Ask the agent to decrypt the challenge. */ - if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) { - /* - * The agent failed to authenticate this identifier - * although it advertised it supports this. Just - * return a wrong value. - */ - log("Authentication agent failed to decrypt challenge."); - memset(response, 0, sizeof(response)); - } - key_free(key); - debug("Sending response to RSA challenge."); - - /* Send the decrypted challenge back to the server. */ - packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - packet_put_char(response[i]); - packet_send(); - packet_write_wait(); - - /* Wait for response from the server. */ - type = packet_read(); - - /* The server returns success if it accepted the authentication. */ - if (type == SSH_SMSG_SUCCESS) { - ssh_close_authentication_connection(auth); - BN_clear_free(challenge); - debug("RSA authentication accepted by server."); - return 1; - } - /* Otherwise it should return failure. */ - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth response: %d", - type); - } - ssh_close_authentication_connection(auth); - BN_clear_free(challenge); - debug("RSA authentication using agent refused."); - return 0; -} - -/* - * Computes the proper response to a RSA challenge, and sends the response to - * the server. - */ -static void -respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) -{ - u_char buf[32], response[16]; - MD5_CTX md; - int i, len; - - /* Decrypt the challenge using the private key. */ - /* XXX think about Bleichenbacher, too */ - if (rsa_private_decrypt(challenge, challenge, prv) <= 0) - packet_disconnect( - "respond_to_rsa_challenge: rsa_private_decrypt failed"); - - /* Compute the response. */ - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > sizeof(buf)) - packet_disconnect( - "respond_to_rsa_challenge: bad challenge length %d", len); - - memset(buf, 0, sizeof(buf)); - BN_bn2bin(challenge, buf + sizeof(buf) - len); - MD5_Init(&md); - MD5_Update(&md, buf, 32); - MD5_Update(&md, session_id, 16); - MD5_Final(response, &md); - - debug("Sending response to host key RSA challenge."); - - /* Send the response back to the server. */ - packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - packet_put_char(response[i]); - packet_send(); - packet_write_wait(); - - memset(buf, 0, sizeof(buf)); - memset(response, 0, sizeof(response)); - memset(&md, 0, sizeof(md)); -} - -/* - * Checks if the user has authentication file, and if so, tries to authenticate - * the user using it. - */ -static int -try_rsa_authentication(int idx) -{ - BIGNUM *challenge; - Key *public, *private; - char buf[300], *passphrase, *comment, *authfile; - int i, type, quit; - - public = options.identity_keys[idx]; - authfile = options.identity_files[idx]; - comment = xstrdup(authfile); - - debug("Trying RSA authentication with key '%.100s'", comment); - - /* Tell the server that we are willing to authenticate using this key. */ - packet_start(SSH_CMSG_AUTH_RSA); - packet_put_bignum(public->rsa->n); - packet_send(); - packet_write_wait(); - - /* Wait for server's response. */ - type = packet_read(); - - /* - * The server responds with failure if it doesn\'t like our key or - * doesn\'t support RSA authentication. - */ - if (type == SSH_SMSG_FAILURE) { - debug("Server refused our key."); - xfree(comment); - return 0; - } - /* Otherwise, the server should respond with a challenge. */ - if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) - packet_disconnect("Protocol error during RSA authentication: %d", type); - - /* Get the challenge from the packet. */ - if ((challenge = BN_new()) == NULL) - fatal("try_rsa_authentication: BN_new failed"); - packet_get_bignum(challenge); - packet_check_eom(); - - debug("Received RSA challenge from server."); - - /* - * If the key is not stored in external hardware, we have to - * load the private key. Try first with empty passphrase; if it - * fails, ask for a passphrase. - */ - if (public->flags & KEY_FLAG_EXT) - private = public; - else - private = key_load_private_type(KEY_RSA1, authfile, "", NULL); - if (private == NULL && !options.batch_mode) { - snprintf(buf, sizeof(buf), - gettext("Enter passphrase for RSA key '%.100s': "), - comment); - for (i = 0; i < options.number_of_password_prompts; i++) { - passphrase = read_passphrase(buf, 0); - if (strcmp(passphrase, "") != 0) { - private = key_load_private_type(KEY_RSA1, - authfile, passphrase, NULL); - quit = 0; - } else { - debug2("no passphrase given, try next key"); - quit = 1; - } - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); - if (private != NULL || quit) - break; - debug2("bad passphrase given, try again..."); - } - } - /* We no longer need the comment. */ - xfree(comment); - - if (private == NULL) { - if (!options.batch_mode) - error("Bad passphrase."); - - /* Send a dummy response packet to avoid protocol error. */ - packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - packet_put_char(0); - packet_send(); - packet_write_wait(); - - /* Expect the server to reject it... */ - packet_read_expect(SSH_SMSG_FAILURE); - BN_clear_free(challenge); - return 0; - } - - /* Compute and send a response to the challenge. */ - respond_to_rsa_challenge(challenge, private->rsa); - - /* Destroy the private key unless it in external hardware. */ - if (!(private->flags & KEY_FLAG_EXT)) - key_free(private); - - /* We no longer need the challenge. */ - BN_clear_free(challenge); - - /* Wait for response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - debug("RSA authentication accepted by server."); - return 1; - } - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth response: %d", type); - debug("RSA authentication refused."); - return 0; -} - -/* - * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv - * authentication and RSA host authentication. - */ -static int -try_rhosts_rsa_authentication(const char *local_user, Key * host_key) -{ - int type; - BIGNUM *challenge; - - debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication."); - - /* Tell the server that we are willing to authenticate using this key. */ - packet_start(SSH_CMSG_AUTH_RHOSTS_RSA); - packet_put_cstring(local_user); - packet_put_int(BN_num_bits(host_key->rsa->n)); - packet_put_bignum(host_key->rsa->e); - packet_put_bignum(host_key->rsa->n); - packet_send(); - packet_write_wait(); - - /* Wait for server's response. */ - type = packet_read(); - - /* The server responds with failure if it doesn't admit our - .rhosts authentication or doesn't know our host key. */ - if (type == SSH_SMSG_FAILURE) { - debug("Server refused our rhosts authentication or host key."); - return 0; - } - /* Otherwise, the server should respond with a challenge. */ - if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) - packet_disconnect("Protocol error during RSA authentication: %d", type); - - /* Get the challenge from the packet. */ - if ((challenge = BN_new()) == NULL) - fatal("try_rhosts_rsa_authentication: BN_new failed"); - packet_get_bignum(challenge); - packet_check_eom(); - - debug("Received RSA challenge for host key from server."); - - /* Compute a response to the challenge. */ - respond_to_rsa_challenge(challenge, host_key->rsa); - - /* We no longer need the challenge. */ - BN_clear_free(challenge); - - /* Wait for response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server."); - return 1; - } - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth response: %d", type); - debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused."); - return 0; -} - -#ifdef KRB4 -static int -try_krb4_authentication(void) -{ - KTEXT_ST auth; /* Kerberos data */ - char *reply; - char inst[INST_SZ]; - char *realm; - CREDENTIALS cred; - int r, type; - socklen_t slen; - Key_schedule schedule; - u_long checksum, cksum; - MSG_DAT msg_data; - struct sockaddr_in local, foreign; - struct stat st; - - /* Don't do anything if we don't have any tickets. */ - if (stat(tkt_string(), &st) < 0) - return 0; - - strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)), - INST_SZ); - - realm = (char *)krb_realmofhost(get_canonical_hostname(1)); - if (!realm) { - debug("Kerberos v4: no realm for %s", get_canonical_hostname(1)); - return 0; - } - /* This can really be anything. */ - checksum = (u_long)getpid(); - - r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum); - if (r != KSUCCESS) { - debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]); - return 0; - } - /* Get session key to decrypt the server's reply with. */ - r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred); - if (r != KSUCCESS) { - debug("get_cred failed: %s", krb_err_txt[r]); - return 0; - } - des_key_sched((des_cblock *) cred.session, schedule); - - /* Send authentication info to server. */ - packet_start(SSH_CMSG_AUTH_KERBEROS); - packet_put_string((char *) auth.dat, auth.length); - packet_send(); - packet_write_wait(); - - /* Zero the buffer. */ - (void) memset(auth.dat, 0, MAX_KTXT_LEN); - - slen = sizeof(local); - memset(&local, 0, sizeof(local)); - if (getsockname(packet_get_connection_in(), - (struct sockaddr *)&local, &slen) < 0) - debug("getsockname failed: %s", strerror(errno)); - - slen = sizeof(foreign); - memset(&foreign, 0, sizeof(foreign)); - if (getpeername(packet_get_connection_in(), - (struct sockaddr *)&foreign, &slen) < 0) { - debug("getpeername failed: %s", strerror(errno)); - fatal_cleanup(); - } - /* Get server reply. */ - type = packet_read(); - switch (type) { - case SSH_SMSG_FAILURE: - /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ - debug("Kerberos v4 authentication failed."); - return 0; - break; - - case SSH_SMSG_AUTH_KERBEROS_RESPONSE: - /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ - debug("Kerberos v4 authentication accepted."); - - /* Get server's response. */ - reply = packet_get_string((u_int *) &auth.length); - if (auth.length >= MAX_KTXT_LEN) - fatal("Kerberos v4: Malformed response from server"); - memcpy(auth.dat, reply, auth.length); - xfree(reply); - - packet_check_eom(); - - /* - * If his response isn't properly encrypted with the session - * key, and the decrypted checksum fails to match, he's - * bogus. Bail out. - */ - r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session, - &foreign, &local, &msg_data); - if (r != KSUCCESS) { - debug("Kerberos v4 krb_rd_priv failed: %s", - krb_err_txt[r]); - packet_disconnect("Kerberos v4 challenge failed!"); - } - /* Fetch the (incremented) checksum that we supplied in the request. */ - memcpy((char *)&cksum, (char *)msg_data.app_data, - sizeof(cksum)); - cksum = ntohl(cksum); - - /* If it matches, we're golden. */ - if (cksum == checksum + 1) { - debug("Kerberos v4 challenge successful."); - return 1; - } else - packet_disconnect("Kerberos v4 challenge failed!"); - break; - - default: - packet_disconnect("Protocol error on Kerberos v4 response: %d", type); - } - return 0; -} - -#endif /* KRB4 */ - -#ifdef KRB5 -static int -try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) -{ - krb5_error_code problem; - const char *tkfile; - struct stat buf; - krb5_ccache ccache = NULL; - const char *remotehost; - krb5_data ap; - int type; - krb5_ap_rep_enc_part *reply = NULL; - int ret; - - memset(&ap, 0, sizeof(ap)); - - problem = krb5_init_context(context); - if (problem) { - debug("Kerberos v5: krb5_init_context failed"); - ret = 0; - goto out; - } - - problem = krb5_auth_con_init(*context, auth_context); - if (problem) { - debug("Kerberos v5: krb5_auth_con_init failed"); - ret = 0; - goto out; - } - -#ifndef HEIMDAL - problem = krb5_auth_con_setflags(*context, *auth_context, - KRB5_AUTH_CONTEXT_RET_TIME); - if (problem) { - debug("Keberos v5: krb5_auth_con_setflags failed"); - ret = 0; - goto out; - } -#endif - - tkfile = krb5_cc_default_name(*context); - if (strncmp(tkfile, "FILE:", 5) == 0) - tkfile += 5; - - if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { - debug("Kerberos v5: could not get default ccache (permission denied)."); - ret = 0; - goto out; - } - - problem = krb5_cc_default(*context, &ccache); - if (problem) { - debug("Kerberos v5: krb5_cc_default failed: %s", - krb5_get_err_text(*context, problem)); - ret = 0; - goto out; - } - - remotehost = get_canonical_hostname(1); - - problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED, - "host", remotehost, NULL, ccache, &ap); - if (problem) { - debug("Kerberos v5: krb5_mk_req failed: %s", - krb5_get_err_text(*context, problem)); - ret = 0; - goto out; - } - - packet_start(SSH_CMSG_AUTH_KERBEROS); - packet_put_string((char *) ap.data, ap.length); - packet_send(); - packet_write_wait(); - - xfree(ap.data); - ap.length = 0; - - type = packet_read(); - switch (type) { - case SSH_SMSG_FAILURE: - /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ - debug("Kerberos v5 authentication failed."); - ret = 0; - break; - - case SSH_SMSG_AUTH_KERBEROS_RESPONSE: - /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ - debug("Kerberos v5 authentication accepted."); - - /* Get server's response. */ - ap.data = packet_get_string((unsigned int *) &ap.length); - packet_check_eom(); - /* XXX je to dobre? */ - - problem = krb5_rd_rep(*context, *auth_context, &ap, &reply); - if (problem) { - ret = 0; - } - ret = 1; - break; - - default: - packet_disconnect("Protocol error on Kerberos v5 response: %d", - type); - ret = 0; - break; - - } - - out: - if (ccache != NULL) - krb5_cc_close(*context, ccache); - if (reply != NULL) - krb5_free_ap_rep_enc_part(*context, reply); - if (ap.length > 0) -#ifdef HEIMDAL - krb5_data_free(&ap); -#else - krb5_free_data_contents(*context, &ap); -#endif - - return (ret); -} - -static void -send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) -{ - int fd, type; - krb5_error_code problem; - krb5_data outbuf; - krb5_ccache ccache = NULL; - krb5_creds creds; -#ifdef HEIMDAL - krb5_kdc_flags flags; -#else - int forwardable; -#endif - const char *remotehost; - - memset(&creds, 0, sizeof(creds)); - memset(&outbuf, 0, sizeof(outbuf)); - - fd = packet_get_connection_in(); - -#ifdef HEIMDAL - problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd); -#else - problem = krb5_auth_con_genaddrs(context, auth_context, fd, - KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR | - KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR); -#endif - if (problem) - goto out; - - problem = krb5_cc_default(context, &ccache); - if (problem) - goto out; - - problem = krb5_cc_get_principal(context, ccache, &creds.client); - if (problem) - goto out; - - remotehost = get_canonical_hostname(1); - -#ifdef HEIMDAL - problem = krb5_build_principal(context, &creds.server, - strlen(creds.client->realm), creds.client->realm, - "krbtgt", creds.client->realm, NULL); -#else - problem = krb5_build_principal(context, &creds.server, - creds.client->realm.length, creds.client->realm.data, - "host", remotehost, NULL); -#endif - if (problem) - goto out; - - creds.times.endtime = 0; - -#ifdef HEIMDAL - flags.i = 0; - flags.b.forwarded = 1; - flags.b.forwardable = krb5_config_get_bool(context, NULL, - "libdefaults", "forwardable", NULL); - problem = krb5_get_forwarded_creds(context, auth_context, - ccache, flags.i, remotehost, &creds, &outbuf); -#else - forwardable = 1; - problem = krb5_fwd_tgt_creds(context, auth_context, remotehost, - creds.client, creds.server, ccache, forwardable, &outbuf); -#endif - - if (problem) - goto out; - - packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); - packet_put_string((char *)outbuf.data, outbuf.length); - packet_send(); - packet_write_wait(); - - type = packet_read(); - - if (type == SSH_SMSG_SUCCESS) { - char *pname; - - krb5_unparse_name(context, creds.client, &pname); - debug("Kerberos v5 TGT forwarded (%s).", pname); - xfree(pname); - } else - debug("Kerberos v5 TGT forwarding failed."); - - return; - - out: - if (problem) - debug("Kerberos v5 TGT forwarding failed: %s", - krb5_get_err_text(context, problem)); - if (creds.client) - krb5_free_principal(context, creds.client); - if (creds.server) - krb5_free_principal(context, creds.server); - if (ccache) - krb5_cc_close(context, ccache); - if (outbuf.data) - xfree(outbuf.data); -} -#endif /* KRB5 */ - -#ifdef AFS -static void -send_krb4_tgt(void) -{ - CREDENTIALS *creds; - struct stat st; - char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; - int problem, type; - - /* Don't do anything if we don't have any tickets. */ - if (stat(tkt_string(), &st) < 0) - return; - - creds = xmalloc(sizeof(*creds)); - - problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm); - if (problem) - goto out; - - problem = krb_get_cred("krbtgt", prealm, prealm, creds); - if (problem) - goto out; - - if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) { - problem = RD_AP_EXP; - goto out; - } - creds_to_radix(creds, (u_char *)buffer, sizeof(buffer)); - - packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); - packet_put_cstring(buffer); - packet_send(); - packet_write_wait(); - - type = packet_read(); - - if (type == SSH_SMSG_SUCCESS) - debug("Kerberos v4 TGT forwarded (%s%s%s@%s).", - creds->pname, creds->pinst[0] ? "." : "", - creds->pinst, creds->realm); - else - debug("Kerberos v4 TGT rejected."); - - xfree(creds); - return; - - out: - debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]); - xfree(creds); -} - -static void -send_afs_tokens(void) -{ - CREDENTIALS creds; - struct ViceIoctl parms; - struct ClearToken ct; - int i, type, len; - char buf[2048], *p, *server_cell; - char buffer[8192]; - - /* Move over ktc_GetToken, here's something leaner. */ - for (i = 0; i < 100; i++) { /* just in case */ - parms.in = (char *) &i; - parms.in_size = sizeof(i); - parms.out = buf; - parms.out_size = sizeof(buf); - if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) - break; - p = buf; - - /* Get secret token. */ - memcpy(&creds.ticket_st.length, p, sizeof(u_int)); - if (creds.ticket_st.length > MAX_KTXT_LEN) - break; - p += sizeof(u_int); - memcpy(creds.ticket_st.dat, p, creds.ticket_st.length); - p += creds.ticket_st.length; - - /* Get clear token. */ - memcpy(&len, p, sizeof(len)); - if (len != sizeof(struct ClearToken)) - break; - p += sizeof(len); - memcpy(&ct, p, len); - p += len; - p += sizeof(len); /* primary flag */ - server_cell = p; - - /* Flesh out our credentials. */ - strlcpy(creds.service, "afs", sizeof(creds.service)); - creds.instance[0] = '\0'; - strlcpy(creds.realm, server_cell, REALM_SZ); - memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ); - creds.issue_date = ct.BeginTimestamp; - creds.lifetime = krb_time_to_life(creds.issue_date, - ct.EndTimestamp); - creds.kvno = ct.AuthHandle; - snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId); - creds.pinst[0] = '\0'; - - /* Encode token, ship it off. */ - if (creds_to_radix(&creds, (u_char *)buffer, - sizeof(buffer)) <= 0) - break; - packet_start(SSH_CMSG_HAVE_AFS_TOKEN); - packet_put_cstring(buffer); - packet_send(); - packet_write_wait(); - - /* Roger, Roger. Clearance, Clarence. What's your vector, - Victor? */ - type = packet_read(); - - if (type == SSH_SMSG_FAILURE) - debug("AFS token for cell %s rejected.", server_cell); - else if (type != SSH_SMSG_SUCCESS) - packet_disconnect("Protocol error on AFS token response: %d", type); - } -} - -#endif /* AFS */ - -/* - * Tries to authenticate with any string-based challenge/response system. - * Note that the client code is not tied to s/key or TIS. - */ -static int -try_challenge_response_authentication(void) -{ - int type, i; - u_int clen; - char prompt[1024]; - char *challenge, *response; - - debug("Doing challenge response authentication."); - - for (i = 0; i < options.number_of_password_prompts; i++) { - /* request a challenge */ - packet_start(SSH_CMSG_AUTH_TIS); - packet_send(); - packet_write_wait(); - - type = packet_read(); - if (type != SSH_SMSG_FAILURE && - type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - packet_disconnect("Protocol error: got %d in response " - "to SSH_CMSG_AUTH_TIS", type); - } - if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - debug("No challenge."); - return 0; - } - challenge = packet_get_string(&clen); - packet_check_eom(); - snprintf(prompt, sizeof prompt, "%s%s", challenge, - strchr(challenge, '\n') ? "" : gettext("\nResponse: ")); - xfree(challenge); - if (i != 0) - error("Permission denied, please try again."); - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! " - "Response will be transmitted in clear text."); - response = read_passphrase(prompt, 0); - if (strcmp(response, "") == 0) { - xfree(response); - break; - } - packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); - ssh_put_password(response); - memset(response, 0, strlen(response)); - xfree(response); - packet_send(); - packet_write_wait(); - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - return 1; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response " - "to SSH_CMSG_AUTH_TIS_RESPONSE", type); - } - /* failure */ - return 0; -} - -/* - * Tries to authenticate with plain passwd authentication. - */ -static int -try_password_authentication(char *prompt) -{ - int type, i; - char *password; - - debug("Doing password authentication."); - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); - for (i = 0; i < options.number_of_password_prompts; i++) { - if (i != 0) - error("Permission denied, please try again."); - password = read_passphrase(prompt, 0); - packet_start(SSH_CMSG_AUTH_PASSWORD); - ssh_put_password(password); - memset(password, 0, strlen(password)); - xfree(password); - packet_send(); - packet_write_wait(); - - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - return 1; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to passwd auth", type); - } - /* failure */ - return 0; -} - -/* - * SSH1 key exchange - */ -void -ssh_kex(char *host, struct sockaddr *hostaddr) -{ - int i; - BIGNUM *key; - Key *host_key, *server_key; - int bits, rbits; - int ssh_cipher_default = SSH_CIPHER_3DES; - u_char session_key[SSH_SESSION_KEY_LENGTH]; - u_char cookie[8]; - u_int supported_ciphers; - u_int server_flags, client_flags; - u_int32_t rand = 0; - - debug("Waiting for server public key."); - - /* Wait for a public key packet from the server. */ - packet_read_expect(SSH_SMSG_PUBLIC_KEY); - - /* Get cookie from the packet. */ - for (i = 0; i < 8; i++) - cookie[i] = packet_get_char(); - - /* Get the public key. */ - server_key = key_new(KEY_RSA1); - bits = packet_get_int(); - packet_get_bignum(server_key->rsa->e); - packet_get_bignum(server_key->rsa->n); - - rbits = BN_num_bits(server_key->rsa->n); - if (bits != rbits) { - log("Warning: Server lies about size of server public key: " - "actual size is %d bits vs. announced %d.", rbits, bits); - log("Warning: This may be due to an old implementation of ssh."); - } - /* Get the host key. */ - host_key = key_new(KEY_RSA1); - bits = packet_get_int(); - packet_get_bignum(host_key->rsa->e); - packet_get_bignum(host_key->rsa->n); - - rbits = BN_num_bits(host_key->rsa->n); - if (bits != rbits) { - log("Warning: Server lies about size of server host key: " - "actual size is %d bits vs. announced %d.", rbits, bits); - log("Warning: This may be due to an old implementation of ssh."); - } - - /* Get protocol flags. */ - server_flags = packet_get_int(); - packet_set_protocol_flags(server_flags); - - supported_ciphers = packet_get_int(); - supported_authentications = packet_get_int(); - packet_check_eom(); - - debug("Received server public key (%d bits) and host key (%d bits).", - BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); - - if (verify_host_key(host, hostaddr, host_key) == -1) - fatal("Host key verification failed."); - - client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; - - compute_session_id(session_id, cookie, host_key->rsa->n, server_key->rsa->n); - - /* Generate a session key. */ - arc4random_stir(); - - /* - * Generate an encryption key for the session. The key is a 256 bit - * random number, interpreted as a 32-byte key, with the least - * significant 8 bits being the first byte of the key. - */ - for (i = 0; i < 32; i++) { - if (i % 4 == 0) - rand = arc4random(); - session_key[i] = rand & 0xff; - rand >>= 8; - } - - /* - * According to the protocol spec, the first byte of the session key - * is the highest byte of the integer. The session key is xored with - * the first 16 bytes of the session id. - */ - if ((key = BN_new()) == NULL) - fatal("respond_to_rsa_challenge: BN_new failed"); - BN_set_word(key, 0); - for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { - BN_lshift(key, key, 8); - if (i < 16) - BN_add_word(key, session_key[i] ^ session_id[i]); - else - BN_add_word(key, session_key[i]); - } - - /* - * Encrypt the integer using the public key and host key of the - * server (key with smaller modulus first). - */ - if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) { - /* Public key has smaller modulus. */ - if (BN_num_bits(host_key->rsa->n) < - BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: host_key %d < server_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(host_key->rsa->n), - BN_num_bits(server_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - rsa_public_encrypt(key, key, server_key->rsa); - rsa_public_encrypt(key, key, host_key->rsa); - } else { - /* Host key has smaller modulus (or they are equal). */ - if (BN_num_bits(server_key->rsa->n) < - BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: server_key %d < host_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(server_key->rsa->n), - BN_num_bits(host_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - rsa_public_encrypt(key, key, host_key->rsa); - rsa_public_encrypt(key, key, server_key->rsa); - } - - /* Destroy the public keys since we no longer need them. */ - key_free(server_key); - key_free(host_key); - - if (options.cipher == SSH_CIPHER_NOT_SET) { - if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default)) - options.cipher = ssh_cipher_default; - } else if (options.cipher == SSH_CIPHER_ILLEGAL || - !(cipher_mask_ssh1(1) & (1 << options.cipher))) { - log("No valid SSH1 cipher, using %.100s instead.", - cipher_name(ssh_cipher_default)); - options.cipher = ssh_cipher_default; - } - /* Check that the selected cipher is supported. */ - if (!(supported_ciphers & (1 << options.cipher))) - fatal("Selected cipher type %.100s not supported by server.", - cipher_name(options.cipher)); - - debug("Encryption type: %.100s", cipher_name(options.cipher)); - - /* Send the encrypted session key to the server. */ - packet_start(SSH_CMSG_SESSION_KEY); - packet_put_char(options.cipher); - - /* Send the cookie back to the server. */ - for (i = 0; i < 8; i++) - packet_put_char(cookie[i]); - - /* Send and destroy the encrypted encryption key integer. */ - packet_put_bignum(key); - BN_clear_free(key); - - /* Send protocol flags. */ - packet_put_int(client_flags); - - /* Send the packet now. */ - packet_send(); - packet_write_wait(); - - debug("Sent encrypted session key."); - - /* Set the encryption key. */ - packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher); - - /* We will no longer need the session key here. Destroy any extra copies. */ - memset(session_key, 0, sizeof(session_key)); - - /* - * Expect a success message from the server. Note that this message - * will be received in encrypted form. - */ - packet_read_expect(SSH_SMSG_SUCCESS); - - debug("Received encrypted confirmation."); -} - -/* - * Authenticate user - */ -void -ssh_userauth1(const char *local_user, const char *server_user, char *host, - Sensitive *sensitive) -{ -#ifdef KRB5 - krb5_context context = NULL; - krb5_auth_context auth_context = NULL; -#endif - int i, type; - - if (supported_authentications == 0) - fatal("ssh_userauth1: server supports no auth methods"); - - /* Send the name of the user to log in as on the server. */ - packet_start(SSH_CMSG_USER); - packet_put_cstring(server_user); - packet_send(); - packet_write_wait(); - - /* - * The server should respond with success if no authentication is - * needed (the user has no password). Otherwise the server responds - * with failure. - */ - type = packet_read(); - - /* check whether the connection was accepted without authentication. */ - if (type == SSH_SMSG_SUCCESS) - goto success; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type); - -#ifdef KRB5 - if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && - options.kerberos_authentication) { - debug("Trying Kerberos v5 authentication."); - - if (try_krb5_authentication(&context, &auth_context)) { - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - goto success; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to Kerberos v5 auth", type); - } - } -#endif /* KRB5 */ - -#ifdef KRB4 - if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && - options.kerberos_authentication) { - debug("Trying Kerberos v4 authentication."); - - if (try_krb4_authentication()) { - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - goto success; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to Kerberos v4 auth", type); - } - } -#endif /* KRB4 */ - - /* - * Use rhosts authentication if running in privileged socket and we - * do not wish to remain anonymous. - */ - if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) && - options.rhosts_authentication) { - debug("Trying rhosts authentication."); - packet_start(SSH_CMSG_AUTH_RHOSTS); - packet_put_cstring(local_user); - packet_send(); - packet_write_wait(); - - /* The server should respond with success or failure. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - goto success; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to rhosts auth", - type); - } - /* - * Try .rhosts or /etc/hosts.equiv authentication with RSA host - * authentication. - */ - if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) && - options.rhosts_rsa_authentication) { - for (i = 0; i < sensitive->nkeys; i++) { - if (sensitive->keys[i] != NULL && - sensitive->keys[i]->type == KEY_RSA1 && - try_rhosts_rsa_authentication(local_user, - sensitive->keys[i])) - goto success; - } - } - /* Try RSA authentication if the server supports it. */ - if ((supported_authentications & (1 << SSH_AUTH_RSA)) && - options.rsa_authentication) { - /* - * Try RSA authentication using the authentication agent. The - * agent is tried first because no passphrase is needed for - * it, whereas identity files may require passphrases. - */ - if (try_agent_authentication()) - goto success; - - /* Try RSA authentication for each identity. */ - for (i = 0; i < options.num_identity_files; i++) - if (options.identity_keys[i] != NULL && - options.identity_keys[i]->type == KEY_RSA1 && - try_rsa_authentication(i)) - goto success; - } - /* Try challenge response authentication if the server supports it. */ - if ((supported_authentications & (1 << SSH_AUTH_TIS)) && - options.challenge_response_authentication && !options.batch_mode) { - if (try_challenge_response_authentication()) - goto success; - } - /* Try password authentication if the server supports it. */ - if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && - options.password_authentication && !options.batch_mode) { - char prompt[80]; - - snprintf(prompt, sizeof(prompt), - gettext("%.30s@%.128s's password: "), - server_user, host); - if (try_password_authentication(prompt)) - goto success; - } - /* All authentication methods have failed. Exit with an error message. */ - fatal("Permission denied (all authentication methods have failed)."); - /* NOTREACHED */ - - success: -#ifdef KRB5 - /* Try Kerberos v5 TGT passing. */ - if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && - options.kerberos_tgt_passing && context && auth_context) { - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); - send_krb5_tgt(context, auth_context); - } - if (auth_context) - krb5_auth_con_free(context, auth_context); - if (context) - krb5_free_context(context); -#endif - -#ifdef AFS - /* Try Kerberos v4 TGT passing if the server supports it. */ - if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && - options.kerberos_tgt_passing) { - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); - send_krb4_tgt(); - } - /* Try AFS token passing if the server supports it. */ - if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) && - options.afs_token_passing && k_hasafs()) { - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Token will be transmitted in the clear!"); - send_afs_tokens(); - } -#endif /* AFS */ - - return; /* need statement after label */ -} diff --git a/usr/src/cmd/ssh/ssh/sshconnect2.c b/usr/src/cmd/ssh/ssh/sshconnect2.c deleted file mode 100644 index e485355b6a..0000000000 --- a/usr/src/cmd/ssh/ssh/sshconnect2.c +++ /dev/null @@ -1,1685 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.107 2002/07/01 19:48:46 markus Exp $"); - -#include "ssh.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "buffer.h" -#include "packet.h" -#include "compat.h" -#include "bufaux.h" -#include "cipher.h" -#include "kex.h" -#include "myproposal.h" -#include "sshconnect.h" -#include "authfile.h" -#include "dh.h" -#include "authfd.h" -#include "log.h" -#include "readconf.h" -#include "readpass.h" -#include "match.h" -#include "dispatch.h" -#include "canohost.h" -#include "msg.h" -#include "pathnames.h" -#include "g11n.h" - -#ifdef GSSAPI -#include "ssh-gss.h" -extern Gssctxt *xxx_gssctxt; -#endif /* GSSAPI */ - -/* import */ -extern char *client_version_string; -extern char *server_version_string; -extern Options options; -extern Buffer command; - -/* - * SSH2 key exchange - */ - -u_char *session_id2 = NULL; -int session_id2_len = 0; - -char *xxx_host; -struct sockaddr *xxx_hostaddr; - -Kex *xxx_kex = NULL; - -static int -verify_host_key_callback(Key *hostkey) -{ - if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) - fatal("Host key verification failed."); - return 0; -} - -static int -accept_host_key_callback(Key *hostkey) -{ - if (accept_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) - log("GSS-API authenticated host key addition to " - "known_hosts file failed"); - return 0; -} - -void -ssh_kex2(char *host, struct sockaddr *hostaddr) -{ - Kex *kex; - Kex_hook_func kex_hook = NULL; - static char **myproposal; - - myproposal = my_clnt_proposal; - - xxx_host = host; - xxx_hostaddr = hostaddr; - -#ifdef GSSAPI - /* Add the GSSAPI mechanisms currently supported on this client to - * the key exchange algorithm proposal */ - if (options.gss_keyex) - kex_hook = ssh_gssapi_client_kex_hook; -#endif /* GSSAPI */ - if (options.ciphers == (char *)-1) { - log("No valid ciphers for protocol version 2 given, using defaults."); - options.ciphers = NULL; - } - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); - myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); - if (options.compression) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib,none"; - } else { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib"; - } - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - } - if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - options.hostkeyalgorithms; - - if (options.rekey_limit) - packet_set_rekey_limit((u_int32_t)options.rekey_limit); - - if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) { - char *locale = setlocale(LC_ALL, ""); - - /* Solaris 9 SSHD expects a locale, not a langtag list */ - myproposal[PROPOSAL_LANG_CTOS] = ""; - if (locale != NULL && *locale != '\0' && - strcmp(locale, "C") != 0) - myproposal[PROPOSAL_LANG_CTOS] = locale; - } else { - myproposal[PROPOSAL_LANG_CTOS] = g11n_getlangs(); - } - - /* Same languages proposal for both directions */ - if (myproposal[PROPOSAL_LANG_CTOS] == NULL) { - myproposal[PROPOSAL_LANG_CTOS] = ""; - myproposal[PROPOSAL_LANG_STOC] = ""; - } else { - myproposal[PROPOSAL_LANG_STOC] = - myproposal[PROPOSAL_LANG_CTOS]; - } - - /* start key exchange */ - kex = kex_setup(host, myproposal, kex_hook); - kex_start(kex); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; -#ifdef GSSAPI - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; - kex->options.gss_deleg_creds = options.gss_deleg_creds; -#endif /* GSSAPI */ - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; - kex->verify_host_key=&verify_host_key_callback; - kex->accept_host_key=&accept_host_key_callback; - - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); - - session_id2 = kex->session_id; - session_id2_len = kex->session_id_len; - -#ifdef DEBUG_KEXDH - /* send 1st encrypted/maced/compressed message */ - packet_start(SSH2_MSG_IGNORE); - packet_put_cstring("markus"); - packet_send(); - packet_write_wait(); -#endif - debug("done: ssh_kex2."); -} - -/* - * Authenticate user - */ - -typedef struct Authctxt Authctxt; -typedef struct Authmethod Authmethod; - -typedef int sign_cb_fn( - Authctxt *authctxt, Key *key, - u_char **sigp, u_int *lenp, u_char *data, u_int datalen); - -struct Authctxt { - const char *server_user; - const char *local_user; - const char *host; - const char *service; - Authmethod *method; - int success; - char *authlist; - /* pubkey */ - Key *last_key; - sign_cb_fn *last_key_sign; - int last_key_hint; - AuthenticationConnection *agent; - /* hostbased */ - Sensitive *sensitive; - /* kbd-interactive */ - int info_req_seen; - /* generic */ - void *methoddata; -}; -struct Authmethod { - char *name; /* string to compare against server's list */ - int (*userauth)(Authctxt *authctxt); - void (*cleanup)(Authctxt *authctxt); - int *enabled; /* flag in option struct that enables method */ - int *batch_flag; /* flag in option struct that disables method */ -}; - -void input_userauth_success(int, u_int32_t, void *); -void input_userauth_failure(int, u_int32_t, void *); -void input_userauth_banner(int, u_int32_t, void *); -void input_userauth_error(int, u_int32_t, void *); -void input_userauth_info_req(int, u_int32_t, void *); -void input_userauth_pk_ok(int, u_int32_t, void *); -void input_userauth_passwd_changereq(int, u_int32_t, void *); - -int userauth_none(Authctxt *); -int userauth_pubkey(Authctxt *); -int userauth_passwd(Authctxt *); -int userauth_kbdint(Authctxt *); -int userauth_hostbased(Authctxt *); - -#ifdef GSSAPI -static int userauth_gssapi_keyex(Authctxt *authctxt); -static int userauth_gssapi(Authctxt *authctxt); -static void userauth_gssapi_cleanup(Authctxt *authctxt); -static void input_gssapi_response(int type, u_int32_t, void *); -static void input_gssapi_token(int type, u_int32_t, void *); -static void input_gssapi_hash(int type, u_int32_t, void *); -static void input_gssapi_error(int, u_int32_t, void *); -static void input_gssapi_errtok(int, u_int32_t, void *); -#endif /* GSSAPI */ - -void userauth(Authctxt *, char *); - -static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); -static void clear_auth_state(Authctxt *); - -static Authmethod *authmethod_get(char *authlist); -static Authmethod *authmethod_lookup(const char *name); -static char *authmethods_get(void); - -Authmethod authmethods[] = { -#ifdef GSSAPI - {"gssapi-keyex", - userauth_gssapi_keyex, - userauth_gssapi_cleanup, - &options.gss_keyex, - NULL}, - {"gssapi-with-mic", - userauth_gssapi, - userauth_gssapi_cleanup, - &options.gss_authentication, - NULL}, -#endif /* GSSAPI */ - {"hostbased", - userauth_hostbased, - NULL, - &options.hostbased_authentication, - NULL}, - {"publickey", - userauth_pubkey, - NULL, - &options.pubkey_authentication, - NULL}, - {"keyboard-interactive", - userauth_kbdint, - NULL, - &options.kbd_interactive_authentication, - &options.batch_mode}, - {"password", - userauth_passwd, - NULL, - &options.password_authentication, - &options.batch_mode}, - {"none", - userauth_none, - NULL, - NULL, - NULL}, - {NULL, NULL, NULL, NULL, NULL} -}; - -void -ssh_userauth2(const char *local_user, const char *server_user, char *host, - Sensitive *sensitive) -{ - Authctxt authctxt; - int type; - - if (options.challenge_response_authentication) - options.kbd_interactive_authentication = 1; - - packet_start(SSH2_MSG_SERVICE_REQUEST); - packet_put_cstring("ssh-userauth"); - packet_send(); - debug("send SSH2_MSG_SERVICE_REQUEST"); - packet_write_wait(); - type = packet_read(); - if (type != SSH2_MSG_SERVICE_ACCEPT) - fatal("Server denied authentication request: %d", type); - if (packet_remaining() > 0) { - char *reply = packet_get_string(NULL); - debug2("service_accept: %s", reply); - xfree(reply); - } else { - debug2("buggy server: service_accept w/o service"); - } - packet_check_eom(); - debug("got SSH2_MSG_SERVICE_ACCEPT"); - - if (options.preferred_authentications == NULL) - options.preferred_authentications = authmethods_get(); - - /* setup authentication context */ - memset(&authctxt, 0, sizeof(authctxt)); - authctxt.agent = ssh_get_authentication_connection(); - authctxt.server_user = server_user; - authctxt.local_user = local_user; - authctxt.host = host; - authctxt.service = "ssh-connection"; /* service name */ - authctxt.success = 0; - authctxt.method = authmethod_lookup("none"); - authctxt.authlist = NULL; - authctxt.methoddata = NULL; - authctxt.sensitive = sensitive; - authctxt.info_req_seen = 0; - if (authctxt.method == NULL) - fatal("ssh_userauth2: internal error: cannot send userauth none request"); - - /* initial userauth request */ - userauth_none(&authctxt); - - dispatch_init(&input_userauth_error); - dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); - dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); - dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); - dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ - - if (authctxt.agent != NULL) - ssh_close_authentication_connection(authctxt.agent); - - debug("Authentication succeeded (%s)", authctxt.method->name); -} -void -userauth(Authctxt *authctxt, char *authlist) -{ - if (authctxt->method != NULL && - authctxt->method->cleanup != NULL) - authctxt->method->cleanup(authctxt); - - if (authlist == NULL) { - authlist = authctxt->authlist; - } else { - if (authctxt->authlist) - xfree(authctxt->authlist); - authctxt->authlist = authlist; - } - for (;;) { - Authmethod *method = authmethod_get(authlist); - if (method == NULL) - fatal("Permission denied (%s).", authlist); - authctxt->method = method; - if (method->userauth(authctxt) != 0) { - debug2("we sent a %s packet, wait for reply", method->name); - break; - } else { - debug2("we did not send a packet, disable method"); - method->enabled = NULL; - } - } -} - -void -input_userauth_error(int type, u_int32_t seq, void *ctxt) -{ - fatal("input_userauth_error: bad message during authentication: " - "type %d", type); -} - -void -input_userauth_banner(int type, u_int32_t seq, void *ctxt) -{ - char *msg, *lang; - - debug3("input_userauth_banner"); - msg = packet_get_utf8_string(NULL); - lang = packet_get_string(NULL); - /* - * Banner is a warning message according to RFC 4252. So, never print - * a banner in error log level or lower. If the log level is higher, - * use DisableBanner option to decide whether to display it or not. - */ - if (options.log_level > SYSLOG_LEVEL_ERROR) { - if (options.disable_banner == 0 || - (options.disable_banner == SSH_NO_BANNER_IN_EXEC_MODE && - buffer_len(&command) == 0)) { - msg = g11n_filter_string(msg); - (void) fprintf(stderr, "%s", msg); - } - } - xfree(msg); - xfree(lang); -} - -void -input_userauth_success(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - if (authctxt == NULL) - fatal("input_userauth_success: no authentication context"); - if (authctxt->authlist) - xfree(authctxt->authlist); - if (authctxt->method != NULL && - authctxt->method->cleanup != NULL) - authctxt->method->cleanup(authctxt); - clear_auth_state(authctxt); - authctxt->success = 1; /* break out */ -} - -void -input_userauth_failure(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - char *authlist = NULL; - int partial; - - if (authctxt == NULL) - fatal("input_userauth_failure: no authentication context"); - - authlist = packet_get_string(NULL); - partial = packet_get_char(); - packet_check_eom(); - - if (partial != 0) - log("Authenticated with partial success."); - debug("Authentications that can continue: %s", authlist); - - clear_auth_state(authctxt); - userauth(authctxt, authlist); -} -void -input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Key *key = NULL; - Buffer b; - int pktype, sent = 0; - u_int alen, blen; - char *pkalg, *fp; - u_char *pkblob; - - if (authctxt == NULL) - fatal("input_userauth_pk_ok: no authentication context"); - if (datafellows & SSH_BUG_PKOK) { - /* this is similar to SSH_BUG_PKAUTH */ - debug2("input_userauth_pk_ok: SSH_BUG_PKOK"); - pkblob = packet_get_string(&blen); - buffer_init(&b); - buffer_append(&b, pkblob, blen); - pkalg = buffer_get_string(&b, &alen); - buffer_free(&b); - } else { - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - } - packet_check_eom(); - - debug("Server accepts key: pkalg %s blen %u lastkey %p hint %d", - pkalg, blen, authctxt->last_key, authctxt->last_key_hint); - - do { - if (authctxt->last_key == NULL || - authctxt->last_key_sign == NULL) { - debug("no last key or no sign cb"); - break; - } - if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { - debug("unknown pkalg %s", pkalg); - break; - } - if ((key = key_from_blob(pkblob, blen)) == NULL) { - debug("no key from blob. pkalg %s", pkalg); - break; - } - if (key->type != pktype) { - error("input_userauth_pk_ok: type mismatch " - "for decoded key (received %d, expected %d)", - key->type, pktype); - break; - } - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - debug2("input_userauth_pk_ok: fp %s", fp); - xfree(fp); - if (!key_equal(key, authctxt->last_key)) { - debug("key != last_key"); - break; - } - sent = sign_and_send_pubkey(authctxt, key, - authctxt->last_key_sign); - } while (0); - - if (key != NULL) - key_free(key); - xfree(pkalg); - xfree(pkblob); - - /* unregister */ - clear_auth_state(authctxt); - dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL); - - /* try another method if we did not send a packet */ - if (sent == 0) - userauth(authctxt, NULL); - -} - -#ifdef GSSAPI -int -userauth_gssapi(Authctxt *authctxt) -{ - Gssctxt *gssctxt = NULL; - static int initialized = 0; - static int mech_idx = 0; - static gss_OID_set supported = GSS_C_NULL_OID_SET; - gss_OID mech = GSS_C_NULL_OID; - - /* Things work better if we send one mechanism at a time, rather - * than them all at once. This means that if we fail at some point - * in the middle of a negotiation, we can come back and try something - * different. */ - - if (datafellows & SSH_OLD_GSSAPI) return 0; - - /* Before we offer a mechanism, check that we can support it. Don't - * bother trying to get credentials - as the standard fallback will - * deal with that kind of failure. - */ - - if (!initialized) { - initialized = 1; - ssh_gssapi_client_mechs(authctxt->host, &supported); - if (supported == GSS_C_NULL_OID_SET || supported->count == 0) - return (0); - } else if (supported != GSS_C_NULL_OID_SET) { - /* Try next mech, if any */ - mech_idx++; - - if (mech_idx >= supported->count) - return (0); - } else { - return (0); - } - - mech = &supported->elements[mech_idx]; - - ssh_gssapi_build_ctx(&gssctxt, 1, mech); - authctxt->methoddata=(void *)gssctxt; - - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - - packet_put_int(1); - - /* The newest gsskeyex draft stipulates that OIDs should - * be DER encoded, so we need to add the object type and - * length information back on */ - if (datafellows & SSH_BUG_GSSAPI_BER) { - packet_put_string(mech->elements, mech->length); - } else { - packet_put_int((mech->length)+2); - packet_put_char(0x06); - packet_put_char(mech->length); - packet_put_raw(mech->elements, mech->length); - } - - packet_send(); - packet_write_wait(); - - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,&input_gssapi_response); - - return 1; -} - -void -input_gssapi_response(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - OM_uint32 status,ms; - u_int oidlen; - char *oidv; - gss_buffer_desc send_tok; - - if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); - gssctxt = authctxt->methoddata; - - /* Setup our OID */ - oidv=packet_get_string(&oidlen); - - if (datafellows & SSH_BUG_GSSAPI_BER) { - if (!ssh_gssapi_check_mech_oid(gssctxt,oidv,oidlen)) { - gss_OID oid; - - oid = ssh_gssapi_make_oid(oidlen, oidv); - debug("Server returned different OID (%s) than expected (%s)", - ssh_gssapi_oid_to_str(oid), - ssh_gssapi_oid_to_str(gssctxt->desired_mech)); - ssh_gssapi_release_oid(&oid); - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return; - } - } else { - if(oidv[0]!=0x06 || oidv[1]!=oidlen-2) { - debug("Badly encoded mechanism OID received"); - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return; - } - if (!ssh_gssapi_check_mech_oid(gssctxt,oidv+2,oidlen-2)) { - gss_OID oid; - - oid = ssh_gssapi_make_oid(oidlen-2, oidv+2); - debug("Server returned different OID (%s) than expected (%s)", - ssh_gssapi_oid_to_str(oid), - ssh_gssapi_oid_to_str(gssctxt->desired_mech)); - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return; - } - } - - packet_check_eom(); - - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,&input_gssapi_token); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,&input_gssapi_error); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,&input_gssapi_errtok); - - status = ssh_gssapi_init_ctx(gssctxt, authctxt->host, - options.gss_deleg_creds, - GSS_C_NO_BUFFER, &send_tok); - if (GSS_ERROR(status)) { - if (send_tok.length>0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); - packet_put_string(send_tok.value,send_tok.length); - packet_send(); - packet_write_wait(); - } - /* Start again with next method on list */ - debug("Trying to start again"); - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return; - } - - /* We must have data to send */ - packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); - packet_put_string(send_tok.value,send_tok.length); - packet_send(); - packet_write_wait(); - gss_release_buffer(&ms, &send_tok); -} - -void -input_gssapi_token(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc send_tok, recv_tok, g_mic_data; - Buffer mic_data; - OM_uint32 status; - u_int slen; - - if (authctxt == NULL || authctxt->method == NULL) - fatal("input_gssapi_response: no authentication context"); - gssctxt = authctxt->methoddata; - - recv_tok.value=packet_get_string(&slen); - recv_tok.length=slen; /* safe typecast */ - - status=ssh_gssapi_init_ctx(gssctxt, authctxt->host, - options.gss_deleg_creds, - &recv_tok, &send_tok); - - packet_check_eom(); - - if (GSS_ERROR(status)) { - if (send_tok.length>0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); - packet_put_string(send_tok.value,send_tok.length); - packet_send(); - packet_write_wait(); - } - /* Start again with the next method in the list */ - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return; - } - - if (send_tok.length>0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); - packet_put_string(send_tok.value,send_tok.length); - packet_send(); - packet_write_wait(); - } - - if (status != GSS_S_COMPLETE) - return; - - /* Make data buffer to MIC */ - buffer_init(&mic_data); - buffer_put_string(&mic_data, session_id2, session_id2_len); - buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&mic_data, authctxt->server_user); - buffer_put_cstring(&mic_data, authctxt->service); - buffer_put_cstring(&mic_data, authctxt->method->name); - - /* Make MIC */ - g_mic_data.value = buffer_ptr(&mic_data); - g_mic_data.length = buffer_len(&mic_data); - - status = ssh_gssapi_get_mic(gssctxt, &g_mic_data, &send_tok); - buffer_clear(&mic_data); - - if (GSS_ERROR(status) || send_tok.length == 0) { - /* - * Oops, now what? There's no error token... - * Next userauth - */ - debug("GSS_GetMIC() failed! - " - "Abandoning GSSAPI userauth"); - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return; - } - packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC); - packet_put_string(send_tok.value,send_tok.length); - packet_send(); - packet_write_wait(); -} - -void -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) -{ - OM_uint32 min_status; - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc send_tok, recv_tok; - - if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); - gssctxt = authctxt->methoddata; - - recv_tok.value=packet_get_string(&recv_tok.length); - - /* Stick it into GSSAPI and see what it says */ - (void) ssh_gssapi_init_ctx(gssctxt, authctxt->host, - options.gss_deleg_creds, - &recv_tok, &send_tok); - - xfree(recv_tok.value); - (void) gss_release_buffer(&min_status, &send_tok); - - debug("Server sent a GSS-API error token during GSS userauth -- %s", - ssh_gssapi_last_error(gssctxt, NULL, NULL)); - - packet_check_eom(); - - /* We can't send a packet to the server */ - - /* The draft says that we should wait for the server to fail - * before starting the next authentication. So, we clear the - * state, but don't do anything else - */ - clear_auth_state(authctxt); - return; -} - -void -input_gssapi_error(int type, u_int32_t plen, void *ctxt) -{ - OM_uint32 maj,min; - char *msg; - char *lang; - - maj = packet_get_int(); - min = packet_get_int(); - msg = packet_get_string(NULL); - lang = packet_get_string(NULL); - - packet_check_eom(); - - fprintf(stderr, "Server GSSAPI Error:\n%s (%d, %d)\n", msg, maj, min); - xfree(msg); - xfree(lang); -} - -int -userauth_gssapi_keyex(Authctxt *authctxt) -{ - Gssctxt *gssctxt; - gss_buffer_desc send_tok; - OM_uint32 status; - static int attempt = 0; - - if (authctxt == NULL || authctxt->method == NULL) - fatal("input_gssapi_response: no authentication context"); - - if (xxx_gssctxt == NULL || xxx_gssctxt->context == GSS_C_NO_CONTEXT) - return 0; - - if (strcmp(authctxt->method->name, "gssapi-keyex") == 0) - authctxt->methoddata = gssctxt = xxx_gssctxt; - - if (attempt++ >= 1) - return 0; - - if (strcmp(authctxt->method->name, "gssapi-keyex") == 0) { - gss_buffer_desc g_mic_data; - Buffer mic_data; - - debug2("Authenticating with GSS-API context from key exchange (w/ MIC)"); - - /* Make data buffer to MIC */ - buffer_init(&mic_data); - buffer_put_string(&mic_data, session_id2, session_id2_len); - buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&mic_data, authctxt->server_user); - buffer_put_cstring(&mic_data, authctxt->service); - buffer_put_cstring(&mic_data, authctxt->method->name); - - /* Make MIC */ - g_mic_data.value = buffer_ptr(&mic_data); - g_mic_data.length = buffer_len(&mic_data); - status = ssh_gssapi_get_mic(gssctxt, &g_mic_data, &send_tok); - buffer_clear(&mic_data); - - if (GSS_ERROR(status) || send_tok.length == 0) { - /* - * Oops, now what? There's no error token... - * Next userauth - */ - debug("GSS_GetMIC() failed! - " - "Abandoning GSSAPI userauth"); - clear_auth_state(authctxt); - userauth(authctxt,NULL); - return 0; - } - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_string(send_tok.value,send_tok.length); /* MIC */ - packet_send(); - packet_write_wait(); - (void) gss_release_buffer(&status, &send_tok); - } else if (strcmp(authctxt->method->name, "external-keyx") == 0) { - debug2("Authentication with deprecated \"external-keyx\"" - " method not supported"); - return 0; - } - return 1; -} - -static -void -userauth_gssapi_cleanup(Authctxt *authctxt) -{ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,NULL); - - if (authctxt == NULL || - authctxt->method == NULL || - authctxt->methoddata == NULL) - return; - - if (strncmp(authctxt->method->name, "gssapi", strlen("gssapi")) == 0) { - ssh_gssapi_delete_ctx((Gssctxt **)&authctxt->methoddata); - } -} -#endif /* GSSAPI */ - -int -userauth_none(Authctxt *authctxt) -{ - /* initial userauth request */ - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_send(); - return 1; - -} - -int -userauth_passwd(Authctxt *authctxt) -{ - static int attempt = 0; - char prompt[150]; - char *password; - - if (attempt++ >= options.number_of_password_prompts) - return 0; - - if (attempt != 1) - error("Permission denied, please try again."); - - snprintf(prompt, sizeof(prompt), gettext("%.30s@%.128s's password: "), - authctxt->server_user, authctxt->host); - password = read_passphrase(prompt, 0); - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_char(0); - packet_put_cstring(password); - memset(password, 0, strlen(password)); - xfree(password); - packet_add_padding(64); - packet_send(); - - dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, - &input_userauth_passwd_changereq); - - return 1; -} -/* - * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST - */ -void -input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) -{ - Authctxt *authctxt = ctxt; - char *info, *lang, *password = NULL, *retype = NULL; - char prompt[150]; - - debug2("input_userauth_passwd_changereq"); - - if (authctxt == NULL) - fatal("input_userauth_passwd_changereq: " - "no authentication context"); - - info = packet_get_utf8_string(NULL); - if (strlen(info) != 0) { - info = g11n_filter_string(info); - log("%s", info); - } - xfree(info); - lang = packet_get_string(NULL); - xfree(lang); - - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_char(1); /* additional info */ - snprintf(prompt, sizeof(prompt), - gettext("Enter %.30s@%.128s's old password: "), - authctxt->server_user, authctxt->host); - password = read_passphrase(prompt, 0); - packet_put_cstring(password); - memset(password, 0, strlen(password)); - xfree(password); - password = NULL; - while (password == NULL) { - snprintf(prompt, sizeof(prompt), - gettext("Enter %.30s@%.128s's new password: "), - authctxt->server_user, authctxt->host); - password = read_passphrase(prompt, RP_ALLOW_EOF); - if (password == NULL) { - /* bail out */ - return; - } - snprintf(prompt, sizeof(prompt), - gettext("Retype %.30s@%.128s's new password: "), - authctxt->server_user, authctxt->host); - retype = read_passphrase(prompt, 0); - if (strcmp(password, retype) != 0) { - memset(password, 0, strlen(password)); - xfree(password); - log("Mismatch; try again, EOF to quit."); - password = NULL; - } - memset(retype, 0, strlen(retype)); - xfree(retype); - } - packet_put_cstring(password); - memset(password, 0, strlen(password)); - xfree(password); - packet_add_padding(64); - packet_send(); - - dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, - &input_userauth_passwd_changereq); -} - -static void -clear_auth_state(Authctxt *authctxt) -{ - /* XXX clear authentication state */ - dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL); -#ifdef GSSAPI - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,NULL); -#endif /* GSSAPI */ - - if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) { - debug3("clear_auth_state: key_free %p", authctxt->last_key); - key_free(authctxt->last_key); - } - authctxt->last_key = NULL; - authctxt->last_key_hint = -2; - authctxt->last_key_sign = NULL; -} - -static int -sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) -{ - Buffer b; - u_char *blob, *signature; - u_int bloblen, slen; - int skip = 0; - int ret = -1; - int have_sig = 1; - - debug3("sign_and_send_pubkey"); - - if (key_to_blob(k, &blob, &bloblen) == 0) { - /* we cannot handle this key */ - debug3("sign_and_send_pubkey: cannot handle key"); - return 0; - } - /* data to be signed */ - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); - skip = session_id2_len; - } else { - buffer_put_string(&b, session_id2, session_id2_len); - skip = buffer_len(&b); - } - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->server_user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); - } else { - buffer_put_cstring(&b, authctxt->method->name); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, key_ssh_name(k)); - } - buffer_put_string(&b, blob, bloblen); - - /* generate signature */ - ret = (*sign_callback)(authctxt, k, &signature, &slen, - buffer_ptr(&b), buffer_len(&b)); - if (ret == -1) { - xfree(blob); - buffer_free(&b); - return 0; - } -#ifdef DEBUG_PK - buffer_dump(&b); -#endif - if (datafellows & SSH_BUG_PKSERVICE) { - buffer_clear(&b); - buffer_append(&b, session_id2, session_id2_len); - skip = session_id2_len; - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->server_user); - buffer_put_cstring(&b, authctxt->service); - buffer_put_cstring(&b, authctxt->method->name); - buffer_put_char(&b, have_sig); - if (!(datafellows & SSH_BUG_PKAUTH)) - buffer_put_cstring(&b, key_ssh_name(k)); - buffer_put_string(&b, blob, bloblen); - } - xfree(blob); - - /* append signature */ - buffer_put_string(&b, signature, slen); - xfree(signature); - - /* skip session id and packet type */ - if (buffer_len(&b) < skip + 1) - fatal("userauth_pubkey: internal error"); - buffer_consume(&b, skip + 1); - - /* put remaining data from buffer into packet */ - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_raw(buffer_ptr(&b), buffer_len(&b)); - buffer_free(&b); - packet_send(); - - return 1; -} - -static int -send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback, - int hint) -{ - u_char *blob; - u_int bloblen, have_sig = 0; - - debug3("send_pubkey_test"); - - if (key_to_blob(k, &blob, &bloblen) == 0) { - /* we cannot handle this key */ - debug3("send_pubkey_test: cannot handle key"); - return 0; - } - /* register callback for USERAUTH_PK_OK message */ - authctxt->last_key_sign = sign_callback; - authctxt->last_key_hint = hint; - authctxt->last_key = k; - dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); - - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_char(have_sig); - if (!(datafellows & SSH_BUG_PKAUTH)) - packet_put_cstring(key_ssh_name(k)); - packet_put_string(blob, bloblen); - xfree(blob); - packet_send(); - return 1; -} - -static Key * -load_identity_file(char *filename) -{ - Key *private; - char prompt[300], *passphrase; - int quit, i; - struct stat st; - - if (stat(filename, &st) < 0) { - debug3("no such identity: %s", filename); - return NULL; - } - private = key_load_private_type(KEY_UNSPEC, filename, "", NULL); - if (private == NULL) { - if (options.batch_mode) - return NULL; - snprintf(prompt, sizeof prompt, - gettext("Enter passphrase for key '%.100s': "), filename); - for (i = 0; i < options.number_of_password_prompts; i++) { - passphrase = read_passphrase(prompt, 0); - if (strcmp(passphrase, "") != 0) { - private = key_load_private_type(KEY_UNSPEC, filename, - passphrase, NULL); - quit = 0; - } else { - debug2("no passphrase given, try next key"); - quit = 1; - } - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); - if (private != NULL || quit) - break; - debug2("bad passphrase given, try again..."); - } - } - return private; -} - -static int -identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - Key *private; - int idx, ret; - - idx = authctxt->last_key_hint; - if (idx < 0) - return -1; - - /* private key is stored in external hardware */ - if (options.identity_keys[idx]->flags & KEY_FLAG_EXT) - return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen); - - private = load_identity_file(options.identity_files[idx]); - if (private == NULL) - return -1; - ret = key_sign(private, sigp, lenp, data, datalen); - key_free(private); - return ret; -} - -static int -agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen); -} - -static int -key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - return key_sign(key, sigp, lenp, data, datalen); -} - -static int -userauth_pubkey_agent(Authctxt *authctxt) -{ - static int called = 0; - int ret = 0; - char *comment; - Key *k; - - if (called == 0) { - if (ssh_get_num_identities(authctxt->agent, 2) == 0) - debug2("userauth_pubkey_agent: no keys at all"); - called = 1; - } - k = ssh_get_next_identity(authctxt->agent, &comment, 2); - if (k == NULL) { - debug2("userauth_pubkey_agent: no more keys"); - } else { - debug("Offering agent key: %s", comment); - xfree(comment); - ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1); - if (ret == 0) - key_free(k); - } - if (ret == 0) - debug2("userauth_pubkey_agent: no message sent"); - return ret; -} - -int -userauth_pubkey(Authctxt *authctxt) -{ - static int idx = 0; - int sent = 0; - Key *key; - char *filename; - - if (authctxt->agent != NULL) { - do { - sent = userauth_pubkey_agent(authctxt); - } while (!sent && authctxt->agent->howmany > 0); - } - while (!sent && idx < options.num_identity_files) { - key = options.identity_keys[idx]; - filename = options.identity_files[idx]; - if (key == NULL) { - debug("Trying private key: %s", filename); - key = load_identity_file(filename); - if (key != NULL) { - sent = sign_and_send_pubkey(authctxt, key, - key_sign_cb); - key_free(key); - } - } else if (key->type != KEY_RSA1) { - debug("Trying public key: %s", filename); - sent = send_pubkey_test(authctxt, key, - identity_sign_cb, idx); - } - idx++; - } - return sent; -} - -/* - * Send userauth request message specifying keyboard-interactive method. - */ -int -userauth_kbdint(Authctxt *authctxt) -{ - static int attempt = 0; - - if (attempt++ >= options.number_of_password_prompts) - return 0; - /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ - if (attempt > 1 && !authctxt->info_req_seen) { - debug3("userauth_kbdint: disable: no info_req_seen"); - dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); - return 0; - } - - debug2("userauth_kbdint"); - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_cstring(""); /* lang */ - packet_put_cstring(options.kbd_interactive_devices ? - options.kbd_interactive_devices : ""); - packet_send(); - - dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); - return 1; -} - -/* - * parse INFO_REQUEST, prompt user and send INFO_RESPONSE - */ -void -input_userauth_info_req(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - char *name, *inst, *lang, *prompt, *response; - u_int num_prompts, i; - int echo = 0; - - debug2("input_userauth_info_req"); - - if (authctxt == NULL) - fatal("input_userauth_info_req: no authentication context"); - - authctxt->info_req_seen = 1; - - /* - * We assume that ASCII is used for user name although it is defined - * by the protocol to use UTF-8 encoding. Therefore, we don't perform - * code conversion from UTF-8 to native codeset for the user name - * string. - */ - name = packet_get_string(NULL); - inst = packet_get_utf8_string(NULL); - lang = packet_get_string(NULL); - if (strlen(name) != 0) { - name = g11n_filter_string(name); - log("%s", name); - } - if (strlen(inst) != 0) { - inst = g11n_filter_string(inst); - log("%s", inst); - } - xfree(name); - xfree(inst); - xfree(lang); - - num_prompts = packet_get_int(); - /* - * Begin to build info response packet based on prompts requested. - * We commit to providing the correct number of responses, so if - * further on we run into a problem that prevents this, we have to - * be sure and clean this up and send a correct error response. - */ - packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); - packet_put_int(num_prompts); - - debug2("input_userauth_info_req: num_prompts %d", num_prompts); - for (i = 0; i < num_prompts; i++) { - prompt = packet_get_utf8_string(NULL); - echo = packet_get_char(); - - prompt = g11n_filter_string(prompt); - response = read_passphrase(prompt, echo ? RP_ECHO : 0); - - /* - * We assume that ASCII is used for password as well. We - * don't perform code conversion from native codeset to - * UTF-8 for the password string. - */ - packet_put_cstring(response); - memset(response, 0, strlen(response)); - xfree(response); - xfree(prompt); - } - packet_check_eom(); /* done with parsing incoming message. */ - - packet_add_padding(64); - packet_send(); -} - -static int -ssh_keysign(Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) -{ - Buffer b; - struct stat st; - pid_t pid; - int to[2], from[2], status, version = 2; - - debug2("ssh_keysign called"); - - if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { - error("ssh_keysign: no installed: %s", strerror(errno)); - return -1; - } - if (fflush(stdout) != 0) - error("ssh_keysign: fflush: %s", strerror(errno)); - if (pipe(to) < 0) { - error("ssh_keysign: pipe: %s", strerror(errno)); - return -1; - } - if (pipe(from) < 0) { - error("ssh_keysign: pipe: %s", strerror(errno)); - return -1; - } - if ((pid = fork()) < 0) { - error("ssh_keysign: fork: %s", strerror(errno)); - return -1; - } - if (pid == 0) { - seteuid(getuid()); - setuid(getuid()); - close(from[0]); - if (dup2(from[1], STDOUT_FILENO) < 0) - fatal("ssh_keysign: dup2: %s", strerror(errno)); - close(to[1]); - if (dup2(to[0], STDIN_FILENO) < 0) - fatal("ssh_keysign: dup2: %s", strerror(errno)); - close(from[1]); - close(to[0]); - execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); - fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, - strerror(errno)); - } - close(from[1]); - close(to[0]); - - buffer_init(&b); - buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ - buffer_put_string(&b, data, datalen); - ssh_msg_send(to[1], version, &b); - - if (ssh_msg_recv(from[0], &b) < 0) { - error("ssh_keysign: no reply"); - buffer_clear(&b); - return -1; - } - close(from[0]); - close(to[1]); - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - break; - - if (buffer_get_char(&b) != version) { - error("ssh_keysign: bad version"); - buffer_clear(&b); - return -1; - } - *sigp = buffer_get_string(&b, lenp); - buffer_clear(&b); - - return 0; -} - -int -userauth_hostbased(Authctxt *authctxt) -{ - Key *private = NULL; - Sensitive *sensitive = authctxt->sensitive; - Buffer b; - u_char *signature, *blob; - char *chost, *pkalg, *p; - const char *service; - u_int blen, slen; - int ok, i, len, found = 0; - static int last_hostkey = -1; - - /* check for a useful key */ - for (i = 0; i < sensitive->nkeys; i++) { - private = sensitive->keys[i]; - if (private && private->type != KEY_RSA1 && i > last_hostkey) { - found = 1; - last_hostkey = i; - /* we take and free the key */ - sensitive->keys[i] = NULL; - break; - } - } - if (!found) { - debug("No more client hostkeys for hostbased authentication"); - return 0; - } - if (key_to_blob(private, &blob, &blen) == 0) { - key_free(private); - return 0; - } - /* figure out a name for the client host */ - p = get_local_name(packet_get_connection_in()); - if (p == NULL) { - error("userauth_hostbased: cannot get local ipaddr/name"); - key_free(private); - return 0; - } - - service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : - authctxt->service; - pkalg = xstrdup(key_ssh_name(private)); - - len = strlen(p) + 2; - chost = xmalloc(len); - strlcpy(chost, p, len); - strlcat(chost, ".", len); - xfree(p); - debug2("userauth_hostbased: chost %s, pkalg %s", chost, pkalg); - - buffer_init(&b); - /* construct data */ - buffer_put_string(&b, session_id2, session_id2_len); - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->server_user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, authctxt->method->name); - buffer_put_cstring(&b, pkalg); - buffer_put_string(&b, blob, blen); - buffer_put_cstring(&b, chost); - buffer_put_cstring(&b, authctxt->local_user); -#ifdef DEBUG_PK - buffer_dump(&b); -#endif - if (sensitive->external_keysign) - ok = ssh_keysign(private, &signature, &slen, - buffer_ptr(&b), buffer_len(&b)); - else - ok = key_sign(private, &signature, &slen, - buffer_ptr(&b), buffer_len(&b)); - key_free(private); - buffer_free(&b); - if (ok != 0) { - error("key_sign failed"); - xfree(chost); - xfree(pkalg); - return 0; - } - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_cstring(pkalg); - packet_put_string(blob, blen); - packet_put_cstring(chost); - packet_put_cstring(authctxt->local_user); - packet_put_string(signature, slen); - memset(signature, 's', slen); - xfree(signature); - xfree(chost); - xfree(pkalg); - - packet_send(); - return 1; -} - -/* find auth method */ - -/* - * given auth method name, if configurable options permit this method fill - * in auth_ident field and return true, otherwise return false. - */ -static int -authmethod_is_enabled(Authmethod *method) -{ - if (method == NULL) - return 0; - /* return false if options indicate this method is disabled */ - if (method->enabled == NULL || *method->enabled == 0) - return 0; - /* return false if batch mode is enabled but method needs interactive mode */ - if (method->batch_flag != NULL && *method->batch_flag != 0) - return 0; - return 1; -} - -static Authmethod * -authmethod_lookup(const char *name) -{ - Authmethod *method = NULL; - if (name != NULL) { - for (method = authmethods; method->name != NULL; method++) { - if (strcmp(name, method->name) == 0) - return method; - } - } - debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); - return NULL; -} - -/* XXX internal state */ -static Authmethod *current = NULL; -static char *supported = NULL; -static char *preferred = NULL; - -/* - * Given the authentication method list sent by the server, return the - * next method we should try. If the server initially sends a nil list, - * use a built-in default list. - */ -static Authmethod * -authmethod_get(char *authlist) -{ - char *name = NULL; - u_int next; - - /* Use a suitable default if we're passed a nil list. */ - if (authlist == NULL || strlen(authlist) == 0) - authlist = options.preferred_authentications; - - if (supported == NULL || strcmp(authlist, supported) != 0) { - debug3("start over, passed a different list %s", authlist); - if (supported != NULL) - xfree(supported); - supported = xstrdup(authlist); - preferred = options.preferred_authentications; - debug3("preferred %s", preferred); - current = NULL; - } else if (current != NULL && authmethod_is_enabled(current)) - return current; - - for (;;) { - if ((name = match_list(preferred, supported, &next)) == NULL) { - debug("No more authentication methods to try."); - current = NULL; - return NULL; - } - preferred += next; - debug3("authmethod_lookup %s", name); - debug3("remaining preferred: %s", preferred); - if ((current = authmethod_lookup(name)) != NULL && - authmethod_is_enabled(current)) { - debug3("authmethod_is_enabled %s", name); - debug("Next authentication method: %s", name); - xfree(name); - return current; - } - xfree(name); - } -} - -static char * -authmethods_get(void) -{ - Authmethod *method = NULL; - Buffer b; - char *list; - - buffer_init(&b); - for (method = authmethods; method->name != NULL; method++) { - if (authmethod_is_enabled(method)) { - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - buffer_append(&b, method->name, strlen(method->name)); - } - } - buffer_append(&b, "\0", 1); - list = xstrdup(buffer_ptr(&b)); - buffer_free(&b); - return list; -} diff --git a/usr/src/cmd/ssh/ssh/sshtty.c b/usr/src/cmd/ssh/ssh/sshtty.c deleted file mode 100644 index b90ff1d1ad..0000000000 --- a/usr/src/cmd/ssh/ssh/sshtty.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2001 Kevin Steves. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: sshtty.c,v 1.3 2002/03/04 17:27:39 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "sshtty.h" -#include "log.h" - -static struct termios _saved_tio; -static int _in_raw_mode = 0; - -int -in_raw_mode(void) -{ - return _in_raw_mode; -} - -struct termios -get_saved_tio(void) -{ - return _saved_tio; -} - -void -leave_raw_mode(void) -{ - if (!_in_raw_mode) - return; - if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) - perror("tcsetattr"); - else - _in_raw_mode = 0; - - fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL); -} - -void -enter_raw_mode(void) -{ - struct termios tio; - - if (tcgetattr(fileno(stdin), &tio) == -1) { - perror("tcgetattr"); - return; - } - _saved_tio = tio; - tio.c_iflag |= IGNPAR; - tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); - tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); -#ifdef IEXTEN - tio.c_lflag &= ~IEXTEN; -#endif - tio.c_oflag &= ~OPOST; - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) - perror("tcsetattr"); - else - _in_raw_mode = 1; - - fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL); -} diff --git a/usr/src/cmd/ssh/sshd/Makefile b/usr/src/cmd/ssh/sshd/Makefile deleted file mode 100644 index a52e9b1cc8..0000000000 --- a/usr/src/cmd/ssh/sshd/Makefile +++ /dev/null @@ -1,116 +0,0 @@ -# -# 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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/ssh/sshd/Makefile - -PROG= sshd - -DIRS= $(ROOTLIBSSH) - -OBJS = sshd.o \ - altprivsep.o \ - auth.o \ - auth1.o \ - auth2.o \ - auth-options.o \ - auth2-chall.o \ - auth2-gss.o \ - auth2-hostbased.o \ - auth2-kbdint.o \ - auth2-none.o \ - auth2-passwd.o \ - auth2-pam.o \ - auth2-pubkey.o \ - auth-bsdauth.o \ - auth-chall.o \ - auth-rhosts.o \ - auth-krb4.o \ - auth-krb5.o \ - auth-pam.o \ - auth-passwd.o \ - auth-rsa.o \ - auth-rh-rsa.o \ - auth-sia.o \ - auth-skey.o \ - bsmaudit.o \ - groupaccess.o \ - gss-serv.o \ - loginrec.o \ - servconf.o \ - serverloop.o \ - session.o \ - sshlogin.o \ - sshpty.o - -EXTOBJS = sftp-server.o - -SRCS = $(OBJS:.o=.c) ../sftp-server/sftp-server.c - -include ../../Makefile.cmd -include ../Makefile.ssh-common - -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket \ - -lnsl \ - -lz \ - -lpam \ - -lbsm \ - -lwrap \ - -lcrypto \ - -lgss \ - -lcontract -MAPFILES = $(MAPFILE.INT) $(MAPFILE.NGB) -LDFLAGS += $(MAPFILES:%=-M%) - -POFILE_DIR= .. - -.KEEP_STATE: - -.PARALLEL: $(OBJS) - -all: $(PROG) - -$(PROG): $(OBJS) $(EXTOBJS) $(MAPFILES) ../libssh/$(MACH)/libssh.a \ - ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a - $(LINK.c) $(OBJS) $(EXTOBJS) -o $@ $(LDLIBS) $(DYNFLAGS) - $(POST_PROCESS) - -%.o : ../sftp-server/%.c - $(COMPILE.c) -o $@ $< - $(POST_PROCESS_O) - -install: all $(DIRS) $(ROOTLIBSSHPROG) $(ROOTLIBSSH) - - -$(ROOTLIBSSHPROG)/%: % - $(INS.file) - -$(DIRS): - $(INS.dir) - -clean: - $(RM) $(OBJS) $(EXTOBJS) - -lint: lint_SRCS - -include ../Makefile.msg.targ -include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/sshd/altprivsep.c b/usr/src/cmd/ssh/sshd/altprivsep.c deleted file mode 100644 index 6f954feab5..0000000000 --- a/usr/src/cmd/ssh/sshd/altprivsep.c +++ /dev/null @@ -1,1187 +0,0 @@ -/* - * 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) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> - -#include <pwd.h> - -#include "includes.h" -#include "atomicio.h" -#include "auth.h" -#include "bufaux.h" -#include "buffer.h" -#include "cipher.h" -#include "compat.h" -#include "dispatch.h" -#include "getput.h" -#include "kex.h" -#include "log.h" -#include "mac.h" -#include "packet.h" -#include "uidswap.h" -#include "ssh2.h" -#include "sshlogin.h" -#include "xmalloc.h" -#include "altprivsep.h" -#include "canohost.h" -#include "engine.h" -#include "servconf.h" - -#ifdef HAVE_BSM -#include "bsmaudit.h" -adt_session_data_t *ah = NULL; -#endif /* HAVE_BSM */ - -#ifdef GSSAPI -#include "ssh-gss.h" -extern Gssctxt *xxx_gssctxt; -#endif /* GSSAPI */ - -extern Kex *xxx_kex; -extern u_char *session_id2; -extern int session_id2_len; - -static Buffer to_monitor; -static Buffer from_monitor; - -/* - * Sun's Alternative Privilege Separation basics: - * - * Abstract - * -------- - * - * sshd(1M) fork()s and drops privs in the child while retaining privs - * in the parent (a.k.a., the monitor). The unprivileged sshd and the - * monitor talk over a pipe using a simple protocol. - * - * The monitor protocol is all about having the monitor carry out the - * only operations that require privileges OR access to privileged - * resources. These are: utmpx/wtmpx record keeping, auditing, and - * SSHv2 re-keying. - * - * Re-Keying - * --------- - * - * Re-keying is the only protocol version specific aspect of sshd in - * which the monitor gets involved. - * - * The monitor processes all SSHv2 re-key protocol packets, but the - * unprivileged sshd process does the transport layer crypto for those - * packets. - * - * The monitor and its unprivileged sshd child process treat - * SSH_MSG_NEWKEYS SSH2 messages specially: a) the monitor does not call - * set_newkeys(), but b) the child asks the monitor for the set of - * negotiated algorithms, key, IV and what not for the relevant - * transport direction and then calls set_newkeys(). - * - * Monitor Protocol - * ---------------- - * - * Monitor IPC message formats are similar to SSHv2 messages, minus - * compression, encryption, padding and MACs: - * - * - 4 octet message length - * - message data - * - 1 octet message type - * - message data - * - * In broad strokes: - * - * - IPC: pipe, exit(2)/wait4(2) - * - * - threads: the monitor and child are single-threaded - * - * - monitor main loop: a variant of server_loop2(), for re-keying only - * - unpriv child main loop: server_loop2(), as usual - * - * - protocol: - * - key exchange packets are always forwarded as is to the monitor - * - newkeys, record_login(), record_logout() are special packets - * using the packet type range reserved for local extensions - * - * - the child drops privs and runs like a normal sshd, except that it - * sets dispatch handlers for key exchange packets that forward the - * packets to the monitor - * - * Event loops: - * - * - all monitor protocols are synchronous: because the SSHv2 rekey - * protocols are synchronous and because the other monitor operations - * are synchronous (or have no replies), - * - * - server_loop2() is modified to check the monitor pipe for rekey - * packets to forward to the client - * - * - and dispatch handlers are set, upon receipt of KEXINIT (and reset - * when NEWKEYS is sent out) to forward incoming rekey packets to the - * monitor. - * - * - the monitor runs an event loop not unlike server_loop2() and runs - * key exchanges almost exactly as a pre-altprivsep sshd would - * - * - unpriv sshd exit -> monitor cleanup (including audit logout) and exit - * - * - fatal() in monitor -> forcibly shutdown() socket and kill/wait for - * child (so that the audit event for the logout better reflects - * reality -- i.e., logged out means logged out, but for bg jobs) - * - * Message formats: - * - * - key exchange packets/replies forwarded "as is" - * - * - all other monitor requests are sent as SSH2_PRIV_MSG_ALTPRIVSEP and have a - * sub-type identifier (one octet) - * - private request sub-types include: - * - get new shared secret from last re-key - * - record login (utmpx/wtmpx), request data contains three arguments: - * pid, ttyname, program name - * - record logout (utmpx/wtmpx), request data contains one argument: pid - * - * Reply sub-types include: - * - * - NOP (for record_login/logout) - * - new shared secret from last re-key - */ - -static int aps_started = 0; -static int is_monitor = 0; - -static pid_t monitor_pid, child_pid; -static int pipe_fds[2]; -static int pipe_fd = -1; -static Buffer input_pipe, output_pipe; /* for pipe I/O */ - -static Authctxt *xxx_authctxt; - -/* Monitor functions */ -extern void aps_monitor_loop(Authctxt *authctxt, pid_t child_pid); -static void aps_record_login(void); -static void aps_record_logout(void); -static void aps_start_rekex(void); -Authctxt *aps_read_auth_context(void); - -/* main functions for handling the monitor */ -static pid_t altprivsep_start_monitor(Authctxt **authctxt); -static void altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid); -static int altprivsep_started(void); -static int altprivsep_is_monitor(void); - -/* calls _to_ monitor from unprivileged process */ -static void altprivsep_get_newkeys(enum kex_modes mode); - -/* monitor-side fatal_cleanup callbacks */ -static void altprivsep_shutdown_sock(void *arg); - -/* Altprivsep packet utilities for communication with the monitor */ -static void altprivsep_packet_start(u_char); -static int altprivsep_packet_send(void); -static int altprivsep_fwd_packet(u_char type); - -static int altprivsep_packet_read(void); -static void altprivsep_packet_read_expect(int type); - -static void altprivsep_packet_put_char(int ch); -static void altprivsep_packet_put_int(u_int value); -static void altprivsep_packet_put_cstring(const char *str); -static void altprivsep_packet_put_raw(const void *buf, u_int len); - -static u_int altprivsep_packet_get_char(void); -static void *altprivsep_packet_get_raw(u_int *length_ptr); -static void *altprivsep_packet_get_string(u_int *length_ptr); - -Kex *prepare_for_ssh2_kex(void); - -/* - * Start monitor from privileged sshd process. - * - * Return values are like fork(2); the parent is the monitor. The caller should - * fatal() on error. - * - * Note that the monitor waits until the still privileged child finishes the - * authentication. The child drops its privileges after the authentication. - */ -static pid_t -altprivsep_start_monitor(Authctxt **authctxt) -{ - pid_t pid; - int junk; - - if (aps_started) - fatal("Monitor startup failed: missing state"); - - buffer_init(&output_pipe); - buffer_init(&input_pipe); - - if (pipe(pipe_fds) != 0) { - error("Monitor startup failure: could not create pipes: %s", - strerror(errno)); - return (-1); - } - - (void) fcntl(pipe_fds[0], F_SETFD, FD_CLOEXEC); - (void) fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC); - - monitor_pid = getpid(); - - if ((pid = fork()) > 0) { - /* - * From now on, all debug messages from monitor will have prefix - * "monitor " - */ - set_log_txt_prefix("monitor "); - (void) prepare_for_ssh2_kex(); - packet_set_server(); - /* parent */ - child_pid = pid; - - debug2("Monitor pid %ld, unprivileged child pid %ld", - monitor_pid, child_pid); - - (void) close(pipe_fds[1]); - pipe_fd = pipe_fds[0]; - - /* - * Signal readiness of the monitor and then read the - * authentication context from the child. - */ - (void) write(pipe_fd, &pid, sizeof (pid)); - packet_set_monitor(pipe_fd); - xxx_authctxt = *authctxt = aps_read_auth_context(); - - if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %.100s", strerror(errno)); - - aps_started = 1; - is_monitor = 1; - - debug2("Monitor started"); - - return (pid); - } - - if (pid < 0) { - debug2("Monitor startup failure: could not fork unprivileged" - " process: %s", strerror(errno)); - return (pid); - } - - /* this is the child that will later drop privileges */ - - /* note that Solaris has bi-directional pipes so one pipe is enough */ - (void) close(pipe_fds[0]); - pipe_fd = pipe_fds[1]; - - /* wait for monitor to be ready */ - debug2("Waiting for monitor"); - (void) read(pipe_fd, &junk, sizeof (junk)); - debug2("Monitor signalled readiness"); - - buffer_init(&to_monitor); - buffer_init(&from_monitor); - - /* AltPrivSep interfaces are set up */ - aps_started = 1; - return (pid); -} - -int -altprivsep_get_pipe_fd(void) -{ - return (pipe_fd); -} - -/* - * This function is used in the unprivileged child for all packets in the range - * between SSH2_MSG_KEXINIT and SSH2_MSG_TRANSPORT_MAX. - */ -void -altprivsep_rekey(int type, u_int32_t seq, void *ctxt) -{ - Kex *kex = (Kex *)ctxt; - - if (kex == NULL) - fatal("Missing key exchange context in unprivileged process"); - - if (type != SSH2_MSG_NEWKEYS) { - debug2("Forwarding re-key packet (%d) to monitor", type); - if (!altprivsep_fwd_packet(type)) - fatal("altprivsep_rekey: Monitor not responding"); - } - - /* tell server_loop2() that we're re-keying */ - kex->done = 0; - - /* NEWKEYS is special: get the new keys for client->server direction */ - if (type == SSH2_MSG_NEWKEYS) { - debug2("received SSH2_MSG_NEWKEYS packet - " - "getting new inbound keys from the monitor"); - altprivsep_get_newkeys(MODE_IN); - kex->done = 1; - } -} - -void -altprivsep_process_input(fd_set *rset) -{ - void *data; - int type; - u_int dlen; - - if (pipe_fd == -1) - return; - - if (!FD_ISSET(pipe_fd, rset)) - return; - - debug2("reading from pipe to monitor (%d)", pipe_fd); - if ((type = altprivsep_packet_read()) == -1) - fatal("altprivsep_process_input: Monitor not responding"); - - if (!compat20) - return; /* shouldn't happen! but be safe */ - - if (type == 0) - return; /* EOF -- nothing to do here */ - - if (type >= SSH2_MSG_MAX) - fatal("Received garbage from monitor"); - - debug2("Read packet type %d from pipe to monitor", (u_int)type); - - if (type == SSH2_PRIV_MSG_ALTPRIVSEP) - return; /* shouldn't happen! */ - - /* NEWKEYS is special: get the new keys for server->client direction */ - if (type == SSH2_MSG_NEWKEYS) { - debug2("forwarding SSH2_MSG_NEWKEYS packet we got from monitor to " - "the client"); - packet_start(SSH2_MSG_NEWKEYS); - packet_send(); - debug2("getting new outbound keys from the monitor"); - altprivsep_get_newkeys(MODE_OUT); - return; - } - - data = altprivsep_packet_get_raw(&dlen); - - packet_start((u_char)type); - - if (data != NULL && dlen > 0) - packet_put_raw(data, dlen); - - packet_send(); -} - -static void -altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid) -{ - aps_monitor_loop(authctxt, child_pid); -} - -static int -altprivsep_started(void) -{ - return (aps_started); -} - -static int -altprivsep_is_monitor(void) -{ - return (is_monitor); -} - -/* - * A fatal cleanup function to forcibly shutdown the connection socket - */ -static void -altprivsep_shutdown_sock(void *arg) -{ - int sock; - - if (arg == NULL) - return; - - sock = *(int *)arg; - - (void) shutdown(sock, SHUT_RDWR); -} - -/* Calls _to_ monitor from unprivileged process */ -static int -altprivsep_fwd_packet(u_char type) -{ - u_int len; - void *data; - - altprivsep_packet_start(type); - data = packet_get_raw(&len); - altprivsep_packet_put_raw(data, len); - - /* packet_send()s any replies from the monitor to the client */ - return (altprivsep_packet_send()); -} - -extern Newkeys *current_keys[MODE_MAX]; - -/* To be called from packet.c:set_newkeys() before referencing current_keys */ -static void -altprivsep_get_newkeys(enum kex_modes mode) -{ - Newkeys *newkeys; - Comp *comp; - Enc *enc; - Mac *mac; - u_int len; - - if (!altprivsep_started()) - return; - - if (altprivsep_is_monitor()) - return; /* shouldn't happen */ - - /* request new keys */ - altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - altprivsep_packet_put_char(APS_MSG_NEWKEYS_REQ); - altprivsep_packet_put_int((u_int)mode); - altprivsep_packet_send(); - altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); - if (altprivsep_packet_get_char() != APS_MSG_NEWKEYS_REP) - fatal("Received garbage from monitor during re-keying"); - - newkeys = xmalloc(sizeof (*newkeys)); - memset(newkeys, 0, sizeof (*newkeys)); - - enc = &newkeys->enc; - mac = &newkeys->mac; - comp = &newkeys->comp; - - /* Cipher name, key, IV */ - enc->name = altprivsep_packet_get_string(NULL); - if ((enc->cipher = cipher_by_name(enc->name)) == NULL) - fatal("Monitor negotiated an unknown cipher during re-key"); - - enc->key = altprivsep_packet_get_string(&enc->key_len); - enc->iv = altprivsep_packet_get_string(&enc->block_size); - - /* MAC name */ - mac->name = altprivsep_packet_get_string(NULL); - if (mac_setup(mac, mac->name) < 0) - fatal("Monitor negotiated an unknown MAC algorithm " - "during re-key"); - - mac->key = altprivsep_packet_get_string(&len); - if (len > mac->key_len) - fatal("%s: bad mac key length: %d > %d", __func__, len, - mac->key_len); - - /* Compression algorithm name */ - comp->name = altprivsep_packet_get_string(NULL); - if (strcmp(comp->name, "zlib") != 0 && strcmp(comp->name, "none") != 0) - fatal("Monitor negotiated an unknown compression " - "algorithm during re-key"); - - comp->type = 0; - comp->enabled = 0; /* forces compression re-init, as per-spec */ - if (strcmp(comp->name, "zlib") == 0) - comp->type = 1; - - /* - * Now install new keys - * - * For now abuse kex.c/packet.c non-interfaces. Someday, when - * the many internal interfaces are parametrized, made reentrant - * and thread-safe, made more consistent, and when necessary-but- - * currently-missing interfaces are added then this bit of - * ugliness can be revisited. - * - * The ugliness is in the set_newkeys(), its name and the lack - * of a (Newkeys *) parameter, which forces us to pass the - * newkeys through current_keys[mode]. But this saves us some - * lines of code for now, though not comments. - * - * Also, we've abused, in the code above, knowledge of what - * set_newkeys() expects the current_keys[mode] to contain. - */ - current_keys[mode] = newkeys; - set_newkeys(mode); - -} - -void -altprivsep_record_login(pid_t pid, const char *ttyname) -{ - altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - altprivsep_packet_put_char(APS_MSG_RECORD_LOGIN); - altprivsep_packet_put_int(pid); - altprivsep_packet_put_cstring(ttyname); - altprivsep_packet_send(); - altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); -} - -void -altprivsep_record_logout(pid_t pid) -{ - altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - altprivsep_packet_put_char(APS_MSG_RECORD_LOGOUT); - altprivsep_packet_put_int(pid); - altprivsep_packet_send(); - altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); -} - -void -altprivsep_start_rekex(void) -{ - altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - altprivsep_packet_put_char(APS_MSG_START_REKEX); - altprivsep_packet_send(); - altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); -} - -/* - * The monitor needs some information that its child learns during the - * authentication process. Since the child was forked before the key exchange - * and authentication started it must send some context to the monitor after the - * authentication is finished. Less obvious part - monitor needs the session ID - * since it is used in the key generation process after the key (re-)exchange is - * finished. - */ -void -altprivsep_send_auth_context(Authctxt *authctxt) -{ - debug("sending auth context to the monitor"); - altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - altprivsep_packet_put_char(APS_MSG_AUTH_CONTEXT); - altprivsep_packet_put_int(authctxt->pw->pw_uid); - altprivsep_packet_put_int(authctxt->pw->pw_gid); - altprivsep_packet_put_cstring(authctxt->pw->pw_name); - altprivsep_packet_put_raw(session_id2, session_id2_len); - debug("will send %d bytes of auth context to the monitor", - buffer_len(&to_monitor)); - altprivsep_packet_send(); - altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); -} - -static void aps_send_newkeys(void); - -/* Monitor side dispatch handler for SSH2_PRIV_MSG_ALTPRIVSEP */ -/* ARGSUSED */ -void -aps_input_altpriv_msg(int type, u_int32_t seq, void *ctxt) -{ - u_char req_type; - - req_type = packet_get_char(); - - switch (req_type) { - case APS_MSG_NEWKEYS_REQ: - aps_send_newkeys(); - break; - case APS_MSG_RECORD_LOGIN: - aps_record_login(); - break; - case APS_MSG_RECORD_LOGOUT: - aps_record_logout(); - break; - case APS_MSG_START_REKEX: - aps_start_rekex(); - break; - default: - break; - } -} - -/* Monitor-side handlers for APS_MSG_* */ -static -void -aps_send_newkeys(void) -{ - Newkeys *newkeys; - Enc *enc; - Mac *mac; - Comp *comp; - enum kex_modes mode; - - /* get direction for which newkeys are wanted */ - mode = (enum kex_modes) packet_get_int(); - packet_check_eom(); - - /* get those newkeys */ - newkeys = kex_get_newkeys(mode); - enc = &newkeys->enc; - mac = &newkeys->mac; - comp = &newkeys->comp; - - /* - * Negotiated algorithms, client->server and server->client, for - * cipher, mac and compression. - */ - packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - packet_put_char(APS_MSG_NEWKEYS_REP); - packet_put_cstring(enc->name); - packet_put_string(enc->key, enc->key_len); - packet_put_string(enc->iv, enc->block_size); - packet_put_cstring(mac->name); - packet_put_string(mac->key, mac->key_len); - packet_put_cstring(comp->name); - - packet_send(); - free_keys(newkeys); -} - -struct _aps_login_rec { - pid_t lr_pid; - char *lr_tty; - struct _aps_login_rec *next; -}; - -typedef struct _aps_login_rec aps_login_rec; - -static aps_login_rec *aps_login_list = NULL; - -static -void -aps_record_login(void) -{ - aps_login_rec *new_rec; - struct stat sbuf; - size_t proc_path_len; - char *proc_path; - - new_rec = xmalloc(sizeof (aps_login_rec)); - memset(new_rec, 0, sizeof (aps_login_rec)); - - new_rec->lr_pid = packet_get_int(); - new_rec->lr_tty = packet_get_string(NULL); - - proc_path_len = snprintf(NULL, 0, "/proc/%d", new_rec->lr_pid); - proc_path = xmalloc(proc_path_len + 1); - (void) snprintf(proc_path, proc_path_len + 1, "/proc/%d", - new_rec->lr_pid); - - if (stat(proc_path, &sbuf) || - sbuf.st_uid != xxx_authctxt->pw->pw_uid || - stat(new_rec->lr_tty, &sbuf) < 0 || - sbuf.st_uid != xxx_authctxt->pw->pw_uid) { - debug2("Spurious record_login request from unprivileged sshd"); - xfree(proc_path); - xfree(new_rec->lr_tty); - xfree(new_rec); - return; - } - - /* Insert new record on list */ - new_rec->next = aps_login_list; - aps_login_list = new_rec; - - record_login(new_rec->lr_pid, new_rec->lr_tty, NULL, - xxx_authctxt->user); - - packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - packet_send(); - - xfree(proc_path); -} - -static -void -aps_record_logout(void) -{ - aps_login_rec **p, *q; - pid_t pid; - - pid = packet_get_int(); - packet_check_eom(); - - for (p = &aps_login_list; *p != NULL; p = &q->next) { - q = *p; - if (q->lr_pid == pid) { - record_logout(q->lr_pid, q->lr_tty, NULL, - xxx_authctxt->user); - - /* dequeue */ - *p = q->next; - xfree(q->lr_tty); - xfree(q); - break; - } - } - - packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - packet_send(); -} - -static -void -aps_start_rekex(void) -{ - /* - * Send confirmation. We could implement it without that but it doesn't - * bring any harm to do that and we are consistent with other subtypes - * of our private SSH2_PRIV_MSG_ALTPRIVSEP message type. - */ - packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - packet_send(); - - /* - * KEX_INIT message could be the one that reached the limit. In that - * case, it was already forwarded to us from the unnprivileged child, - * and maybe even acted upon. Obviously we must not send another - * KEX_INIT message. - */ - if (!(xxx_kex->flags & KEX_INIT_SENT)) - kex_send_kexinit(xxx_kex); - else - debug2("rekeying already in progress"); -} - -/* - * This is the monitor side of altprivsep_send_auth_context(). - */ -Authctxt * -aps_read_auth_context(void) -{ - unsigned char *tmp; - Authctxt *authctxt; - - /* - * After the successful authentication we get the context. Getting - * end-of-file means that authentication failed and we can exit as well. - */ - debug("reading the context from the child"); - packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); - debug3("got SSH2_PRIV_MSG_ALTPRIVSEP"); - if (packet_get_char() != APS_MSG_AUTH_CONTEXT) { - fatal("APS_MSG_AUTH_CONTEXT message subtype expected."); - } - - authctxt = xcalloc(1, sizeof(Authctxt)); - authctxt->pw = xcalloc(1, sizeof(struct passwd)); - - /* uid_t and gid_t are integers (UNIX spec) */ - authctxt->pw->pw_uid = packet_get_int(); - authctxt->pw->pw_gid = packet_get_int(); - authctxt->pw->pw_name = packet_get_string(NULL); - authctxt->user = xstrdup(authctxt->pw->pw_name); - debug3("uid/gid/username %d/%d/%s", authctxt->pw->pw_uid, - authctxt->pw->pw_gid, authctxt->user); - session_id2 = (unsigned char *)packet_get_raw((unsigned int*)&session_id2_len); - - /* we don't have this for SSH1. In that case, session_id2_len is 0. */ - if (session_id2_len > 0) { - tmp = (unsigned char *)xmalloc(session_id2_len); - memcpy(tmp, session_id2, session_id2_len); - session_id2 = tmp; - debug3("read session ID (%d B)", session_id2_len); - xxx_kex->session_id = tmp; - xxx_kex->session_id_len = session_id2_len; - } - debug("finished reading the context"); - - /* send confirmation */ - packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); - packet_send(); - - return (authctxt); -} - - -/* Utilities for communication with the monitor */ -static void -altprivsep_packet_start(u_char type) -{ - buffer_clear(&to_monitor); - buffer_put_char(&to_monitor, type); -} - -static void -altprivsep_packet_put_char(int ch) -{ - buffer_put_char(&to_monitor, ch); -} - -static void -altprivsep_packet_put_int(u_int value) -{ - buffer_put_int(&to_monitor, value); -} - -static void -altprivsep_packet_put_cstring(const char *str) -{ - buffer_put_cstring(&to_monitor, str); -} - -static void -altprivsep_packet_put_raw(const void *buf, u_int len) -{ - buffer_append(&to_monitor, buf, len); -} - -/* - * Send a monitor packet to the monitor. This function is blocking. - * - * Returns -1 if the monitor pipe has been closed earlier, fatal()s if - * there's any other problems. - */ -static int -altprivsep_packet_send(void) -{ - ssize_t len; - u_int32_t plen; /* packet length */ - u_char plen_buf[sizeof (plen)]; - u_char padlen; /* padding length */ - fd_set *setp; - int err; - - if (pipe_fd == -1) - return (-1); - - if ((plen = buffer_len(&to_monitor)) == 0) - return (0); - - /* - * We talk the SSHv2 binary packet protocol to the monitor, - * using the none cipher, mac and compression algorithms. - * - * But, interestingly, the none cipher has a block size of 8 - * bytes, thus we must pad the packet. - * - * Also, encryption includes the packet length, so the padding - * must account for that field. I.e., (sizeof (packet length) + - * sizeof (padding length) + packet length + padding length) % - * block_size must == 0. - * - * Also, there must be at least four (4) bytes of padding. - */ - padlen = (8 - ((plen + sizeof (plen) + sizeof (padlen)) % 8)) % 8; - if (padlen < 4) - padlen += 8; - - /* packet length counts padding and padding length field */ - plen += padlen + sizeof (padlen); - - PUT_32BIT(plen_buf, plen); - - setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); - memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); - FD_SET(pipe_fd, setp); - - while (select(pipe_fd + 1, NULL, setp, NULL, NULL) == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - else - goto pipe_gone; - } - - xfree(setp); - - /* packet length field */ - len = atomicio(write, pipe_fd, plen_buf, sizeof (plen)); - - if (len != sizeof (plen)) - goto pipe_gone; - - /* padding length field */ - len = atomicio(write, pipe_fd, &padlen, sizeof (padlen)); - - if (len != sizeof (padlen)) - goto pipe_gone; - - len = atomicio(write, pipe_fd, buffer_ptr(&to_monitor), plen - 1); - - if (len != (plen - 1)) - goto pipe_gone; - - buffer_clear(&to_monitor); - - return (1); - -pipe_gone: - - err = errno; - - (void) close(pipe_fd); - - pipe_fd = -1; - - fatal("altprvsep_packet_send: Monitor not responding: %.100s", - strerror(err)); - - /* NOTREACHED */ - return (0); -} - -/* - * Read a monitor packet from the monitor. This function is blocking. - */ -static int -altprivsep_packet_read(void) -{ - ssize_t len = -1; - u_int32_t plen; - u_char plen_buf[sizeof (plen)]; - u_char padlen; - fd_set *setp; - int err; - - if (pipe_fd == -1) - return (-1); - - setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); - memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); - FD_SET(pipe_fd, setp); - - while (select(pipe_fd + 1, setp, NULL, NULL, NULL) == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - else - goto pipe_gone; - } - - xfree(setp); - - /* packet length field */ - len = atomicio(read, pipe_fd, plen_buf, sizeof (plen)); - - plen = GET_32BIT(plen_buf); - - if (len != sizeof (plen)) - goto pipe_gone; - - /* padding length field */ - len = atomicio(read, pipe_fd, &padlen, sizeof (padlen)); - - if (len != sizeof (padlen)) - goto pipe_gone; - - plen -= sizeof (padlen); - - buffer_clear(&from_monitor); - buffer_append_space(&from_monitor, plen); - - /* packet data + padding */ - len = atomicio(read, pipe_fd, buffer_ptr(&from_monitor), plen); - - if (len != plen) - goto pipe_gone; - - /* remove padding */ - if (padlen > 0) - buffer_consume_end(&from_monitor, padlen); - - /* packet type */ - return (buffer_get_char(&from_monitor)); - -pipe_gone: - - err = errno; - - (void) close(pipe_fd); - - pipe_fd = -1; - - if (len < 0) - fatal("altpriv_packet_read: Monitor not responding %.100s", - strerror(err)); - - debug2("Monitor pipe closed by monitor"); - return (0); -} - -static void -altprivsep_packet_read_expect(int expected) -{ - int type; - - type = altprivsep_packet_read(); - - if (type <= 0) - fatal("altprivsep_packet_read_expect: Monitor not responding"); - - if (type != expected) - fatal("Protocol error in privilege separation; expected " - "packet type %d, got %d", expected, type); -} - -static u_int -altprivsep_packet_get_char(void) -{ - return (buffer_get_char(&from_monitor)); -} -void -*altprivsep_packet_get_raw(u_int *length_ptr) -{ - if (length_ptr != NULL) - *length_ptr = buffer_len(&from_monitor); - - return (buffer_ptr(&from_monitor)); -} -void -*altprivsep_packet_get_string(u_int *length_ptr) -{ - return (buffer_get_string(&from_monitor, length_ptr)); -} - -/* - * Start and execute the code for the monitor which never returns from this - * function. The child will return and continue in the caller. - */ -void -altprivsep_start_and_do_monitor(int use_engine, int inetd, int newsock, - int statup_pipe) -{ - pid_t aps_child; - Authctxt *authctxt; - - /* - * The monitor will packet_close() in packet_set_monitor() called from - * altprivsep_start_monitor() below to clean up the socket stuff before - * it switches to pipes for communication to the child. The socket fd is - * closed there so we must dup it here - monitor needs that socket to - * shutdown the connection in case of any problem; see comments below. - * Note that current newsock was assigned to connection_(in|out) which - * are the variables used in packet_close() to close the communication - * socket. - */ - newsock = dup(newsock); - - if ((aps_child = altprivsep_start_monitor(&authctxt)) == -1) - fatal("Monitor could not be started."); - - if (aps_child > 0) { - /* ALTPRIVSEP Monitor */ - - /* - * The ALTPRIVSEP monitor here does: - * - * - record keeping and auditing - * - PAM cleanup - */ - - /* this is for MaxStartups and the child takes care of that */ - (void) close(statup_pipe); - (void) pkcs11_engine_load(use_engine); - - /* - * If the monitor fatal()s it will audit/record a logout, so - * we'd better do something to really mean it: shutdown the - * socket but leave the child alone -- it's been disconnected - * and we hope it exits, but killing any pid from a privileged - * monitor could be dangerous. - * - * NOTE: Order matters -- these fatal cleanups must come before - * the audit logout fatal cleanup as these functions are called - * in LIFO. - */ - fatal_add_cleanup((void (*)(void *))altprivsep_shutdown_sock, - (void *)&newsock); - - if (compat20) { - debug3("Recording SSHv2 session login in wtmpx"); - /* - * record_login() relies on connection_in to be the - * socket to get the peer address. The problem is that - * connection_in had to be set to the pipe descriptor in - * altprivsep_start_monitor(). It's not nice but the - * easiest way to get the peer's address is to - * temporarily set connection_in to the socket's file - * descriptor. - */ - packet_set_fds(inetd == 1 ? -1 : newsock, 0); - record_login(getpid(), NULL, "sshd", authctxt->user); - packet_set_fds(0, 1); - } - -#ifdef HAVE_BSM - /* Initialize the group list, audit sometimes needs it. */ - if (initgroups(authctxt->pw->pw_name, - authctxt->pw->pw_gid) < 0) { - perror("initgroups"); - exit (1); - } - - /* - * The monitor process fork()ed before the authentication - * process started so at this point we have an unaudited - * context. Thus we need to obtain the audit session data - * from the authentication process (aps_child) which will - * have the correct audit context for the user logging in. - * To do so we pass along the process-ID of the aps_child - * process so that it is referenced for this audit session - * rather than referencing the monitor's unaudited context. - */ - audit_sshd_login(&ah, aps_child); - - fatal_add_cleanup((void (*)(void *))audit_sshd_logout, - (void *)&ah); -#endif /* HAVE_BSM */ - -#ifdef GSSAPI - fatal_add_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, - (void *)&xxx_gssctxt); -#endif /* GSSAPI */ - - altprivsep_do_monitor(authctxt, aps_child); - - /* If we got here the connection is dead. */ - fatal_remove_cleanup((void (*)(void *))altprivsep_shutdown_sock, - (void *)&newsock); - - if (compat20) { - debug3("Recording SSHv2 session logout in wtmpx"); - record_logout(getpid(), NULL, "sshd", authctxt->user); - } - - /* - * Make sure the socket is closed. The monitor can't call - * packet_close here as it's done a packet_set_connection() - * with the pipe to the child instead of the socket. - */ - (void) shutdown(newsock, SHUT_RDWR); - -#ifdef GSSAPI - fatal_remove_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, - &xxx_gssctxt); - ssh_gssapi_cleanup_creds(xxx_gssctxt); - ssh_gssapi_server_mechs(NULL); /* release cached mechs list */ -#endif /* GSSAPI */ - -#ifdef HAVE_BSM - fatal_remove_cleanup((void (*)(void *))audit_sshd_logout, (void *)&ah); - audit_sshd_logout(&ah); -#endif /* HAVE_BSM */ - - exit(0); - } else { - /* - * This is the child, close the dup()ed file descriptor for a - * socket. It's not needed in the child. - */ - close(newsock); - } -} diff --git a/usr/src/cmd/ssh/sshd/auth-bsdauth.c b/usr/src/cmd/ssh/sshd/auth-bsdauth.c deleted file mode 100644 index 090fa0ef39..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-bsdauth.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: auth-bsdauth.c,v 1.5 2002/06/30 21:59:45 deraadt Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef BSD_AUTH -#include "xmalloc.h" -#include "auth.h" -#include "log.h" - -static void * -bsdauth_init_ctx(Authctxt *authctxt) -{ - return authctxt; -} - -int -bsdauth_query(void *ctx, char **name, char **infotxt, - u_int *numprompts, char ***prompts, u_int **echo_on) -{ - Authctxt *authctxt = ctx; - char *challenge = NULL; - - if (authctxt->as != NULL) { - debug2("bsdauth_query: try reuse session"); - challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); - if (challenge == NULL) { - auth_close(authctxt->as); - authctxt->as = NULL; - } - } - - if (challenge == NULL) { - debug2("bsdauth_query: new bsd auth session"); - debug3("bsdauth_query: style %s", - authctxt->style ? authctxt->style : "<default>"); - authctxt->as = auth_userchallenge(authctxt->user, - authctxt->style, "auth-ssh", &challenge); - if (authctxt->as == NULL) - challenge = NULL; - debug2("bsdauth_query: <%s>", challenge ? challenge : "empty"); - } - - if (challenge == NULL) - return -1; - - *name = xstrdup(""); - *infotxt = xstrdup(""); - *numprompts = 1; - *prompts = xmalloc(*numprompts * sizeof(char *)); - *echo_on = xmalloc(*numprompts * sizeof(u_int)); - (*echo_on)[0] = 0; - (*prompts)[0] = xstrdup(challenge); - - return 0; -} - -int -bsdauth_respond(void *ctx, u_int numresponses, char **responses) -{ - Authctxt *authctxt = ctx; - int authok; - - if (authctxt->as == 0) - error("bsdauth_respond: no bsd auth session"); - - if (numresponses != 1) - return -1; - - authok = auth_userresponse(authctxt->as, responses[0], 0); - authctxt->as = NULL; - debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok); - - return (authok == 0) ? -1 : 0; -} - -static void -bsdauth_free_ctx(void *ctx) -{ - Authctxt *authctxt = ctx; - - if (authctxt && authctxt->as) { - auth_close(authctxt->as); - authctxt->as = NULL; - } -} - -KbdintDevice bsdauth_device = { - "bsdauth", - bsdauth_init_ctx, - bsdauth_query, - bsdauth_respond, - bsdauth_free_ctx -}; - -KbdintDevice mm_bsdauth_device = { - "bsdauth", - bsdauth_init_ctx, - mm_bsdauth_query, - mm_bsdauth_respond, - bsdauth_free_ctx -}; -#endif diff --git a/usr/src/cmd/ssh/sshd/auth-chall.c b/usr/src/cmd/ssh/sshd/auth-chall.c deleted file mode 100644 index 07073f0d98..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-chall.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-chall.c,v 1.8 2001/05/18 14:13:28 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "auth.h" -#include "log.h" -#include "xmalloc.h" - -/* limited protocol v1 interface to kbd-interactive authentication */ - -extern KbdintDevice *devices[]; -static KbdintDevice *device; - -char * -get_challenge(Authctxt *authctxt) -{ - char *challenge, *name, *info, **prompts; - u_int i, numprompts; - u_int *echo_on; - - device = devices[0]; /* we always use the 1st device for protocol 1 */ - if (device == NULL) - return NULL; - if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL) - return NULL; - if (device->query(authctxt->kbdintctxt, &name, &info, - &numprompts, &prompts, &echo_on)) { - device->free_ctx(authctxt->kbdintctxt); - authctxt->kbdintctxt = NULL; - return NULL; - } - if (numprompts < 1) - fatal("get_challenge: numprompts < 1"); - challenge = xstrdup(prompts[0]); - for (i = 0; i < numprompts; i++) - xfree(prompts[i]); - xfree(prompts); - xfree(name); - xfree(echo_on); - xfree(info); - - return (challenge); -} -int -verify_response(Authctxt *authctxt, const char *response) -{ - char *resp[1]; - int res; - - if (device == NULL) - return 0; - if (authctxt->kbdintctxt == NULL) - return 0; - resp[0] = (char *)response; - res = device->respond(authctxt->kbdintctxt, 1, resp); - device->free_ctx(authctxt->kbdintctxt); - authctxt->kbdintctxt = NULL; - return res ? 0 : 1; -} diff --git a/usr/src/cmd/ssh/sshd/auth-krb4.c b/usr/src/cmd/ssh/sshd/auth-krb4.c deleted file mode 100644 index 2a9103f232..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-krb4.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 1999 Dug Song. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-krb4.c,v 1.28 2002/09/26 11:38:43 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "ssh.h" -#include "ssh1.h" -#include "packet.h" -#include "xmalloc.h" -#include "log.h" -#include "servconf.h" -#include "uidswap.h" -#include "auth.h" - -#ifdef AFS -#include "radix.h" -#endif - -#ifdef KRB4 -extern ServerOptions options; - -static int -krb4_init(void *context) -{ - static int cleanup_registered = 0; - Authctxt *authctxt = (Authctxt *)context; - const char *tkt_root = TKT_ROOT; - struct stat st; - int fd; - - if (!authctxt->krb4_ticket_file) { - /* Set unique ticket string manually since we're still root. */ - authctxt->krb4_ticket_file = xmalloc(MAXPATHLEN); -#ifdef AFS - if (lstat("/ticket", &st) != -1) - tkt_root = "/ticket/"; -#endif /* AFS */ - snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%ld", - tkt_root, authctxt->pw->pw_uid, (long)getpid()); - krb_set_tkt_string(authctxt->krb4_ticket_file); - } - /* Register ticket cleanup in case of fatal error. */ - if (!cleanup_registered) { - fatal_add_cleanup(krb4_cleanup_proc, authctxt); - cleanup_registered = 1; - } - /* Try to create our ticket file. */ - if ((fd = mkstemp(authctxt->krb4_ticket_file)) != -1) { - close(fd); - return (1); - } - /* Ticket file exists - make sure user owns it (just passed ticket). */ - if (lstat(authctxt->krb4_ticket_file, &st) != -1) { - if (st.st_mode == (S_IFREG | S_IRUSR | S_IWUSR) && - st.st_uid == authctxt->pw->pw_uid) - return (1); - } - /* Failure - cancel cleanup function, leaving ticket for inspection. */ - log("WARNING: bad ticket file %s", authctxt->krb4_ticket_file); - - fatal_remove_cleanup(krb4_cleanup_proc, authctxt); - cleanup_registered = 0; - - xfree(authctxt->krb4_ticket_file); - authctxt->krb4_ticket_file = NULL; - - return (0); -} - -/* - * try krb4 authentication, - * return 1 on success, 0 on failure, -1 if krb4 is not available - */ -int -auth_krb4_password(Authctxt *authctxt, const char *password) -{ - AUTH_DAT adata; - KTEXT_ST tkt; - struct hostent *hp; - struct passwd *pw; - char localhost[MAXHOSTNAMELEN], phost[INST_SZ], realm[REALM_SZ]; - u_int32_t faddr; - int r; - - if ((pw = authctxt->pw) == NULL) - return (0); - - /* - * Try Kerberos password authentication only for non-root - * users and only if Kerberos is installed. - */ - if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) { - /* Set up our ticket file. */ - if (!krb4_init(authctxt)) { - log("Couldn't initialize Kerberos ticket file for %s!", - pw->pw_name); - goto failure; - } - /* Try to get TGT using our password. */ - r = krb_get_pw_in_tkt((char *) pw->pw_name, "", realm, - "krbtgt", realm, DEFAULT_TKT_LIFE, (char *)password); - if (r != INTK_OK) { - debug("Kerberos v4 password authentication for %s " - "failed: %s", pw->pw_name, krb_err_txt[r]); - goto failure; - } - /* Successful authentication. */ - chown(tkt_string(), pw->pw_uid, pw->pw_gid); - - /* - * Now that we have a TGT, try to get a local - * "rcmd" ticket to ensure that we are not talking - * to a bogus Kerberos server. - */ - gethostname(localhost, sizeof(localhost)); - strlcpy(phost, (char *)krb_get_phost(localhost), - sizeof(phost)); - r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33); - - if (r == KSUCCESS) { - if ((hp = gethostbyname(localhost)) == NULL) { - log("Couldn't get local host address!"); - goto failure; - } - memmove((void *)&faddr, (void *)hp->h_addr, - sizeof(faddr)); - - /* Verify our "rcmd" ticket. */ - r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, - faddr, &adata, ""); - if (r == RD_AP_UNDEC) { - /* - * Probably didn't have a srvtab on - * localhost. Disallow login. - */ - log("Kerberos v4 TGT for %s unverifiable, " - "no srvtab installed? krb_rd_req: %s", - pw->pw_name, krb_err_txt[r]); - goto failure; - } else if (r != KSUCCESS) { - log("Kerberos v4 %s ticket unverifiable: %s", - KRB4_SERVICE_NAME, krb_err_txt[r]); - goto failure; - } - } else if (r == KDC_PR_UNKNOWN) { - /* - * Disallow login if no rcmd service exists, and - * log the error. - */ - log("Kerberos v4 TGT for %s unverifiable: %s; %s.%s " - "not registered, or srvtab is wrong?", pw->pw_name, - krb_err_txt[r], KRB4_SERVICE_NAME, phost); - goto failure; - } else { - /* - * TGT is bad, forget it. Possibly spoofed! - */ - debug("WARNING: Kerberos v4 TGT possibly spoofed " - "for %s: %s", pw->pw_name, krb_err_txt[r]); - goto failure; - } - /* Authentication succeeded. */ - return (1); - } else - /* Logging in as root or no local Kerberos realm. */ - debug("Unable to authenticate to Kerberos."); - - failure: - krb4_cleanup_proc(authctxt); - - if (!options.kerberos_or_local_passwd) - return (0); - - /* Fall back to ordinary passwd authentication. */ - return (-1); -} - -void -krb4_cleanup_proc(void *context) -{ - Authctxt *authctxt = (Authctxt *)context; - debug("krb4_cleanup_proc called"); - if (authctxt->krb4_ticket_file) { - (void) dest_tkt(); - xfree(authctxt->krb4_ticket_file); - authctxt->krb4_ticket_file = NULL; - } -} - -int -auth_krb4(Authctxt *authctxt, KTEXT auth, char **client, KTEXT reply) -{ - AUTH_DAT adat = {0}; - Key_schedule schedule; - struct sockaddr_in local, foreign; - char instance[INST_SZ]; - socklen_t slen; - u_int cksum; - int r, s; - - s = packet_get_connection_in(); - - slen = sizeof(local); - memset(&local, 0, sizeof(local)); - if (getsockname(s, (struct sockaddr *) & local, &slen) < 0) - debug("getsockname failed: %.100s", strerror(errno)); - slen = sizeof(foreign); - memset(&foreign, 0, sizeof(foreign)); - if (getpeername(s, (struct sockaddr *) & foreign, &slen) < 0) { - debug("getpeername failed: %.100s", strerror(errno)); - fatal_cleanup(); - } - instance[0] = '*'; - instance[1] = 0; - - /* Get the encrypted request, challenge, and session key. */ - if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, - 0, &adat, ""))) { - debug("Kerberos v4 krb_rd_req: %.100s", krb_err_txt[r]); - return (0); - } - des_key_sched((des_cblock *) adat.session, schedule); - - *client = xmalloc(MAX_K_NAME_SZ); - (void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname, - *adat.pinst ? "." : "", adat.pinst, adat.prealm); - - /* Check ~/.klogin authorization now. */ - if (kuserok(&adat, authctxt->user) != KSUCCESS) { - log("Kerberos v4 .klogin authorization failed for %s to " - "account %s", *client, authctxt->user); - xfree(*client); - *client = NULL; - return (0); - } - /* Increment the checksum, and return it encrypted with the - session key. */ - cksum = adat.checksum + 1; - cksum = htonl(cksum); - - /* If we can't successfully encrypt the checksum, we send back an - empty message, admitting our failure. */ - if ((r = krb_mk_priv((u_char *) & cksum, reply->dat, sizeof(cksum) + 1, - schedule, &adat.session, &local, &foreign)) < 0) { - debug("Kerberos v4 mk_priv: (%d) %s", r, krb_err_txt[r]); - reply->dat[0] = 0; - reply->length = 0; - } else - reply->length = r; - - /* Clear session key. */ - memset(&adat.session, 0, sizeof(&adat.session)); - return (1); -} -#endif /* KRB4 */ - -#ifdef AFS -int -auth_krb4_tgt(Authctxt *authctxt, const char *string) -{ - CREDENTIALS creds; - struct passwd *pw; - - if ((pw = authctxt->pw) == NULL) - goto failure; - - temporarily_use_uid(pw); - - if (!radix_to_creds(string, &creds)) { - log("Protocol error decoding Kerberos v4 TGT"); - goto failure; - } - if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */ - strlcpy(creds.service, "krbtgt", sizeof creds.service); - - if (strcmp(creds.service, "krbtgt")) { - log("Kerberos v4 TGT (%s%s%s@%s) rejected for %s", - creds.pname, creds.pinst[0] ? "." : "", creds.pinst, - creds.realm, pw->pw_name); - goto failure; - } - if (!krb4_init(authctxt)) - goto failure; - - if (in_tkt(creds.pname, creds.pinst) != KSUCCESS) - goto failure; - - if (save_credentials(creds.service, creds.instance, creds.realm, - creds.session, creds.lifetime, creds.kvno, &creds.ticket_st, - creds.issue_date) != KSUCCESS) { - debug("Kerberos v4 TGT refused: couldn't save credentials"); - goto failure; - } - /* Successful authentication, passed all checks. */ - chown(tkt_string(), pw->pw_uid, pw->pw_gid); - - debug("Kerberos v4 TGT accepted (%s%s%s@%s)", - creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm); - memset(&creds, 0, sizeof(creds)); - - restore_uid(); - - return (1); - - failure: - krb4_cleanup_proc(authctxt); - memset(&creds, 0, sizeof(creds)); - restore_uid(); - - return (0); -} - -int -auth_afs_token(Authctxt *authctxt, const char *token_string) -{ - CREDENTIALS creds; - struct passwd *pw; - uid_t uid; - - if ((pw = authctxt->pw) == NULL) - return (0); - - if (!radix_to_creds(token_string, &creds)) { - log("Protocol error decoding AFS token"); - return (0); - } - if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */ - strlcpy(creds.service, "afs", sizeof creds.service); - - if (strncmp(creds.pname, "AFS ID ", 7) == 0) - uid = atoi(creds.pname + 7); - else - uid = pw->pw_uid; - - if (kafs_settoken(creds.realm, uid, &creds)) { - log("AFS token (%s@%s) rejected for %s", - creds.pname, creds.realm, pw->pw_name); - memset(&creds, 0, sizeof(creds)); - return (0); - } - debug("AFS token accepted (%s@%s)", creds.pname, creds.realm); - memset(&creds, 0, sizeof(creds)); - - return (1); -} -#endif /* AFS */ diff --git a/usr/src/cmd/ssh/sshd/auth-krb5.c b/usr/src/cmd/ssh/sshd/auth-krb5.c deleted file mode 100644 index 3f5416af41..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-krb5.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Kerberos v5 authentication and ticket-passing routines. - * - * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $ - */ -/* - * Copyright (c) 2002 Daniel Kouril. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-krb5.c,v 1.9 2002/09/09 06:48:06 itojun Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "ssh.h" -#include "ssh1.h" -#include "packet.h" -#include "xmalloc.h" -#include "log.h" -#include "servconf.h" -#include "uidswap.h" -#include "auth.h" - -#ifdef KRB5 -#include <krb5.h> -#ifndef HEIMDAL -#define krb5_get_err_text(context,code) error_message(code) -#endif /* !HEIMDAL */ - -extern ServerOptions options; - -static int -krb5_init(void *context) -{ - Authctxt *authctxt = (Authctxt *)context; - krb5_error_code problem; - static int cleanup_registered = 0; - - if (authctxt->krb5_ctx == NULL) { - problem = krb5_init_context(&authctxt->krb5_ctx); - if (problem) - return (problem); - krb5_init_ets(authctxt->krb5_ctx); - } - if (!cleanup_registered) { - fatal_add_cleanup(krb5_cleanup_proc, authctxt); - cleanup_registered = 1; - } - return (0); -} - -/* - * Try krb5 authentication. server_user is passed for logging purposes - * only, in auth is received ticket, in client is returned principal - * from the ticket - */ -int -auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *reply) -{ - krb5_error_code problem; - krb5_principal server; - krb5_ticket *ticket; - int fd, ret; - - ret = 0; - server = NULL; - ticket = NULL; - reply->length = 0; - - problem = krb5_init(authctxt); - if (problem) - goto err; - - problem = krb5_auth_con_init(authctxt->krb5_ctx, - &authctxt->krb5_auth_ctx); - if (problem) - goto err; - - fd = packet_get_connection_in(); -#ifdef HEIMDAL - problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx, - authctxt->krb5_auth_ctx, &fd); -#else - problem = krb5_auth_con_genaddrs(authctxt->krb5_ctx, - authctxt->krb5_auth_ctx,fd, - KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR | - KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR); -#endif - if (problem) - goto err; - - problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL , - KRB5_NT_SRV_HST, &server); - if (problem) - goto err; - - problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx, - auth, server, NULL, NULL, &ticket); - if (problem) - goto err; - -#ifdef HEIMDAL - problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client, - &authctxt->krb5_user); -#else - problem = krb5_copy_principal(authctxt->krb5_ctx, - ticket->enc_part2->client, - &authctxt->krb5_user); -#endif - if (problem) - goto err; - - /* if client wants mutual auth */ - problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, - reply); - if (problem) - goto err; - - /* Check .k5login authorization now. */ - if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, - authctxt->pw->pw_name)) - goto err; - - if (client) - krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, - client); - - ret = 1; - err: - if (server) - krb5_free_principal(authctxt->krb5_ctx, server); - if (ticket) - krb5_free_ticket(authctxt->krb5_ctx, ticket); - if (!ret && reply->length) { - xfree(reply->data); - memset(reply, 0, sizeof(*reply)); - } - - if (problem) { - if (authctxt->krb5_ctx != NULL) - debug("Kerberos v5 authentication failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); - else - debug("Kerberos v5 authentication failed: %d", - problem); - } - - return (ret); -} - -int -auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) -{ - krb5_error_code problem; - krb5_ccache ccache = NULL; - char *pname; - krb5_creds **creds; - - if (authctxt->pw == NULL || authctxt->krb5_user == NULL) - return (0); - - temporarily_use_uid(authctxt->pw); - -#ifdef HEIMDAL - problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache); -#else -{ - char ccname[40]; - int tmpfd; - - snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); - - if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { - log("mkstemp(): %.100s", strerror(errno)); - problem = errno; - goto fail; - } - if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { - log("fchmod(): %.100s", strerror(errno)); - close(tmpfd); - problem = errno; - goto fail; - } - close(tmpfd); - problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache); -} -#endif - if (problem) - goto fail; - - problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, - authctxt->krb5_user); - if (problem) - goto fail; - -#ifdef HEIMDAL - problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, - ccache, tgt); - if (problem) - goto fail; -#else - problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, - tgt, &creds, NULL); - if (problem) - goto fail; - problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds); - if (problem) - goto fail; -#endif - - authctxt->krb5_fwd_ccache = ccache; - ccache = NULL; - - authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - - problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, - &pname); - if (problem) - goto fail; - - debug("Kerberos v5 TGT accepted (%s)", pname); - - restore_uid(); - - return (1); - - fail: - if (problem) - debug("Kerberos v5 TGT passing failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); - if (ccache) - krb5_cc_destroy(authctxt->krb5_ctx, ccache); - - restore_uid(); - - return (0); -} - -int -auth_krb5_password(Authctxt *authctxt, const char *password) -{ -#ifndef HEIMDAL - krb5_creds creds; - krb5_principal server; - char ccname[40]; - int tmpfd; -#endif - krb5_error_code problem; - - if (authctxt->pw == NULL) - return (0); - - temporarily_use_uid(authctxt->pw); - - problem = krb5_init(authctxt); - if (problem) - goto out; - - problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, - &authctxt->krb5_user); - if (problem) - goto out; - -#ifdef HEIMDAL - problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, - &authctxt->krb5_fwd_ccache); - if (problem) - goto out; - - problem = krb5_cc_initialize(authctxt->krb5_ctx, - authctxt->krb5_fwd_ccache, authctxt->krb5_user); - if (problem) - goto out; - - restore_uid(); - problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, - authctxt->krb5_fwd_ccache, password, 1, NULL); - temporarily_use_uid(authctxt->pw); - - if (problem) - goto out; - -#else - problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, - authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); - if (problem) - goto out; - - problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, - KRB5_NT_SRV_HST, &server); - if (problem) - goto out; - - restore_uid(); - problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, - NULL, NULL, NULL); - krb5_free_principal(authctxt->krb5_ctx, server); - temporarily_use_uid(authctxt->pw); - if (problem) - goto out; - - if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, - authctxt->pw->pw_name)) { - problem = -1; - goto out; - } - - snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); - - if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { - log("mkstemp(): %.100s", strerror(errno)); - problem = errno; - goto out; - } - - if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { - log("fchmod(): %.100s", strerror(errno)); - close(tmpfd); - problem = errno; - goto out; - } - close(tmpfd); - - problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache); - if (problem) - goto out; - - problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, - authctxt->krb5_user); - if (problem) - goto out; - - problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, - &creds); - if (problem) - goto out; -#endif - - authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - - out: - restore_uid(); - - if (problem) { - if (authctxt->krb5_ctx != NULL && problem!=-1) - debug("Kerberos password authentication failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); - else - debug("Kerberos password authentication failed: %d", - problem); - - krb5_cleanup_proc(authctxt); - - if (options.kerberos_or_local_passwd) - return (-1); - else - return (0); - } - return (1); -} - -void -krb5_cleanup_proc(void *context) -{ - Authctxt *authctxt = (Authctxt *)context; - - debug("krb5_cleanup_proc called"); - if (authctxt->krb5_fwd_ccache) { - krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - authctxt->krb5_fwd_ccache = NULL; - } - if (authctxt->krb5_user) { - krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); - authctxt->krb5_user = NULL; - } - if (authctxt->krb5_auth_ctx) { - krb5_auth_con_free(authctxt->krb5_ctx, - authctxt->krb5_auth_ctx); - authctxt->krb5_auth_ctx = NULL; - } - if (authctxt->krb5_ctx) { - krb5_free_context(authctxt->krb5_ctx); - authctxt->krb5_ctx = NULL; - } -} - -#endif /* KRB5 */ diff --git a/usr/src/cmd/ssh/sshd/auth-options.c b/usr/src/cmd/ssh/sshd/auth-options.c deleted file mode 100644 index b186cbe045..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-options.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-options.c,v 1.26 2002/07/30 17:03:55 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "xmalloc.h" -#include "match.h" -#include "log.h" -#include "canohost.h" -#include "channels.h" -#include "auth-options.h" -#include "servconf.h" -#include "misc.h" -#include "auth.h" - -/* Flags set authorized_keys flags */ -int no_port_forwarding_flag = 0; -int no_agent_forwarding_flag = 0; -int no_x11_forwarding_flag = 0; -int no_pty_flag = 0; - -/* "command=" option. */ -char *forced_command = NULL; - -/* "environment=" options. */ -struct envstring *custom_environment = NULL; - -extern ServerOptions options; - -void -auth_clear_options(void) -{ - no_agent_forwarding_flag = 0; - no_port_forwarding_flag = 0; - no_pty_flag = 0; - no_x11_forwarding_flag = 0; - while (custom_environment) { - struct envstring *ce = custom_environment; - custom_environment = ce->next; - xfree(ce->s); - xfree(ce); - } - if (forced_command) { - xfree(forced_command); - forced_command = NULL; - } - channel_clear_permitted_opens(); - auth_debug_reset(); -} - -/* - * return 1 if access is granted, 0 if not. - * side effect: sets key option flags - */ -int -auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) -{ - const char *cp; - int i; - - /* reset options */ - auth_clear_options(); - - if (!opts) - return 1; - - while (*opts && *opts != ' ' && *opts != '\t') { - cp = "no-port-forwarding"; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - auth_debug_add("Port forwarding disabled."); - no_port_forwarding_flag = 1; - opts += strlen(cp); - goto next_option; - } - cp = "no-agent-forwarding"; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - auth_debug_add("Agent forwarding disabled."); - no_agent_forwarding_flag = 1; - opts += strlen(cp); - goto next_option; - } - cp = "no-X11-forwarding"; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - auth_debug_add("X11 forwarding disabled."); - no_x11_forwarding_flag = 1; - opts += strlen(cp); - goto next_option; - } - cp = "no-pty"; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - auth_debug_add("Pty allocation disabled."); - no_pty_flag = 1; - opts += strlen(cp); - goto next_option; - } - cp = "command=\""; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - opts += strlen(cp); - forced_command = xmalloc(strlen(opts) + 1); - i = 0; - while (*opts) { - if (*opts == '"') - break; - if (*opts == '\\' && opts[1] == '"') { - opts += 2; - forced_command[i++] = '"'; - continue; - } - forced_command[i++] = *opts++; - } - if (!*opts) { - debug("%.100s, line %lu: missing end quote", - file, linenum); - auth_debug_add("%.100s, line %lu: missing end quote", - file, linenum); - xfree(forced_command); - forced_command = NULL; - goto bad_option; - } - forced_command[i] = 0; - auth_debug_add("Forced command: %.900s", forced_command); - opts++; - goto next_option; - } - cp = "environment=\""; - if (options.permit_user_env && - strncasecmp(opts, cp, strlen(cp)) == 0) { - char *s; - struct envstring *new_envstring; - - opts += strlen(cp); - s = xmalloc(strlen(opts) + 1); - i = 0; - while (*opts) { - if (*opts == '"') - break; - if (*opts == '\\' && opts[1] == '"') { - opts += 2; - s[i++] = '"'; - continue; - } - s[i++] = *opts++; - } - if (!*opts) { - debug("%.100s, line %lu: missing end quote", - file, linenum); - auth_debug_add("%.100s, line %lu: missing end quote", - file, linenum); - xfree(s); - goto bad_option; - } - s[i] = 0; - auth_debug_add("Adding to environment: %.900s", s); - debug("Adding to environment: %.900s", s); - opts++; - new_envstring = xmalloc(sizeof(struct envstring)); - new_envstring->s = s; - new_envstring->next = custom_environment; - custom_environment = new_envstring; - goto next_option; - } - cp = "from=\""; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - const char *remote_ip = get_remote_ipaddr(); - const char *remote_host = get_canonical_hostname( - options.verify_reverse_mapping); - char *patterns = xmalloc(strlen(opts) + 1); - - opts += strlen(cp); - i = 0; - while (*opts) { - if (*opts == '"') - break; - if (*opts == '\\' && opts[1] == '"') { - opts += 2; - patterns[i++] = '"'; - continue; - } - patterns[i++] = *opts++; - } - if (!*opts) { - debug("%.100s, line %lu: missing end quote", - file, linenum); - auth_debug_add("%.100s, line %lu: missing end quote", - file, linenum); - xfree(patterns); - goto bad_option; - } - patterns[i] = 0; - opts++; - if (match_host_and_ip(remote_host, remote_ip, - patterns) != 1) { - xfree(patterns); - log("Authentication tried for %.100s with " - "correct key but not from a permitted " - "host (host=%.200s, ip=%.200s).", - pw->pw_name, remote_host, remote_ip); - auth_debug_add("Your host '%.200s' is not " - "permitted to use this key for login.", - remote_host); - /* deny access */ - return 0; - } - xfree(patterns); - /* Host name matches. */ - goto next_option; - } - cp = "permitopen=\""; - if (strncasecmp(opts, cp, strlen(cp)) == 0) { - char host[256], sport[6]; - u_short port; - char *patterns = xmalloc(strlen(opts) + 1); - - opts += strlen(cp); - i = 0; - while (*opts) { - if (*opts == '"') - break; - if (*opts == '\\' && opts[1] == '"') { - opts += 2; - patterns[i++] = '"'; - continue; - } - patterns[i++] = *opts++; - } - if (!*opts) { - debug("%.100s, line %lu: missing end quote", - file, linenum); - auth_debug_add("%.100s, line %lu: missing end quote", - file, linenum); - xfree(patterns); - goto bad_option; - } - patterns[i] = 0; - opts++; - if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && - sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { - debug("%.100s, line %lu: Bad permitopen specification " - "<%.100s>", file, linenum, patterns); - auth_debug_add("%.100s, line %lu: " - "Bad permitopen specification", file, linenum); - xfree(patterns); - goto bad_option; - } - if ((port = a2port(sport)) == 0) { - debug("%.100s, line %lu: Bad permitopen port <%.100s>", - file, linenum, sport); - auth_debug_add("%.100s, line %lu: " - "Bad permitopen port", file, linenum); - xfree(patterns); - goto bad_option; - } - if (options.allow_tcp_forwarding) - channel_add_permitted_opens(host, port); - xfree(patterns); - goto next_option; - } -next_option: - /* - * Skip the comma, and move to the next option - * (or break out if there are no more). - */ - if (!*opts) - fatal("Bugs in auth-options.c option processing."); - if (*opts == ' ' || *opts == '\t') - break; /* End of options. */ - if (*opts != ',') - goto bad_option; - opts++; - /* Process the next option. */ - } - - auth_debug_send(); - - /* grant access */ - return 1; - -bad_option: - log("Bad options in %.100s file, line %lu: %.50s", - file, linenum, opts); - auth_debug_add("Bad options in %.100s file, line %lu: %.50s", - file, linenum, opts); - - auth_debug_send(); - - /* deny access */ - return 0; -} diff --git a/usr/src/cmd/ssh/sshd/auth-pam.c b/usr/src/cmd/ssh/sshd/auth-pam.c deleted file mode 100644 index c3686b4928..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-pam.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Copyright (c) 2000 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include "includes.h" - -#ifdef USE_PAM -#include "xmalloc.h" -#include "log.h" -#include "auth.h" -#include "auth-options.h" -#include "auth-pam.h" -#include "buffer.h" -#include "servconf.h" -#include "canohost.h" -#include "compat.h" -#include "misc.h" -#include "sshlogin.h" -#include "ssh-gss.h" - -#include <security/pam_appl.h> - -extern char *__progname; - -extern u_int utmp_len; -extern ServerOptions options; - -extern Authmethod method_kbdint; - -RCSID("$Id: auth-pam.c,v 1.54 2002/07/28 20:24:08 stevesk Exp $"); - -#define NEW_AUTHTOK_MSG \ - "Warning: Your password has expired, please change it now." - -/* PAM conversation for non-interactive userauth methods */ -static int do_pam_conversation(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr); - -static void do_pam_cleanup_proc(void *context); - -static char *get_method_name(Authctxt *authctxt); - -/* PAM conversation for non-interactive userauth methods */ -static struct pam_conv conv = { - (int (*)())do_pam_conversation, - NULL -}; -static char *__pam_msg = NULL; - -static -char * -get_method_name(Authctxt *authctxt) -{ - if (!authctxt) - return "(unknown)"; - - if (!compat20) - return (authctxt->v1_auth_name) ? authctxt->v1_auth_name : - "(sshv1-unknown)"; - - if (!authctxt->method || !authctxt->method->name) - return "(sshv2-unknown)"; - - return authctxt->method->name; -} - -char * -derive_pam_service_name(Authmethod *method) -{ - char *svcname = xmalloc(BUFSIZ); - - /* - * If PamServiceName is set we use that for everything, including - * SSHv1 - */ - if (options.pam_service_name != NULL) { - (void) strlcpy(svcname, options.pam_service_name, BUFSIZ); - return (svcname); - } - - if (compat20 && method) { - char *method_name = method->name; - - if (!method_name) - fatal("Userauth method unknown while starting PAM"); - - /* - * For SSHv2 we use "sshd-<userauth name> - * The "sshd" prefix can be changed via the PAMServicePrefix - * sshd_config option. - */ - if (strcmp(method_name, "none") == 0) { - snprintf(svcname, BUFSIZ, "%s-none", - options.pam_service_prefix); - } - if (strcmp(method_name, "password") == 0) { - snprintf(svcname, BUFSIZ, "%s-password", - options.pam_service_prefix); - } - if (strcmp(method_name, "keyboard-interactive") == 0) { - /* "keyboard-interactive" is too long, shorten it */ - snprintf(svcname, BUFSIZ, "%s-kbdint", - options.pam_service_prefix); - } - if (strcmp(method_name, "publickey") == 0) { - /* "publickey" is too long, shorten it */ - snprintf(svcname, BUFSIZ, "%s-pubkey", - options.pam_service_prefix); - } - if (strcmp(method_name, "hostbased") == 0) { - /* "hostbased" can't really be shortened... */ - snprintf(svcname, BUFSIZ, "%s-hostbased", - options.pam_service_prefix); - } - if (strncmp(method_name, "gss", 3) == 0) { - /* "gss" is too short, elongate it */ - snprintf(svcname, BUFSIZ, "%s-gssapi", - options.pam_service_prefix); - } - return svcname; - } else { - /* SSHv1 doesn't get to be so cool */ - snprintf(svcname, BUFSIZ, "%s-v1", - options.pam_service_prefix); - } - return svcname; -} - -void -new_start_pam(Authctxt *authctxt, struct pam_conv *conv) -{ - int retval; - pam_handle_t *pamh; - const char *rhost; - char *svc; - char *user = NULL; - pam_stuff *pam; - - if (authctxt == NULL) - fatal("Internal error during userauth"); - - if (compat20 && authctxt->method == NULL) - fatal("Userauth method unknown while starting PAM"); - - /* PAM service selected here */ - svc = derive_pam_service_name(authctxt->method); - debug2("Starting PAM service %s for method %s", svc, - get_method_name(authctxt)); - - if (authctxt->user != NULL) - user = authctxt->user; - - /* Cleanup previous PAM state */ - if (authctxt->pam != NULL) { - fatal_remove_cleanup(&do_pam_cleanup_proc, authctxt->pam); - do_pam_cleanup_proc(authctxt->pam); - } - - pam = xmalloc(sizeof(pam_stuff)); - (void) memset(pam, 0, sizeof(pam_stuff)); - - /* - * pam->last_pam_retval has to be and is considered - * along with pam->state. - * - * pam->state = 0; -> no PAM auth, account, etc, work - * done yet. (Set by memset() above.) - * - * pam->last_pam_retval = PAM_SUCCESS; -> meaningless at - * this point. - * - * See finish_userauth_do_pam() below. - */ - pam->authctxt = authctxt; - pam->last_pam_retval = PAM_SUCCESS; - - authctxt->pam = pam; - - /* Free any previously stored text/error PAM prompts */ - if (__pam_msg) { - xfree(__pam_msg); - __pam_msg = NULL; - } - - if ((retval = pam_start(svc, user, conv, &pamh)) != PAM_SUCCESS) { - fatal("PAM initialization failed during %s userauth", - get_method_name(authctxt)); - } - - free(svc); - - fatal_add_cleanup((void (*)(void *)) &do_pam_cleanup_proc, - (void *) authctxt->pam); - - rhost = get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping); - if ((retval = pam_set_item(pamh, PAM_RHOST, rhost)) != PAM_SUCCESS) { - (void) pam_end(pamh, retval); - fatal("Could not set PAM_RHOST item during %s userauth", - get_method_name(authctxt)); - } - - if ((retval = pam_set_item(pamh, PAM_TTY, "sshd")) != PAM_SUCCESS) { - (void) pam_end(pamh, retval); - fatal("Could not set PAM_TTY item during %s userauth", - get_method_name(authctxt)); - } - - if (authctxt->cuser != NULL) - if ((retval = pam_set_item(pamh, PAM_AUSER, authctxt->cuser)) != PAM_SUCCESS) { - (void) pam_end(pamh, retval); - fatal("Could not set PAM_AUSER item during %s userauth", - get_method_name(authctxt)); - } - - authctxt->pam->h = pamh; -} - -/* - * To be called from userauth methods, directly (as in keyboard-interactive) or - * indirectly (from auth_pam_password() or from do_pam_non_initial_userauth(). - * - * The caller is responsible for calling new_start_pam() first. - * - * PAM state is not cleaned up here on error. This is left to subsequent calls - * to new_start_pam() or to the cleanup function upon authentication error. - */ -int -finish_userauth_do_pam(Authctxt *authctxt) -{ - int retval; - char *user, *method; - - /* Various checks; fail gracefully */ - if (authctxt == NULL || authctxt->pam == NULL) - return PAM_SYSTEM_ERR; /* shouldn't happen */ - - if (compat20) { - if (authctxt->method == NULL || authctxt->method->name == NULL) - return PAM_SYSTEM_ERR; /* shouldn't happen */ - method = authctxt->method->name; - } else if ((method = authctxt->v1_auth_name) == NULL) - return PAM_SYSTEM_ERR; /* shouldn't happen */ - - if (AUTHPAM_DONE(authctxt)) - return PAM_SYSTEM_ERR; /* shouldn't happen */ - - if (!(authctxt->pam->state & PAM_S_DONE_ACCT_MGMT)) { - retval = pam_acct_mgmt(authctxt->pam->h, 0); - authctxt->pam->last_pam_retval = retval; - if (retval == PAM_NEW_AUTHTOK_REQD) { - userauth_force_kbdint(); - return retval; - } - if (retval != PAM_SUCCESS) - return retval; - authctxt->pam->state |= PAM_S_DONE_ACCT_MGMT; - } - - /* - * Handle PAM_USER change, if any. - * - * We do this before pam_open_session() because we need the PAM_USER's - * UID for: - * - * a) PermitRootLogin checking - * b) to get at the lastlog entry before pam_open_session() updates it. - */ - retval = pam_get_item(authctxt->pam->h, PAM_USER, (void **) &user); - if (retval != PAM_SUCCESS) { - fatal("PAM failure: pam_get_item(PAM_USER) " - "returned %d: %.200s", retval, - PAM_STRERROR(authctxt->pam->h, retval)); - } - - if (user == NULL || *user == '\0') { - debug("PAM set NULL PAM_USER"); - return PAM_PERM_DENIED; - } - - if (strcmp(user, authctxt->user) != 0) { - log("PAM changed the SSH username"); - pwfree(&authctxt->pw); - authctxt->pw = getpwnamallow(user); - authctxt->valid = (authctxt->pw != NULL); - xfree(authctxt->user); - authctxt->user = xstrdup(user); - } - - if (!authctxt->valid) { - debug2("PAM set PAM_USER to unknown user"); - /* - * Return success, userauth_finish() will catch - * this and send back a failure message. - */ - return PAM_SUCCESS; - } - - /* Check PermitRootLogin semantics */ - if (authctxt->pw->pw_uid == 0 && !auth_root_allowed(method)) - return PAM_PERM_DENIED; - - if (!(authctxt->pam->state & PAM_S_DONE_SETCRED)) { - retval = pam_setcred(authctxt->pam->h, - PAM_ESTABLISH_CRED); - authctxt->pam->last_pam_retval = retval; - if (retval != PAM_SUCCESS) - return retval; - authctxt->pam->state |= PAM_S_DONE_SETCRED; - -#ifdef GSSAPI - /* - * Store GSS-API delegated creds after pam_setcred(), which may - * have set the current credential store. - */ - ssh_gssapi_storecreds(NULL, authctxt); -#endif /* GSSAPI */ - } - - /* - * On Solaris pam_unix_session.so updates the lastlog, but does - * not converse a PAM_TEXT_INFO message about it. So we need to - * fetch the lastlog entry here and save it for use later. - */ - authctxt->last_login_time = - get_last_login_time(authctxt->pw->pw_uid, - authctxt->pw->pw_name, - authctxt->last_login_host, - sizeof(authctxt->last_login_host)); - - if (!(authctxt->pam->state & PAM_S_DONE_OPEN_SESSION)) { - retval = pam_open_session(authctxt->pam->h, 0); - authctxt->pam->last_pam_retval = retval; - if (retval != PAM_SUCCESS) - return retval; - authctxt->pam->state |= PAM_S_DONE_OPEN_SESSION; - } - - /* - * All PAM work done successfully. - * - * PAM handle stays around so we can call pam_close_session() on - * it later. - */ - return PAM_SUCCESS; -} - -/* - * PAM conversation function for non-interactive userauth methods that - * really cannot do any prompting. Password userauth and CHANGEREQ can - * always set the PAM_AUTHTOK and PAM_OLDAUTHTOK items to avoid - * conversation (and if they do and nonetheless some module tries to - * converse, then password userauth / CHANGEREQ MUST fail). - * - * Except, PAM_TEXT_INFO and PAM_ERROR_MSG prompts can be squirelled - * away and shown to the user later. - * - * Keyboard-interactive userauth has its own much more interesting - * conversation function. - * - */ -static int -do_pam_conversation(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) -{ - struct pam_response *reply; - int count; - - /* PAM will free this later */ - reply = xmalloc(num_msg * sizeof(*reply)); - - (void) memset(reply, 0, num_msg * sizeof(*reply)); - - for (count = 0; count < num_msg; count++) { - /* - * We can't use stdio yet, queue messages for - * printing later - */ - switch(PAM_MSG_MEMBER(msg, count, msg_style)) { - case PAM_PROMPT_ECHO_ON: - xfree(reply); - return PAM_CONV_ERR; - case PAM_PROMPT_ECHO_OFF: - xfree(reply); - return PAM_CONV_ERR; - break; - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - if (PAM_MSG_MEMBER(msg, count, msg) != NULL) { - message_cat(&__pam_msg, - PAM_MSG_MEMBER(msg, count, msg)); - } - reply[count].resp = xstrdup(""); - reply[count].resp_retcode = PAM_SUCCESS; - break; - default: - xfree(reply); - return PAM_CONV_ERR; - } - } - - *resp = reply; - - return PAM_SUCCESS; -} - -/* Called at exit to cleanly shutdown PAM */ -static void -do_pam_cleanup_proc(void *context) -{ - int pam_retval; - pam_stuff *pam = (pam_stuff *) context; - - if (pam == NULL) - return; - - if (pam->authctxt != NULL && pam->authctxt->pam == pam) { - pam->authctxt->pam_retval = pam->last_pam_retval; - pam->authctxt->pam = NULL; - pam->authctxt = NULL; - } - - if (pam->h == NULL) - return; - - /* - * We're in fatal_cleanup() or not in userauth or without a - * channel -- can't converse now, too bad. - */ - pam_retval = pam_set_item(pam->h, PAM_CONV, NULL); - if (pam_retval != PAM_SUCCESS) { - log("Cannot remove PAM conv, close session or delete creds[%d]: %.200s", - pam_retval, PAM_STRERROR(pam->h, pam_retval)); - goto cleanup; - } - - if (pam->state & PAM_S_DONE_OPEN_SESSION) { - pam_retval = pam_close_session(pam->h, 0); - if (pam_retval != PAM_SUCCESS) - log("Cannot close PAM session[%d]: %.200s", - pam_retval, PAM_STRERROR(pam->h, pam_retval)); - } - - if (pam->state & PAM_S_DONE_SETCRED) { - pam_retval = pam_setcred(pam->h, PAM_DELETE_CRED); - if (pam_retval != PAM_SUCCESS) - debug("Cannot delete credentials[%d]: %.200s", - pam_retval, PAM_STRERROR(pam->h, pam_retval)); - } - -cleanup: - - /* Use the previous PAM result, if not PAM_SUCCESS for pam_end() */ - if (pam->last_pam_retval != PAM_SUCCESS) - pam_retval = pam_end(pam->h, pam->last_pam_retval); - else if (pam_retval != PAM_SUCCESS) - pam_retval = pam_end(pam->h, pam_retval); - else - pam_retval = pam_end(pam->h, PAM_ABORT); - - if (pam_retval != PAM_SUCCESS) - log("Cannot release PAM authentication[%d]: %.200s", - pam_retval, PAM_STRERROR(pam->h, pam_retval)); - - xfree(pam); -} - -/* Attempt password authentation using PAM */ -int -auth_pam_password(Authctxt *authctxt, const char *password) -{ - int retval; - - /* Ensure we have a fresh PAM handle / state */ - new_start_pam(authctxt, &conv); - - retval = pam_set_item(authctxt->pam->h, PAM_AUTHTOK, password); - if (retval != PAM_SUCCESS) { - authctxt->pam->last_pam_retval = retval; - return 1; - } - - retval = pam_authenticate(authctxt->pam->h, - options.permit_empty_passwd ? 0 : - PAM_DISALLOW_NULL_AUTHTOK); - - if (retval != PAM_SUCCESS) { - authctxt->pam->last_pam_retval = retval; - return 0; - } - - if ((retval = finish_userauth_do_pam(authctxt)) != PAM_SUCCESS) - return 0; - - if (authctxt->method) - authctxt->method->authenticated = 1; /* SSHv2 */ - - return 1; -} - -int -do_pam_non_initial_userauth(Authctxt *authctxt) -{ - new_start_pam(authctxt, NULL); - return (finish_userauth_do_pam(authctxt) == PAM_SUCCESS); -} - -/* Cleanly shutdown PAM */ -void finish_pam(Authctxt *authctxt) -{ - fatal_remove_cleanup(&do_pam_cleanup_proc, authctxt->pam); - do_pam_cleanup_proc(authctxt->pam); -} - -static -char ** -find_env(char **env, char *var) -{ - char **p; - int len; - - if (strchr(var, '=') == NULL) - len = strlen(var); - else - len = (strchr(var, '=') - var) + 1; - - for ( p = env ; p != NULL && *p != NULL ; p++ ) { - if (strncmp(*p, var, len) == 0) - return (p); - } - - return (NULL); -} - -/* Return list of PAM environment strings */ -char ** -fetch_pam_environment(Authctxt *authctxt) -{ -#ifdef HAVE_PAM_GETENVLIST - char **penv; - - if (authctxt == NULL || authctxt->pam == NULL || - authctxt->pam->h == NULL) - return (NULL); - - penv = pam_getenvlist(authctxt->pam->h); - - return (penv); -#else /* HAVE_PAM_GETENVLIST */ - return(NULL); -#endif /* HAVE_PAM_GETENVLIST */ -} - -void free_pam_environment(char **env) -{ - int i; - - if (env != NULL) { - for (i = 0; env[i] != NULL; i++) - xfree(env[i]); - } - - xfree(env); -} - -/* Print any messages that have been generated during authentication */ -/* or account checking to stderr */ -void print_pam_messages(void) -{ - if (__pam_msg != NULL) - (void) fputs(__pam_msg, stderr); -} - -/* Append a message to buffer */ -void message_cat(char **p, const char *a) -{ - char *cp; - size_t new_len; - - new_len = strlen(a); - - if (*p) { - size_t len = strlen(*p); - - *p = xrealloc(*p, new_len + len + 2); - cp = *p + len; - } else - *p = cp = xmalloc(new_len + 2); - - (void) memcpy(cp, a, new_len); - cp[new_len] = '\n'; - cp[new_len + 1] = '\0'; -} - -#endif /* USE_PAM */ diff --git a/usr/src/cmd/ssh/sshd/auth-passwd.c b/usr/src/cmd/ssh/sshd/auth-passwd.c deleted file mode 100644 index 815231d4d4..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-passwd.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Password authentication. This file contains the functions to check whether - * the password is valid for the user. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * Copyright (c) 1999 Dug Song. All rights reserved. - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $"); - -#include "packet.h" -#include "log.h" -#include "servconf.h" -#include "auth.h" - -#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA) -/* Don't need any of these headers for the PAM or SIA cases */ -# ifdef HAVE_CRYPT_H -# include <crypt.h> -# endif -# ifdef WITH_AIXAUTHENTICATE -# include <login.h> -# endif -# ifdef __hpux -# include <hpsecurity.h> -# include <prot.h> -# endif -# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) -# include <shadow.h> -# endif -# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) -# include <sys/label.h> -# include <sys/audit.h> -# include <pwdadj.h> -# endif -# if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) -# include "md5crypt.h" -# endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */ - -# ifdef HAVE_CYGWIN -# undef ERROR -# include <windows.h> -# include <sys/cygwin.h> -# define is_winnt (GetVersion() < 0x80000000) -# endif -#endif /* !USE_PAM && !HAVE_OSF_SIA */ - -extern ServerOptions options; -#ifdef WITH_AIXAUTHENTICATE -extern char *aixloginmsg; -#endif - -/* - * Tries to authenticate the user using password. Returns true if - * authentication succeeds. - */ -int -auth_password(Authctxt *authctxt, const char *password) -{ -#if defined(USE_PAM) - if (*password == '\0' && options.permit_empty_passwd == 0) - return 0; - return auth_pam_password(authctxt, password); -#elif defined(HAVE_OSF_SIA) - if (*password == '\0' && options.permit_empty_passwd == 0) - return 0; - return auth_sia_password(authctxt, password); -#else - struct passwd * pw = authctxt->pw; - char *encrypted_password; - char *pw_password; - char *salt; -#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) - struct spwd *spw; -#endif -#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) - struct passwd_adjunct *spw; -#endif -#ifdef WITH_AIXAUTHENTICATE - char *authmsg; - int authsuccess; - int reenter = 1; -#endif - - /* deny if no user. */ - if (pw == NULL) - return 0; -#ifndef HAVE_CYGWIN - if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) - return 0; -#endif - if (*password == '\0' && options.permit_empty_passwd == 0) - return 0; -#ifdef KRB5 - if (options.kerberos_authentication == 1) { - int ret = auth_krb5_password(authctxt, password); - if (ret == 1 || ret == 0) - return ret; - /* Fall back to ordinary passwd authentication. */ - } -#endif -#ifdef HAVE_CYGWIN - if (is_winnt) { - HANDLE hToken = cygwin_logon_user(pw, password); - - if (hToken == INVALID_HANDLE_VALUE) - return 0; - cygwin_set_impersonation_token(hToken); - return 1; - } -#endif -#ifdef WITH_AIXAUTHENTICATE - authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0); - - if (authsuccess) - /* We don't have a pty yet, so just label the line as "ssh" */ - if (loginsuccess(authctxt->user, - get_canonical_hostname(options.verify_reverse_mapping), - "ssh", &aixloginmsg) < 0) - aixloginmsg = NULL; - - return(authsuccess); -#endif -#ifdef KRB4 - if (options.kerberos_authentication == 1) { - int ret = auth_krb4_password(authctxt, password); - if (ret == 1 || ret == 0) - return ret; - /* Fall back to ordinary passwd authentication. */ - } -#endif -#ifdef BSD_AUTH - if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh", - (char *)password) == 0) - return 0; - else - return 1; -#endif - pw_password = pw->pw_passwd; - - /* - * Various interfaces to shadow or protected password data - */ -#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) - spw = getspnam(pw->pw_name); - if (spw != NULL) - pw_password = spw->sp_pwdp; -#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */ - -#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) - if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL) - pw_password = spw->pwa_passwd; -#endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */ - - /* Check for users with no password. */ - if ((password[0] == '\0') && (pw_password[0] == '\0')) - return 1; - - if (pw_password[0] != '\0') - salt = pw_password; - else - salt = "xx"; - -#ifdef HAVE_MD5_PASSWORDS - if (is_md5_salt(salt)) - encrypted_password = md5_crypt(password, salt); - else - encrypted_password = crypt(password, salt); -#else /* HAVE_MD5_PASSWORDS */ - encrypted_password = crypt(password, salt); -#endif /* HAVE_MD5_PASSWORDS */ - - /* Authentication is accepted if the encrypted passwords are identical. */ - return (strcmp(encrypted_password, pw_password) == 0); -#endif /* !USE_PAM && !HAVE_OSF_SIA */ -} diff --git a/usr/src/cmd/ssh/sshd/auth-rh-rsa.c b/usr/src/cmd/ssh/sshd/auth-rh-rsa.c deleted file mode 100644 index ab10e1738a..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-rh-rsa.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Rhosts or /etc/hosts.equiv authentication combined with RSA host - * authentication. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-rh-rsa.c,v 1.34 2002/03/25 09:25:06 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "packet.h" -#include "uidswap.h" -#include "log.h" -#include "servconf.h" -#include "key.h" -#include "hostfile.h" -#include "pathnames.h" -#include "auth.h" -#include "canohost.h" - -/* import */ -extern ServerOptions options; - -int -auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost, - Key *client_host_key) -{ - HostStatus host_status; - - /* Check if we would accept it using rhosts authentication. */ - if (!auth_rhosts(pw, cuser)) - return 0; - - host_status = check_key_in_hostfiles(pw, client_host_key, - chost, _PATH_SSH_SYSTEM_HOSTFILE, - options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); - - return (host_status == HOST_OK); -} - -/* - * Tries to authenticate the user using the .rhosts file and the host using - * its host key. Returns true if authentication succeeds. - */ -int -auth_rhosts_rsa(struct passwd *pw, char *cuser, Key *client_host_key) -{ - char *chost; - - debug("Trying rhosts with RSA host authentication for client user %.100s", - cuser); - - if (pw == NULL || client_host_key == NULL || - client_host_key->rsa == NULL) - return 0; - - chost = (char *)get_canonical_hostname(options.verify_reverse_mapping); - debug("Rhosts RSA authentication: canonical host %.900s", chost); - - if (!auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key)) { - debug("Rhosts with RSA host authentication denied: unknown or invalid host key"); - packet_send_debug("Your host key cannot be verified: unknown or invalid host key."); - return 0; - } - /* A matching host key was found and is known. */ - - /* Perform the challenge-response dialog with the client for the host key. */ - if (!auth_rsa_challenge_dialog(client_host_key)) { - log("Client on %.800s failed to respond correctly to host authentication.", - chost); - return 0; - } - /* - * We have authenticated the user using .rhosts or /etc/hosts.equiv, - * and the host using RSA. We accept the authentication. - */ - - verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.", - pw->pw_name, cuser, chost); - packet_send_debug("Rhosts with RSA host authentication accepted."); - return 1; -} diff --git a/usr/src/cmd/ssh/sshd/auth-rhosts.c b/usr/src/cmd/ssh/sshd/auth-rhosts.c deleted file mode 100644 index 2326eef8ae..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-rhosts.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Rhosts authentication. This file contains code to check whether to admit - * the login based on rhosts authentication. This file also processes - * /etc/hosts.equiv. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-rhosts.c,v 1.28 2002/05/13 21:26:49 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "packet.h" -#include "uidswap.h" -#include "pathnames.h" -#include "log.h" -#include "servconf.h" -#include "canohost.h" -#include "auth.h" - -/* import */ -extern ServerOptions options; - -/* - * This function processes an rhosts-style file (.rhosts, .shosts, or - * /etc/hosts.equiv). This returns true if authentication can be granted - * based on the file, and returns zero otherwise. - */ - -static int -check_rhosts_file(const char *filename, const char *hostname, - const char *ipaddr, const char *client_user, - const char *server_user) -{ - FILE *f; - char buf[1024]; /* Must not be larger than host, user, dummy below. */ - - /* Open the .rhosts file, deny if unreadable */ - f = fopen(filename, "r"); - if (!f) - return 0; - - while (fgets(buf, sizeof(buf), f)) { - /* All three must be at least as big as buf to avoid overflows. */ - char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp; - int negated; - - for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) - ; - if (*cp == '#' || *cp == '\n' || !*cp) - continue; - - /* - * NO_PLUS is supported at least on OSF/1. We skip it (we - * don't ever support the plus syntax). - */ - if (strncmp(cp, "NO_PLUS", 7) == 0) - continue; - - /* - * This should be safe because each buffer is as big as the - * whole string, and thus cannot be overwritten. - */ - switch (sscanf(buf, "%1024s %1024s %1024s", - hostbuf, userbuf, dummy)) { - case 0: - auth_debug_add("Found empty line in %.100s.", filename); - continue; - case 1: - /* Host name only. */ - strlcpy(userbuf, server_user, sizeof(userbuf)); - break; - case 2: - /* Got both host and user name. */ - break; - case 3: - auth_debug_add("Found garbage in %.100s.", filename); - continue; - default: - /* Weird... */ - continue; - } - - host = hostbuf; - user = userbuf; - negated = 0; - - /* Process negated host names, or positive netgroups. */ - if (host[0] == '-') { - negated = 1; - host++; - } else if (host[0] == '+') - host++; - - if (user[0] == '-') { - negated = 1; - user++; - } else if (user[0] == '+') - user++; - - /* Check for empty host/user names (particularly '+'). */ - if (!host[0] || !user[0]) { - /* We come here if either was '+' or '-'. */ - auth_debug_add("Ignoring wild host/user names in %.100s.", - filename); - continue; - } - /* Verify that host name matches. */ - if (host[0] == '@') { - if (!innetgr(host + 1, hostname, NULL, NULL) && - !innetgr(host + 1, ipaddr, NULL, NULL)) - continue; - } else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0) - continue; /* Different hostname. */ - - /* Verify that user name matches. */ - if (user[0] == '@') { - if (!innetgr(user + 1, NULL, client_user, NULL)) - continue; - } else if (strcmp(user, client_user) != 0) - continue; /* Different username. */ - - /* Found the user and host. */ - fclose(f); - - /* If the entry was negated, deny access. */ - if (negated) { - auth_debug_add("Matched negative entry in %.100s.", - filename); - return 0; - } - /* Accept authentication. */ - return 1; - } - - /* Authentication using this file denied. */ - fclose(f); - return 0; -} - -/* - * Tries to authenticate the user using the .shosts or .rhosts file. Returns - * true if authentication succeeds. If ignore_rhosts is true, only - * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored). - */ - -int -auth_rhosts(struct passwd *pw, const char *client_user) -{ - const char *hostname, *ipaddr; - - hostname = get_canonical_hostname(options.verify_reverse_mapping); - ipaddr = get_remote_ipaddr(); - return auth_rhosts2(pw, client_user, hostname, ipaddr); -} - -static int -auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname, - const char *ipaddr) -{ - char buf[1024]; - struct stat st; - static const char *rhosts_files[] = {".shosts", ".rhosts", NULL}; - u_int rhosts_file_index; - - debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s", - client_user, hostname, ipaddr); - - /* no user given */ - if (pw == NULL) - return 0; - - /* Switch to the user's uid. */ - temporarily_use_uid(pw); - /* - * Quick check: if the user has no .shosts or .rhosts files, return - * failure immediately without doing costly lookups from name - * servers. - */ - for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; - rhosts_file_index++) { - /* Check users .rhosts or .shosts. */ - snprintf(buf, sizeof buf, "%.500s/%.100s", - pw->pw_dir, rhosts_files[rhosts_file_index]); - if (stat(buf, &st) >= 0) - break; - } - /* Switch back to privileged uid. */ - restore_uid(); - - /* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */ - if (!rhosts_files[rhosts_file_index] && - stat(_PATH_RHOSTS_EQUIV, &st) < 0 && - stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) - return 0; - - /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */ - if (pw->pw_uid != 0) { - if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, - client_user, pw->pw_name)) { - auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.", - hostname, ipaddr); - return 1; - } - if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, - client_user, pw->pw_name)) { - auth_debug_add("Accepted for %.100s [%.100s] by %.100s.", - hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); - return 1; - } - } - /* - * Check that the home directory is owned by root or the user, and is - * not group or world writable. - */ - if (stat(pw->pw_dir, &st) < 0) { - log("Rhosts authentication refused for %.100s: " - "no home directory %.200s", pw->pw_name, pw->pw_dir); - auth_debug_add("Rhosts authentication refused for %.100s: " - "no home directory %.200s", pw->pw_name, pw->pw_dir); - return 0; - } - if (options.strict_modes && - ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { - log("Rhosts authentication refused for %.100s: " - "bad ownership or modes for home directory.", pw->pw_name); - auth_debug_add("Rhosts authentication refused for %.100s: " - "bad ownership or modes for home directory.", pw->pw_name); - return 0; - } - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - - /* Check all .rhosts files (currently .shosts and .rhosts). */ - for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; - rhosts_file_index++) { - /* Check users .rhosts or .shosts. */ - snprintf(buf, sizeof buf, "%.500s/%.100s", - pw->pw_dir, rhosts_files[rhosts_file_index]); - if (stat(buf, &st) < 0) - continue; - - /* - * Make sure that the file is either owned by the user or by - * root, and make sure it is not writable by anyone but the - * owner. This is to help avoid novices accidentally - * allowing access to their account by anyone. - */ - if (options.strict_modes && - ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { - log("Rhosts authentication refused for %.100s: bad modes for %.200s", - pw->pw_name, buf); - auth_debug_add("Bad file modes for %.200s", buf); - continue; - } - /* Check if we have been configured to ignore .rhosts and .shosts files. */ - if (options.ignore_rhosts) { - auth_debug_add("Server has been configured to ignore %.100s.", - rhosts_files[rhosts_file_index]); - continue; - } - /* Check if authentication is permitted by the file. */ - if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) { - auth_debug_add("Accepted by %.100s.", - rhosts_files[rhosts_file_index]); - /* Restore the privileged uid. */ - restore_uid(); - auth_debug_add("Accepted host %s ip %s client_user %s server_user %s", - hostname, ipaddr, client_user, pw->pw_name); - return 1; - } - } - - /* Restore the privileged uid. */ - restore_uid(); - return 0; -} - -int -auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, - const char *ipaddr) -{ - int ret; - - auth_debug_reset(); - ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr); - auth_debug_send(); - return ret; -} diff --git a/usr/src/cmd/ssh/sshd/auth-rsa.c b/usr/src/cmd/ssh/sshd/auth-rsa.c deleted file mode 100644 index 3e0e6ea50d..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-rsa.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * RSA-based authentication. This code determines whether to admit a login - * based on RSA authentication. This file also contains functions to check - * validity of the host key. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: auth-rsa.c,v 1.56 2002/06/10 16:53:06 stevesk Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/rsa.h> -#include <openssl/md5.h> - -#include "rsa.h" -#include "packet.h" -#include "xmalloc.h" -#include "ssh1.h" -#include "mpaux.h" -#include "uidswap.h" -#include "match.h" -#include "auth-options.h" -#include "pathnames.h" -#include "log.h" -#include "servconf.h" -#include "auth.h" -#include "hostfile.h" -#include "ssh.h" - -/* import */ -extern ServerOptions options; - -/* - * Session identifier that is used to bind key exchange and authentication - * responses to a particular session. - */ -extern u_char session_id[16]; - -/* - * The .ssh/authorized_keys file contains public keys, one per line, in the - * following format: - * options bits e n comment - * where bits, e and n are decimal numbers, - * and comment is any string of characters up to newline. The maximum - * length of a line is 8000 characters. See the documentation for a - * description of the options. - */ - -BIGNUM * -auth_rsa_generate_challenge(Key *key) -{ - BIGNUM *challenge; - BN_CTX *ctx; - - if ((challenge = BN_new()) == NULL) - fatal("auth_rsa_generate_challenge: BN_new() failed"); - /* Generate a random challenge. */ - BN_rand(challenge, 256, 0, 0); - if ((ctx = BN_CTX_new()) == NULL) - fatal("auth_rsa_generate_challenge: BN_CTX_new() failed"); - BN_mod(challenge, challenge, key->rsa->n, ctx); - BN_CTX_free(ctx); - - return challenge; -} - -int -auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) -{ - u_char buf[32], mdbuf[16]; - MD5_CTX md; - int len; - - /* don't allow short keys */ - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits", - BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); - return (0); - } - - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > 32) - fatal("auth_rsa_verify_response: bad challenge length %d", len); - memset(buf, 0, 32); - BN_bn2bin(challenge, buf + 32 - len); - MD5_Init(&md); - MD5_Update(&md, buf, 32); - MD5_Update(&md, session_id, 16); - MD5_Final(mdbuf, &md); - - /* Verify that the response is the original challenge. */ - if (memcmp(response, mdbuf, 16) != 0) { - /* Wrong answer. */ - return (0); - } - /* Correct answer. */ - return (1); -} - -/* - * Performs the RSA authentication challenge-response dialog with the client, - * and returns true (non-zero) if the client gave the correct answer to - * our challenge; returns zero if the client gives a wrong answer. - */ - -int -auth_rsa_challenge_dialog(Key *key) -{ - BIGNUM *challenge, *encrypted_challenge; - u_char response[16]; - int i, success; - - if ((encrypted_challenge = BN_new()) == NULL) - fatal("auth_rsa_challenge_dialog: BN_new() failed"); - - challenge = auth_rsa_generate_challenge(key); - - /* Encrypt the challenge with the public key. */ - rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); - - /* Send the encrypted challenge to the client. */ - packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); - packet_put_bignum(encrypted_challenge); - packet_send(); - BN_clear_free(encrypted_challenge); - packet_write_wait(); - - /* Wait for a response. */ - packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - response[i] = packet_get_char(); - packet_check_eom(); - - success = auth_rsa_verify_response(key, challenge, response); - BN_clear_free(challenge); - return (success); -} - -/* - * check if there's user key matching client_n, - * return key if login is allowed, NULL otherwise - */ - -int -auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) -{ - char line[8192], *file; - int allowed = 0; - u_int bits; - FILE *f; - u_long linenum = 0; - struct stat st; - Key *key; - - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - - /* The authorized keys. */ - file = authorized_keys_file(pw); - debug("trying public RSA key file %s", file); - - /* Fail quietly if file does not exist */ - if (stat(file, &st) < 0) { - /* Restore the privileged uid. */ - restore_uid(); - xfree(file); - return (0); - } - /* Open the file containing the authorized keys. */ - f = fopen(file, "r"); - if (!f) { - /* Restore the privileged uid. */ - restore_uid(); - xfree(file); - return (0); - } - if (options.strict_modes && - secure_filename(f, file, pw, line, sizeof(line)) != 0) { - xfree(file); - fclose(f); - log("Authentication refused: %s", line); - restore_uid(); - return (0); - } - - /* Flag indicating whether the key is allowed. */ - allowed = 0; - - key = key_new(KEY_RSA1); - - /* - * Go though the accepted keys, looking for the current key. If - * found, perform a challenge-response dialog to verify that the - * user really has the corresponding private key. - */ - while (fgets(line, sizeof(line), f)) { - char *cp; - char *options; - - linenum++; - - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; - - /* - * Check if there are options for this key, and if so, - * save their starting address and skip the option part - * for now. If there are no options, set the starting - * address to NULL. - */ - if (*cp < '0' || *cp > '9') { - int quoted = 0; - options = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - } else - options = NULL; - - /* Parse the key from the line. */ - if (hostfile_read_key(&cp, &bits, key) == 0) { - debug("%.100s, line %lu: non ssh1 key syntax", - file, linenum); - continue; - } - /* cp now points to the comment part. */ - - /* Check if the we have found the desired key (identified by its modulus). */ - if (BN_cmp(key->rsa->n, client_n) != 0) - continue; - - /* check the real bits */ - if (bits != BN_num_bits(key->rsa->n)) - log("Warning: %s, line %lu: keysize mismatch: " - "actual %d vs. announced %d.", - file, linenum, BN_num_bits(key->rsa->n), bits); - - /* We have found the desired key. */ - /* - * If our options do not allow this key to be used, - * do not send challenge. - */ - if (!auth_parse_options(pw, options, file, linenum)) - continue; - - /* break out, this key is allowed */ - allowed = 1; - break; - } - - /* Restore the privileged uid. */ - restore_uid(); - - /* Close the file. */ - xfree(file); - fclose(f); - - /* return key if allowed */ - if (allowed && rkey != NULL) - *rkey = key; - else - key_free(key); - return (allowed); -} - -/* - * Performs the RSA authentication dialog with the client. This returns - * 0 if the client could not be authenticated, and 1 if authentication was - * successful. This may exit if there is a serious protocol violation. - */ -int -auth_rsa(struct passwd *pw, BIGNUM *client_n) -{ - Key *key; - char *fp; - - /* no user given */ - if (pw == NULL) - return 0; - - if (!auth_rsa_key_allowed(pw, client_n, &key)) { - auth_clear_options(); - return (0); - } - - /* Perform the challenge-response dialog for this key. */ - if (!auth_rsa_challenge_dialog(key)) { - /* Wrong response. */ - verbose("Wrong response to RSA authentication challenge."); - packet_send_debug("Wrong response to RSA authentication challenge."); - /* - * Break out of the loop. Otherwise we might send - * another challenge and break the protocol. - */ - key_free(key); - return (0); - } - /* - * Correct response. The client has been successfully - * authenticated. Note that we have not yet processed the - * options; this will be reset if the options cause the - * authentication to be rejected. - */ - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(key), fp); - xfree(fp); - key_free(key); - - packet_send_debug("RSA authentication accepted."); - return (1); -} diff --git a/usr/src/cmd/ssh/sshd/auth-sia.c b/usr/src/cmd/ssh/sshd/auth-sia.c deleted file mode 100644 index 6afa02cf75..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-sia.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2002 Chris Adams. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef HAVE_OSF_SIA -#include "ssh.h" -#include "auth.h" -#include "auth-sia.h" -#include "log.h" -#include "servconf.h" -#include "canohost.h" - -#include <sia.h> -#include <siad.h> -#include <pwd.h> -#include <signal.h> -#include <setjmp.h> -#include <sys/resource.h> -#include <unistd.h> -#include <string.h> - -extern ServerOptions options; -extern int saved_argc; -extern char **saved_argv; - -extern int errno; - -int -auth_sia_password(Authctxt *authctxt, char *pass) -{ - int ret; - SIAENTITY *ent = NULL; - const char *host; - char *user = authctxt->user; - - host = get_canonical_hostname(options.verify_reverse_mapping); - - if (!user || !pass || pass[0] == '\0') - return(0); - - if (sia_ses_init(&ent, saved_argc, saved_argv, host, user, NULL, 0, - NULL) != SIASUCCESS) - return(0); - - if ((ret = sia_ses_authent(NULL, pass, ent)) != SIASUCCESS) { - error("Couldn't authenticate %s from %s", user, host); - if (ret & SIASTOP) - sia_ses_release(&ent); - return(0); - } - - sia_ses_release(&ent); - - return(1); -} - -void -session_setup_sia(char *user, char *tty) -{ - struct passwd *pw; - SIAENTITY *ent = NULL; - const char *host; - - host = get_canonical_hostname (options.verify_reverse_mapping); - - if (sia_ses_init(&ent, saved_argc, saved_argv, host, user, tty, 0, - NULL) != SIASUCCESS) { - fatal("sia_ses_init failed"); - } - - if ((pw = getpwnam(user)) == NULL) { - sia_ses_release(&ent); - fatal("getpwnam: no user: %s", user); - } - if (sia_make_entity_pwd(pw, ent) != SIASUCCESS) { - sia_ses_release(&ent); - fatal("sia_make_entity_pwd failed"); - } - - ent->authtype = SIA_A_NONE; - if (sia_ses_estab(sia_collect_trm, ent) != SIASUCCESS) { - fatal("Couldn't establish session for %s from %s", user, - host); - } - - if (setpriority(PRIO_PROCESS, 0, 0) == -1) { - sia_ses_release(&ent); - fatal("setpriority: %s", strerror (errno)); - } - - if (sia_ses_launch(sia_collect_trm, ent) != SIASUCCESS) { - fatal("Couldn't launch session for %s from %s", user, host); - } - - sia_ses_release(&ent); - - if (setreuid(geteuid(), geteuid()) < 0) { - fatal("setreuid: %s", strerror(errno)); - } -} - -#endif /* HAVE_OSF_SIA */ - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/ssh/sshd/auth-skey.c b/usr/src/cmd/ssh/sshd/auth-skey.c deleted file mode 100644 index 436f66aed8..0000000000 --- a/usr/src/cmd/ssh/sshd/auth-skey.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: auth-skey.c,v 1.20 2002/06/30 21:59:45 deraadt Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef SKEY - -#include <skey.h> - -#include "xmalloc.h" -#include "auth.h" - -static void * -skey_init_ctx(Authctxt *authctxt) -{ - return authctxt; -} - -int -skey_query(void *ctx, char **name, char **infotxt, - u_int* numprompts, char ***prompts, u_int **echo_on) -{ - Authctxt *authctxt = ctx; - char challenge[1024], *p; - int len; - struct skey skey; - - if (skeychallenge(&skey, authctxt->user, challenge) == -1) - return -1; - - *name = xstrdup(""); - *infotxt = xstrdup(""); - *numprompts = 1; - *prompts = xmalloc(*numprompts * sizeof(char *)); - *echo_on = xmalloc(*numprompts * sizeof(u_int)); - (*echo_on)[0] = 0; - - len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; - p = xmalloc(len); - strlcpy(p, challenge, len); - strlcat(p, SKEY_PROMPT, len); - (*prompts)[0] = p; - - return 0; -} - -int -skey_respond(void *ctx, u_int numresponses, char **responses) -{ - Authctxt *authctxt = ctx; - - if (authctxt->valid && - numresponses == 1 && - skey_haskey(authctxt->pw->pw_name) == 0 && - skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1) - return 0; - return -1; -} - -static void -skey_free_ctx(void *ctx) -{ - /* we don't have a special context */ -} - -KbdintDevice skey_device = { - "skey", - skey_init_ctx, - skey_query, - skey_respond, - skey_free_ctx -}; - -KbdintDevice mm_skey_device = { - "skey", - skey_init_ctx, - mm_skey_query, - mm_skey_respond, - skey_free_ctx -}; -#endif /* SKEY */ diff --git a/usr/src/cmd/ssh/sshd/auth.c b/usr/src/cmd/ssh/sshd/auth.c deleted file mode 100644 index 64e6959ecf..0000000000 --- a/usr/src/cmd/ssh/sshd/auth.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth.c,v 1.45 2002/09/20 18:41:29 stevesk Exp $"); - -#ifdef HAVE_LOGIN_H -#include <login.h> -#endif -#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) -#include <shadow.h> -#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */ - -#ifdef HAVE_LIBGEN_H -#include <libgen.h> -#endif - -#include "xmalloc.h" -#include "match.h" -#include "groupaccess.h" -#include "log.h" -#include "buffer.h" -#include "servconf.h" -#include "auth.h" -#include "auth-options.h" -#include "canohost.h" -#include "bufaux.h" -#include "uidswap.h" -#include "tildexpand.h" -#include "misc.h" -#include "bufaux.h" -#include "packet.h" -#include "channels.h" -#include "session.h" - -#ifdef HAVE_BSM -#include "bsmaudit.h" -#include <bsm/adt.h> -#endif /* HAVE_BSM */ - -/* import */ -extern ServerOptions options; - -/* Debugging messages */ -Buffer auth_debug; -int auth_debug_init; - -/* - * Check if the user is allowed to log in via ssh. If user is listed - * in DenyUsers or one of user's groups is listed in DenyGroups, false - * will be returned. If AllowUsers isn't empty and user isn't listed - * there, or if AllowGroups isn't empty and one of user's groups isn't - * listed there, false will be returned. - * If the user's shell is not executable, false will be returned. - * Otherwise true is returned. - */ -int -allowed_user(struct passwd * pw) -{ - struct stat st; - const char *hostname = NULL, *ipaddr = NULL; - char *shell; - int i; -#ifdef WITH_AIXAUTHENTICATE - char *loginmsg; -#endif /* WITH_AIXAUTHENTICATE */ -#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ - !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) - struct spwd *spw; - - /* Shouldn't be called if pw is NULL, but better safe than sorry... */ - if (!pw || !pw->pw_name) - return 0; - -#define DAY (24L * 60 * 60) /* 1 day in seconds */ - spw = getspnam(pw->pw_name); - if (spw != NULL) { - time_t today = time(NULL) / DAY; - debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" - " sp_max %d", (int)today, (int)spw->sp_expire, - (int)spw->sp_lstchg, (int)spw->sp_max); - - /* - * We assume account and password expiration occurs the - * day after the day specified. - */ - if (spw->sp_expire != -1 && today > spw->sp_expire) { - log("Account %.100s has expired", pw->pw_name); - return 0; - } - - if (spw->sp_lstchg == 0) { - log("User %.100s password has expired (root forced)", - pw->pw_name); - return 0; - } - - if (spw->sp_max != -1 && - today > spw->sp_lstchg + spw->sp_max) { - log("User %.100s password has expired (password aged)", - pw->pw_name); - return 0; - } - } -#else - /* Shouldn't be called if pw is NULL, but better safe than sorry... */ - if (!pw || !pw->pw_name) - return 0; -#endif - - /* - * Get the shell from the password data. An empty shell field is - * legal, and means /bin/sh. - */ - shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; - - /* deny if shell does not exists or is not executable */ - if (stat(shell, &st) != 0) { - log("User %.100s not allowed because shell %.100s does not exist", - pw->pw_name, shell); - return 0; - } - if (S_ISREG(st.st_mode) == 0 || - (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { - log("User %.100s not allowed because shell %.100s is not executable", - pw->pw_name, shell); - return 0; - } - - if (options.num_deny_users > 0 || options.num_allow_users > 0) { - hostname = get_canonical_hostname(options.verify_reverse_mapping); - ipaddr = get_remote_ipaddr(); - } - - /* Return false if user is listed in DenyUsers */ - if (options.num_deny_users > 0) { - for (i = 0; i < options.num_deny_users; i++) - if (match_user(pw->pw_name, hostname, ipaddr, - options.deny_users[i])) { - log("User %.100s not allowed because listed in DenyUsers", - pw->pw_name); - return 0; - } - } - /* Return false if AllowUsers isn't empty and user isn't listed there */ - if (options.num_allow_users > 0) { - for (i = 0; i < options.num_allow_users; i++) - if (match_user(pw->pw_name, hostname, ipaddr, - options.allow_users[i])) - break; - /* i < options.num_allow_users iff we break for loop */ - if (i >= options.num_allow_users) { - log("User %.100s not allowed because not listed in AllowUsers", - pw->pw_name); - return 0; - } - } - if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { - /* Get the user's group access list (primary and supplementary) */ - if (ga_init(pw->pw_name, pw->pw_gid) == 0) { - log("User %.100s not allowed because not in any group", - pw->pw_name); - return 0; - } - - /* Return false if one of user's groups is listed in DenyGroups */ - if (options.num_deny_groups > 0) - if (ga_match(options.deny_groups, - options.num_deny_groups)) { - ga_free(); - log("User %.100s not allowed because a group is listed in DenyGroups", - pw->pw_name); - return 0; - } - /* - * Return false if AllowGroups isn't empty and one of user's groups - * isn't listed there - */ - if (options.num_allow_groups > 0) - if (!ga_match(options.allow_groups, - options.num_allow_groups)) { - ga_free(); - log("User %.100s not allowed because none of user's groups are listed in AllowGroups", - pw->pw_name); - return 0; - } - ga_free(); - } - -#ifdef WITH_AIXAUTHENTICATE - if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) { - if (loginmsg && *loginmsg) { - /* Remove embedded newlines (if any) */ - char *p; - for (p = loginmsg; *p; p++) { - if (*p == '\n') - *p = ' '; - } - /* Remove trailing newline */ - *--p = '\0'; - log("Login restricted for %s: %.100s", pw->pw_name, loginmsg); - } - return 0; - } -#endif /* WITH_AIXAUTHENTICATE */ - - /* We found no reason not to let this user try to log on... */ - return 1; -} - -Authctxt * -authctxt_new(void) -{ - Authctxt *authctxt = xmalloc(sizeof(*authctxt)); - memset(authctxt, 0, sizeof(*authctxt)); - return authctxt; -} - -void -auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) -{ - void (*authlog) (const char *fmt,...) = verbose; - char *authmsg, *user_str; - - if (authctxt == NULL) - fatal("%s: INTERNAL ERROR", __func__); - - /* Raise logging level */ - if (authenticated == 1 || !authctxt->valid) - authlog = log; - else if (authctxt->failures >= AUTH_FAIL_LOG || - authctxt->attempt >= options.max_auth_tries_log || - authctxt->init_attempt >= options.max_init_auth_tries_log) - authlog = notice; - - if (authctxt->method) { - authmsg = "Failed"; - if (authctxt->method->postponed) - authmsg = "Postponed"; /* shouldn't happen */ - if (authctxt->method->abandoned) - authmsg = "Abandoned"; - if (authctxt->method->authenticated) { - if (userauth_check_partial_failure(authctxt)) - authmsg = "Partially accepted"; - else - authmsg = "Accepted"; - } - else - authmsg = "Failed"; - } - else { - authmsg = authenticated ? "Accepted" : "Failed"; - } - - if (authctxt->user == NULL || *authctxt->user == '\0') - user_str = "<implicit>"; - else if (!authctxt->valid) - user_str = "<invalid username>"; - else - user_str = authctxt->user; - - authlog("%s %s for %s from %.200s port %d%s", - authmsg, - (method != NULL) ? method : "<unknown authentication method>", - user_str, - get_remote_ipaddr(), - get_remote_port(), - info); - -#ifdef WITH_AIXAUTHENTICATE - if (authenticated == 0 && strcmp(method, "password") == 0) - loginfailed(authctxt->user, - get_canonical_hostname(options.verify_reverse_mapping), - "ssh"); -#endif /* WITH_AIXAUTHENTICATE */ - -} - -#ifdef HAVE_BSM -void -audit_failed_login_cleanup(void *ctxt) -{ - Authctxt *authctxt = (Authctxt *)ctxt; - adt_session_data_t *ah; - - /* - * This table lists the different variable combinations evaluated and - * what the resulting PAM return value is. As the table shows - * authctxt and authctxt->valid need to be checked before either of - * the authctxt->pam* variables. - * - * authctxt-> authctxt-> - * authctxt valid authctxt->pam pam_retval PAM rval - * -------- ---------- ------------- ------------ -------- - * NULL ANY ANY ANY PAM_ABORT - * OK zero (0) ANY ANY PAM_USER_UNKNOWN - * OK one (1) NULL PAM_SUCCESS PAM_PERM_DENIED - * OK one (1) NULL !PAM_SUCCESS authctxt-> - * pam_retval - * OK one (1) VALID ANY authctxt-> - * pam_retval (+) - * (+) If not set then default to PAM_PERM_DENIED - */ - - if (authctxt == NULL) { - /* Internal error */ - audit_sshd_login_failure(&ah, PAM_ABORT, NULL); - return; - } - - if (authctxt->valid == 0) { - audit_sshd_login_failure(&ah, PAM_USER_UNKNOWN, NULL); - } else if (authctxt->pam == NULL) { - if (authctxt->pam_retval == PAM_SUCCESS) { - audit_sshd_login_failure(&ah, PAM_PERM_DENIED, - authctxt->user); - } else { - audit_sshd_login_failure(&ah, authctxt->pam_retval, - authctxt->user); - } - } else { - audit_sshd_login_failure(&ah, AUTHPAM_ERROR(authctxt, - PAM_PERM_DENIED), authctxt->user); - } -} -#endif /* HAVE_BSM */ - -/* - * Check whether root logins are disallowed. - */ -int -auth_root_allowed(char *method) -{ - switch (options.permit_root_login) { - case PERMIT_YES: - return 1; - break; - case PERMIT_NO_PASSWD: - if (strcmp(method, "password") != 0 && - strcmp(method, "keyboard-interactive") != 0) - return 1; - break; - case PERMIT_FORCED_ONLY: - if (forced_command) { - log("Root login accepted for forced command."); - return 1; - } - break; - } - log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); - return 0; -} - - -/* - * Given a template and a passwd structure, build a filename - * by substituting % tokenised options. Currently, %% becomes '%', - * %h becomes the home directory and %u the username. - * - * This returns a buffer allocated by xmalloc. - */ -char * -expand_filename(const char *filename, struct passwd *pw) -{ - Buffer buffer; - char *file; - const char *cp; - - if (pw == 0) - return NULL; /* shouldn't happen */ - /* - * Build the filename string in the buffer by making the appropriate - * substitutions to the given file name. - */ - buffer_init(&buffer); - for (cp = filename; *cp; cp++) { - if (cp[0] == '%' && cp[1] == '%') { - buffer_append(&buffer, "%", 1); - cp++; - continue; - } - if (cp[0] == '%' && cp[1] == 'h') { - buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir)); - cp++; - continue; - } - if (cp[0] == '%' && cp[1] == 'u') { - buffer_append(&buffer, pw->pw_name, - strlen(pw->pw_name)); - cp++; - continue; - } - buffer_append(&buffer, cp, 1); - } - buffer_append(&buffer, "\0", 1); - - /* - * Ensure that filename starts anchored. If not, be backward - * compatible and prepend the '%h/' - */ - file = xmalloc(MAXPATHLEN); - cp = buffer_ptr(&buffer); - if (*cp != '/') - snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp); - else - strlcpy(file, cp, MAXPATHLEN); - - buffer_free(&buffer); - return file; -} - -char * -authorized_keys_file(struct passwd *pw) -{ - return expand_filename(options.authorized_keys_file, pw); -} - -char * -authorized_keys_file2(struct passwd *pw) -{ - return expand_filename(options.authorized_keys_file2, pw); -} - -/* return ok if key exists in sysfile or userfile */ -HostStatus -check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, - const char *sysfile, const char *userfile) -{ - Key *found; - char *user_hostfile; - struct stat st; - HostStatus host_status; - - /* Check if we know the host and its host key. */ - found = key_new(key->type); - host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); - - if (host_status != HOST_OK && userfile != NULL) { - user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); - if (options.strict_modes && - (stat(user_hostfile, &st) == 0) && - ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { - log("Authentication refused for %.100s: " - "bad owner or modes for %.200s", - pw->pw_name, user_hostfile); - } else { - temporarily_use_uid(pw); - host_status = check_host_in_hostfile(user_hostfile, - host, key, found, NULL); - restore_uid(); - } - xfree(user_hostfile); - } - key_free(found); - - debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ? - "ok" : "not found", host); - return host_status; -} - - -/* - * Check a given file for security. This is defined as all components - * of the path to the file must be owned by either the owner of - * of the file or root and no directories must be group or world writable. - * - * XXX Should any specific check be done for sym links ? - * - * Takes an open file descriptor, the file name, a uid and and - * error buffer plus max size as arguments. - * - * Returns 0 on success and -1 on failure - */ -int -secure_filename(FILE *f, const char *file, struct passwd *pw, - char *err, size_t errlen) -{ - uid_t uid; - char buf[MAXPATHLEN], homedir[MAXPATHLEN]; - char *cp; - int comparehome = 0; - struct stat st; - - if (pw == NULL) - return 0; - - uid = pw->pw_uid; - - if (realpath(file, buf) == NULL) { - snprintf(err, errlen, "realpath %s failed: %s", file, - strerror(errno)); - return -1; - } - - /* - * A user is not required to have all the files that are subject to - * the strict mode checking in his/her home directory. If the - * directory is not present at the moment, which might be the case if - * the directory is not mounted until the user is authenticated, do - * not perform the home directory check below. - */ - if (realpath(pw->pw_dir, homedir) != NULL) - comparehome = 1; - - /* check the open file to avoid races */ - if (fstat(fileno(f), &st) < 0 || - (st.st_uid != 0 && st.st_uid != uid) || - (st.st_mode & 022) != 0) { - snprintf(err, errlen, "bad ownership or modes for file %s", - buf); - return -1; - } - - /* for each component of the canonical path, walking upwards */ - for (;;) { - if ((cp = dirname(buf)) == NULL) { - snprintf(err, errlen, "dirname() failed"); - return -1; - } - strlcpy(buf, cp, sizeof(buf)); - - debug3("secure_filename: checking '%s'", buf); - if (stat(buf, &st) < 0 || - (st.st_uid != 0 && st.st_uid != uid) || - (st.st_mode & 022) != 0) { - snprintf(err, errlen, - "bad ownership or modes for directory %s", buf); - return -1; - } - - /* If we passed the homedir then we can stop. */ - if (comparehome && strcmp(homedir, buf) == 0) { - debug3("secure_filename: terminating check at '%s'", - buf); - break; - } - /* - * dirname should always complete with a "/" path, - * but we can be paranoid and check for "." too - */ - if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) - break; - } - return 0; -} - -struct passwd * -getpwnamallow(const char *user) -{ -#ifdef HAVE_LOGIN_CAP - extern login_cap_t *lc; -#ifdef BSD_AUTH - auth_session_t *as; -#endif -#endif - struct passwd *pw; - - if (user == NULL || *user == '\0') - return (NULL); /* implicit user, will be set later */ - - parse_server_match_config(&options, user, - get_canonical_hostname(options.verify_reverse_mapping), get_remote_ipaddr()); - - pw = getpwnam(user); - if (pw == NULL) { - log("Illegal user %.100s from %.100s", - user, get_remote_ipaddr()); - return (NULL); - } - if (!allowed_user(pw)) - return (NULL); -#ifdef HAVE_LOGIN_CAP - if ((lc = login_getclass(pw->pw_class)) == NULL) { - debug("unable to get login class: %s", user); - return (NULL); - } -#ifdef BSD_AUTH - if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || - auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { - debug("Approval failure for %s", user); - pw = NULL; - } - if (as != NULL) - auth_close(as); -#endif -#endif - if (pw != NULL) - return (pwcopy(pw)); - return (NULL); -} - - -/* - * The fatal_cleanup method to kill the hook. Since hook has been put into - * new process group all descendants will be killed as well. - */ -static void -kill_hook(void *arg) -{ - pid_t pid; - - pid = *(pid_t*)arg; - debug("killing hook and all it's children, process group: %ld", pid); - xfree(arg); - (void)killpg(pid, SIGTERM); -} - -/* - * Runs the PreUserauthHook. - * Returns -1 on execution error or the exit code of the hook if execution is - * successful. - */ -int -run_auth_hook(const char *path, const char *user, const char *method) -{ - struct stat st; - int i, status, ret = 1; - u_int envsize, argsize; - char buf[256]; - char **env, **args; - pid_t pid, *ppid; - - if (path == NULL || user == NULL || method == NULL) { - return (-1); - } - - /* Initialize the environment/arguments for the hook. */ - envsize = 4; /* 3 env vars + EndOfList marker */ - argsize = 4; /* 2 args + exe name + EndOfList marker */ - env = xmalloc(envsize * sizeof (char *)); - args = xmalloc(argsize * sizeof (char *)); - env[0] = NULL; - - /* we use the SSH env handling scheme */ - child_set_env_silent(&env, &envsize, "PATH", "/usr/bin:/bin"); - child_set_env_silent(&env, &envsize, "IFS", " \t\n"); - - (void) snprintf(buf, sizeof (buf), "%.50s %d %.50s %d", - get_remote_ipaddr(), get_remote_port(), - get_local_ipaddr(packet_get_connection_in()), get_local_port()); - child_set_env_silent(&env, &envsize, "SSH_CONNECTION", buf); - - args[0] = xstrdup(path); - args[1] = xstrdup(method); - args[2] = xstrdup(user); - args[3] = NULL; - - /* - * sanity checks - * note: the checks do not make sure that the file checked is actually - * the same which is executed. However, in this case it shouldn't be a - * major issue since the hook is rather static and the worst case would - * be an uncorrect message in the log or a hook is run even though the - * permissions are not right. - */ - - /* check if script does exist */ - if (stat(path, &st) < 0) { - log("Error executing PreUserauthHook \"%s\": %s", path, - strerror(errno)); - goto cleanup; - } - - /* Check correct permissions for script (uid of SSHD, mode 500) */ - if (st.st_uid != getuid() || ((st.st_mode & 0777) != 0500)) { - log("PreUserauthHook has invalid permissions (should be 500, is" - " %o) or ownership (should be %d, is %d)", - (uint) st.st_mode & 0777, getuid(), st.st_uid); - goto cleanup; - } - - if ((pid = fork()) == 0) { - /* - * We put the hook and all its (possible) descendants into - * a new process group so that in case of a hanging hook - * we can wipe out the whole "family". - */ - if (setpgid(0, 0) != 0) { - log("setpgid: %s", strerror(errno)); - _exit(255); - } - (void) execve(path, args, env); - /* child is gone so we shouldn't get here */ - log("Error executing PreUserauthHook \"%s\": %s", path, - strerror(errno)); - _exit(255); - } else if (pid == -1) { - log("Error executing PreUserauthHook \"%s\": %s", path, - strerror(errno)); - goto cleanup; - } - - /* make preparations to kill hook if it is hanging */ - ppid = xmalloc(sizeof (pid_t)); - *ppid = pid; - fatal_add_cleanup((void (*)(void *))kill_hook, (void *) ppid); - - if (waitpid(pid, &status, 0) == -1) { - log("Error executing PreUserauthHook \"%s\": %s", path, - strerror(errno)); - goto cleanup; - } - - ret = WEXITSTATUS(status); - - if (ret == 255) { - ret = -1; /* execve() failed, error msg already logged */ - } else if (ret != 0) { - log("PreUserauthHook \"%s\" failed with exit code %d", - path, ret); - } else { - debug("PreUserauthHook \"%s\" finished successfully", path); - } - -cleanup: - for (i = 0; args[i] != NULL; i++) { - xfree(args[i]); - } - for (i = 0; env[i] != NULL; i++) { - xfree(env[i]); - } - xfree(args); - xfree(env); - - fatal_remove_cleanup((void (*)(void *))kill_hook, (void *) ppid); - - return (ret); -} - -void -auth_debug_add(const char *fmt,...) -{ - char buf[1024]; - va_list args; - - if (!auth_debug_init) - return; - - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - buffer_put_cstring(&auth_debug, buf); -} - -void -auth_debug_send(void) -{ - char *msg; - - if (!auth_debug_init) - return; - while (buffer_len(&auth_debug)) { - msg = buffer_get_string(&auth_debug, NULL); - packet_send_debug("%s", msg); - xfree(msg); - } -} - -void -auth_debug_reset(void) -{ - if (auth_debug_init) - buffer_clear(&auth_debug); - else { - buffer_init(&auth_debug); - auth_debug_init = 1; - } -} diff --git a/usr/src/cmd/ssh/sshd/auth1.c b/usr/src/cmd/ssh/sshd/auth1.c deleted file mode 100644 index e77a021393..0000000000 --- a/usr/src/cmd/ssh/sshd/auth1.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth1.c,v 1.44 2002/09/26 11:38:43 markus Exp $"); - -#include "xmalloc.h" -#include "rsa.h" -#include "ssh1.h" -#include "packet.h" -#include "buffer.h" -#include "mpaux.h" -#include "log.h" -#include "servconf.h" -#include "compat.h" -#include "auth.h" -#include "channels.h" -#include "session.h" -#include "uidswap.h" - -#ifdef HAVE_BSM -#include "bsmaudit.h" -extern adt_session_data_t *ah; -#endif /* HAVE_BSM */ - -/* import */ -extern ServerOptions options; - -/* - * convert ssh auth msg type into description - */ -static char * -get_authname(int type) -{ - static char buf[1024]; - switch (type) { - case SSH_CMSG_AUTH_PASSWORD: - return "password"; - case SSH_CMSG_AUTH_RSA: - return "rsa"; - case SSH_CMSG_AUTH_RHOSTS_RSA: - return "rhosts-rsa"; - case SSH_CMSG_AUTH_RHOSTS: - return "rhosts"; - case SSH_CMSG_AUTH_TIS: - case SSH_CMSG_AUTH_TIS_RESPONSE: - return "challenge-response"; -#if defined(KRB4) || defined(KRB5) - case SSH_CMSG_AUTH_KERBEROS: - return "kerberos"; -#endif - } - snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); - return buf; -} - -/* - * read packets, try to authenticate the user and - * return only if authentication is successful - */ -static void -do_authloop(Authctxt *authctxt) -{ - int authenticated = 0; - u_int bits; - Key *client_host_key; - BIGNUM *n; - char *client_user, *password; - char info[1024]; - u_int dlen; - u_int ulen; - int type = 0; - struct passwd *pw = authctxt->pw; - - debug("Attempting authentication for %s%.100s.", - authctxt->valid ? "" : "illegal user ", authctxt->user); - - /* If the user has no password, accept authentication immediately. */ - if (options.password_authentication && -#if defined(KRB4) || defined(KRB5) - (!options.kerberos_authentication || options.kerberos_or_local_passwd) && -#endif - auth_password(authctxt, "")) { - auth_log(authctxt, 1, "without authentication", ""); - return; - } - - /* Indicate that authentication is needed. */ - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - - client_user = NULL; - - for ( ;; ) { - /* default to fail */ - authenticated = 0; - - info[0] = '\0'; - - /* Get a packet from the client. */ - authctxt->v1_auth_type = type = packet_read(); - authctxt->v1_auth_name = get_authname(type); - - authctxt->attempt++; - - /* Process the packet. */ - switch (type) { - -#if defined(KRB4) || defined(KRB5) - case SSH_CMSG_AUTH_KERBEROS: - if (!options.kerberos_authentication) { - verbose("Kerberos authentication disabled."); - } else { - char *kdata = packet_get_string(&dlen); - packet_check_eom(); - - if (kdata[0] == 4) { /* KRB_PROT_VERSION */ -#ifdef KRB4 - KTEXT_ST tkt, reply; - tkt.length = dlen; - if (tkt.length < MAX_KTXT_LEN) - memcpy(tkt.dat, kdata, tkt.length); - - if (auth_krb4(authctxt, &tkt, - &client_user, &reply)) { - authenticated = 1; - snprintf(info, sizeof(info), - " tktuser %.100s", - client_user); - - packet_start( - SSH_SMSG_AUTH_KERBEROS_RESPONSE); - packet_put_string((char *) - reply.dat, reply.length); - packet_send(); - packet_write_wait(); - } -#endif /* KRB4 */ - } else { -#ifdef KRB5 - krb5_data tkt, reply; - tkt.length = dlen; - tkt.data = kdata; - - if (auth_krb5(authctxt, &tkt, - &client_user, &reply)) { - authenticated = 1; - snprintf(info, sizeof(info), - " tktuser %.100s", - client_user); - - /* Send response to client */ - packet_start( - SSH_SMSG_AUTH_KERBEROS_RESPONSE); - packet_put_string((char *) - reply.data, reply.length); - packet_send(); - packet_write_wait(); - - if (reply.length) - xfree(reply.data); - } -#endif /* KRB5 */ - } - xfree(kdata); - } - break; -#endif /* KRB4 || KRB5 */ - -#if defined(AFS) || defined(KRB5) - /* XXX - punt on backward compatibility here. */ - case SSH_CMSG_HAVE_KERBEROS_TGT: - packet_send_debug("Kerberos TGT passing disabled before authentication."); - break; -#ifdef AFS - case SSH_CMSG_HAVE_AFS_TOKEN: - packet_send_debug("AFS token passing disabled before authentication."); - break; -#endif /* AFS */ -#endif /* AFS || KRB5 */ - - case SSH_CMSG_AUTH_RHOSTS: - if (!options.rhosts_authentication) { - verbose("Rhosts authentication disabled."); - break; - } - /* - * Get client user name. Note that we just have to - * trust the client; this is one reason why rhosts - * authentication is insecure. (Another is - * IP-spoofing on a local network.) - */ - client_user = packet_get_string(&ulen); - packet_check_eom(); - - /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ - authenticated = auth_rhosts(pw, client_user); - - snprintf(info, sizeof info, " ruser %.100s", client_user); - break; - - case SSH_CMSG_AUTH_RHOSTS_RSA: - if (!options.rhosts_rsa_authentication) { - verbose("Rhosts with RSA authentication disabled."); - break; - } - /* - * Get client user name. Note that we just have to - * trust the client; root on the client machine can - * claim to be any user. - */ - client_user = packet_get_string(&ulen); - - /* Get the client host key. */ - client_host_key = key_new(KEY_RSA1); - bits = packet_get_int(); - packet_get_bignum(client_host_key->rsa->e); - packet_get_bignum(client_host_key->rsa->n); - - if (bits != BN_num_bits(client_host_key->rsa->n)) - verbose("Warning: keysize mismatch for client_host_key: " - "actual %d, announced %d", - BN_num_bits(client_host_key->rsa->n), bits); - packet_check_eom(); - - authenticated = auth_rhosts_rsa(pw, client_user, - client_host_key); - key_free(client_host_key); - - snprintf(info, sizeof info, " ruser %.100s", client_user); - break; - - case SSH_CMSG_AUTH_RSA: - if (!options.rsa_authentication) { - verbose("RSA authentication disabled."); - break; - } - /* RSA authentication requested. */ - if ((n = BN_new()) == NULL) - fatal("do_authloop: BN_new failed"); - packet_get_bignum(n); - packet_check_eom(); - authenticated = auth_rsa(pw, n); - BN_clear_free(n); - break; - - case SSH_CMSG_AUTH_PASSWORD: - authctxt->init_attempt++; - - if (!options.password_authentication) { - verbose("Password authentication disabled."); - break; - } - /* - * Read user password. It is in plain text, but was - * transmitted over the encrypted channel so it is - * not visible to an outside observer. - */ - password = packet_get_string(&dlen); - packet_check_eom(); - - /* Try authentication with the password. */ - if (authctxt->init_failures < - options.max_init_auth_tries) - authenticated = - auth_password(authctxt, password); - - memset(password, 0, strlen(password)); - xfree(password); - break; - - case SSH_CMSG_AUTH_TIS: - debug("rcvd SSH_CMSG_AUTH_TIS"); - if (options.challenge_response_authentication == 1) { - char *challenge = get_challenge(authctxt); - if (challenge != NULL) { - debug("sending challenge '%s'", challenge); - packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); - packet_put_cstring(challenge); - xfree(challenge); - packet_send(); - packet_write_wait(); - continue; - } - } - break; - case SSH_CMSG_AUTH_TIS_RESPONSE: - debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); - if (options.challenge_response_authentication == 1) { - char *response = packet_get_string(&dlen); - debug("got response '%s'", response); - packet_check_eom(); - authenticated = verify_response(authctxt, response); - memset(response, 'r', dlen); - xfree(response); - } - break; - - default: - /* - * Any unknown messages will be ignored (and failure - * returned) during authentication. - */ - log("Unknown message during authentication: type %d", type); - break; - } -#ifdef BSD_AUTH - if (authctxt->as) { - auth_close(authctxt->as); - authctxt->as = NULL; - } -#endif - if (!authctxt->valid && authenticated) { - authenticated = 0; - log("Ignoring authenticated invalid user %s", - authctxt->user); - } - -#ifdef _UNICOS - if (type == SSH_CMSG_AUTH_PASSWORD && !authenticated) - cray_login_failure(authctxt->user, IA_UDBERR); - if (authenticated && cray_access_denied(authctxt->user)) { - authenticated = 0; - fatal("Access denied for user %s.",authctxt->user); - } -#endif /* _UNICOS */ - -#ifdef HAVE_CYGWIN - if (authenticated && - !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) { - packet_disconnect("Authentication rejected for uid %d.", - pw == NULL ? -1 : pw->pw_uid); - authenticated = 0; - } -#else - /* Special handling for root */ - if (authenticated && authctxt->pw->pw_uid == 0 && - !auth_root_allowed(get_authname(type))) - authenticated = 0; -#endif -#ifdef USE_PAM - if (authenticated && type != SSH_CMSG_AUTH_PASSWORD) - authenticated = do_pam_non_initial_userauth(authctxt); - else if (authenticated && !AUTHPAM_DONE(authctxt)) - authenticated = 0; - - if (!authenticated) - authctxt->pam_retval = AUTHPAM_ERROR(authctxt, - PAM_PERM_DENIED); -#endif /* USE_PAM */ - - /* Log before sending the reply */ - auth_log(authctxt, authenticated, get_authname(type), info); - - if (client_user != NULL) { - xfree(client_user); - client_user = NULL; - } - - if (authenticated) - return; - - if (type == SSH_CMSG_AUTH_PASSWORD) - authctxt->init_failures++; - - if (authctxt->failures++ > options.max_auth_tries) { -#ifdef HAVE_BSM - fatal_remove_cleanup(audit_failed_login_cleanup, - authctxt); - audit_sshd_login_failure(&ah, PAM_MAXTRIES, - authctxt->user); -#endif /* HAVE_BSM */ - packet_disconnect(AUTH_FAIL_MSG, authctxt->user); - } - - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - } -} - -/* - * Performs authentication of an incoming connection. Session key has already - * been exchanged and encryption is enabled. - */ -Authctxt * -do_authentication(void) -{ - Authctxt *authctxt; - u_int ulen; - char *user, *style = NULL; - - /* Get the name of the user that we wish to log in as. */ - packet_read_expect(SSH_CMSG_USER); - - /* Get the user name. */ - user = packet_get_string(&ulen); - packet_check_eom(); - - if ((style = strchr(user, ':')) != NULL) - *style++ = '\0'; - -#ifdef KRB5 - /* XXX - SSH.com Kerberos v5 braindeath. */ - if ((datafellows & SSH_BUG_K5USER) && - options.kerberos_authentication) { - char *p; - if ((p = strchr(user, '@')) != NULL) - *p = '\0'; - } -#endif - - authctxt = authctxt_new(); - authctxt->user = user; - authctxt->style = style; - -#ifdef HAVE_BSM - fatal_add_cleanup(audit_failed_login_cleanup, authctxt); -#endif /* HAVE_BSM */ - - /* Verify that the user is a valid user. */ - if ((authctxt->pw = getpwnamallow(user)) != NULL) { - authctxt->valid = 1; - } else { - authctxt->valid = 0; - debug("do_authentication: illegal user %s", user); - } - - setproctitle("%s", authctxt->pw ? user : "unknown"); - - /* - * If we are not running as root, the user must have the same uid as - * the server. (Unless you are running Windows) - */ -#ifndef HAVE_CYGWIN - if (getuid() != 0 && authctxt->pw && - authctxt->pw->pw_uid != getuid()) - packet_disconnect("Cannot change user when server not running as root."); -#endif - - /* - * Loop until the user has been authenticated or the connection is - * closed, do_authloop() returns only if authentication is successful - */ - do_authloop(authctxt); - - /* The user has been authenticated and accepted. */ - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); - - return (authctxt); -} diff --git a/usr/src/cmd/ssh/sshd/auth2-chall.c b/usr/src/cmd/ssh/sshd/auth2-chall.c deleted file mode 100644 index 72dcc6dc5b..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-chall.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2001 Per Allansson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2-chall.c,v 1.20 2002/06/30 21:59:45 deraadt Exp $"); - -#include "ssh2.h" -#include "auth.h" -#include "buffer.h" -#include "packet.h" -#include "xmalloc.h" -#include "dispatch.h" -#include "auth.h" -#include "log.h" - -#ifndef lint -static void auth2_challenge_start(Authctxt *); -static int send_userauth_info_request(Authctxt *); -static void input_userauth_info_response(int, u_int32_t, void *); - -#ifdef BSD_AUTH -extern KbdintDevice bsdauth_device; -#else -#ifdef SKEY -extern KbdintDevice skey_device; -#endif -#endif - -KbdintDevice *devices[] = { -#ifdef BSD_AUTH - &bsdauth_device, -#else -#ifdef SKEY - &skey_device, -#endif -#endif - NULL -}; - -typedef struct KbdintAuthctxt KbdintAuthctxt; -struct KbdintAuthctxt -{ - char *devices; - void *ctxt; - KbdintDevice *device; - u_int nreq; -}; - -static KbdintAuthctxt * -kbdint_alloc(const char *devs) -{ - KbdintAuthctxt *kbdintctxt; - Buffer b; - int i; - - kbdintctxt = xmalloc(sizeof(KbdintAuthctxt)); - if (strcmp(devs, "") == 0) { - buffer_init(&b); - for (i = 0; devices[i]; i++) { - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - buffer_append(&b, devices[i]->name, - strlen(devices[i]->name)); - } - buffer_append(&b, "\0", 1); - kbdintctxt->devices = xstrdup(buffer_ptr(&b)); - buffer_free(&b); - } else { - kbdintctxt->devices = xstrdup(devs); - } - debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); - kbdintctxt->ctxt = NULL; - kbdintctxt->device = NULL; - kbdintctxt->nreq = 0; - - return kbdintctxt; -} -static void -kbdint_reset_device(KbdintAuthctxt *kbdintctxt) -{ - if (kbdintctxt->ctxt) { - kbdintctxt->device->free_ctx(kbdintctxt->ctxt); - kbdintctxt->ctxt = NULL; - } - kbdintctxt->device = NULL; -} -static void -kbdint_free(KbdintAuthctxt *kbdintctxt) -{ - if (kbdintctxt->device) - kbdint_reset_device(kbdintctxt); - if (kbdintctxt->devices) { - xfree(kbdintctxt->devices); - kbdintctxt->devices = NULL; - } - xfree(kbdintctxt); -} -/* get next device */ -static int -kbdint_next_device(KbdintAuthctxt *kbdintctxt) -{ - size_t len; - char *t; - int i; - - if (kbdintctxt->device) - kbdint_reset_device(kbdintctxt); - do { - len = kbdintctxt->devices ? - strcspn(kbdintctxt->devices, ",") : 0; - - if (len == 0) - break; - for (i = 0; devices[i]; i++) - if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) - kbdintctxt->device = devices[i]; - t = kbdintctxt->devices; - kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; - xfree(t); - debug2("kbdint_next_device: devices %s", kbdintctxt->devices ? - kbdintctxt->devices : "<empty>"); - } while (kbdintctxt->devices && !kbdintctxt->device); - - return kbdintctxt->device ? 1 : 0; -} - -/* - * try challenge-response, set authctxt->method->postponed if we have to - * wait for the response. - */ -void -auth2_challenge(Authctxt *authctxt, char *devs) -{ - debug("auth2_challenge: user=%s devs=%s", - authctxt->user ? authctxt->user : "<nouser>", - devs ? devs : "<no devs>"); - - if (authctxt->user == NULL || !devs) - return; - if (authctxt->method->method_data != NULL) { - auth2_challenge_abandon(authctxt); - authctxt->method->abandoned = 0; - } - authctxt->method->method_data = (void *) kbdint_alloc(devs); - auth2_challenge_start(authctxt); -} - -/* unregister kbd-int callbacks and context */ -static void -auth2_challenge_stop(Authctxt *authctxt) -{ - /* unregister callback */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); - if (authctxt->method->method_data != NULL) { - kbdint_free((KbdintAuthctxt *) authctxt->method->method_data); - authctxt->method->method_data = NULL; - } -} - -void -auth2_challenge_abandon(Authctxt *authctxt) -{ - auth2_challenge_stop(authctxt); - authctxt->method->abandoned = 1; - authctxt->method->postponed = 0; - authctxt->method->authenticated = 0; - authctxt->method->abandons++; - authctxt->method->attempts++; -} - -/* side effect: sets authctxt->method->postponed if a reply was sent*/ -static void -auth2_challenge_start(Authctxt *authctxt) -{ - KbdintAuthctxt *kbdintctxt = (KbdintAuthctxt *) - authctxt->method->method_data; - - debug2("auth2_challenge_start: devices %s", - kbdintctxt->devices ? kbdintctxt->devices : "<empty>"); - - if (kbdint_next_device(kbdintctxt) == 0) { - auth2_challenge_stop(authctxt); - return; - } - debug("auth2_challenge_start: trying authentication method '%s'", - kbdintctxt->device->name); - - if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { - auth2_challenge_stop(authctxt); - return; - } - if (send_userauth_info_request(authctxt) == 0) { - auth2_challenge_stop(authctxt); - return; - } - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, - &input_userauth_info_response); - - authctxt->method->postponed = 1; -} - -static int -send_userauth_info_request(Authctxt *authctxt) -{ - KbdintAuthctxt *kbdintctxt; - char *name, *instr, **prompts; - int i; - u_int *echo_on; - - kbdintctxt = (KbdintAuthctxt *) authctxt->method->method_data; - if (kbdintctxt->device->query(kbdintctxt->ctxt, - &name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) - return 0; - - packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); - packet_put_cstring(name); - packet_put_utf8_cstring(instr); - packet_put_cstring(""); /* language not used */ - packet_put_int(kbdintctxt->nreq); - for (i = 0; i < kbdintctxt->nreq; i++) { - packet_put_utf8_cstring(prompts[i]); - packet_put_char(echo_on[i]); - } - packet_send(); - packet_write_wait(); - - for (i = 0; i < kbdintctxt->nreq; i++) - xfree(prompts[i]); - xfree(prompts); - xfree(echo_on); - xfree(name); - xfree(instr); - return 1; -} - -static void -input_userauth_info_response(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - KbdintAuthctxt *kbdintctxt; - int i, res, len; - u_int nresp; - char **response = NULL, *method; - - if (authctxt == NULL) - fatal("input_userauth_info_response: no authctxt"); - kbdintctxt = (KbdintAuthctxt *) authctxt->method->method_data; - if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL) - fatal("input_userauth_info_response: no kbdintctxt"); - if (kbdintctxt->device == NULL) - fatal("input_userauth_info_response: no device"); - - nresp = packet_get_int(); - if (nresp != kbdintctxt->nreq) - fatal("input_userauth_info_response: wrong number of replies"); - if (nresp > 100) - fatal("input_userauth_info_response: too many replies"); - if (nresp > 0) { - response = xmalloc(nresp * sizeof(char *)); - for (i = 0; i < nresp; i++) - response[i] = packet_get_string(NULL); - } - packet_check_eom(); - - if (authctxt->valid) { - res = kbdintctxt->device->respond(kbdintctxt->ctxt, - nresp, response); - } else { - res = -1; - } - - for (i = 0; i < nresp; i++) { - memset(response[i], 'r', strlen(response[i])); - xfree(response[i]); - } - if (response) - xfree(response); - - authctxt->method->postponed = 0; /* reset */ - switch (res) { - case 0: - /* Success! */ - authctxt->method->authenticated = 1; - break; - case 1: - /* Authentication needs further interaction */ - if (send_userauth_info_request(authctxt) == 1) { - authctxt->method->postponed = 1; - } - break; - default: - /* Failure! */ - break; - } - - - len = strlen("keyboard-interactive") + 2 + - strlen(kbdintctxt->device->name); - method = xmalloc(len); - snprintf(method, len, "keyboard-interactive/%s", - kbdintctxt->device->name); - - if (authctxt->method->authenticated || authctxt->method->abandoned) { - auth2_challenge_stop(authctxt); - } else { - /* start next device */ - /* may set authctxt->method->postponed */ - auth2_challenge_start(authctxt); - } - userauth_finish(authctxt, method); - xfree(method); -} - -void -privsep_challenge_enable(void) -{ -#ifdef BSD_AUTH - extern KbdintDevice mm_bsdauth_device; -#endif -#ifdef SKEY - extern KbdintDevice mm_skey_device; -#endif - /* As long as SSHv1 has devices[0] hard coded this is fine */ -#ifdef BSD_AUTH - devices[0] = &mm_bsdauth_device; -#else -#ifdef SKEY - devices[0] = &mm_skey_device; -#endif -#endif -} -#endif /* lint */ diff --git a/usr/src/cmd/ssh/sshd/auth2-gss.c b/usr/src/cmd/ssh/sshd/auth2-gss.c deleted file mode 100644 index 8525707c1e..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-gss.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -#ifdef GSSAPI -#include "auth.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "log.h" -#include "dispatch.h" -#include "buffer.h" -#include "servconf.h" -#include "compat.h" -#include "bufaux.h" -#include "packet.h" - -#include <gssapi/gssapi.h> -#include "ssh-gss.h" - -extern ServerOptions options; -extern uchar_t *session_id2; -extern int session_id2_len; -extern Gssctxt *xxx_gssctxt; - -static void userauth_gssapi_finish(Authctxt *authctxt, Gssctxt *gssctxt); - -static void -userauth_gssapi_keyex(Authctxt *authctxt) -{ - gss_buffer_desc g_mic_data, mic_tok; - Buffer mic_data; - OM_uint32 maj_status, min_status; - - if (authctxt == NULL || authctxt->method == NULL) - fatal("No authentication context during gssapi-keyex userauth"); - - if (xxx_gssctxt == NULL || xxx_gssctxt->context == GSS_C_NO_CONTEXT) { - /* fatal()? or return? */ - debug("No GSS-API context during gssapi-keyex userauth"); - return; - } - - /* Make data buffer to verify MIC with */ - buffer_init(&mic_data); - buffer_put_string(&mic_data, session_id2, session_id2_len); - buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&mic_data, authctxt->user); - buffer_put_cstring(&mic_data, authctxt->service); - buffer_put_cstring(&mic_data, authctxt->method->name); - - g_mic_data.value = buffer_ptr(&mic_data); - g_mic_data.length = buffer_len(&mic_data); - - mic_tok.value = packet_get_string(&mic_tok.length); - - maj_status = gss_verify_mic(&min_status, xxx_gssctxt->context, - &g_mic_data, &mic_tok, NULL); - - packet_check_eom(); - buffer_clear(&mic_data); - - if (maj_status != GSS_S_COMPLETE) - debug2("MIC verification failed, GSSAPI userauth failed"); - else - userauth_gssapi_finish(authctxt, xxx_gssctxt); - - /* Leave Gssctxt around for ssh_gssapi_cleanup/storecreds() */ - if (xxx_gssctxt->deleg_creds == GSS_C_NO_CREDENTIAL) - ssh_gssapi_delete_ctx(&xxx_gssctxt); -} - -static void ssh_gssapi_userauth_error(Gssctxt *ctxt); -static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); -static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); -static void input_gssapi_errtok(int, u_int32_t, void *); -static void input_gssapi_exchange_complete(int type, u_int32_t plen, - void *ctxt); - -static void -userauth_gssapi_abandon(Authctxt *authctxt, Authmethod *method) -{ - ssh_gssapi_delete_ctx((Gssctxt **)&method->method_data); - xxx_gssctxt = NULL; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); -} - -static void -userauth_gssapi(Authctxt *authctxt) -{ - gss_OID_set supported_mechs; - int mechs, present = 0; - OM_uint32 min_status; - uint_t len; - char *doid = NULL; - gss_OID oid = GSS_C_NULL_OID; - - if (datafellows & SSH_OLD_GSSAPI) { - debug("Early drafts of GSSAPI userauth not supported"); - return; - } - - mechs = packet_get_int(); - if (mechs == 0) { - packet_check_eom(); - debug("Mechanism negotiation is not supported"); - return; - } - - ssh_gssapi_server_mechs(&supported_mechs); - - do { - mechs--; - - if (oid != GSS_C_NULL_OID) - ssh_gssapi_release_oid(&oid); - - doid = packet_get_string(&len); - - /* ick */ - if (doid[0] != 0x06 || (len > 2 && doid[1] != len - 2)) { - log("Mechanism OID received using the old " - "encoding form"); - oid = ssh_gssapi_make_oid(len, doid); - } else { - oid = ssh_gssapi_make_oid(len - 2, doid + 2); - } - - (void) gss_test_oid_set_member(&min_status, oid, - supported_mechs, &present); - - debug("Client offered gssapi userauth with %s (%s)", - ssh_gssapi_oid_to_str(oid), - present ? "supported" : "unsupported"); - } while (!present && (mechs > 0)); - - if (!present) { - /* userauth_finish() will send SSH2_MSG_USERAUTH_FAILURE */ - debug2("No mechanism offered by the client is available"); - ssh_gssapi_release_oid(&oid); - return; - } - - ssh_gssapi_build_ctx((Gssctxt **)&authctxt->method->method_data, - 0, oid); - ssh_gssapi_release_oid(&oid); - /* Send SSH_MSG_USERAUTH_GSSAPI_RESPONSE */ - - packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); - - /* Just return whatever we found -- the matched mech does us no good */ - packet_put_string(doid, len); - xfree(doid); - - packet_send(); - packet_write_wait(); - - /* Setup rest of gssapi userauth conversation */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); - authctxt->method->postponed = 1; -} - -static void -input_gssapi_token(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc send_tok, recv_tok; - OM_uint32 maj_status, min_status; - uint_t len; - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) { - fatal("No authentication or GSSAPI context during " - "gssapi-with-mic userauth"); - } - - gssctxt = authctxt->method->method_data; - recv_tok.value = packet_get_string(&len); - recv_tok.length = len; /* u_int vs. size_t */ - - maj_status = ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok); - packet_check_eom(); - - if (GSS_ERROR(maj_status)) { - ssh_gssapi_userauth_error(gssctxt); - if (send_tok.length != 0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); - packet_put_string(send_tok.value, send_tok.length); - packet_send(); - packet_write_wait(); - } - authctxt->method->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, authctxt->method->name); - } else { - if (send_tok.length != 0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); - packet_put_string(send_tok.value, send_tok.length); - packet_send(); - packet_write_wait(); - } - if (maj_status == GSS_S_COMPLETE) { - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, - &input_gssapi_mic); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, - &input_gssapi_exchange_complete); - } - } - - gss_release_buffer(&min_status, &send_tok); -} - -static void -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc send_tok, recv_tok; - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) { - fatal("No authentication or GSSAPI context during " - "gssapi-with-mic userauth"); - } - - gssctxt = authctxt->method->method_data; - recv_tok.value = packet_get_string(&recv_tok.length); - packet_check_eom(); - - /* Push the error token into GSSAPI to see what it says */ - (void) ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok); - - debug("Client sent GSS-API error token during GSS userauth-- %s", - ssh_gssapi_last_error(gssctxt, NULL, NULL)); - - /* We can't return anything to the client, even if we wanted to */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - - - /* - * The client will have already moved on to the next auth and - * will send a new userauth request. The spec says that the - * server MUST NOT send a SSH_MSG_USERAUTH_FAILURE packet in - * response to this. - * - * We leave authctxt->method->postponed == 1 here so that a call - * to input_userauth_request() will detect this failure (as - * userauth abandonment) and act accordingly. - */ -} - -static void -input_gssapi_mic(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc g_mic_data, mic_tok; - Buffer mic_data; - OM_uint32 maj_status, min_status; - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) { - debug3("No authentication or GSSAPI context during " - "gssapi-with-mic userauth"); - return; - } - - gssctxt = authctxt->method->method_data; - - /* Make data buffer to verify MIC with */ - buffer_init(&mic_data); - buffer_put_string(&mic_data, session_id2, session_id2_len); - buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&mic_data, authctxt->user); - buffer_put_cstring(&mic_data, authctxt->service); - buffer_put_cstring(&mic_data, authctxt->method->name); - - g_mic_data.value = buffer_ptr(&mic_data); - g_mic_data.length = buffer_len(&mic_data); - - mic_tok.value = packet_get_string(&mic_tok.length); - - maj_status = gss_verify_mic(&min_status, gssctxt->context, - &g_mic_data, &mic_tok, NULL); - - packet_check_eom(); - buffer_free(&mic_data); - - if (maj_status != GSS_S_COMPLETE) - debug2("MIC verification failed, GSSAPI userauth failed"); - else - userauth_gssapi_finish(authctxt, gssctxt); - - /* Delete context from keyex */ - if (xxx_gssctxt != gssctxt) - ssh_gssapi_delete_ctx(&xxx_gssctxt); - - /* Leave Gssctxt around for ssh_gssapi_cleanup/storecreds() */ - if (gssctxt->deleg_creds == GSS_C_NO_CREDENTIAL) - ssh_gssapi_delete_ctx(&gssctxt); - - xxx_gssctxt = gssctxt; - - authctxt->method->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - userauth_finish(authctxt, authctxt->method->name); -} - -/* - * This is called when the client thinks we've completed authentication. - * It should only be enabled in the dispatch handler by the function above, - * which only enables it once the GSSAPI exchange is complete. - */ -static void -input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - - packet_check_eom(); - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) - fatal("No authentication or GSSAPI context"); - - gssctxt = authctxt->method->method_data; - - /* - * SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE -> gssapi userauth - * failure, the client should use SSH2_MSG_USERAUTH_GSSAPI_MIC - * instead. - * - * There's two reasons for this: - * - * 1) we don't have GSS mechs that don't support integrity - * protection, and even if we did we'd not want to use them with - * SSHv2, and, - * - * 2) we currently have no way to dynamically detect whether a - * given mechanism does or does not support integrity - * protection, so when a context's flags do not indicate - * integrity protection we can't know if the client simply - * didn't request it, so we assume it didn't and reject the - * userauth. - * - * We could fail partially (i.e., force the use of other - * userauth methods without counting this one as failed). But - * this will do for now. - */ -#if 0 - authctxt->method->authenticated = ssh_gssapi_userok(gssctxt, - authctxt->user); -#endif - - if (xxx_gssctxt != gssctxt) - ssh_gssapi_delete_ctx(&gssctxt); - ssh_gssapi_delete_ctx(&gssctxt); - authctxt->method->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authctxt->method->name); -} - -static void -ssh_gssapi_userauth_error(Gssctxt *ctxt) -{ - char *errstr; - OM_uint32 maj, min; - - errstr = ssh_gssapi_last_error(ctxt, &maj, &min); - if (errstr) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR); - packet_put_int(maj); - packet_put_int(min); - packet_put_cstring(errstr); - packet_put_cstring(""); - packet_send(); - packet_write_wait(); - xfree(errstr); - } -} - -/* - * Code common to gssapi-keyex and gssapi-with-mic userauth. - * - * Does authorization, figures out how to store delegated creds. - */ -static void -userauth_gssapi_finish(Authctxt *authctxt, Gssctxt *gssctxt) -{ - char *local_user = NULL; - gss_buffer_desc dispname; - OM_uint32 major; - - if (*authctxt->user != '\0' && - ssh_gssapi_userok(gssctxt, authctxt->user)) { - - /* - * If the client princ did not map to the requested - * username then we don't want to clobber existing creds - * for the user with the delegated creds. - */ - local_user = ssh_gssapi_localname(gssctxt); - if (local_user == NULL || - strcmp(local_user, authctxt->user) == 0) - gssctxt->default_creds = 1; /* store creds as default */ - - authctxt->method->authenticated = - do_pam_non_initial_userauth(authctxt); - - } else if (*authctxt->user == '\0') { - /* Requested username == ""; derive username from princ name */ - if ((local_user = ssh_gssapi_localname(gssctxt)) == NULL) - return; - - /* Changed username (from implicit, '') */ - userauth_user_svc_change(authctxt, local_user, NULL); - - gssctxt->default_creds = 1; /* store creds as default */ - - authctxt->method->authenticated = - do_pam_non_initial_userauth(authctxt); - } - - if (local_user != NULL) - xfree(local_user); - - if (*authctxt->user != '\0' && authctxt->method->authenticated != 0) { - major = gss_display_name(&gssctxt->minor, gssctxt->src_name, - &dispname, NULL); - if (major == GSS_S_COMPLETE) { - log("Authorized principal %.*s, authenticated with " - "GSS mechanism %s, to: %s", - dispname.length, (char *)dispname.value, - ssh_gssapi_oid_to_name(gssctxt->actual_mech), - authctxt->user); - } - (void) gss_release_buffer(&gssctxt->minor, &dispname); - } -} - -#if 0 -/* Deprecated userauths -- should not be enabled */ -Authmethod method_external = { - "external-keyx", - &options.gss_authentication, - userauth_gssapi_keyex, - NULL, /* no abandon function */ - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; - -Authmethod method_gssapi = { - "gssapi", - &options.gss_authentication, - userauth_gssapi, - userauth_gssapi_abandon, - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; -#endif - -Authmethod method_external = { - "gssapi-keyex", - &options.gss_authentication, - userauth_gssapi_keyex, - NULL, /* no abandon function */ - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; - -Authmethod method_gssapi = { - "gssapi-with-mic", - &options.gss_authentication, - userauth_gssapi, - userauth_gssapi_abandon, - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; - -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/sshd/auth2-hostbased.c b/usr/src/cmd/ssh/sshd/auth2-hostbased.c deleted file mode 100644 index c88e308100..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-hostbased.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "ssh2.h" -#include "xmalloc.h" -#include "packet.h" -#include "buffer.h" -#include "log.h" -#include "servconf.h" -#include "compat.h" -#include "bufaux.h" -#include "auth.h" - -#ifdef USE_PAM -#include "auth-pam.h" -#endif /* USE_PAM */ - -#include "key.h" -#include "canohost.h" -#include "pathnames.h" - -/* import */ -extern ServerOptions options; -extern u_char *session_id2; -extern int session_id2_len; - -static void -userauth_hostbased(Authctxt *authctxt) -{ - Buffer b; - Key *key = NULL; - char *pkalg, *cuser, *chost, *service; - u_char *pkblob, *sig; - u_int alen, blen, slen; - int pktype; - int authenticated = 0; - - if (!authctxt || !authctxt->method) - fatal("%s: missing context", __func__); - - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - chost = packet_get_string(NULL); - cuser = packet_get_string(NULL); - sig = packet_get_string(&slen); - - debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", - cuser, chost, pkalg, slen); -#ifdef DEBUG_PK - debug("signature:"); - buffer_init(&b); - buffer_append(&b, sig, slen); - buffer_dump(&b); - buffer_free(&b); -#endif - pktype = key_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) { - /* this is perfectly legal */ - log("userauth_hostbased: unsupported " - "public key algorithm: %s", pkalg); - goto done; - } - key = key_from_blob(pkblob, blen); - if (key == NULL) { - error("userauth_hostbased: cannot decode key: %s", pkalg); - goto done; - } - if (key->type != pktype) { - error("userauth_hostbased: type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); - goto done; - } - service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : - authctxt->service; - buffer_init(&b); - buffer_put_string(&b, session_id2, session_id2_len); - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, "hostbased"); - buffer_put_string(&b, pkalg, alen); - buffer_put_string(&b, pkblob, blen); - buffer_put_cstring(&b, chost); - buffer_put_cstring(&b, cuser); -#ifdef DEBUG_PK - buffer_dump(&b); -#endif - /* test for allowed key and correct signature */ - authenticated = 0; - if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && - key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) - authenticated = 1; - - buffer_clear(&b); -done: - /* - * XXX TODO: Add config options for specifying users for whom - * this userauth is insufficient and what userauths - * may continue. - * - * NOTE: do_pam_non_initial_userauth() does this for - * users with expired passwords. - */ -#ifdef USE_PAM - if (authenticated) { - authctxt->cuser = cuser; - if (!do_pam_non_initial_userauth(authctxt)) - authenticated = 0; - /* Make sure nobody else will use this pointer since we are - * going to free that string. */ - authctxt->cuser = NULL; - } -#endif /* USE_PAM */ - - if (authenticated) - authctxt->method->authenticated = 1; - - debug2("userauth_hostbased: authenticated %d", authenticated); - if (key != NULL) - key_free(key); - xfree(pkalg); - xfree(pkblob); - xfree(cuser); - xfree(chost); - xfree(sig); - return; -} - -/* return 1 if given hostkey is allowed */ -int -hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - Key *key) -{ - const char *resolvedname, *ipaddr, *lookup; - HostStatus host_status; - int len; - - resolvedname = get_canonical_hostname(options.verify_reverse_mapping); - ipaddr = get_remote_ipaddr(); - - debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", - chost, resolvedname, ipaddr); - - if (pw == NULL) - return 0; - - if (options.hostbased_uses_name_from_packet_only) { - if (auth_rhosts2(pw, cuser, chost, chost) == 0) - return 0; - lookup = chost; - } else { - if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { - debug2("stripping trailing dot from chost %s", chost); - chost[len - 1] = '\0'; - } - if (strcasecmp(resolvedname, chost) != 0) - log("userauth_hostbased mismatch: " - "client sends %s, but we resolve %s to %s", - chost, ipaddr, resolvedname); - if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) - return 0; - lookup = resolvedname; - } - debug2("userauth_hostbased: access allowed by auth_rhosts2"); - - host_status = check_key_in_hostfiles(pw, key, lookup, - _PATH_SSH_SYSTEM_HOSTFILE, - options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); - - /* backward compat if no key has been found. */ - if (host_status == HOST_NEW) - host_status = check_key_in_hostfiles(pw, key, lookup, - _PATH_SSH_SYSTEM_HOSTFILE2, - options.ignore_user_known_hosts ? NULL : - _PATH_SSH_USER_HOSTFILE2); - - return (host_status == HOST_OK); -} - -Authmethod method_hostbased = { - "hostbased", - &options.hostbased_authentication, - userauth_hostbased, - NULL, /* no abandon function */ - NULL, NULL, /* method data and hist data */ - 0, /* is not initial userauth */ - 0, 0, 0, /* counters */ - 0, 0, 0, 0, 0, 0 /* state */ -}; diff --git a/usr/src/cmd/ssh/sshd/auth2-kbdint.c b/usr/src/cmd/ssh/sshd/auth2-kbdint.c deleted file mode 100644 index 2ea8104182..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-kbdint.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2-kbdint.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); - -#include "packet.h" -#include "auth.h" -#include "log.h" -#include "servconf.h" -#include "xmalloc.h" - -/* import */ -extern ServerOptions options; - -static void -userauth_kbdint(Authctxt *authctxt) -{ - char *lang, *devs; - - if (!authctxt || !authctxt->method) - fatal("%s: missing contex", __func__); - - lang = packet_get_string(NULL); - devs = packet_get_string(NULL); - packet_check_eom(); - - debug("keyboard-interactive devs %s", devs); - -#ifdef USE_PAM - if (options.kbd_interactive_authentication) - auth2_pam(authctxt); -#else - if (options.challenge_response_authentication) - auth2_challenge(authctxt, devs); -#endif /* USE_PAM */ - xfree(devs); - xfree(lang); -#ifdef HAVE_CYGWIN - if (check_nt_auth(0, authctxt->pw) == 0) { - authctxt->method->authenticated = 0; - return; - } -#endif -} - -static void -userauth_kbdint_abandon(Authctxt *authctxt, Authmethod *method) -{ -#ifdef USE_PAM - kbdint_pam_abandon(authctxt, method); -#else - auth2_challenge_abandon(authctxt); -#endif /* USE_PAM */ -} - -Authmethod method_kbdint = { - "keyboard-interactive", - &options.kbd_interactive_authentication, - userauth_kbdint, - userauth_kbdint_abandon, - NULL, NULL, /* method data and historical data */ - 1, /* initial userauth */ - 0, 0, 0, /* counters */ - 0, 0, 0, 0, 0, 0 /* state */ -}; diff --git a/usr/src/cmd/ssh/sshd/auth2-none.c b/usr/src/cmd/ssh/sshd/auth2-none.c deleted file mode 100644 index 5d49ee95e8..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-none.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2-none.c,v 1.4 2002/06/27 10:35:47 deraadt Exp $"); - -#include "auth.h" -#include "xmalloc.h" -#include "packet.h" -#include "log.h" -#include "servconf.h" -#include "atomicio.h" -#include "compat.h" -#include "ssh2.h" - -/* import */ -extern ServerOptions options; - -/* "none" is allowed only one time */ -static int none_enabled = 1; - -char * -auth2_read_banner(void) -{ - struct stat st; - char *banner, *ubanner, *errstr; - off_t len, n; - int fd; - uint_t ilen; - - if ((fd = open(options.banner, O_RDONLY)) == -1) - return (NULL); - if (fstat(fd, &st) == -1) { - close(fd); - return (NULL); - } - len = st.st_size; - banner = xmalloc(len + 1); - n = atomicio(read, fd, banner, len); - close(fd); - - if (n != len) { - xfree(banner); - return (NULL); - } - banner[n] = '\0'; - - if (datafellows & SSH_BUG_STRING_ENCODING) { - ubanner = banner; - } else { - ilen = (uint_t)n; - ubanner = g11n_convert_to_utf8(banner, &ilen, 1, &errstr); - if (ubanner == NULL) { - if (errstr != NULL) { - error("Can't convert banner contents " - "to UTF-8: %s\n", errstr); - } - ubanner = banner; - } else { - xfree(banner); - } - } - - return (ubanner); -} - -static void -userauth_banner(void) -{ - char *banner = NULL; - - if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) - return; - - if ((banner = auth2_read_banner()) == NULL) - goto done; - - packet_start(SSH2_MSG_USERAUTH_BANNER); - packet_put_cstring(banner); - packet_put_cstring(""); /* language, unused */ - packet_send(); - debug("userauth_banner: sent"); -done: - if (banner) - xfree(banner); -} - -static void -userauth_none(Authctxt *authctxt) -{ - none_enabled = 0; - - if (!authctxt || !authctxt->method) - fatal("%s: missing context", __func__); - - packet_check_eom(); - userauth_banner(); -#ifdef HAVE_CYGWIN - if (check_nt_auth(1, authctxt->pw) == 0) - return (0); -#endif - authctxt->method->authenticated = auth_password(authctxt, ""); -} - -Authmethod method_none = { - "none", - &none_enabled, - userauth_none, - NULL, /* no abandon function */ - NULL, NULL, /* method data and hist data */ - 0, /* not really initial userauth */ - 0, 0, 0, /* counters */ - 0, 0, 0, 0, 0, 0 /* state */ -}; diff --git a/usr/src/cmd/ssh/sshd/auth2-pam.c b/usr/src/cmd/ssh/sshd/auth2-pam.c deleted file mode 100644 index 1b0fa40f2b..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-pam.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -RCSID("$Id: auth2-pam.c,v 1.14 2002/06/28 16:48:12 mouring Exp $"); - -#ifdef USE_PAM -#include <security/pam_appl.h> - -#include "ssh.h" -#include "ssh2.h" -#include "auth.h" -#include "auth-pam.h" -#include "auth-options.h" -#include "packet.h" -#include "xmalloc.h" -#include "dispatch.h" -#include "canohost.h" -#include "log.h" -#include "servconf.h" -#include "misc.h" - -#ifdef HAVE_BSM -#include "bsmaudit.h" -#endif /* HAVE_BSM */ - -extern u_int utmp_len; -extern ServerOptions options; - -extern Authmethod method_kbdint; -extern Authmethod method_passwd; - -#define SSHD_PAM_KBDINT_SVC "sshd-kbdint" -/* Maximum attempts for changing expired password */ -#define DEF_ATTEMPTS 3 - -static int do_pam_conv_kbd_int(int num_msg, - struct pam_message **msg, struct pam_response **resp, - void *appdata_ptr); -static void input_userauth_info_response_pam(int type, - u_int32_t seqnr, - void *ctxt); - -static struct pam_conv conv2 = { - do_pam_conv_kbd_int, - NULL, -}; - -static void do_pam_kbdint_cleanup(pam_handle_t *pamh); -static void do_pam_kbdint(Authctxt *authctxt); - -void -auth2_pam(Authctxt *authctxt) -{ - if (authctxt->user == NULL) - fatal("auth2_pam: internal error: no user"); - if (authctxt->method == NULL) - fatal("auth2_pam: internal error: no method"); - - conv2.appdata_ptr = authctxt; - new_start_pam(authctxt, &conv2); - - authctxt->method->method_data = NULL; /* freed in the conv func */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, - &input_userauth_info_response_pam); - - /* - * Since password userauth and keyboard-interactive userauth - * both use PAM, and since keyboard-interactive is so much - * better than password userauth, we should not allow the user - * to try password userauth after trying keyboard-interactive. - */ - if (method_passwd.enabled) - *method_passwd.enabled = 0; - - do_pam_kbdint(authctxt); - - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); -} - -static void -do_pam_kbdint(Authctxt *authctxt) -{ - int retval, retval2; - pam_handle_t *pamh = authctxt->pam->h; - const char *where = "authenticating"; - char *text = NULL; - - debug2("Calling pam_authenticate()"); - retval = pam_authenticate(pamh, - options.permit_empty_passwd ? 0 : - PAM_DISALLOW_NULL_AUTHTOK); - - if (retval != PAM_SUCCESS) - goto cleanup; - - debug2("kbd-int: pam_authenticate() succeeded"); - where = "authorizing"; - retval = pam_acct_mgmt(pamh, 0); - - if (retval == PAM_NEW_AUTHTOK_REQD) { - if (authctxt->valid && authctxt->pw != NULL) { - /* send password expiration warning */ - message_cat(&text, - gettext("Warning: Your password has expired," - " please change it now.")); - packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); - packet_put_cstring(""); /* name */ - packet_put_utf8_cstring(text); /* instructions */ - packet_put_cstring(""); /* language, unused */ - packet_put_int(0); - packet_send(); - packet_write_wait(); - debug("expiration message sent"); - if (text) - xfree(text); - /* - * wait for the response so it does not mix - * with the upcoming PAM conversation - */ - packet_read_expect(SSH2_MSG_USERAUTH_INFO_RESPONSE); - /* - * Can't use temporarily_use_uid() and restore_uid() - * here because we need (euid == 0 && ruid == pw_uid) - * whereas temporarily_use_uid() arranges for - * (suid = 0 && euid == pw_uid && ruid == pw_uid). - */ - (void) setreuid(authctxt->pw->pw_uid, -1); - debug2("kbd-int: changing expired password"); - where = "changing authentication tokens (password)"; - /* - * Depending on error returned from pam_chauthtok, we - * need to try to change password a few times before - * we error out and return. - */ - int tries = 0; - while ((retval = pam_chauthtok(pamh, - PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) { - if (tries++ < DEF_ATTEMPTS) { - if ((retval == PAM_AUTHTOK_ERR) || - (retval == PAM_TRY_AGAIN)) { - continue; - } - } - break; - } - audit_sshd_chauthtok(retval, authctxt->pw->pw_uid, - authctxt->pw->pw_gid); - (void) setreuid(0, -1); - } else { - retval = PAM_PERM_DENIED; - } - } - - if (retval != PAM_SUCCESS) - goto cleanup; - - authctxt->pam->state |= PAM_S_DONE_ACCT_MGMT; - - retval = finish_userauth_do_pam(authctxt); - - if (retval != PAM_SUCCESS) - goto cleanup; - - /* - * PAM handle stays around so we can call pam_close_session() - * on it later. - */ - authctxt->method->authenticated = 1; - debug2("kbd-int: success (pam->state == %x)", authctxt->pam->state); - return; - -cleanup: - /* - * Check for abandonment and cleanup. When kbdint is abandoned - * authctxt->pam->h is NULLed and by this point a new handle may - * be allocated. - */ - if (authctxt->pam->h != pamh) { - log("Keyboard-interactive (PAM) userauth abandoned " - "while %s", where); - if ((retval2 = pam_end(pamh, retval)) != PAM_SUCCESS) { - log("Cannot close PAM handle after " - "kbd-int userauth abandonment[%d]: %.200s", - retval2, PAM_STRERROR(pamh, retval2)); - } - authctxt->method->abandoned = 1; - - /* - * Avoid double counting; these are incremented in - * kbdint_pam_abandon() so that they reflect the correct - * count when userauth_finish() is called before - * unwinding the dispatch_run() loop, but they are - * incremented again in input_userauth_request() when - * the loop is unwound, right here. - */ - if (authctxt->method->abandons) - authctxt->method->abandons--; - if (authctxt->method->attempts) - authctxt->method->attempts--; - } - else { - /* Save error value for pam_end() */ - authctxt->pam->last_pam_retval = retval; - log("Keyboard-interactive (PAM) userauth failed[%d] " - "while %s: %.200s", retval, where, - PAM_STRERROR(pamh, retval)); - /* pam handle can be reused elsewhere, so no pam_end() here */ - } - - return; -} - -static int -do_pam_conv_kbd_int(int num_msg, struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) -{ - int i, j; - char *text; - Convctxt *conv_ctxt; - Authctxt *authctxt = (Authctxt *)appdata_ptr; - - if (!authctxt || !authctxt->method) { - debug("Missing state during PAM conversation"); - return PAM_CONV_ERR; - } - - conv_ctxt = xmalloc(sizeof(Convctxt)); - (void) memset(conv_ctxt, 0, sizeof(Convctxt)); - conv_ctxt->finished = 0; - conv_ctxt->num_received = 0; - conv_ctxt->num_expected = 0; - conv_ctxt->prompts = xmalloc(sizeof(int) * num_msg); - conv_ctxt->responses = xmalloc(sizeof(struct pam_response) * num_msg); - (void) memset(conv_ctxt->responses, 0, sizeof(struct pam_response) * num_msg); - - text = NULL; - for (i = 0, conv_ctxt->num_expected = 0; i < num_msg; i++) { - int style = PAM_MSG_MEMBER(msg, i, msg_style); - switch (style) { - case PAM_PROMPT_ECHO_ON: - debug2("PAM echo on prompt: %s", - PAM_MSG_MEMBER(msg, i, msg)); - conv_ctxt->num_expected++; - break; - case PAM_PROMPT_ECHO_OFF: - debug2("PAM echo off prompt: %s", - PAM_MSG_MEMBER(msg, i, msg)); - conv_ctxt->num_expected++; - break; - case PAM_TEXT_INFO: - debug2("PAM text info prompt: %s", - PAM_MSG_MEMBER(msg, i, msg)); - message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); - break; - case PAM_ERROR_MSG: - debug2("PAM error prompt: %s", - PAM_MSG_MEMBER(msg, i, msg)); - message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); - break; - default: - /* Capture all these messages to be sent at once */ - message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); - break; - } - } - - if (conv_ctxt->num_expected == 0 && text == NULL) { - xfree(conv_ctxt->prompts); - xfree(conv_ctxt->responses); - xfree(conv_ctxt); - return PAM_SUCCESS; - } - - authctxt->method->method_data = (void *) conv_ctxt; - - packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); - packet_put_cstring(""); /* Name */ - packet_put_utf8_cstring(text ? text : ""); /* Instructions */ - packet_put_cstring(""); /* Language */ - packet_put_int(conv_ctxt->num_expected); - - if (text) - xfree(text); - - for (i = 0, j = 0; i < num_msg; i++) { - int style = PAM_MSG_MEMBER(msg, i, msg_style); - - /* Skip messages which don't need a reply */ - if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF) - continue; - - conv_ctxt->prompts[j++] = i; - packet_put_utf8_cstring(PAM_MSG_MEMBER(msg, i, msg)); - packet_put_char(style == PAM_PROMPT_ECHO_ON); - } - packet_send(); - packet_write_wait(); - - /* - * Here the dispatch_run() loop is nested. It should be unwound - * if keyboard-interactive userauth is abandoned (or restarted; - * same thing). - * - * The condition for breaking out of the nested dispatch_run() loop is - * ((got kbd-int info reponse) || (kbd-int abandoned)) - * - * conv_ctxt->finished is set in either of those cases. - * - * When abandonment is detected the conv_ctxt->finished is set as - * is conv_ctxt->abandoned, causing this function to signal - * userauth nested dispatch_run() loop unwinding and to return - * PAM_CONV_ERR; - */ - debug2("Nesting dispatch_run loop"); - dispatch_run(DISPATCH_BLOCK, &conv_ctxt->finished, appdata_ptr); - debug2("Nested dispatch_run loop exited"); - - if (conv_ctxt->abandoned) { - authctxt->unwind_dispatch_loop = 1; - xfree(conv_ctxt->prompts); - xfree(conv_ctxt->responses); - xfree(conv_ctxt); - debug("PAM conv function returns PAM_CONV_ERR"); - return PAM_CONV_ERR; - } - - if (conv_ctxt->num_received == conv_ctxt->num_expected) { - *resp = conv_ctxt->responses; - xfree(conv_ctxt->prompts); - xfree(conv_ctxt); - debug("PAM conv function returns PAM_SUCCESS"); - return PAM_SUCCESS; - } - - debug("PAM conv function returns PAM_CONV_ERR"); - xfree(conv_ctxt->prompts); - xfree(conv_ctxt->responses); - xfree(conv_ctxt); - return PAM_CONV_ERR; -} - -static void -input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Convctxt *conv_ctxt; - unsigned int nresp = 0, rlen = 0, i = 0; - char *resp; - - if (authctxt == NULL) - fatal("input_userauth_info_response_pam: no authentication context"); - - /* Check for spurious/unexpected info response */ - if (method_kbdint.method_data == NULL) { - debug("input_userauth_info_response_pam: no method context"); - return; - } - - conv_ctxt = (Convctxt *) method_kbdint.method_data; - - nresp = packet_get_int(); /* Number of responses. */ - debug("got %d responses", nresp); - - -#if 0 - if (nresp != conv_ctxt->num_expected) - fatal("%s: Received incorrect number of responses " - "(expected %d, received %u)", __func__, - conv_ctxt->num_expected, nresp); -#endif - - if (nresp > 100) - fatal("%s: too many replies", __func__); - - for (i = 0; i < nresp && i < conv_ctxt->num_expected ; i++) { - int j = conv_ctxt->prompts[i]; - - /* - * We assume that ASCII charset is used for password - * although the protocol requires UTF-8 encoding for the - * password string. Therefore, we don't perform code - * conversion for the string. - */ - resp = packet_get_string(&rlen); - if (i < conv_ctxt->num_expected) { - conv_ctxt->responses[j].resp_retcode = PAM_SUCCESS; - conv_ctxt->responses[j].resp = xstrdup(resp); - conv_ctxt->num_received++; - } - xfree(resp); - } - - if (nresp < conv_ctxt->num_expected) - fatal("%s: too few replies (%d < %d)", __func__, - nresp, conv_ctxt->num_expected); - - /* XXX - This could make a covert channel... */ - if (nresp > conv_ctxt->num_expected) - debug("Ignoring additional PAM replies"); - - conv_ctxt->finished = 1; - - packet_check_eom(); -} - -#if 0 -int -kbdint_pam_abandon_chk(Authctxt *authctxt, Authmethod *method) -{ - if (!method) - return 0; /* fatal(), really; it'll happen somewhere else */ - - if (!method->method_data) - return 0; - - return 1; -} -#endif - -void -kbdint_pam_abandon(Authctxt *authctxt, Authmethod *method) -{ - Convctxt *conv_ctxt; - - /* - * But, if it ever becomes desirable and possible to support - * kbd-int userauth abandonment, here's what must be done. - */ - if (!method) - return; - - if (!method->method_data) - return; - - conv_ctxt = (Convctxt *) method->method_data; - - /* dispatch_run() loop will exit */ - conv_ctxt->abandoned = 1; - conv_ctxt->finished = 1; - - /* - * The method_data will be free in the corresponding, active - * conversation function - */ - method->method_data = NULL; - - /* update counts that can't be updated elsewhere */ - method->abandons++; - method->attempts++; - - /* Finally, we cannot re-use the current current PAM handle */ - authctxt->pam->h = NULL; /* Let the conv function cleanup */ -} -#endif diff --git a/usr/src/cmd/ssh/sshd/auth2-passwd.c b/usr/src/cmd/ssh/sshd/auth2-passwd.c deleted file mode 100644 index 9a1837fb05..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-passwd.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "xmalloc.h" -#include "packet.h" -#include "log.h" -#include "auth.h" -#include "servconf.h" - -/* import */ -extern ServerOptions options; - -static void -userauth_passwd(Authctxt *authctxt) -{ - char *password; - int change; - u_int len; - - if (!authctxt || !authctxt->method) - fatal("%s: missing context", __func__); - - change = packet_get_char(); - if (change) - log("password change not supported"); - password = packet_get_string(&len); - packet_check_eom(); - if ( -#ifdef HAVE_CYGWIN - check_nt_auth(1, authctxt->pw) && -#endif - auth_password(authctxt, password) == 1) { - authctxt->method->authenticated = 1; - } - memset(password, 0, len); - xfree(password); -} - -Authmethod method_passwd = { - "password", - &options.password_authentication, - userauth_passwd, - NULL, /* no abandon function */ - NULL, NULL, /* method data and hist data */ - 1, /* initial userauth */ - 0, 0, 0, /* counters */ - 0, 0, 0, 0, 0, 0 /* state */ -}; diff --git a/usr/src/cmd/ssh/sshd/auth2-pubkey.c b/usr/src/cmd/ssh/sshd/auth2-pubkey.c deleted file mode 100644 index 658634c195..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-pubkey.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); - -#include "ssh2.h" -#include "xmalloc.h" -#include "packet.h" -#include "buffer.h" -#include "log.h" -#include "servconf.h" -#include "compat.h" -#include "bufaux.h" -#include "auth.h" -#include "key.h" -#include "pathnames.h" -#include "uidswap.h" -#include "auth-options.h" -#include "canohost.h" - -#ifdef USE_PAM -#include <security/pam_appl.h> -#include "auth-pam.h" -#endif /* USE_PAM */ - -/* import */ -extern ServerOptions options; -extern u_char *session_id2; -extern int session_id2_len; - -static void -userauth_pubkey(Authctxt *authctxt) -{ - Buffer b; - Key *key = NULL; - char *pkalg; - u_char *pkblob, *sig; - u_int alen, blen, slen; - int have_sig, pktype; - int authenticated = 0; - - if (!authctxt || !authctxt->method) - fatal("%s: missing context", __func__); - - have_sig = packet_get_char(); - if (datafellows & SSH_BUG_PKAUTH) { - debug2("userauth_pubkey: SSH_BUG_PKAUTH"); - /* no explicit pkalg given */ - pkblob = packet_get_string(&blen); - buffer_init(&b); - buffer_append(&b, pkblob, blen); - /* so we have to extract the pkalg from the pkblob */ - pkalg = buffer_get_string(&b, &alen); - buffer_free(&b); - } else { - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - } - pktype = key_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) { - /* this is perfectly legal */ - log("userauth_pubkey: unsupported public key algorithm: %s", - pkalg); - goto done; - } - key = key_from_blob(pkblob, blen); - if (key == NULL) { - error("userauth_pubkey: cannot decode key: %s", pkalg); - goto done; - } - if (key->type != pktype) { - error("userauth_pubkey: type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); - goto done; - } - - /* Detect and count abandonment */ - if (authctxt->method->method_data) { - Key *prev_key; - unsigned char *prev_pkblob; - int prev_blen; - - /* - * Check for earlier test of a key that was allowed but - * not followed up with a pubkey req for the same pubkey - * and with a signature. - */ - prev_key = authctxt->method->method_data; - if ((prev_blen = key_to_blob(prev_key, - &prev_pkblob, NULL))) { - if (prev_blen != blen || - memcmp(prev_pkblob, pkblob, blen) != 0) { - authctxt->method->abandons++; - authctxt->method->attempts++; - } - } - key_free(prev_key); - authctxt->method->method_data = NULL; - } - - if (have_sig) { - sig = packet_get_string(&slen); - packet_check_eom(); - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); - } else { - buffer_put_string(&b, session_id2, session_id2_len); - } - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); - } else { - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, pkalg); - } - buffer_put_string(&b, pkblob, blen); -#ifdef DEBUG_PK - buffer_dump(&b); -#endif - /* test for correct signature */ - if (user_key_allowed(authctxt->pw, key) && - key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b)) == 1) { - authenticated = 1; - } - authctxt->method->postponed = 0; - buffer_free(&b); - xfree(sig); - } else { - debug("test whether pkalg/pkblob are acceptable"); - packet_check_eom(); - - /* XXX fake reply and always send PK_OK ? */ - /* - * XXX this allows testing whether a user is allowed - * to login: if you happen to have a valid pubkey this - * message is sent. the message is NEVER sent at all - * if a user is not allowed to login. is this an - * issue? -markus - */ - if (user_key_allowed(authctxt->pw, key)) { - packet_start(SSH2_MSG_USERAUTH_PK_OK); - packet_put_string(pkalg, alen); - packet_put_string(pkblob, blen); - packet_send(); - packet_write_wait(); - authctxt->method->postponed = 1; - /* - * Remember key that was tried so we can - * correctly detect abandonment. See above. - */ - authctxt->method->method_data = (void *) key; - key = NULL; - } - } - if (authenticated != 1) - auth_clear_options(); - -done: - /* - * XXX TODO: add config options for specifying users for whom - * this userauth is insufficient and what userauths may - * continue. - */ -#ifdef USE_PAM - if (authenticated) { - if (!do_pam_non_initial_userauth(authctxt)) - authenticated = 0; - } -#endif /* USE_PAM */ - - debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); - if (key != NULL) - key_free(key); - xfree(pkalg); - xfree(pkblob); -#ifdef HAVE_CYGWIN - if (check_nt_auth(0, authctxt->pw) == 0) - return; -#endif - if (authenticated) - authctxt->method->authenticated = 1; -} - -/* return 1 if user allows given key */ -static int -user_key_allowed2(struct passwd *pw, Key *key, char *file) -{ - char line[8192]; - int found_key = 0; - FILE *f; - u_long linenum = 0; - struct stat st; - Key *found; - char *fp; - - if (pw == NULL) - return 0; - - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - - debug("trying public key file %s", file); - - /* Fail quietly if file does not exist */ - if (stat(file, &st) < 0) { - /* Restore the privileged uid. */ - restore_uid(); - return 0; - } - /* Open the file containing the authorized keys. */ - f = fopen(file, "r"); - if (!f) { - /* Restore the privileged uid. */ - restore_uid(); - return 0; - } - if (options.strict_modes && - secure_filename(f, file, pw, line, sizeof(line)) != 0) { - (void) fclose(f); - log("Authentication refused: %s", line); - restore_uid(); - return 0; - } - - found_key = 0; - found = key_new(key->type); - - while (fgets(line, sizeof(line), f)) { - char *cp, *options = NULL; - linenum++; - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; - - if (key_read(found, &cp) != 1) { - /* no key? check if there are options for this key */ - int quoted = 0; - debug2("user_key_allowed: check options: '%s'", cp); - options = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - /* Skip remaining whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - if (key_read(found, &cp) != 1) { - debug2("user_key_allowed: advance: '%s'", cp); - /* still no key? advance to next line*/ - continue; - } - } - if (key_equal(found, key) && - auth_parse_options(pw, options, file, linenum) == 1) { - found_key = 1; - debug("matching key found: file %s, line %lu", - file, linenum); - fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(found), fp); - xfree(fp); - break; - } - } - restore_uid(); - (void) fclose(f); - key_free(found); - if (!found_key) - debug2("key not found"); - return found_key; -} - -/* check whether given key is in .ssh/authorized_keys* */ -int -user_key_allowed(struct passwd *pw, Key *key) -{ - int success; - char *file; - - if (pw == NULL) - return 0; - - file = authorized_keys_file(pw); - success = user_key_allowed2(pw, key, file); - xfree(file); - if (success) - return success; - - /* try suffix "2" for backward compat, too */ - file = authorized_keys_file2(pw); - success = user_key_allowed2(pw, key, file); - xfree(file); - return success; -} - -static -void -userauth_pubkey_abandon(Authctxt *authctxt, Authmethod *method) -{ - if (!authctxt || !method) - return; - - if (method->method_data) { - method->abandons++; - method->attempts++; - key_free((Key *) method->method_data); - method->method_data = NULL; - } -} - -Authmethod method_pubkey = { - "publickey", - &options.pubkey_authentication, - userauth_pubkey, - userauth_pubkey_abandon, - NULL, NULL, /* method data and hist data */ - 0, /* not initial userauth */ - 0, 0, 0, /* counters */ - 0, 0, 0, 0, 0, 0 /* state */ -}; diff --git a/usr/src/cmd/ssh/sshd/auth2.c b/usr/src/cmd/ssh/sshd/auth2.c deleted file mode 100644 index bc3f4284f3..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.95 2002/08/22 21:33:58 markus Exp $"); - -#include "ssh2.h" -#include "xmalloc.h" -#include "packet.h" -#include "log.h" -#include "servconf.h" -#include "compat.h" -#include "misc.h" -#include "auth.h" -#include "dispatch.h" -#include "sshlogin.h" -#include "pathnames.h" - -#ifdef HAVE_BSM -#include "bsmaudit.h" -extern adt_session_data_t *ah; -#endif /* HAVE_BSM */ - -#ifdef GSSAPI -#include "ssh-gss.h" -#endif - -/* import */ -extern ServerOptions options; -extern u_char *session_id2; -extern int session_id2_len; - -Authctxt *x_authctxt = NULL; - -/* methods */ - -extern Authmethod method_none; -extern Authmethod method_pubkey; -extern Authmethod method_passwd; -extern Authmethod method_kbdint; -extern Authmethod method_hostbased; -extern Authmethod method_external; -extern Authmethod method_gssapi; - -static Authmethod *authmethods[] = { - &method_none, -#ifdef GSSAPI - &method_external, - &method_gssapi, -#endif - &method_pubkey, - &method_passwd, - &method_kbdint, - &method_hostbased, - NULL -}; - -/* protocol */ - -static void input_service_request(int, u_int32_t, void *); -static void input_userauth_request(int, u_int32_t, void *); - -/* helper */ -static Authmethod *authmethod_lookup(const char *); -static char *authmethods_get(void); -static char *authmethods_check_abandonment(Authctxt *authctxt, - Authmethod *method); -static void authmethod_count_attempt(Authmethod *method); -/*static char *authmethods_get_kbdint(void);*/ -int user_key_allowed(struct passwd *, Key *); -int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); -static int userauth_method_can_run(Authmethod *method); -static void userauth_reset_methods(void); - -/* - * loop until authctxt->success == TRUE - */ - -Authctxt * -do_authentication2(void) -{ - Authctxt *authctxt = authctxt_new(); - - x_authctxt = authctxt; /*XXX*/ - -#ifdef HAVE_BSM - fatal_add_cleanup(audit_failed_login_cleanup, authctxt); -#endif /* HAVE_BSM */ - - dispatch_init(&dispatch_protocol_error); - dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); - dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); - - return (authctxt); -} - -static void -input_service_request(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - u_int len; - int acceptit = 0; - char *service = packet_get_string(&len); - packet_check_eom(); - - if (authctxt == NULL) - fatal("input_service_request: no authctxt"); - - if (strcmp(service, "ssh-userauth") == 0) { - if (!authctxt->success) { - acceptit = 1; - /* now we can handle user-auth requests */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); - } - } - /* XXX all other service requests are denied */ - - if (acceptit) { - packet_start(SSH2_MSG_SERVICE_ACCEPT); - packet_put_cstring(service); - packet_send(); - packet_write_wait(); - } else { - debug("bad service request %s", service); - packet_disconnect("bad service request %s", service); - } - xfree(service); -} - -static void -input_userauth_request(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Authmethod *m = NULL; - char *user, *service, *method, *style = NULL; - int valid_attempt; - - if (authctxt == NULL) - fatal("input_userauth_request: no authctxt"); - - user = packet_get_string(NULL); - service = packet_get_string(NULL); - method = packet_get_string(NULL); - debug("userauth-request for user %s service %s method %s", user, - service, method); - debug("attempt %d initial attempt %d failures %d initial failures %d", - authctxt->attempt, authctxt->init_attempt, - authctxt->failures, authctxt->init_failures); - - m = authmethod_lookup(method); - - if ((style = strchr(user, ':')) != NULL) - *style++ = 0; - - authctxt->attempt++; - if (m != NULL && m->is_initial) - authctxt->init_attempt++; - - if (options.pre_userauth_hook != NULL && - run_auth_hook(options.pre_userauth_hook, user, m->name) != 0) { - valid_attempt = 0; - } else { - valid_attempt = 1; - } - - if (authctxt->attempt == 1) { - /* setup auth context */ - authctxt->pw = getpwnamallow(user); - /* May want to abstract SSHv2 services someday */ - if (authctxt->pw && strcmp(service, "ssh-connection")==0) { - /* enforced in userauth_finish() below */ - if (valid_attempt) { - authctxt->valid = 1; - } - debug2("input_userauth_request: setting up authctxt for %s", user); - } else { - log("input_userauth_request: illegal user %s", user); - } - setproctitle("%s", authctxt->pw ? user : "unknown"); - authctxt->user = xstrdup(user); - authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; - userauth_reset_methods(); - } else { - char *abandoned; - - /* - * Check for abandoned [multi-round-trip] userauths - * methods (e.g., kbdint). Userauth method abandonment - * should be treated as userauth method failure and - * counted against max_auth_tries. - */ - abandoned = authmethods_check_abandonment(authctxt, m); - - if (abandoned != NULL && - authctxt->failures > options.max_auth_tries) { - /* userauth_finish() will now packet_disconnect() */ - userauth_finish(authctxt, abandoned); - /* NOTREACHED */ - } - - /* Handle user|service changes, possibly packet_disconnect() */ - userauth_user_svc_change(authctxt, user, service); - } - - authctxt->method = m; - - /* run userauth method, try to authenticate user */ - if (m != NULL && userauth_method_can_run(m)) { - debug2("input_userauth_request: try method %s", method); - - m->postponed = 0; - m->abandoned = 0; - m->authenticated = 0; - - if (!m->is_initial || - authctxt->init_failures < options.max_init_auth_tries) - m->userauth(authctxt); - - authmethod_count_attempt(m); - - if (authctxt->unwind_dispatch_loop) { - /* - * Method ran nested dispatch loop but was - * abandoned. Cleanup and return without doing - * anything else; we're just unwinding the stack. - */ - authctxt->unwind_dispatch_loop = 0; - goto done; - } - - if (m->postponed) - goto done; /* multi-round trip userauth not finished */ - - if (m->abandoned) { - /* multi-round trip userauth abandoned, log failure */ - auth_log(authctxt, 0, method, " ssh2"); - goto done; - } - } - - userauth_finish(authctxt, method); - -done: - xfree(service); - xfree(user); - xfree(method); -} - -void -userauth_finish(Authctxt *authctxt, char *method) -{ - int authenticated, partial; - - if (authctxt == NULL) - fatal("%s: missing context", __func__); - - /* unknown method handling -- must elicit userauth failure msg */ - if (authctxt->method == NULL) { - authenticated = 0; - partial = 0; - goto done_checking; - } - -#ifndef USE_PAM - /* Special handling for root (done elsewhere for PAM) */ - if (authctxt->method->authenticated && - authctxt->pw != NULL && authctxt->pw->pw_uid == 0 && - !auth_root_allowed(method)) - authctxt->method->authenticated = 0; -#endif /* USE_PAM */ - -#ifdef _UNICOS - if (authctxt->method->authenticated && - cray_access_denied(authctxt->user)) { - authctxt->method->authenticated = 0; - fatal("Access denied for user %s.",authctxt->user); - } -#endif /* _UNICOS */ - - partial = userauth_check_partial_failure(authctxt); - authenticated = authctxt->method->authenticated; - -#ifdef USE_PAM - /* - * If the userauth method failed to complete PAM work then force - * partial failure. - */ - if (authenticated && !AUTHPAM_DONE(authctxt)) - partial = 1; -#endif /* USE_PAM */ - - /* - * To properly support invalid userauth method names we set - * authenticated=0, partial=0 above and know that - * authctxt->method == NULL. - * - * No unguarded reference to authctxt->method allowed from here. - * Checking authenticated != 0 is a valid guard; authctxt->method - * MUST NOT be NULL if authenticated. - */ -done_checking: - if (!authctxt->valid && authenticated) { - /* - * We get here if the PreUserauthHook fails but the - * user is otherwise valid. - * An error in the PAM handling could also get us here - * but we need not panic, just treat as a failure. - */ - authctxt->method->authenticated = 0; - authenticated = 0; - log("Ignoring authenticated invalid user %s", - authctxt->user); - auth_log(authctxt, 0, method, " ssh2"); - } - - /* Log before sending the reply */ - auth_log(authctxt, authenticated, method, " ssh2"); - - if (authenticated && !partial) { - - /* turn off userauth */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); - packet_start(SSH2_MSG_USERAUTH_SUCCESS); - packet_send(); - packet_write_wait(); - /* now we can break out */ - authctxt->success = 1; - } else { - char *methods; - - if (authctxt->method && authctxt->method->is_initial) - authctxt->init_failures++; - - authctxt->method = NULL; - -#ifdef USE_PAM - /* - * Keep track of last PAM error (or PERM_DENIED) for BSM - * login failure auditing, which may run after the PAM - * state has been cleaned up. - */ - authctxt->pam_retval = AUTHPAM_ERROR(authctxt, PAM_PERM_DENIED); -#endif /* USE_PAM */ - - if (authctxt->failures++ > options.max_auth_tries) { -#ifdef HAVE_BSM - fatal_remove_cleanup(audit_failed_login_cleanup, - authctxt); - audit_sshd_login_failure(&ah, PAM_MAXTRIES, - authctxt->user); -#endif /* HAVE_BSM */ - packet_disconnect(AUTH_FAIL_MSG, authctxt->user); - } - -#ifdef _UNICOS - if (strcmp(method, "password") == 0) - cray_login_failure(authctxt->user, IA_UDBERR); -#endif /* _UNICOS */ - packet_start(SSH2_MSG_USERAUTH_FAILURE); - - /* - * If (partial) then authmethods_get() will return only - * required methods, likely only "keyboard-interactive;" - * (methods == NULL) implies failure, even if (partial == 1) - */ - methods = authmethods_get(); - packet_put_cstring(methods); - packet_put_char((authenticated && partial && methods) ? 1 : 0); - if (methods) - xfree(methods); - packet_send(); - packet_write_wait(); - } -} - -/* get current user */ - -struct passwd* -auth_get_user(void) -{ - return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL; -} - -#define DELIM "," - -#if 0 -static char * -authmethods_get_kbdint(void) -{ - Buffer b; - int i; - - for (i = 0; authmethods[i] != NULL; i++) { - if (strcmp(authmethods[i]->name, "keyboard-interactive") != 0) - continue; - return xstrdup(authmethods[i]->name); - } - return NULL; -} -#endif - -void -userauth_user_svc_change(Authctxt *authctxt, char *user, char *service) -{ - /* - * NOTE: - * - * SSHv2 services should be abstracted and service changes during - * userauth should be supported as per the userauth draft. In the PAM - * case, support for multiple SSHv2 services means that we have to - * format the PAM service name according to the SSHv2 service *and* the - * SSHv2 userauth being attempted ("passwd", "kbdint" and "other"). - * - * We'll cross that bridge when we come to it. For now disallow service - * changes during userauth if using PAM, but allow username changes. - */ - - /* authctxt->service must == ssh-connection here */ - if (service != NULL && strcmp(service, authctxt->service) != 0) { - packet_disconnect("Change of service not " - "allowed: %s and %s", - authctxt->service, service); - } - if (user != NULL && authctxt->user != NULL && - strcmp(user, authctxt->user) == 0) - return; - - /* All good; update authctxt */ - xfree(authctxt->user); - authctxt->user = xstrdup(user); - pwfree(&authctxt->pw); - authctxt->pw = getpwnamallow(user); - authctxt->valid = (authctxt->pw != NULL); - - /* Forget method state; abandon postponed userauths */ - userauth_reset_methods(); -} - -int -userauth_check_partial_failure(Authctxt *authctxt) -{ - int i; - int required = 0; - int sufficient = 0; - - /* - * v1 does not set authctxt->method - * partial userauth failure is a v2 concept - */ - if (authctxt->method == NULL) - return 0; - - for (i = 0; authmethods[i] != NULL; i++) { - if (authmethods[i]->required) - required++; - if (authmethods[i]->sufficient) - sufficient++; - } - - if (required == 0 && sufficient == 0) - return !authctxt->method->authenticated; - - if (required == 1 && authctxt->method->required) - return !authctxt->method->authenticated; - - if (sufficient && authctxt->method->sufficient) - return !authctxt->method->authenticated; - - return 1; -} - -int -userauth_method_can_run(Authmethod *method) -{ - if (method->not_again) - return 0; - - return 1; -} - -static -void -userauth_reset_methods(void) -{ - int i; - - for (i = 0; authmethods[i] != NULL; i++) { - /* note: counters not reset */ - authmethods[i]->required = 0; - authmethods[i]->sufficient = 0; - authmethods[i]->authenticated = 0; - authmethods[i]->not_again = 0; - authmethods[i]->postponed = 0; - authmethods[i]->abandoned = 0; - } -} - -void -userauth_force_kbdint(void) -{ - int i; - - for (i = 0; authmethods[i] != NULL; i++) { - authmethods[i]->required = 0; - authmethods[i]->sufficient = 0; - } - method_kbdint.required = 1; -} - -/* - * Check to see if a previously run multi-round trip userauth method has - * been abandoned and call its cleanup function. - * - * Abandoned userauth method invocations are counted as userauth failures. - */ -static -char * -authmethods_check_abandonment(Authctxt *authctxt, Authmethod *method) -{ - int i; - - /* optimization: check current method first */ - if (method && method->postponed) { - method->postponed = 0; - if (method->abandon) - method->abandon(authctxt, method); - else - method->abandons++; - authctxt->failures++; /* abandonment -> failure */ - if (method->is_initial) - authctxt->init_failures++; - - /* - * Since we check for abandonment whenever a userauth is - * requested we know only one method could have been - * in postponed state, so we can return now. - */ - return (method->name); - } - for (i = 0; authmethods[i] != NULL; i++) { - if (!authmethods[i]->postponed) - continue; - - /* some method was postponed and a diff one is being started */ - if (method != authmethods[i]) { - authmethods[i]->postponed = 0; - if (authmethods[i]->abandon) - authmethods[i]->abandon(authctxt, - authmethods[i]); - else - authmethods[i]->abandons++; - authctxt->failures++; - if (authmethods[i]->is_initial) - authctxt->init_failures++; - return (authmethods[i]->name); /* see above */ - } - } - - return NULL; -} - -static char * -authmethods_get(void) -{ - Buffer b; - char *list; - int i; - int sufficient = 0; - int required = 0; - int authenticated = 0; - int partial = 0; - - /* - * If at least one method succeeded partially then at least one - * authmethod will be required and only required methods should - * continue. - */ - for (i = 0; authmethods[i] != NULL; i++) { - if (authmethods[i]->authenticated) - authenticated++; - if (authmethods[i]->required) - required++; - if (authmethods[i]->sufficient) - sufficient++; - } - - partial = (required + sufficient) > 0; - - buffer_init(&b); - for (i = 0; authmethods[i] != NULL; i++) { - if (strcmp(authmethods[i]->name, "none") == 0) - continue; - if (required && !authmethods[i]->required) - continue; - if (sufficient && !required && !authmethods[i]->sufficient) - continue; - if (authmethods[i]->not_again) - continue; - - if (authmethods[i]->required) { - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - buffer_append(&b, authmethods[i]->name, - strlen(authmethods[i]->name)); - continue; - } - - /* - * A method can be enabled (marked sufficient) - * dynamically provided that at least one other method - * has succeeded partially. - */ - if ((partial && authmethods[i]->sufficient) || - (authmethods[i]->enabled != NULL && - *(authmethods[i]->enabled) != 0)) { - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - buffer_append(&b, authmethods[i]->name, - strlen(authmethods[i]->name)); - } - } - buffer_append(&b, "\0", 1); - list = xstrdup(buffer_ptr(&b)); - buffer_free(&b); - return list; -} - -static Authmethod * -authmethod_lookup(const char *name) -{ - int i; - - /* - * Method must be sufficient, required or enabled and must not - * be marked as not able to run again - */ - if (name != NULL) - for (i = 0; authmethods[i] != NULL; i++) - if (((authmethods[i]->sufficient || - authmethods[i]->required) || - (authmethods[i]->enabled != NULL && - *(authmethods[i]->enabled) != 0)) && - !authmethods[i]->not_again && - strcmp(name, authmethods[i]->name) == 0) - return authmethods[i]; - debug2("Unrecognized authentication method name: %s", - name ? name : "NULL"); - return NULL; -} - -static void -authmethod_count_attempt(Authmethod *method) -{ - if (!method) - fatal("Internal error in authmethod_count_attempt()"); - - if (method->postponed) - return; - - method->attempts++; - - if (method->abandoned) - method->abandons++; - else if (method->authenticated) - method->successes++; - else - method->failures++; - - return; -} diff --git a/usr/src/cmd/ssh/sshd/bsmaudit.c b/usr/src/cmd/ssh/sshd/bsmaudit.c deleted file mode 100644 index c46d295972..0000000000 --- a/usr/src/cmd/ssh/sshd/bsmaudit.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * usr/src/cmd/ssh/sshd/bsmaudit.c - * - * Taken from the on81 usr/src/lib/libbsm/common/audit_login.c - */ -#include "includes.h" - -#include <sys/systeminfo.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/systeminfo.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <netinet/in.h> -#include <netdb.h> -#include <signal.h> - -#include <stdarg.h> -#include <pwd.h> -#include <shadow.h> -#include <utmpx.h> -#include <unistd.h> -#include <string.h> - -#include <locale.h> - -#include "log.h" -#include "packet.h" -#include "canohost.h" -#include "servconf.h" -#include "xmalloc.h" -#include <errno.h> -#include <bsm/adt.h> -#include <bsm/adt_event.h> - -extern uint_t utmp_len; /* XXX - Yuck; we'll keep this for now */ -extern ServerOptions options; - /* - * XXX - Yuck; we should have a - * get_client_name_or_ip that does the - * right thing wrt reverse lookups - */ - -void -audit_sshd_chauthtok(int pam_retval, uid_t uid, gid_t gid) -{ - adt_session_data_t *ah = NULL; - adt_event_data_t *event = NULL; - const char *how = "couldn't start adt session"; - int saved_errno = 0; - - if (adt_start_session(&ah, NULL, 0) != 0) { - saved_errno = errno; - goto fail; - } - if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW) != 0) { - saved_errno = errno; - how = "couldn't set adt user"; - goto fail; - } - - if ((event = adt_alloc_event(ah, ADT_passwd)) == NULL) { - saved_errno = errno; - how = "couldn't allocate adt event"; - goto fail; - } - - if (pam_retval == PAM_SUCCESS) { - if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - saved_errno = errno; - how = "couldn't put adt event"; - goto fail; - } - } else if (adt_put_event(event, ADT_FAILURE, - ADT_FAIL_PAM + pam_retval) != 0) { - saved_errno = errno; - how = "couldn't put adt event"; - goto fail; - } - - adt_free_event(event); - (void) adt_end_session(ah); - return; - -fail: - adt_free_event(event); - (void) adt_end_session(ah); - - fatal("Auditing of password change failed: %s (%s)", - strerror(saved_errno), how); -} - -void -audit_sshd_login(adt_session_data_t **ah, pid_t pid) -{ - adt_event_data_t *event = NULL; - const char *how; - int saved_errno = 0; - ucred_t *ucred = NULL; - - if (ah == NULL) { - how = "programmer error"; - saved_errno = EINVAL; - goto fail; - } - - if (adt_start_session(ah, NULL, 0) != 0) { - saved_errno = errno; - how = "couldn't start adt session"; - goto fail; - } - - if ((ucred = ucred_get(pid)) == NULL) { - saved_errno = errno; - how = "ucred_get() failed to obtain user credential"; - goto fail; - } - - if (adt_set_from_ucred(*ah, ucred, ADT_NEW)) { - saved_errno = errno; - how = "adt_set_from_ucred() failed to set user credential"; - goto fail; - } - - if ((event = adt_alloc_event(*ah, ADT_ssh)) == NULL) { - saved_errno = errno; - how = "couldn't allocate adt event"; - goto fail; - } - - if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - saved_errno = errno; - how = "couldn't put adt event"; - goto fail; - } - - adt_free_event(event); - ucred_free(ucred); - /* Don't end adt session - leave for when logging out */ - return; - -fail: - if (ucred != NULL) - ucred_free(ucred); - adt_free_event(event); - (void) adt_end_session(*ah); - - fatal("Auditing of login failed: %s (%s)", - strerror(saved_errno), how); -} - -void -audit_sshd_login_failure(adt_session_data_t **ah, int pam_retval, char *user) -{ - adt_event_data_t *event = NULL; - const char *how; - int saved_errno = 0; - struct passwd pwd; - char *pwdbuf = NULL; - size_t pwdbuf_len; - long pwdbuf_len_max; - uid_t uid = ADT_NO_ATTRIB; - gid_t gid = ADT_NO_ATTRIB; - - if (ah == NULL) { - how = "programmer error"; - saved_errno = EINVAL; - goto fail; - } - - if ((pwdbuf_len_max = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) { - saved_errno = errno; - how = "couldn't determine maximum size of password buffer"; - goto fail; - } - - pwdbuf_len = (size_t)pwdbuf_len_max; - pwdbuf = xmalloc(pwdbuf_len); - - if (adt_start_session(ah, NULL, ADT_USE_PROC_DATA) != 0) { - saved_errno = errno; - how = "couldn't start adt session"; - goto fail; - } - - /* - * Its possible to reach this point with user being invalid so - * we check here to make sure that the user in question has a valid - * password entry. - */ - if ((user != NULL) && - (getpwnam_r(user, &pwd, pwdbuf, pwdbuf_len) != NULL)) { - uid = pwd.pw_uid; - gid = pwd.pw_gid; - } - - if (adt_set_user(*ah, uid, gid, uid, gid, NULL, ADT_NEW) != 0) { - saved_errno = errno; - how = "couldn't set adt user"; - goto fail; - } - - if ((event = adt_alloc_event(*ah, ADT_ssh)) == NULL) { - saved_errno = errno; - how = "couldn't allocate adt event"; - goto fail; - } - - if (adt_put_event(event, ADT_FAILURE, ADT_FAIL_PAM + pam_retval) != 0) { - saved_errno = errno; - how = "couldn't put adt event"; - goto fail; - } - - xfree(pwdbuf); - adt_free_event(event); - (void) adt_end_session(*ah); - *ah = NULL; - return; - -fail: - if (pwdbuf != NULL) - xfree(pwdbuf); - adt_free_event(event); - (void) adt_end_session(*ah); - - fatal("Auditing of login failed: %s (%s)", - strerror(saved_errno), how); -} - -void -audit_sshd_logout(adt_session_data_t **ah) -{ - adt_event_data_t *event = NULL; - const char *how = "programmer error"; - int saved_errno = 0; - - if (!ah) { - saved_errno = EINVAL; - goto fail; - } - - if ((event = adt_alloc_event(*ah, ADT_logout)) == NULL) { - saved_errno = errno; - how = "couldn't allocate adt event"; - goto fail; - } - - if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - saved_errno = errno; - how = "couldn't put adt event"; - goto fail; - } - - adt_free_event(event); - (void) adt_end_session(*ah); - *ah = NULL; - return; - -fail: - adt_free_event(event); - (void) adt_end_session(*ah); - - fatal("Auditing of logout failed: %s (%s)", - how, strerror(saved_errno)); -} - -/* - * audit_sshd_settid stores the terminal id while it is still - * available. - * - * The failure cases are lack of resources or incorrect permissions. - * libbsm generates syslog messages, so there's no value doing more - * here. ADT_NO_AUDIT leaves the auid at AU_NOAUDITID and will be - * replaced when one of the above functions is called. - */ -void -audit_sshd_settid(int sock) -{ - adt_session_data_t *ah; - adt_termid_t *termid; - - if (adt_start_session(&ah, NULL, 0) == 0) { - if (adt_load_termid(sock, &termid) == 0) { - if (adt_set_user(ah, ADT_NO_AUDIT, - ADT_NO_AUDIT, 0, ADT_NO_AUDIT, - termid, ADT_SETTID) == 0) - (void) adt_set_proc(ah); - free(termid); - } - (void) adt_end_session(ah); - } -} diff --git a/usr/src/cmd/ssh/sshd/bsmaudit.h b/usr/src/cmd/ssh/sshd/bsmaudit.h deleted file mode 100644 index 72f599a240..0000000000 --- a/usr/src/cmd/ssh/sshd/bsmaudit.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#ifndef _BSMAUDIT_H -#define _BSMAUDIT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <bsm/adt.h> -#include <bsm/adt_event.h> -#include <pwd.h> - -void audit_sshd_chauthtok(int pam_retval, uid_t uid, gid_t gid); -void audit_sshd_login(adt_session_data_t **ah, pid_t pid); -void audit_sshd_login_failure(adt_session_data_t **ah, int pam_retval, - char *user); -void audit_sshd_logout(adt_session_data_t **ah); -void audit_sshd_settid(int); - -#ifdef __cplusplus -} -#endif - -#endif /* _BSMAUDIT_H */ diff --git a/usr/src/cmd/ssh/sshd/groupaccess.c b/usr/src/cmd/ssh/sshd/groupaccess.c deleted file mode 100644 index 2239832e1b..0000000000 --- a/usr/src/cmd/ssh/sshd/groupaccess.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 2001 Kevin Steves. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: groupaccess.c,v 1.5 2002/03/04 17:27:39 stevesk Exp $"); - -#include "groupaccess.h" -#include "xmalloc.h" -#include "match.h" -#include "log.h" -#include <alloca.h> - -static int ngroups, ngroups_lim; -static char **groups_byname; - -/* - * Initialize group access list for user with primary (base) and - * supplementary groups. Return the number of groups in the list. - */ -int -ga_init(const char *user, gid_t base) -{ - gid_t *groups_bygid; - int i, j; - struct group *gr; - - if (ngroups_lim == 0) { - /* Add one for the base gid */ - ngroups_lim = sysconf(_SC_NGROUPS_MAX) + 1; - groups_byname = malloc(sizeof (char *) * ngroups_lim); - } else if (ngroups > 0) - ga_free(); - - groups_bygid = alloca(ngroups_lim * sizeof (gid_t)); - - ngroups = ngroups_lim; - if (getgrouplist(user, base, groups_bygid, &ngroups) == -1) - log("getgrouplist: groups list too small"); - for (i = 0, j = 0; i < ngroups; i++) - if ((gr = getgrgid(groups_bygid[i])) != NULL) - groups_byname[j++] = xstrdup(gr->gr_name); - return (ngroups = j); -} - -/* - * Return 1 if one of user's groups is contained in groups. - * Return 0 otherwise. Use match_pattern() for string comparison. - */ -int -ga_match(char * const *groups, int n) -{ - int i, j; - - for (i = 0; i < ngroups; i++) - for (j = 0; j < n; j++) - if (match_pattern(groups_byname[i], groups[j])) - return (1); - return (0); -} - -/* - * Return 1 if one of user's groups matches group_pattern list. - * Return 0 on negated or no match. - */ -int -ga_match_pattern_list(const char *group_pattern) -{ - int i, found = 0; - size_t len = strlen(group_pattern); - - for (i = 0; i < ngroups; i++) { - switch (match_pattern_list(groups_byname[i], - group_pattern, len, 0)) { - case -1: - return (0); /* Negated match wins */ - case 0: - continue; - case 1: - found = 1; - } - } - return (found); -} - -/* - * Free memory allocated for group access list. - */ -void -ga_free(void) -{ - int i; - - if (ngroups > 0) { - for (i = 0; i < ngroups; i++) - xfree(groups_byname[i]); - ngroups = 0; - } -} diff --git a/usr/src/cmd/ssh/sshd/gss-serv.c b/usr/src/cmd/ssh/sshd/gss-serv.c deleted file mode 100644 index 7ff525c306..0000000000 --- a/usr/src/cmd/ssh/sshd/gss-serv.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -#ifdef GSSAPI - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "includes.h" -#include "ssh.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "packet.h" -#include "compat.h" -#include <openssl/evp.h> -#include "cipher.h" -#include "kex.h" -#include "auth.h" -#include "log.h" -#include "channels.h" -#include "session.h" -#include "dispatch.h" -#include "servconf.h" -#include "uidswap.h" -#include "compat.h" -#include <pwd.h> - -#include "ssh-gss.h" - -extern char **environ; - -extern ServerOptions options; -extern uchar_t *session_id2; -extern int session_id2_len; - -Gssctxt *xxx_gssctxt; - -void -ssh_gssapi_server_kex_hook(Kex *kex, char **proposal) -{ - gss_OID_set mechs = GSS_C_NULL_OID_SET; - - if (kex == NULL || !kex->server) - fatal("INTERNAL ERROR (%s)", __func__); - - ssh_gssapi_server_mechs(&mechs); - ssh_gssapi_modify_kex(kex, mechs, proposal); -} - -void -ssh_gssapi_server_mechs(gss_OID_set *mechs) -{ - static gss_OID_set supported = GSS_C_NULL_OID_SET; - gss_OID_set s, acquired, indicated = GSS_C_NULL_OID_SET; - gss_cred_id_t creds; - OM_uint32 maj, min; - int i; - - if (!mechs) { - (void) gss_release_oid_set(&min, &supported); - return; - } - - if (supported != GSS_C_NULL_OID_SET) { - *mechs = supported; - return; - } - - *mechs = GSS_C_NULL_OID_SET; - - maj = gss_create_empty_oid_set(&min, &s); - if (GSS_ERROR(maj)) { - debug("Could not allocate GSS-API resources (%s)", - ssh_gssapi_last_error(NULL, &maj, &min)); - return; - } - - maj = gss_indicate_mechs(&min, &indicated); - if (GSS_ERROR(maj)) { - debug("No GSS-API mechanisms are installed"); - return; - } - - maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated, - GSS_C_ACCEPT, &creds, &acquired, NULL); - - if (GSS_ERROR(maj)) - debug("Failed to acquire GSS-API credentials for any " - "mechanisms (%s)", ssh_gssapi_last_error(NULL, &maj, &min)); - - (void) gss_release_oid_set(&min, &indicated); - (void) gss_release_cred(&min, &creds); - - if (acquired == GSS_C_NULL_OID_SET || acquired->count == 0) - return; - - for (i = 0; i < acquired->count; i++) { - if (ssh_gssapi_is_spnego(&acquired->elements[i])) - continue; - - maj = gss_add_oid_set_member(&min, &acquired->elements[i], &s); - if (GSS_ERROR(maj)) { - debug("Could not allocate GSS-API resources (%s)", - ssh_gssapi_last_error(NULL, &maj, &min)); - return; - } - } - (void) gss_release_oid_set(&min, &acquired); - - if (s->count) { - supported = s; - *mechs = s; - } -} - -/* - * Wrapper around accept_sec_context. Requires that the context contains: - * - * oid - * credentials (from ssh_gssapi_acquire_cred) - */ -/* Priviledged */ -OM_uint32 -ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_t recv_tok, - gss_buffer_t send_tok) -{ - /* - * Acquiring a cred for the ctx->desired_mech for GSS_C_NO_NAME - * may well be probably better than using GSS_C_NO_CREDENTIAL - * and then checking that ctx->desired_mech agrees with - * ctx->actual_mech... - */ - ctx->major = gss_accept_sec_context(&ctx->minor, &ctx->context, - GSS_C_NO_CREDENTIAL, recv_tok, GSS_C_NO_CHANNEL_BINDINGS, - &ctx->src_name, &ctx->actual_mech, send_tok, &ctx->flags, - NULL, &ctx->deleg_creds); - - if (GSS_ERROR(ctx->major)) - ssh_gssapi_error(ctx, "accepting security context"); - - if (ctx->major == GSS_S_CONTINUE_NEEDED && send_tok->length == 0) - fatal("Zero length GSS context token output when " - "continue needed"); - else if (GSS_ERROR(ctx->major) && send_tok->length == 0) - debug2("Zero length GSS context error token output"); - - if (ctx->major == GSS_S_COMPLETE && - ctx->desired_mech != GSS_C_NULL_OID && - (ctx->desired_mech->length != ctx->actual_mech->length || - memcmp(ctx->desired_mech->elements, ctx->actual_mech->elements, - ctx->desired_mech->length) != 0)) { - - gss_OID_set supported; - OM_uint32 min; - int present = 0; - - debug("The client did not use the GSS-API mechanism it " - "asked for"); - - /* Let it slide as long as the mech is supported */ - ssh_gssapi_server_mechs(&supported); - if (supported != GSS_C_NULL_OID_SET) { - (void) gss_test_oid_set_member(&min, ctx->actual_mech, - supported, &present); - } - if (!present) - ctx->major = GSS_S_BAD_MECH; - } - - if (ctx->deleg_creds) - debug("Received delegated GSS credentials"); - - if (ctx->major == GSS_S_COMPLETE) { - ctx->major = gss_inquire_context(&ctx->minor, ctx->context, - NULL, &ctx->dst_name, NULL, NULL, NULL, NULL, - &ctx->established); - - if (GSS_ERROR(ctx->major)) { - ssh_gssapi_error(ctx, - "inquiring established sec context"); - return (ctx->major); - } - - xxx_gssctxt = ctx; - } - - return (ctx->major); -} - - -/* As user - called through fatal cleanup hook */ -void -ssh_gssapi_cleanup_creds(Gssctxt *ctx) -{ -#ifdef HAVE_GSS_STORE_CRED - /* pam_setcred() will take care of this */ - return; -#else - return; -/* #error "Portability broken in cleanup of stored creds" */ -#endif /* HAVE_GSS_STORE_CRED */ -} - -void -ssh_gssapi_storecreds(Gssctxt *ctx, Authctxt *authctxt) -{ -#ifdef USE_PAM - char **penv, **tmp_env; -#endif /* USE_PAM */ - - if (authctxt == NULL) { - error("Missing context while storing GSS-API credentials"); - return; - } - - if (ctx == NULL && xxx_gssctxt == NULL) - return; - - if (ctx == NULL) - ctx = xxx_gssctxt; - - if (!options.gss_cleanup_creds || - ctx->deleg_creds == GSS_C_NO_CREDENTIAL) { - debug3("Not storing delegated GSS credentials" - " (none delegated)"); - return; - } - - if (!authctxt->valid || authctxt->pw == NULL) { - debug3("Not storing delegated GSS credentials" - " for invalid user"); - return; - } - - debug("Storing delegated GSS-API credentials"); - - /* - * The GSS-API has a flaw in that it does not provide a - * mechanism by which delegated credentials can be made - * available for acquisition by GSS_Acquire_cred() et. al.; - * gss_store_cred() is the proposed GSS-API extension for - * generically storing delegated credentials. - * - * gss_store_cred() does not speak to how credential stores are - * referenced. Generically this may be done by switching to the - * user context of the user in whose default credential store we - * wish to place delegated credentials. But environment - * variables could conceivably affect the choice of credential - * store as well, and perhaps in a mechanism-specific manner. - * - * SUNW -- On Solaris the euid selects the current credential - * store, but PAM modules could select alternate stores by - * setting, for example, KRB5CCNAME, so we also use the PAM - * environment temporarily. - */ - -#ifdef HAVE_GSS_STORE_CRED -#ifdef USE_PAM - /* - * PAM may have set mechanism-specific variables (e.g., - * KRB5CCNAME). fetch_pam_environment() protects against LD_* - * and other environment variables. - */ - penv = fetch_pam_environment(authctxt); - tmp_env = environ; - environ = penv; -#endif /* USE_PAM */ - if (authctxt->pw->pw_uid != geteuid()) { - temporarily_use_uid(authctxt->pw); - ctx->major = gss_store_cred(&ctx->minor, ctx->deleg_creds, - GSS_C_INITIATE, GSS_C_NULL_OID, 0, ctx->default_creds, - NULL, NULL); - restore_uid(); - } else { - /* only when logging in as the privileged user used by sshd */ - ctx->major = gss_store_cred(&ctx->minor, ctx->deleg_creds, - GSS_C_INITIATE, GSS_C_NULL_OID, 0, ctx->default_creds, - NULL, NULL); - } -#ifdef USE_PAM - environ = tmp_env; - free_pam_environment(penv); -#endif /* USE_PAM */ - if (GSS_ERROR(ctx->major)) - ssh_gssapi_error(ctx, "storing delegated credentials"); - -#else -#ifdef KRB5_GSS -#error "MIT/Heimdal krb5-specific code missing in ssh_gssapi_storecreds()" - if (ssh_gssapi_is_krb5(ctx->mech)) - ssh_gssapi_krb5_storecreds(ctx); -#endif /* KRB5_GSS */ -#ifdef GSI_GSS -#error "GSI krb5-specific code missing in ssh_gssapi_storecreds()" - if (ssh_gssapi_is_gsi(ctx->mech)) - ssh_gssapi_krb5_storecreds(ctx); -#endif /* GSI_GSS */ -/* #error "Mechanism-specific code missing in ssh_gssapi_storecreds()" */ - return; -#endif /* HAVE_GSS_STORE_CRED */ -} - -void -ssh_gssapi_do_child(Gssctxt *ctx, char ***envp, uint_t *envsizep) -{ - /* - * MIT/Heimdal/GSI specific code goes here. - * - * On Solaris there's nothing to do here as the GSS store and - * related environment variables are to be set by PAM, if at all - * (no environment variables are needed to address the default - * credential store -- the euid does that). - */ -#ifdef KRB5_GSS -#error "MIT/Heimdal krb5-specific code missing in ssh_gssapi_storecreds()" -#endif /* KRB5_GSS */ -#ifdef GSI_GSS -#error "GSI krb5-specific code missing in ssh_gssapi_storecreds()" -#endif /* GSI_GSS */ -} - -int -ssh_gssapi_userok(Gssctxt *ctx, char *user) -{ - if (ctx == NULL) { - debug3("INTERNAL ERROR: %s", __func__); - return (0); - } - - if (user == NULL || *user == '\0') - return (0); - -#ifdef HAVE___GSS_USEROK - { - int user_ok = 0; - - ctx->major = __gss_userok(&ctx->minor, ctx->src_name, user, - &user_ok); - if (GSS_ERROR(ctx->major)) { - debug2("__GSS_userok() failed"); - return (0); - } - - if (user_ok) - return (1); - - /* fall through */ - } -#else -#ifdef GSSAPI_SIMPLE_USEROK - { - /* Mechanism-generic */ - OM_uint32 min; - gss_buffer_desc buf, ename1, ename2; - gss_name_t iname, cname; - int eql; - - buf.value = user; - buf.length = strlen(user); - ctx->major = gss_import_name(&ctx->minor, &buf, - GSS_C_NULL_OID, &iname); - if (GSS_ERROR(ctx->major)) { - ssh_gssapi_error(ctx, - "importing name for authorizing initiator"); - goto failed_simple_userok; - } - - ctx->major = gss_canonicalize_name(&ctx->minor, iname, - ctx->actual_mech, &cname); - (void) gss_release_name(&min, &iname); - if (GSS_ERROR(ctx->major)) { - ssh_gssapi_error(ctx, "canonicalizing name"); - goto failed_simple_userok; - } - - ctx->major = gss_export_name(&ctx->minor, cname, &ename1); - (void) gss_release_name(&min, &cname); - if (GSS_ERROR(ctx->major)) { - ssh_gssapi_error(ctx, "exporting name"); - goto failed_simple_userok; - } - - ctx->major = gss_export_name(&ctx->minor, ctx->src_name, - &ename2); - if (GSS_ERROR(ctx->major)) { - ssh_gssapi_error(ctx, - "exporting client principal name"); - (void) gss_release_buffer(&min, &ename1); - goto failed_simple_userok; - } - - eql = (ename1.length == ename2.length && - memcmp(ename1.value, ename2.value, ename1.length) == 0); - - (void) gss_release_buffer(&min, &ename1); - (void) gss_release_buffer(&min, &ename2); - - if (eql) - return (1); - /* fall through */ - } -failed_simple_userok: -#endif /* GSSAPI_SIMPLE_USEROK */ -#ifdef HAVE_GSSCRED_API - { - /* Mechanism-generic, Solaris-specific */ - OM_uint32 maj; - uid_t uid; - struct passwd *pw; - - maj = gsscred_name_to_unix_cred(ctx->src_name, - ctx->actual_mech, &uid, NULL, NULL, NULL); - - if (GSS_ERROR(maj)) - goto failed_simple_gsscred_userok; - - if ((pw = getpwnam(user)) == NULL) - goto failed_simple_gsscred_userok; - - if (pw->pw_uid == uid) - return (1); - /* fall through */ - } - -failed_simple_gsscred_userok: -#endif /* HAVE_GSSCRED_API */ -#ifdef KRB5_GSS - if (ssh_gssapi_is_krb5(ctx->mech)) - if (ssh_gssapi_krb5_userok(ctx->src_name, user)) - return (1); -#endif /* KRB5_GSS */ -#ifdef GSI_GSS - if (ssh_gssapi_is_gsi(ctx->mech)) - if (ssh_gssapi_gsi_userok(ctx->src_name, user)) - return (1); -#endif /* GSI_GSS */ -#endif /* HAVE___GSS_USEROK */ - - /* default to not authorized */ - return (0); -} - -char * -ssh_gssapi_localname(Gssctxt *ctx) -{ - if (ctx == NULL) { - debug3("INTERNAL ERROR: %s", __func__); - return (NULL); - } - - debug2("Mapping initiator GSS-API principal to local username"); -#ifdef HAVE_GSSCRED_API - { - /* Mechanism-generic, Solaris-specific */ - OM_uint32 maj; - uid_t uid; - struct passwd *pw; - - if (ctx->src_name == GSS_C_NO_NAME) - goto failed_gsscred_localname; - - maj = gsscred_name_to_unix_cred(ctx->src_name, - ctx->actual_mech, &uid, NULL, NULL, NULL); - - if (GSS_ERROR(maj)) - goto failed_gsscred_localname; - - if ((pw = getpwuid(uid)) == NULL) - goto failed_gsscred_localname; - - debug2("Mapped the initiator to: %s", pw->pw_name); - return (xstrdup(pw->pw_name)); - } -failed_gsscred_localname: -#endif /* HAVE_GSSCRED_API */ -#ifdef KRB5_GSS -#error "ssh_gssapi_krb5_localname() not implemented" - if (ssh_gssapi_is_krb5(ctx->mech)) - return (ssh_gssapi_krb5_localname(ctx->src_name)); -#endif /* KRB5_GSS */ -#ifdef GSI_GSS -#error "ssh_gssapi_gsi_localname() not implemented" - if (ssh_gssapi_is_gsi(ctx->mech)) - return (ssh_gssapi_gsi_localname(ctx->src_name)); -#endif /* GSI_GSS */ - return (NULL); -} -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/sshd/loginrec.c b/usr/src/cmd/ssh/sshd/loginrec.c deleted file mode 100644 index 33998b02b9..0000000000 --- a/usr/src/cmd/ssh/sshd/loginrec.c +++ /dev/null @@ -1,1533 +0,0 @@ -/* - * Copyright (c) 2000 Andre Lucas. All rights reserved. - * Portions copyright (c) 1998 Todd C. Miller - * Portions copyright (c) 1996 Jason Downs - * Portions copyright (c) 1996 Theo de Raadt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Markus Friedl. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/** - ** loginrec.c: platform-independent login recording and lastlog retrieval - **/ - -/* - The new login code explained - ============================ - - This code attempts to provide a common interface to login recording - (utmp and friends) and last login time retrieval. - - Its primary means of achieving this is to use 'struct logininfo', a - union of all the useful fields in the various different types of - system login record structures one finds on UNIX variants. - - We depend on autoconf to define which recording methods are to be - used, and which fields are contained in the relevant data structures - on the local system. Many C preprocessor symbols affect which code - gets compiled here. - - The code is designed to make it easy to modify a particular - recording method, without affecting other methods nor requiring so - many nested conditional compilation blocks as were commonplace in - the old code. - - For login recording, we try to use the local system's libraries as - these are clearly most likely to work correctly. For utmp systems - this usually means login() and logout() or setutent() etc., probably - in libutil, along with logwtmp() etc. On these systems, we fall back - to writing the files directly if we have to, though this method - requires very thorough testing so we do not corrupt local auditing - information. These files and their access methods are very system - specific indeed. - - For utmpx systems, the corresponding library functions are - setutxent() etc. To the author's knowledge, all utmpx systems have - these library functions and so no direct write is attempted. If such - a system exists and needs support, direct analogues of the [uw]tmp - code should suffice. - - Retrieving the time of last login ('lastlog') is in some ways even - more problemmatic than login recording. Some systems provide a - simple table of all users which we seek based on uid and retrieve a - relatively standard structure. Others record the same information in - a directory with a separate file, and others don't record the - information separately at all. For systems in the latter category, - we look backwards in the wtmp or wtmpx file for the last login entry - for our user. Naturally this is slower and on busy systems could - incur a significant performance penalty. - - Calling the new code - -------------------- - - In OpenSSH all login recording and retrieval is performed in - login.c. Here you'll find working examples. Also, in the logintest.c - program there are more examples. - - Internal handler calling method - ------------------------------- - - When a call is made to login_login() or login_logout(), both - routines set a struct logininfo flag defining which action (log in, - or log out) is to be taken. They both then call login_write(), which - calls whichever of the many structure-specific handlers autoconf - selects for the local system. - - The handlers themselves handle system data structure specifics. Both - struct utmp and struct utmpx have utility functions (see - construct_utmp*()) to try to make it simpler to add extra systems - that introduce new features to either structure. - - While it may seem terribly wasteful to replicate so much similar - code for each method, experience has shown that maintaining code to - write both struct utmp and utmpx in one function, whilst maintaining - support for all systems whether they have library support or not, is - a difficult and time-consuming task. - - Lastlog support proceeds similarly. Functions login_get_lastlog() - (and its OpenSSH-tuned friend login_get_lastlog_time()) call - getlast_entry(), which tries one of three methods to find the last - login time. It uses local system lastlog support if it can, - otherwise it tries wtmp or wtmpx before giving up and returning 0, - meaning "tilt". - - Maintenance - ----------- - - In many cases it's possible to tweak autoconf to select the correct - methods for a particular platform, either by improving the detection - code (best), or by presetting DISABLE_<method> or CONF_<method>_FILE - symbols for the platform. - - Use logintest to check which symbols are defined before modifying - configure.ac and loginrec.c. (You have to build logintest yourself - with 'make logintest' as it's not built by default.) - - Otherwise, patches to the specific method(s) are very helpful! - -*/ - -/** - ** TODO: - ** homegrown ttyslot() - ** test, test, test - ** - ** Platform status: - ** ---------------- - ** - ** Known good: - ** Linux (Redhat 6.2, Debian) - ** Solaris - ** HP-UX 10.20 (gcc only) - ** IRIX - ** NeXT - M68k/HPPA/Sparc (4.2/3.3) - ** - ** Testing required: Please send reports! - ** NetBSD - ** HP-UX 11 - ** AIX - ** - ** Platforms with known problems: - ** Some variants of Slackware Linux - ** - **/ - -#include "includes.h" - -#include "ssh.h" -#include "xmalloc.h" -#include "loginrec.h" -#include "log.h" -#include "atomicio.h" - -RCSID("$Id: loginrec.c,v 1.44 2002/09/26 00:38:49 tim Exp $"); - -#ifdef HAVE_UTIL_H -# include <util.h> -#endif - -#ifdef HAVE_LIBUTIL_H -# include <libutil.h> -#endif - -/** - ** prototypes for helper functions in this file - **/ - -#if HAVE_UTMP_H -void set_utmp_time(struct logininfo *li, struct utmp *ut); -void construct_utmp(struct logininfo *li, struct utmp *ut); -#endif - -#ifdef HAVE_UTMPX_H -void set_utmpx_time(struct logininfo *li, struct utmpx *ut); -void construct_utmpx(struct logininfo *li, struct utmpx *ut); -#endif - -int utmp_write_entry(struct logininfo *li); -int utmpx_write_entry(struct logininfo *li); -int wtmp_write_entry(struct logininfo *li); -int wtmpx_write_entry(struct logininfo *li); -int lastlog_write_entry(struct logininfo *li); -int syslogin_write_entry(struct logininfo *li); - -int getlast_entry(struct logininfo *li); -int lastlog_get_entry(struct logininfo *li); -int wtmp_get_entry(struct logininfo *li); -int wtmpx_get_entry(struct logininfo *li); - -/* pick the shortest string */ -#define MIN_SIZEOF(s1,s2) ( sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2) ) - -/** - ** platform-independent login functions - **/ - -/* login_login(struct logininfo *) -Record a login - * - * Call with a pointer to a struct logininfo initialised with - * login_init_entry() or login_alloc_entry() - * - * Returns: - * >0 if successful - * 0 on failure (will use OpenSSH's logging facilities for diagnostics) - */ -int -login_login (struct logininfo *li) -{ - li->type = LTYPE_LOGIN; - return login_write(li); -} - - -/* login_logout(struct logininfo *) - Record a logout - * - * Call as with login_login() - * - * Returns: - * >0 if successful - * 0 on failure (will use OpenSSH's logging facilities for diagnostics) - */ -int -login_logout(struct logininfo *li) -{ - li->type = LTYPE_LOGOUT; - return login_write(li); -} - -/* login_get_lastlog_time(int) - Retrieve the last login time - * - * Retrieve the last login time for the given uid. Will try to use the - * system lastlog facilities if they are available, but will fall back - * to looking in wtmp/wtmpx if necessary - * - * Returns: - * 0 on failure, or if user has never logged in - * Time in seconds from the epoch if successful - * - * Useful preprocessor symbols: - * DISABLE_LASTLOG: If set, *never* even try to retrieve lastlog - * info - * USE_LASTLOG: If set, indicates the presence of system lastlog - * facilities. If this and DISABLE_LASTLOG are not set, - * try to retrieve lastlog information from wtmp/wtmpx. - */ -#if 0 -unsigned int -login_get_lastlog_time(const int uid) -{ - struct logininfo li; - - if (login_get_lastlog(&li, uid)) - return li.tv_sec; - else - return 0; -} -#endif - -/* login_get_lastlog(struct logininfo *, int) - Retrieve a lastlog entry - * - * Retrieve a logininfo structure populated (only partially) with - * information from the system lastlog data, or from wtmp/wtmpx if no - * system lastlog information exists. - * - * Note this routine must be given a pre-allocated logininfo. - * - * Returns: - * >0: A pointer to your struct logininfo if successful - * 0 on failure (will use OpenSSH's logging facilities for diagnostics) - * - */ -struct logininfo * -login_get_lastlog(struct logininfo *li, const int uid) -{ - struct passwd *pw; - - (void) memset(li, '\0', sizeof(*li)); - li->uid = uid; - - /* - * If we don't have a 'real' lastlog, we need the username to - * reliably search wtmp(x) for the last login (see - * wtmp_get_entry().) - */ - pw = getpwuid(uid); - if (pw == NULL) - fatal("login_get_lastlog: Cannot find account for uid %i", uid); - - /* No MIN_SIZEOF here - we absolutely *must not* truncate the - * username */ - (void) strlcpy(li->username, pw->pw_name, sizeof(li->username)); - - if (getlast_entry(li)) - return li; - else - return NULL; -} - - -/* login_alloc_entry() - Allocate and initialise a logininfo - * structure - * - * This function creates a new struct logininfo, a data structure - * meant to carry the information required to portably record login info. - * - * Returns a pointer to a newly created struct logininfo. If memory - * allocation fails, the program halts. - */ -struct -logininfo *login_alloc_entry(int pid, const char *username, - const char *hostname, const char *line, - const char *progname) -{ - struct logininfo *newli; - - newli = (struct logininfo *) xmalloc (sizeof(*newli)); - (void)login_init_entry(newli, pid, username, hostname, line, progname); - return newli; -} - - -/* login_free_entry(struct logininfo *) - free struct memory */ -void -login_free_entry(struct logininfo *li) -{ - xfree(li); -} - - -/* login_init_entry() - * - initialise a struct logininfo - * - * Populates a new struct logininfo, a data structure meant to carry - * the information required to portably record login info. - * - * Returns: 1 - */ -int -login_init_entry(struct logininfo *li, int pid, const char *username, - const char *hostname, const char *line, const char *progname) -{ - struct passwd *pw; - - (void) memset(li, 0, sizeof(*li)); - - li->pid = pid; - - /* set the line information */ - if (line) - (void) line_fullname(li->line, line, sizeof(li->line)); - else - li->line_null = 1; - - if (progname) - (void) strlcpy(li->progname, progname, sizeof(li->progname)); - else - li->progname_null = 1; - - if (username) { - (void) strlcpy(li->username, username, sizeof(li->username)); - pw = getpwnam(li->username); - if (pw == NULL) - fatal("login_init_entry: Cannot find user \"%s\"", li->username); - li->uid = pw->pw_uid; - } - - if (hostname) - (void) strlcpy(li->hostname, hostname, sizeof(li->hostname)); - - return 1; -} - -/* login_set_current_time(struct logininfo *) - set the current time - * - * Set the current time in a logininfo structure. This function is - * meant to eliminate the need to deal with system dependencies for - * time handling. - */ -void -login_set_current_time(struct logininfo *li) -{ - struct timeval tv; - - (void) gettimeofday(&tv, NULL); - - li->tv_sec = tv.tv_sec; - li->tv_usec = tv.tv_usec; -} - -/* copy a sockaddr_* into our logininfo */ -void -login_set_addr(struct logininfo *li, const struct sockaddr *sa, - const unsigned int sa_size) -{ - unsigned int bufsize = sa_size; - - /* make sure we don't overrun our union */ - if (sizeof(li->hostaddr) < sa_size) - bufsize = sizeof(li->hostaddr); - - (void) memcpy((void *)&(li->hostaddr.sa), (const void *)sa, bufsize); -} - - -/** - ** login_write: Call low-level recording functions based on autoconf - ** results - **/ -int -login_write (struct logininfo *li) -{ -#ifndef HAVE_CYGWIN - if ((int)geteuid() != 0) { - log("Attempt to write login records by non-root user (aborting)"); - return 1; - } -#endif - - /* set the timestamp */ - login_set_current_time(li); -#ifdef USE_LOGIN - syslogin_write_entry(li); -#endif -#ifdef USE_LASTLOG - if (li->type == LTYPE_LOGIN) { - (void) lastlog_write_entry(li); - } -#endif -#ifdef USE_UTMP - utmp_write_entry(li); -#endif -#ifdef USE_WTMP - wtmp_write_entry(li); -#endif -#ifdef USE_UTMPX - (void) utmpx_write_entry(li); -#endif -#ifdef USE_WTMPX - (void) wtmpx_write_entry(li); -#endif - return 0; -} - -/** - ** getlast_entry: Call low-level functions to retrieve the last login - ** time. - **/ - -/* take the uid in li and return the last login time */ -int -getlast_entry(struct logininfo *li) -{ -#ifdef USE_LASTLOG - return(lastlog_get_entry(li)); -#else /* !USE_LASTLOG */ - -#ifdef DISABLE_LASTLOG - /* On some systems we shouldn't even try to obtain last login - * time, e.g. AIX */ - return 0; -# else /* DISABLE_LASTLOG */ - /* Try to retrieve the last login time from wtmp */ -# if defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) - /* retrieve last login time from utmp */ - return (wtmp_get_entry(li)); -# else /* defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) */ - /* If wtmp isn't available, try wtmpx */ -# if defined(USE_WTMPX) && (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX)) - /* retrieve last login time from utmpx */ - return (wtmpx_get_entry(li)); -# else - /* Give up: No means of retrieving last login time */ - return 0; -# endif /* USE_WTMPX && (HAVE_TIME_IN_UTMPX || HAVE_TV_IN_UTMPX) */ -# endif /* USE_WTMP && (HAVE_TIME_IN_UTMP || HAVE_TV_IN_UTMP) */ -# endif /* DISABLE_LASTLOG */ -#endif /* USE_LASTLOG */ -} - - - -/* - * 'line' string utility functions - * - * These functions process the 'line' string into one of three forms: - * - * 1. The full filename (including '/dev') - * 2. The stripped name (excluding '/dev') - * 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00 - * /dev/pts/1 -> ts/1 ) - * - * Form 3 is used on some systems to identify a .tmp.? entry when - * attempting to remove it. Typically both addition and removal is - * performed by one application - say, sshd - so as long as the choice - * uniquely identifies a terminal it's ok. - */ - - -/* line_fullname(): add the leading '/dev/' if it doesn't exist make - * sure dst has enough space, if not just copy src (ugh) */ -char * -line_fullname(char *dst, const char *src, int dstsize) -{ - (void) memset(dst, '\0', dstsize); - /* "sshd" is special, like "ftp" */ - if (strcmp(src, "sshd") || - ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5)))) { - (void) strlcpy(dst, src, dstsize); - } else { - (void) strlcpy(dst, "/dev/", dstsize); - (void) strlcat(dst, src, dstsize); - } - return dst; -} - -/* line_stripname(): strip the leading '/dev' if it exists, return dst */ -char * -line_stripname(char *dst, const char *src, int dstsize) -{ - (void) memset(dst, '\0', dstsize); - if (strncmp(src, "/dev/", 5) == 0) - (void) strlcpy(dst, src + 5, dstsize); - else - (void) strlcpy(dst, src, dstsize); - return dst; -} - -/* line_abbrevname(): Return the abbreviated (usually four-character) - * form of the line (Just use the last <dstsize> characters of the - * full name.) - * - * NOTE: use strncpy because we do NOT necessarily want zero - * termination */ -char * -line_abbrevname(char *dst, const char *src, int dstsize) -{ - size_t len; - - (void) memset(dst, '\0', dstsize); - - /* Always skip prefix if present */ - if (strncmp(src, "/dev/", 5) == 0) - src += 5; - -#ifdef WITH_ABBREV_NO_TTY - if (strncmp(src, "tty", 3) == 0) - src += 3; -#endif - - len = strlen(src); - - if (len > 0) { - if (((int)len - dstsize) > 0) - src += ((int)len - dstsize); - - /* note: _don't_ change this to strlcpy */ - (void) strncpy(dst, src, (size_t)dstsize); - } - - return dst; -} - -/** - ** utmp utility functions - ** - ** These functions manipulate struct utmp, taking system differences - ** into account. - **/ - -#if defined(USE_UTMP) || defined (USE_WTMP) || defined (USE_LOGIN) - -/* build the utmp structure */ -void -set_utmp_time(struct logininfo *li, struct utmp *ut) -{ -# ifdef HAVE_TV_IN_UTMP - ut->ut_tv.tv_sec = li->tv_sec; - ut->ut_tv.tv_usec = li->tv_usec; -# else -# ifdef HAVE_TIME_IN_UTMP - ut->ut_time = li->tv_sec; -# endif -# endif -} - -void -construct_utmp(struct logininfo *li, - struct utmp *ut) -{ - (void) memset(ut, '\0', sizeof(*ut)); - - /* First fill out fields used for both logins and logouts */ - -# ifdef HAVE_ID_IN_UTMP - (void) line_abbrevname(ut->ut_id, li->line, sizeof(ut->ut_id)); -# endif - -# ifdef HAVE_TYPE_IN_UTMP - /* This is done here to keep utmp constants out of struct logininfo */ - switch (li->type) { - case LTYPE_LOGIN: - ut->ut_type = USER_PROCESS; -#ifdef _UNICOS - cray_set_tmpdir(ut); -#endif - break; - case LTYPE_LOGOUT: - ut->ut_type = DEAD_PROCESS; -#ifdef _UNICOS - cray_retain_utmp(ut, li->pid); -#endif - break; - } -# endif - set_utmp_time(li, ut); - - (void) line_stripname(ut->ut_line, li->line, sizeof(ut->ut_line)); - -# ifdef HAVE_PID_IN_UTMP - ut->ut_pid = li->pid; -# endif - - /* If we're logging out, leave all other fields blank */ - if (li->type == LTYPE_LOGOUT) - return; - - /* - * These fields are only used when logging in, and are blank - * for logouts. - */ - - /* Use strncpy because we don't necessarily want null termination */ - (void) strncpy(ut->ut_name, li->username, MIN_SIZEOF(ut->ut_name, li->username)); -# ifdef HAVE_HOST_IN_UTMP - (void) strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname)); -# endif -# ifdef HAVE_ADDR_IN_UTMP - /* this is just a 32-bit IP address */ - if (li->hostaddr.sa.sa_family == AF_INET) - ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; -# endif -} -#endif /* USE_UTMP || USE_WTMP || USE_LOGIN */ - -/** - ** utmpx utility functions - ** - ** These functions manipulate struct utmpx, accounting for system - ** variations. - **/ - -#if defined(USE_UTMPX) || defined (USE_WTMPX) -/* build the utmpx structure */ -void -set_utmpx_time(struct logininfo *li, struct utmpx *utx) -{ -# ifdef HAVE_TV_IN_UTMPX - utx->ut_tv.tv_sec = li->tv_sec; - utx->ut_tv.tv_usec = li->tv_usec; -# else /* HAVE_TV_IN_UTMPX */ -# ifdef HAVE_TIME_IN_UTMPX - utx->ut_time = li->tv_sec; -# endif /* HAVE_TIME_IN_UTMPX */ -# endif /* HAVE_TV_IN_UTMPX */ -} - -void -construct_utmpx(struct logininfo *li, struct utmpx *utx) -{ - (void) memset(utx, '\0', sizeof(*utx)); -# ifdef HAVE_ID_IN_UTMPX - (void) line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id)); -# endif - - /* this is done here to keep utmp constants out of loginrec.h */ - switch (li->type) { - case LTYPE_LOGIN: - utx->ut_type = USER_PROCESS; - break; - case LTYPE_LOGOUT: - utx->ut_type = DEAD_PROCESS; - break; - } - if (!li->line_null) - (void) line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line)); - else if (!li->progname_null) - (void) line_stripname(utx->ut_line, li->progname, sizeof(utx->ut_line)); - - set_utmpx_time(li, utx); - utx->ut_pid = li->pid; - /* strncpy(): Don't necessarily want null termination */ - (void) strncpy(utx->ut_name, li->username, MIN_SIZEOF(utx->ut_name, li->username)); - - if (li->type == LTYPE_LOGOUT) - return; - - /* - * These fields are only used when logging in, and are blank - * for logouts. - */ - -# ifdef HAVE_HOST_IN_UTMPX - (void) strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); -# endif -# ifdef HAVE_ADDR_IN_UTMPX - /* this is just a 32-bit IP address */ - if (li->hostaddr.sa.sa_family == AF_INET) - utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; -# endif -# ifdef HAVE_SYSLEN_IN_UTMPX - /* ut_syslen is the length of the utx_host string */ - utx->ut_syslen = MIN(strlen(li->hostname), sizeof(utx->ut_host)); -# endif -} -#endif /* USE_UTMPX || USE_WTMPX */ - -/** - ** Low-level utmp functions - **/ - -/* FIXME: (ATL) utmp_write_direct needs testing */ -#ifdef USE_UTMP - -/* if we can, use pututline() etc. */ -# if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \ - defined(HAVE_PUTUTLINE) -# define UTMP_USE_LIBRARY -# endif - - -/* write a utmp entry with the system's help (pututline() and pals) */ -# ifdef UTMP_USE_LIBRARY -static int -utmp_write_library(struct logininfo *li, struct utmp *ut) -{ - setutent(); - pututline(ut); - -# ifdef HAVE_ENDUTENT - endutent(); -# endif - return 1; -} -# else /* UTMP_USE_LIBRARY */ - -/* write a utmp entry direct to the file */ -/* This is a slightly modification of code in OpenBSD's login.c */ -static int -utmp_write_direct(struct logininfo *li, struct utmp *ut) -{ - struct utmp old_ut; - register int fd; - int tty; - - /* FIXME: (ATL) ttyslot() needs local implementation */ - -#if defined(HAVE_GETTTYENT) - register struct ttyent *ty; - - tty=0; - - setttyent(); - while ((struct ttyent *)0 != (ty = getttyent())) { - tty++; - if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line))) - break; - } - endttyent(); - - if((struct ttyent *)0 == ty) { - log("utmp_write_entry: tty not found"); - return(1); - } -#else /* FIXME */ - - tty = ttyslot(); /* seems only to work for /dev/ttyp? style names */ - -#endif /* HAVE_GETTTYENT */ - - if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) { - (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); - /* - * Prevent luser from zero'ing out ut_host. - * If the new ut_line is empty but the old one is not - * and ut_line and ut_name match, preserve the old ut_line. - */ - if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) && - (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') && - (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) && - (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) { - (void)memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); - } - - (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); - if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) - log("utmp_write_direct: error writing %s: %s", - UTMP_FILE, strerror(errno)); - - (void)close(fd); - return 1; - } else { - return 0; - } -} -# endif /* UTMP_USE_LIBRARY */ - -static int -utmp_perform_login(struct logininfo *li) -{ - struct utmp ut; - - construct_utmp(li, &ut); -# ifdef UTMP_USE_LIBRARY - if (!utmp_write_library(li, &ut)) { - log("utmp_perform_login: utmp_write_library() failed"); - return 0; - } -# else - if (!utmp_write_direct(li, &ut)) { - log("utmp_perform_login: utmp_write_direct() failed"); - return 0; - } -# endif - return 1; -} - - -static int -utmp_perform_logout(struct logininfo *li) -{ - struct utmp ut; - - construct_utmp(li, &ut); -# ifdef UTMP_USE_LIBRARY - if (!utmp_write_library(li, &ut)) { - log("utmp_perform_logout: utmp_write_library() failed"); - return 0; - } -# else - if (!utmp_write_direct(li, &ut)) { - log("utmp_perform_logout: utmp_write_direct() failed"); - return 0; - } -# endif - return 1; -} - - -int -utmp_write_entry(struct logininfo *li) -{ - if (li->line_null) { - debug3("not writing utmp entry"); - return 1; - } - debug3("writing utmp entry"); - - switch(li->type) { - case LTYPE_LOGIN: - return utmp_perform_login(li); - - case LTYPE_LOGOUT: - return utmp_perform_logout(li); - - default: - log("utmp_write_entry: invalid type field"); - return 0; - } -} -#endif /* USE_UTMP */ - - -/** - ** Low-level utmpx functions - **/ - -/* not much point if we don't want utmpx entries */ -#ifdef USE_UTMPX - -/* if we have the wherewithall, use pututxline etc. */ -# if !defined(DISABLE_PUTUTXLINE) && defined(HAVE_SETUTXENT) && \ - defined(HAVE_PUTUTXLINE) -# define UTMPX_USE_LIBRARY -# endif - - -/* write a utmpx entry with the system's help (pututxline() and pals) */ -# ifdef UTMPX_USE_LIBRARY -static int -utmpx_write_library(struct logininfo *li, struct utmpx *utx) -{ - setutxent(); - (void) pututxline(utx); - -# ifdef HAVE_ENDUTXENT - endutxent(); -# endif - return 1; -} - -# else /* UTMPX_USE_LIBRARY */ - -/* write a utmp entry direct to the file */ -static int -utmpx_write_direct(struct logininfo *li, struct utmpx *utx) -{ - log("utmpx_write_direct: not implemented!"); - return 0; -} -# endif /* UTMPX_USE_LIBRARY */ - -static int -utmpx_perform_login(struct logininfo *li) -{ - struct utmpx utx; - - construct_utmpx(li, &utx); -# ifdef UTMPX_USE_LIBRARY - if (!utmpx_write_library(li, &utx)) { - log("tmpx_perform_login: utmp_write_library() failed"); - return 0; - } -# else - if (!utmpx_write_direct(li, &ut)) { - log("utmpx_perform_login: utmp_write_direct() failed"); - return 0; - } -# endif - return 1; -} - - -static int -utmpx_perform_logout(struct logininfo *li) -{ - struct utmpx utx; - - construct_utmpx(li, &utx); -# ifdef HAVE_ID_IN_UTMPX - (void) line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id)); -# endif -# ifdef HAVE_TYPE_IN_UTMPX - utx.ut_type = DEAD_PROCESS; -# endif - -# ifdef UTMPX_USE_LIBRARY - (void) utmpx_write_library(li, &utx); -# else - utmpx_write_direct(li, &utx); -# endif - return 1; -} - -int -utmpx_write_entry(struct logininfo *li) -{ - if (li->line_null) { - debug3("not writing utmpx entry"); - return 1; - } - debug3("writing utmpx entry"); - - switch(li->type) { - case LTYPE_LOGIN: - return utmpx_perform_login(li); - case LTYPE_LOGOUT: - return utmpx_perform_logout(li); - default: - log("utmpx_write_entry: invalid type field"); - return 0; - } -} -#endif /* USE_UTMPX */ - - -/** - ** Low-level wtmp functions - **/ - -#ifdef USE_WTMP - -/* write a wtmp entry direct to the end of the file */ -/* This is a slight modification of code in OpenBSD's logwtmp.c */ -static int -wtmp_write(struct logininfo *li, struct utmp *ut) -{ - struct stat buf; - int fd, ret = 1; - - if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - log("wtmp_write: problem writing %s: %s", - WTMP_FILE, strerror(errno)); - return 0; - } - if (fstat(fd, &buf) == 0) - if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) { - (void) ftruncate(fd, buf.st_size); - log("wtmp_write: problem writing %s: %s", - WTMP_FILE, strerror(errno)); - ret = 0; - } - (void)close(fd); - return ret; -} - -static int -wtmp_perform_login(struct logininfo *li) -{ - struct utmp ut; - - construct_utmp(li, &ut); - return wtmp_write(li, &ut); -} - - -static int -wtmp_perform_logout(struct logininfo *li) -{ - struct utmp ut; - - construct_utmp(li, &ut); - return wtmp_write(li, &ut); -} - - -int -wtmp_write_entry(struct logininfo *li) -{ - switch(li->type) { - case LTYPE_LOGIN: - return wtmp_perform_login(li); - case LTYPE_LOGOUT: - return wtmp_perform_logout(li); - default: - log("wtmp_write_entry: invalid type field"); - return 0; - } -} - - -/* Notes on fetching login data from wtmp/wtmpx - * - * Logouts are usually recorded with (amongst other things) a blank - * username on a given tty line. However, some systems (HP-UX is one) - * leave all fields set, but change the ut_type field to DEAD_PROCESS. - * - * Since we're only looking for logins here, we know that the username - * must be set correctly. On systems that leave it in, we check for - * ut_type==USER_PROCESS (indicating a login.) - * - * Portability: Some systems may set something other than USER_PROCESS - * to indicate a login process. I don't know of any as I write. Also, - * it's possible that some systems may both leave the username in - * place and not have ut_type. - */ - -/* return true if this wtmp entry indicates a login */ -static int -wtmp_islogin(struct logininfo *li, struct utmp *ut) -{ - if (strncmp(li->username, ut->ut_name, - MIN_SIZEOF(li->username, ut->ut_name)) == 0) { -# ifdef HAVE_TYPE_IN_UTMP - if (ut->ut_type & USER_PROCESS) - return 1; -# else - return 1; -# endif - } - return 0; -} - -int -wtmp_get_entry(struct logininfo *li) -{ - struct stat st; - struct utmp ut; - int fd, found=0; - - /* Clear the time entries in our logininfo */ - li->tv_sec = li->tv_usec = 0; - - if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { - log("wtmp_get_entry: problem opening %s: %s", - WTMP_FILE, strerror(errno)); - return 0; - } - if (fstat(fd, &st) != 0) { - log("wtmp_get_entry: couldn't stat %s: %s", - WTMP_FILE, strerror(errno)); - (void) close(fd); - return 0; - } - - /* Seek to the start of the last struct utmp */ - if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) { - /* Looks like we've got a fresh wtmp file */ - (void) close(fd); - return 0; - } - - while (!found) { - if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) { - log("wtmp_get_entry: read of %s failed: %s", - WTMP_FILE, strerror(errno)); - (void) close (fd); - return 0; - } - if ( wtmp_islogin(li, &ut) ) { - found = 1; - /* We've already checked for a time in struct - * utmp, in login_getlast(). */ -# ifdef HAVE_TIME_IN_UTMP - li->tv_sec = ut.ut_time; -# else -# if HAVE_TV_IN_UTMP - li->tv_sec = ut.ut_tv.tv_sec; -# endif -# endif - (void) line_fullname(li->line, ut.ut_line, - MIN_SIZEOF(li->line, ut.ut_line)); -# ifdef HAVE_HOST_IN_UTMP - (void) strlcpy(li->hostname, ut.ut_host, - MIN_SIZEOF(li->hostname, ut.ut_host)); -# endif - continue; - } - /* Seek back 2 x struct utmp */ - if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) { - /* We've found the start of the file, so quit */ - (void) close (fd); - return 0; - } - } - - /* We found an entry. Tidy up and return */ - (void) close(fd); - return 1; -} -# endif /* USE_WTMP */ - - -/** - ** Low-level wtmpx functions - **/ - -#ifdef USE_WTMPX -/* write a wtmpx entry direct to the end of the file */ -/* This is a slight modification of code in OpenBSD's logwtmp.c */ -static int -wtmpx_write(struct logininfo *li, struct utmpx *utx) -{ - struct stat buf; - int fd, ret = 1; - - if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - log("wtmpx_write: problem opening %s: %s", - WTMPX_FILE, strerror(errno)); - return 0; - } - - if (fstat(fd, &buf) == 0) - if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) { - (void) ftruncate(fd, buf.st_size); - log("wtmpx_write: problem writing %s: %s", - WTMPX_FILE, strerror(errno)); - ret = 0; - } - (void)close(fd); - - return ret; -} - - -static int -wtmpx_perform_login(struct logininfo *li) -{ - struct utmpx utx; - - construct_utmpx(li, &utx); - return wtmpx_write(li, &utx); -} - - -static int -wtmpx_perform_logout(struct logininfo *li) -{ - struct utmpx utx; - - construct_utmpx(li, &utx); - return wtmpx_write(li, &utx); -} - - -int -wtmpx_write_entry(struct logininfo *li) -{ - switch(li->type) { - case LTYPE_LOGIN: - return wtmpx_perform_login(li); - case LTYPE_LOGOUT: - return wtmpx_perform_logout(li); - default: - log("wtmpx_write_entry: invalid type field"); - return 0; - } -} - -/* Please see the notes above wtmp_islogin() for information about the - next two functions */ - -/* Return true if this wtmpx entry indicates a login */ -static int -wtmpx_islogin(struct logininfo *li, struct utmpx *utx) -{ - if ( strncmp(li->username, utx->ut_name, - MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) { -# ifdef HAVE_TYPE_IN_UTMPX - if (utx->ut_type == USER_PROCESS) - return 1; -# else - return 1; -# endif - } - return 0; -} - - -#if 0 -int -wtmpx_get_entry(struct logininfo *li) -{ - struct stat st; - struct utmpx utx; - int fd, found=0; - - /* Clear the time entries */ - li->tv_sec = li->tv_usec = 0; - - if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { - log("wtmpx_get_entry: problem opening %s: %s", - WTMPX_FILE, strerror(errno)); - return 0; - } - if (fstat(fd, &st) != 0) { - log("wtmpx_get_entry: couldn't stat %s: %s", - WTMPX_FILE, strerror(errno)); - (void) close(fd); - return 0; - } - - /* Seek to the start of the last struct utmpx */ - if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) { - /* probably a newly rotated wtmpx file */ - (void) close(fd); - return 0; - } - - while (!found) { - if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) { - log("wtmpx_get_entry: read of %s failed: %s", - WTMPX_FILE, strerror(errno)); - (void) close (fd); - return 0; - } - /* Logouts are recorded as a blank username on a particular line. - * So, we just need to find the username in struct utmpx */ - if ( wtmpx_islogin(li, &utx) ) { - found = 1; -# ifdef HAVE_TV_IN_UTMPX - li->tv_sec = utx.ut_tv.tv_sec; -# else -# ifdef HAVE_TIME_IN_UTMPX - li->tv_sec = utx.ut_time; -# endif -# endif - (void) line_fullname(li->line, utx.ut_line, sizeof(li->line)); -# ifdef HAVE_HOST_IN_UTMPX - (void) strlcpy(li->hostname, utx.ut_host, - MIN_SIZEOF(li->hostname, utx.ut_host)); -# endif - continue; - } - if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) { - (void) close (fd); - return 0; - } - } - - (void) close(fd); - return 1; -} -#endif -#endif /* USE_WTMPX */ - -/** - ** Low-level libutil login() functions - **/ - -#ifdef USE_LOGIN -static int -syslogin_perform_login(struct logininfo *li) -{ - struct utmp *ut; - - if (! (ut = (struct utmp *)malloc(sizeof(*ut)))) { - log("syslogin_perform_login: couldn't malloc()"); - return 0; - } - construct_utmp(li, ut); - login(ut); - - return 1; -} - -static int -syslogin_perform_logout(struct logininfo *li) -{ -# ifdef HAVE_LOGOUT - char line[8]; - - (void)line_stripname(line, li->line, sizeof(line)); - - if (!logout(line)) { - log("syslogin_perform_logout: logout() returned an error"); -# ifdef HAVE_LOGWTMP - } else { - logwtmp(line, "", ""); -# endif - } - /* FIXME: (ATL - if the need arises) What to do if we have - * login, but no logout? what if logout but no logwtmp? All - * routines are in libutil so they should all be there, - * but... */ -# endif - return 1; -} - -int -syslogin_write_entry(struct logininfo *li) -{ - switch (li->type) { - case LTYPE_LOGIN: - return syslogin_perform_login(li); - case LTYPE_LOGOUT: - return syslogin_perform_logout(li); - default: - log("syslogin_write_entry: Invalid type field"); - return 0; - } -} -#endif /* USE_LOGIN */ - -/* end of file log-syslogin.c */ - -/** - ** Low-level lastlog functions - **/ - -#ifdef USE_LASTLOG -#define LL_FILE 1 -#define LL_DIR 2 -#define LL_OTHER 3 - -static void -lastlog_construct(struct logininfo *li, struct lastlog *last) -{ - /* clear the structure */ - (void) memset(last, '\0', sizeof(*last)); - - (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); - (void) strlcpy(last->ll_host, li->hostname, - MIN_SIZEOF(last->ll_host, li->hostname)); - last->ll_time = li->tv_sec; -} - -static int -lastlog_filetype(char *filename) -{ - struct stat st; - - if (stat(LASTLOG_FILE, &st) != 0) { - log("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE, - strerror(errno)); - return 0; - } - if (S_ISDIR(st.st_mode)) - return LL_DIR; - else if (S_ISREG(st.st_mode)) - return LL_FILE; - else - return LL_OTHER; -} - - -/* open the file (using filemode) and seek to the login entry */ -static int -lastlog_openseek(struct logininfo *li, int *fd, int filemode) -{ - off_t offset; - int type; - char lastlog_file[1024]; - - type = lastlog_filetype(LASTLOG_FILE); - switch (type) { - case LL_FILE: - (void) strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); - break; - case LL_DIR: - (void) snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", - LASTLOG_FILE, li->username); - break; - default: - log("lastlog_openseek: %.100s is not a file or directory!", - LASTLOG_FILE); - return 0; - } - - *fd = open(lastlog_file, filemode); - if ( *fd < 0) { - debug("lastlog_openseek: Couldn't open %s: %s", - lastlog_file, strerror(errno)); - return 0; - } - - if (type == LL_FILE) { - /* find this uid's offset in the lastlog file */ - offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); - - if ( lseek(*fd, offset, SEEK_SET) != offset ) { - log("lastlog_openseek: %s->lseek(): %s", - lastlog_file, strerror(errno)); - return 0; - } - } - - return 1; -} - -static int -lastlog_perform_login(struct logininfo *li) -{ - struct lastlog last; - int fd; - - /* create our struct lastlog */ - lastlog_construct(li, &last); - - if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) - return(0); - - /* write the entry */ - if (atomicio(write, fd, &last, sizeof(last)) != sizeof(last)) { - (void) close(fd); - log("lastlog_write_filemode: Error writing to %s: %s", - LASTLOG_FILE, strerror(errno)); - return 0; - } - - (void) close(fd); - return 1; -} - -int -lastlog_write_entry(struct logininfo *li) -{ - switch(li->type) { - case LTYPE_LOGIN: - return lastlog_perform_login(li); - default: - log("lastlog_write_entry: Invalid type field"); - return 0; - } -} - -static void -lastlog_populate_entry(struct logininfo *li, struct lastlog *last) -{ - (void) line_fullname(li->line, last->ll_line, sizeof(li->line)); - (void) strlcpy(li->hostname, last->ll_host, - MIN_SIZEOF(li->hostname, last->ll_host)); - li->tv_sec = last->ll_time; -} - -int -lastlog_get_entry(struct logininfo *li) -{ - struct lastlog last; - int fd, ret; - - if (!lastlog_openseek(li, &fd, O_RDONLY)) - return (0); - - ret = atomicio(read, fd, &last, sizeof(last)); - close(fd); - - switch (ret) { - case 0: - memset(&last, '\0', sizeof(last)); - /* FALLTHRU */ - case sizeof(last): - lastlog_populate_entry(li, &last); - return (1); - case -1: - error("%s: Error reading from %s: %s", __func__, - LASTLOG_FILE, strerror(errno)); - return (0); - default: - error("%s: Error reading from %s: Expecting %d, got %d", - __func__, LASTLOG_FILE, (int)sizeof(last), ret); - return (0); - } - - /* NOTREACHED */ - return (0); -} -#endif /* USE_LASTLOG */ diff --git a/usr/src/cmd/ssh/sshd/mapfile-intf b/usr/src/cmd/ssh/sshd/mapfile-intf deleted file mode 100644 index 6981212730..0000000000 --- a/usr/src/cmd/ssh/sshd/mapfile-intf +++ /dev/null @@ -1,49 +0,0 @@ -# -# 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) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# -# sshd defines its own log(), as do various other ssh utilities, thus their -# symbols are reduced to locals via MAPFILE.NGB in Makefile-ssh.common. sshd -# must export some symbols too, thus this mapfile augments the former. - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -SYMBOL_SCOPE { - global: - allow_severity; # required by libwrap - deny_severity; # required by libwrap -}; diff --git a/usr/src/cmd/ssh/sshd/servconf.c b/usr/src/cmd/ssh/sshd/servconf.c deleted file mode 100644 index 516466bbc1..0000000000 --- a/usr/src/cmd/ssh/sshd/servconf.c +++ /dev/null @@ -1,1494 +0,0 @@ -/* - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Joyent, Inc. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.115 2002/09/04 18:52:42 stevesk Exp $"); - -#ifdef HAVE_DEFOPEN -#include <deflt.h> -#endif /* HAVE_DEFOPEN */ - -#if defined(KRB4) -#include <krb.h> -#endif -#if defined(KRB5) -#ifdef HEIMDAL -#include <krb.h> -#else -/* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V - * keytab */ -#define KEYFILE "/etc/krb5.keytab" -#endif -#endif -#ifdef AFS -#include <kafs.h> -#endif - -#include "ssh.h" -#include "log.h" -#include "buffer.h" -#include "servconf.h" -#include "xmalloc.h" -#include "compat.h" -#include "pathnames.h" -#include "tildexpand.h" -#include "misc.h" -#include "cipher.h" -#include "kex.h" -#include "mac.h" -#include "auth.h" -#include "match.h" -#include "groupaccess.h" - -static void add_listen_addr(ServerOptions *, char *, u_short); -static void add_one_listen_addr(ServerOptions *, char *, u_short); - -extern Buffer cfg; - -/* AF_UNSPEC or AF_INET or AF_INET6 */ -extern int IPv4or6; - -/* - * Initializes the server options to their initial (unset) values. Some of those - * that stay unset after the command line options and configuration files are - * read are set to their default values in fill_default_server_options(). - */ -void -initialize_server_options(ServerOptions *options) -{ - (void) memset(options, 0, sizeof(*options)); - - /* Standard Options */ - options->num_ports = 0; - options->ports_from_cmdline = 0; - options->listen_addrs = NULL; - options->num_host_key_files = 0; - options->pid_file = NULL; - options->server_key_bits = -1; - options->login_grace_time = -1; - options->key_regeneration_time = -1; - options->permit_root_login = PERMIT_NOT_SET; - options->ignore_rhosts = -1; - options->ignore_user_known_hosts = -1; - options->print_motd = -1; - options->print_lastlog = -1; - options->x11_forwarding = -1; - options->x11_display_offset = -1; - options->x11_use_localhost = -1; - options->xauth_location = NULL; - options->strict_modes = -1; - options->keepalives = -1; - options->log_facility = SYSLOG_FACILITY_NOT_SET; - options->log_level = SYSLOG_LEVEL_NOT_SET; - options->rhosts_authentication = -1; - options->rhosts_rsa_authentication = -1; - options->hostbased_authentication = -1; - options->hostbased_uses_name_from_packet_only = -1; - options->rsa_authentication = -1; - options->pubkey_authentication = -1; -#ifdef GSSAPI - options->gss_authentication = -1; - options->gss_keyex = -1; - options->gss_store_creds = -1; - options->gss_use_session_ccache = -1; - options->gss_cleanup_creds = -1; -#endif -#if defined(KRB4) || defined(KRB5) - options->kerberos_authentication = -1; - options->kerberos_or_local_passwd = -1; - options->kerberos_ticket_cleanup = -1; -#endif -#if defined(AFS) || defined(KRB5) - options->kerberos_tgt_passing = -1; -#endif -#ifdef AFS - options->afs_token_passing = -1; -#endif - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; - options->pam_authentication_via_kbd_int = -1; - options->permit_empty_passwd = -1; - options->permit_user_env = -1; - options->compression = -1; - options->allow_tcp_forwarding = -1; - options->num_allow_users = 0; - options->num_deny_users = 0; - options->num_allow_groups = 0; - options->num_deny_groups = 0; - options->ciphers = NULL; - options->macs = NULL; - options->protocol = SSH_PROTO_UNKNOWN; - options->gateway_ports = -1; - options->num_subsystems = 0; - options->max_startups_begin = -1; - options->max_startups_rate = -1; - options->max_startups = -1; - options->banner = NULL; - options->verify_reverse_mapping = -1; - options->client_alive_interval = -1; - options->client_alive_count_max = -1; - options->authorized_keys_file = NULL; - options->authorized_keys_file2 = NULL; - - options->max_auth_tries = -1; - options->max_auth_tries_log = -1; - - options->max_init_auth_tries = -1; - options->max_init_auth_tries_log = -1; - - options->lookup_client_hostnames = -1; - options->use_openssl_engine = -1; - options->chroot_directory = NULL; - options->pre_userauth_hook = NULL; - options->pam_service_name = NULL; - options->pam_service_prefix = NULL; -} - -#ifdef HAVE_DEFOPEN -/* - * Reads /etc/default/login and defaults several ServerOptions: - * - * PermitRootLogin - * PermitEmptyPasswords - * LoginGraceTime - * - * CONSOLE=* -> PermitRootLogin=without-password - * #CONSOLE=* -> PermitRootLogin=yes - * - * PASSREQ=YES -> PermitEmptyPasswords=no - * PASSREQ=NO -> PermitEmptyPasswords=yes - * #PASSREQ=* -> PermitEmptyPasswords=no - * - * TIMEOUT=<secs> -> LoginGraceTime=<secs> - * #TIMEOUT=<secs> -> LoginGraceTime=300 - */ -static -void -deflt_fill_default_server_options(ServerOptions *options) -{ - int flags; - char *ptr; - - if (defopen(_PATH_DEFAULT_LOGIN)) - return; - - /* Ignore case */ - flags = defcntl(DC_GETFLAGS, 0); - TURNOFF(flags, DC_CASE); - (void) defcntl(DC_SETFLAGS, flags); - - if (options->permit_root_login == PERMIT_NOT_SET && - (ptr = defread("CONSOLE=")) != NULL) - options->permit_root_login = PERMIT_NO_PASSWD; - - if (options->permit_empty_passwd == -1 && - (ptr = defread("PASSREQ=")) != NULL) { - if (strcasecmp("YES", ptr) == 0) - options->permit_empty_passwd = 0; - else if (strcasecmp("NO", ptr) == 0) - options->permit_empty_passwd = 1; - } - - if (options->max_init_auth_tries == -1 && - (ptr = defread("RETRIES=")) != NULL) { - options->max_init_auth_tries = atoi(ptr); - } - - if (options->max_init_auth_tries_log == -1 && - (ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) { - options->max_init_auth_tries_log = atoi(ptr); - } - - if (options->login_grace_time == -1) { - if ((ptr = defread("TIMEOUT=")) != NULL) - options->login_grace_time = (unsigned)atoi(ptr); - else - options->login_grace_time = 300; - } - - (void) defopen((char *)NULL); -} -#endif /* HAVE_DEFOPEN */ - -void -fill_default_server_options(ServerOptions *options) -{ - -#ifdef HAVE_DEFOPEN - deflt_fill_default_server_options(options); -#endif /* HAVE_DEFOPEN */ - - /* Standard Options */ - if (options->protocol == SSH_PROTO_UNKNOWN) - options->protocol = SSH_PROTO_1|SSH_PROTO_2; - if (options->num_host_key_files == 0) { - /* fill default hostkeys for protocols */ - if (options->protocol & SSH_PROTO_1) - options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_KEY_FILE; -#ifndef GSSAPI - /* With GSS keyex we can run v2 w/ no host keys */ - if (options->protocol & SSH_PROTO_2) { - options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_RSA_KEY_FILE; - options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_DSA_KEY_FILE; - } -#endif /* GSSAPI */ - } - if (options->num_ports == 0) - options->ports[options->num_ports++] = SSH_DEFAULT_PORT; - if (options->listen_addrs == NULL) - add_listen_addr(options, NULL, 0); - if (options->pid_file == NULL) - options->pid_file = _PATH_SSH_DAEMON_PID_FILE; - if (options->server_key_bits == -1) - options->server_key_bits = 768; - if (options->login_grace_time == -1) - options->login_grace_time = 120; - if (options->key_regeneration_time == -1) - options->key_regeneration_time = 3600; - if (options->permit_root_login == PERMIT_NOT_SET) - options->permit_root_login = PERMIT_YES; - if (options->ignore_rhosts == -1) - options->ignore_rhosts = 1; - if (options->ignore_user_known_hosts == -1) - options->ignore_user_known_hosts = 0; - if (options->print_motd == -1) - options->print_motd = 1; - if (options->print_lastlog == -1) - options->print_lastlog = 1; - if (options->x11_forwarding == -1) - options->x11_forwarding = 1; - if (options->x11_display_offset == -1) - options->x11_display_offset = 10; - if (options->x11_use_localhost == -1) - options->x11_use_localhost = 1; - if (options->xauth_location == NULL) - options->xauth_location = _PATH_XAUTH; - if (options->strict_modes == -1) - options->strict_modes = 1; - if (options->keepalives == -1) - options->keepalives = 1; - if (options->log_facility == SYSLOG_FACILITY_NOT_SET) - options->log_facility = SYSLOG_FACILITY_AUTH; - if (options->log_level == SYSLOG_LEVEL_NOT_SET) - options->log_level = SYSLOG_LEVEL_INFO; - if (options->rhosts_authentication == -1) - options->rhosts_authentication = 0; - if (options->rhosts_rsa_authentication == -1) - options->rhosts_rsa_authentication = 0; - if (options->hostbased_authentication == -1) - options->hostbased_authentication = 0; - if (options->hostbased_uses_name_from_packet_only == -1) - options->hostbased_uses_name_from_packet_only = 0; - if (options->rsa_authentication == -1) - options->rsa_authentication = 1; - if (options->pubkey_authentication == -1) - options->pubkey_authentication = 1; -#ifdef GSSAPI - if (options->gss_authentication == -1) - options->gss_authentication = 1; - if (options->gss_keyex == -1) - options->gss_keyex = 1; - if (options->gss_store_creds == -1) - options->gss_store_creds = 1; - if (options->gss_use_session_ccache == -1) - options->gss_use_session_ccache = 1; - if (options->gss_cleanup_creds == -1) - options->gss_cleanup_creds = 1; -#endif -#if defined(KRB4) || defined(KRB5) - if (options->kerberos_authentication == -1) - options->kerberos_authentication = 0; - if (options->kerberos_or_local_passwd == -1) - options->kerberos_or_local_passwd = 1; - if (options->kerberos_ticket_cleanup == -1) - options->kerberos_ticket_cleanup = 1; -#endif -#if defined(AFS) || defined(KRB5) - if (options->kerberos_tgt_passing == -1) - options->kerberos_tgt_passing = 0; -#endif -#ifdef AFS - if (options->afs_token_passing == -1) - options->afs_token_passing = 0; -#endif - if (options->password_authentication == -1) - options->password_authentication = 1; - /* - * options->pam_authentication_via_kbd_int has intentionally no default - * value since we do not need it. - */ - if (options->kbd_interactive_authentication == -1) - options->kbd_interactive_authentication = 1; - if (options->challenge_response_authentication == -1) - options->challenge_response_authentication = 1; - if (options->permit_empty_passwd == -1) - options->permit_empty_passwd = 0; - if (options->permit_user_env == -1) - options->permit_user_env = 0; - if (options->compression == -1) - options->compression = 1; - if (options->allow_tcp_forwarding == -1) - options->allow_tcp_forwarding = 1; - if (options->gateway_ports == -1) - options->gateway_ports = 0; - if (options->max_startups == -1) - options->max_startups = 10; - if (options->max_startups_rate == -1) - options->max_startups_rate = 100; /* 100% */ - if (options->max_startups_begin == -1) - options->max_startups_begin = options->max_startups; - if (options->verify_reverse_mapping == -1) - options->verify_reverse_mapping = 0; - if (options->client_alive_interval == -1) - options->client_alive_interval = 0; - if (options->client_alive_count_max == -1) - options->client_alive_count_max = 3; - if (options->authorized_keys_file2 == NULL) { - /* authorized_keys_file2 falls back to authorized_keys_file */ - if (options->authorized_keys_file != NULL) - options->authorized_keys_file2 = options->authorized_keys_file; - else - options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; - } - if (options->authorized_keys_file == NULL) - options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; - - if (options->max_auth_tries == -1) - options->max_auth_tries = AUTH_FAIL_MAX; - if (options->max_auth_tries_log == -1) - options->max_auth_tries_log = options->max_auth_tries / 2; - - if (options->max_init_auth_tries == -1) - options->max_init_auth_tries = AUTH_FAIL_MAX; - if (options->max_init_auth_tries_log == -1) - options->max_init_auth_tries_log = options->max_init_auth_tries / 2; - - if (options->lookup_client_hostnames == -1) - options->lookup_client_hostnames = 1; - if (options->use_openssl_engine == -1) - options->use_openssl_engine = 1; - if (options->pam_service_prefix == NULL) - options->pam_service_prefix = _SSH_PAM_SERVICE_PREFIX; - if (options->pam_service_name == NULL) - options->pam_service_name = NULL; -} - -/* Keyword tokens. */ -typedef enum { - sBadOption, /* == unknown option */ - /* Portable-specific options */ - sPAMAuthenticationViaKbdInt, - /* Standard Options */ - sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, -#ifdef GSSAPI - sGssAuthentication, sGssKeyEx, sGssStoreDelegCreds, - sGssUseSessionCredCache, sGssCleanupCreds, -#endif /* GSSAPI */ -#if defined(KRB4) || defined(KRB5) - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -#endif -#if defined(AFS) || defined(KRB5) - sKerberosTgtPassing, -#endif -#ifdef AFS - sAFSTokenPassing, -#endif - sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, - sStrictModes, sEmptyPasswd, sKeepAlives, - sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, - sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, - sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, - sBanner, sVerifyReverseMapping, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sMaxAuthTries, sMaxAuthTriesLog, sUsePrivilegeSeparation, - sLookupClientHostnames, sUseOpenSSLEngine, sChrootDirectory, - sPreUserauthHook, sMatch, sPAMServicePrefix, sPAMServiceName, - sDeprecated -} ServerOpCodes; - -#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ -#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ -#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) - -/* Textual representation of the tokens. */ -static struct { - const char *name; - ServerOpCodes opcode; - u_int flags; -} keywords[] = { - /* Portable-specific options */ - { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt, SSHCFG_GLOBAL }, - /* Standard Options */ - { "port", sPort, SSHCFG_GLOBAL }, - { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, - { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ - { "pidfile", sPidFile, SSHCFG_GLOBAL }, - { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, - { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, - { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, - { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, - { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, - { "loglevel", sLogLevel, SSHCFG_GLOBAL }, - { "rhostsauthentication", sRhostsAuthentication, SSHCFG_GLOBAL }, - { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, - { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, - { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, - { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, - { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, - { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ -#ifdef GSSAPI - { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, - { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, - { "gssapistoredelegatedcredentials", sGssStoreDelegCreds, SSHCFG_GLOBAL }, - { "gssauthentication", sGssAuthentication, SSHCFG_GLOBAL }, /* alias */ - { "gsskeyex", sGssKeyEx, SSHCFG_GLOBAL }, /* alias */ - { "gssstoredelegcreds", sGssStoreDelegCreds, SSHCFG_GLOBAL }, /* alias */ -#ifndef SUNW_GSSAPI - { "gssusesessionccache", sGssUseSessionCredCache, SSHCFG_GLOBAL }, - { "gssusesessioncredcache", sGssUseSessionCredCache, SSHCFG_GLOBAL }, - { "gsscleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, -#endif /* SUNW_GSSAPI */ -#endif -#if defined(KRB4) || defined(KRB5) - { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, - { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, - { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, -#endif -#if defined(AFS) || defined(KRB5) - { "kerberostgtpassing", sKerberosTgtPassing, SSHCFG_GLOBAL }, -#endif -#ifdef AFS - { "afstokenpassing", sAFSTokenPassing, SSHCFG_GLOBAL }, -#endif - { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, - { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, - { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, - { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ - { "checkmail", sDeprecated, SSHCFG_GLOBAL }, - { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, - { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, - { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, - { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, - { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, - { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, - { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, - { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, - { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, - { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, - { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, - { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, - { "uselogin", sUseLogin, SSHCFG_GLOBAL }, - { "compression", sCompression, SSHCFG_GLOBAL }, - { "tcpkeepalive", sKeepAlives, SSHCFG_GLOBAL }, - { "keepalive", sKeepAlives, SSHCFG_GLOBAL }, /* obsolete */ - { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, - { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, - { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, - { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, - { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, - { "ciphers", sCiphers, SSHCFG_GLOBAL }, - { "macs", sMacs, SSHCFG_GLOBAL}, - { "protocol", sProtocol,SSHCFG_GLOBAL }, - { "gatewayports", sGatewayPorts, SSHCFG_ALL }, - { "subsystem", sSubsystem, SSHCFG_GLOBAL}, - { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, - { "banner", sBanner, SSHCFG_ALL }, - { "verifyreversemapping", sVerifyReverseMapping, SSHCFG_GLOBAL }, - { "reversemappingcheck", sVerifyReverseMapping,SSHCFG_GLOBAL }, - { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, - { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, - { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, - { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, - { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, - { "maxauthtrieslog", sMaxAuthTriesLog, SSHCFG_GLOBAL }, - { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, - { "lookupclienthostnames", sLookupClientHostnames, SSHCFG_GLOBAL }, - { "useopensslengine", sUseOpenSSLEngine, SSHCFG_GLOBAL }, - { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, - { "preuserauthhook", sPreUserauthHook, SSHCFG_ALL}, - { "match", sMatch, SSHCFG_ALL }, - { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL }, - { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL }, - - { NULL, sBadOption, 0 } -}; - -/* - * Returns the number of the token pointed to by cp or sBadOption. - */ - -static ServerOpCodes -parse_token(const char *cp, const char *filename, - int linenum, u_int *flags) -{ - u_int i; - - for (i = 0; keywords[i].name; i++) - if (strcasecmp(cp, keywords[i].name) == 0) { - *flags = keywords[i].flags; - return keywords[i].opcode; - } - - error("%s: line %d: Bad configuration option: %s", - filename, linenum, cp); - return sBadOption; -} - -static void -add_listen_addr(ServerOptions *options, char *addr, u_short port) -{ - int i; - - if (options->num_ports == 0) - options->ports[options->num_ports++] = SSH_DEFAULT_PORT; - if (port == 0) - for (i = 0; i < options->num_ports; i++) - add_one_listen_addr(options, addr, options->ports[i]); - else - add_one_listen_addr(options, addr, port); -} - -static void -add_one_listen_addr(ServerOptions *options, char *addr, u_short port) -{ - struct addrinfo hints, *ai, *aitop; - char strport[NI_MAXSERV]; - int gaierr; - - (void) memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; - (void) snprintf(strport, sizeof strport, "%u", port); - if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) - fatal("bad addr or host: %s (%s)", - addr ? addr : "<NULL>", - gai_strerror(gaierr)); - for (ai = aitop; ai->ai_next; ai = ai->ai_next) - ; - ai->ai_next = options->listen_addrs; - options->listen_addrs = aitop; -} - -/* - * The strategy for the Match blocks is that the config file is parsed twice. - * - * The first time is at startup. activep is initialized to 1 and the - * directives in the global context are processed and acted on. Hitting a - * Match directive unsets activep and the directives inside the block are - * checked for syntax only. - * - * The second time is after a connection has been established but before - * authentication. activep is initialized to 2 and global config directives - * are ignored since they have already been processed. If the criteria in a - * Match block is met, activep is set and the subsequent directives - * processed and actioned until EOF or another Match block unsets it. Any - * options set are copied into the main server config. - * - * Potential additions/improvements: - * - Add Match support for pre-kex directives, eg Protocol, Ciphers. - * - * - Add a Tag directive (idea from David Leonard) ala pf, eg: - * Match Address 192.168.0.* - * Tag trusted - * Match Group wheel - * Tag trusted - * Match Tag trusted - * AllowTcpForwarding yes - * GatewayPorts clientspecified - * [...] - * - * - Add a PermittedChannelRequests directive - * Match Group shell - * PermittedChannelRequests session,forwarded-tcpip - */ - -static int -match_cfg_line_group(const char *grps, int line, const char *user) -{ - int result = 0; - struct passwd *pw; - - if (user == NULL) - goto out; - - if ((pw = getpwnam(user)) == NULL) { - debug("Can't match group at line %d because user %.100s does " - "not exist", line, user); - } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { - debug("Can't Match group because user %.100s not in any group " - "at line %d", user, line); - } else if (ga_match_pattern_list(grps) != 1) { - debug("user %.100s does not match group list %.100s at line %d", - user, grps, line); - } else { - debug("user %.100s matched group list %.100s at line %d", user, - grps, line); - result = 1; - } -out: - ga_free(); - return result; -} - -static int -match_cfg_line(char **condition, int line, const char *user, const char *host, - const char *address) -{ - int result = 1; - char *arg, *attrib, *cp = *condition; - size_t len; - - if (user == NULL) - debug3("checking syntax for 'Match %s'", cp); - else - debug3("checking match for '%s' user %s host %s addr %s", cp, - user ? user : "(null)", host ? host : "(null)", - address ? address : "(null)"); - - while ((attrib = strdelim(&cp)) != NULL && *attrib != '\0') { - if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { - error("Missing Match criteria for %s", attrib); - return -1; - } - len = strlen(arg); - if (strcasecmp(attrib, "user") == 0) { - if (!user) { - result = 0; - continue; - } - if (match_pattern_list(user, arg, len, 0) != 1) - result = 0; - else - debug("user %.100s matched 'User %.100s' at " - "line %d", user, arg, line); - } else if (strcasecmp(attrib, "group") == 0) { - switch (match_cfg_line_group(arg, line, user)) { - case -1: - return -1; - case 0: - result = 0; - } - } else if (strcasecmp(attrib, "host") == 0) { - if (!host) { - result = 0; - continue; - } - if (match_hostname(host, arg, len) != 1) - result = 0; - else - debug("connection from %.100s matched 'Host " - "%.100s' at line %d", host, arg, line); - } else if (strcasecmp(attrib, "address") == 0) { - switch (addr_match_list(address, arg)) { - case 1: - debug("connection from %.100s matched 'Address " - "%.100s' at line %d", address, arg, line); - break; - case 0: - case -1: - result = 0; - break; - case -2: - return -1; - } - } else { - error("Unsupported Match attribute %s", attrib); - return -1; - } - } - if (user != NULL) - debug3("match %sfound", result ? "" : "not "); - *condition = cp; - return result; -} - -#define WHITESPACE " \t\r\n" - -int -process_server_config_line(ServerOptions *options, char *line, - const char *filename, int linenum, int *activep, const char *user, - const char *host, const char *address) -{ - char *cp, **charptr, *arg, *p; - int cmdline = 0, *intptr, value, n; - ServerOpCodes opcode; - u_int i, flags = 0; - size_t len; - - cp = line; - arg = strdelim(&cp); - /* Ignore leading whitespace */ - if (*arg == '\0') - arg = strdelim(&cp); - if (!arg || !*arg || *arg == '#') - return 0; - intptr = NULL; - charptr = NULL; - opcode = parse_token(arg, filename, linenum, &flags); - - if (activep == NULL) { /* We are processing a command line directive */ - cmdline = 1; - activep = &cmdline; - } - if (*activep && opcode != sMatch) - debug3("%s:%d setting %s %s", filename, linenum, arg, cp); - if (*activep == 0 && !(flags & SSHCFG_MATCH)) { - if (user == NULL) { - fatal("%s line %d: Directive '%s' is not allowed " - "within a Match block", filename, linenum, arg); - } else { /* this is a directive we have already processed */ - while (arg) - arg = strdelim(&cp); - return 0; - } - } - - switch (opcode) { - /* Portable-specific options */ - case sPAMAuthenticationViaKbdInt: - log("%s line %d: PAMAuthenticationViaKbdInt has been " - "deprecated. You should use KbdInteractiveAuthentication " - "instead (which defaults to \"yes\").", filename, linenum); - intptr = &options->pam_authentication_via_kbd_int; - goto parse_flag; - - /* Standard Options */ - case sBadOption: - return -1; - case sPort: - /* ignore ports from configfile if cmdline specifies ports */ - if (options->ports_from_cmdline) - return 0; - if (options->listen_addrs != NULL) - fatal("%s line %d: ports must be specified before " - "ListenAddress.", filename, linenum); - if (options->num_ports >= MAX_PORTS) - fatal("%s line %d: too many ports.", - filename, linenum); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing port number.", - filename, linenum); - options->ports[options->num_ports++] = a2port(arg); - if (options->ports[options->num_ports-1] == 0) - fatal("%s line %d: Badly formatted port number.", - filename, linenum); - break; - - case sServerKeyBits: - intptr = &options->server_key_bits; -parse_int: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing integer value.", - filename, linenum); - value = atoi(arg); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case sLoginGraceTime: - intptr = &options->login_grace_time; -parse_time: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing time value.", - filename, linenum); - if ((value = convtime(arg)) == -1) - fatal("%s line %d: invalid time value.", - filename, linenum); - if (*intptr == -1) - *intptr = value; - break; - - case sKeyRegenerationTime: - intptr = &options->key_regeneration_time; - goto parse_time; - - case sListenAddress: - arg = strdelim(&cp); - if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) - fatal("%s line %d: missing inet addr.", - filename, linenum); - if (*arg == '[') { - if ((p = strchr(arg, ']')) == NULL) - fatal("%s line %d: bad ipv6 inet addr usage.", - filename, linenum); - arg++; - (void) memmove(p, p+1, strlen(p+1)+1); - } else if (((p = strchr(arg, ':')) == NULL) || - (strchr(p+1, ':') != NULL)) { - add_listen_addr(options, arg, 0); - break; - } - if (*p == ':') { - u_short port; - - p++; - if (*p == '\0') - fatal("%s line %d: bad inet addr:port usage.", - filename, linenum); - else { - *(p-1) = '\0'; - if ((port = a2port(p)) == 0) - fatal("%s line %d: bad port number.", - filename, linenum); - add_listen_addr(options, arg, port); - } - } else if (*p == '\0') - add_listen_addr(options, arg, 0); - else - fatal("%s line %d: bad inet addr usage.", - filename, linenum); - break; - - case sHostKeyFile: - intptr = &options->num_host_key_files; - if (*intptr >= MAX_HOSTKEYS) - fatal("%s line %d: too many host keys specified (max %d).", - filename, linenum, MAX_HOSTKEYS); - charptr = &options->host_key_files[*intptr]; -parse_filename: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing file name.", - filename, linenum); - if (*activep && *charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ - if (intptr != NULL) - *intptr = *intptr + 1; - } - break; - - case sPidFile: - charptr = &options->pid_file; - goto parse_filename; - - case sPermitRootLogin: - intptr = &options->permit_root_login; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/" - "without-password/forced-commands-only/no " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "without-password") == 0) - value = PERMIT_NO_PASSWD; - else if (strcmp(arg, "forced-commands-only") == 0) - value = PERMIT_FORCED_ONLY; - else if (strcmp(arg, "yes") == 0) - value = PERMIT_YES; - else if (strcmp(arg, "no") == 0) - value = PERMIT_NO; - else - fatal("%s line %d: Bad yes/" - "without-password/forced-commands-only/no " - "argument: %s", filename, linenum, arg); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case sIgnoreRhosts: - intptr = &options->ignore_rhosts; -parse_flag: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no argument.", - filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no argument: %s", - filename, linenum, arg); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case sIgnoreUserKnownHosts: - intptr = &options->ignore_user_known_hosts; - goto parse_flag; - - case sRhostsAuthentication: - intptr = &options->rhosts_authentication; - goto parse_flag; - - case sRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; - - case sHostbasedAuthentication: - intptr = &options->hostbased_authentication; - goto parse_flag; - - case sHostbasedUsesNameFromPacketOnly: - intptr = &options->hostbased_uses_name_from_packet_only; - goto parse_flag; - - case sRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; - - case sPubkeyAuthentication: - intptr = &options->pubkey_authentication; - goto parse_flag; -#ifdef GSSAPI - case sGssAuthentication: - intptr = &options->gss_authentication; - goto parse_flag; - case sGssKeyEx: - intptr = &options->gss_keyex; - goto parse_flag; - case sGssStoreDelegCreds: - intptr = &options->gss_keyex; - goto parse_flag; -#ifndef SUNW_GSSAPI - case sGssUseSessionCredCache: - intptr = &options->gss_use_session_ccache; - goto parse_flag; - case sGssCleanupCreds: - intptr = &options->gss_cleanup_creds; - goto parse_flag; -#endif /* SUNW_GSSAPI */ -#endif /* GSSAPI */ -#if defined(KRB4) || defined(KRB5) - case sKerberosAuthentication: - intptr = &options->kerberos_authentication; - goto parse_flag; - - case sKerberosOrLocalPasswd: - intptr = &options->kerberos_or_local_passwd; - goto parse_flag; - - case sKerberosTicketCleanup: - intptr = &options->kerberos_ticket_cleanup; - goto parse_flag; -#endif -#if defined(AFS) || defined(KRB5) - case sKerberosTgtPassing: - intptr = &options->kerberos_tgt_passing; - goto parse_flag; -#endif -#ifdef AFS - case sAFSTokenPassing: - intptr = &options->afs_token_passing; - goto parse_flag; -#endif - - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; - - case sKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; - - case sChallengeResponseAuthentication: - intptr = &options->challenge_response_authentication; - goto parse_flag; - - case sPrintMotd: - intptr = &options->print_motd; - goto parse_flag; - - case sPrintLastLog: - intptr = &options->print_lastlog; - goto parse_flag; - - case sX11Forwarding: - intptr = &options->x11_forwarding; - goto parse_flag; - - case sX11DisplayOffset: - intptr = &options->x11_display_offset; - goto parse_int; - - case sX11UseLocalhost: - intptr = &options->x11_use_localhost; - goto parse_flag; - - case sXAuthLocation: - charptr = &options->xauth_location; - goto parse_filename; - - case sStrictModes: - intptr = &options->strict_modes; - goto parse_flag; - - case sKeepAlives: - intptr = &options->keepalives; - goto parse_flag; - - case sEmptyPasswd: - intptr = &options->permit_empty_passwd; - goto parse_flag; - - case sPermitUserEnvironment: - intptr = &options->permit_user_env; - goto parse_flag; - - case sUseLogin: - log("%s line %d: ignoring UseLogin option value." - " This option is always off.", filename, linenum); - while (arg) - arg = strdelim(&cp); - break; - - case sCompression: - intptr = &options->compression; - goto parse_flag; - - case sGatewayPorts: - intptr = &options->gateway_ports; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no/clientspecified " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "clientspecified") == 0) - value = 2; - else if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no/clientspecified " - "argument: %s", filename, linenum, arg); - if (*activep && *intptr == -1) - *intptr = value; - break; - - case sVerifyReverseMapping: - intptr = &options->verify_reverse_mapping; - goto parse_flag; - - case sLogFacility: - intptr = (int *) &options->log_facility; - arg = strdelim(&cp); - value = log_facility_number(arg); - if (value == SYSLOG_FACILITY_NOT_SET) - fatal("%.200s line %d: unsupported log facility '%s'", - filename, linenum, arg ? arg : "<NONE>"); - if (*intptr == -1) - *intptr = (SyslogFacility) value; - break; - - case sLogLevel: - intptr = (int *) &options->log_level; - arg = strdelim(&cp); - value = log_level_number(arg); - if (value == SYSLOG_LEVEL_NOT_SET) - fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : "<NONE>"); - if (*intptr == -1) - *intptr = (LogLevel) value; - break; - - case sAllowTcpForwarding: - intptr = &options->allow_tcp_forwarding; - goto parse_flag; - - case sUsePrivilegeSeparation: - log("%s line %d: ignoring UsePrivilegeSeparation option value." - " This option is always on.", filename, linenum); - while (arg) - arg = strdelim(&cp); - break; - - case sAllowUsers: - while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { - if (options->num_allow_users >= MAX_ALLOW_USERS) - fatal("%s line %d: too many allow users.", - filename, linenum); - options->allow_users[options->num_allow_users++] = - xstrdup(arg); - } - break; - - case sDenyUsers: - while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { - if (options->num_deny_users >= MAX_DENY_USERS) - fatal( "%s line %d: too many deny users.", - filename, linenum); - options->deny_users[options->num_deny_users++] = - xstrdup(arg); - } - break; - - case sAllowGroups: - while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { - if (options->num_allow_groups >= MAX_ALLOW_GROUPS) - fatal("%s line %d: too many allow groups.", - filename, linenum); - options->allow_groups[options->num_allow_groups++] = - xstrdup(arg); - } - break; - - case sDenyGroups: - while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { - if (options->num_deny_groups >= MAX_DENY_GROUPS) - fatal("%s line %d: too many deny groups.", - filename, linenum); - options->deny_groups[options->num_deny_groups++] = xstrdup(arg); - } - break; - - case sCiphers: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) - fatal("%s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (options->ciphers == NULL) - options->ciphers = xstrdup(arg); - break; - - case sMacs: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) - fatal("%s line %d: Bad SSH2 mac spec '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (options->macs == NULL) - options->macs = xstrdup(arg); - break; - - case sProtocol: - intptr = &options->protocol; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - value = proto_spec(arg); - if (value == SSH_PROTO_UNKNOWN) - fatal("%s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : "<NONE>"); - if (*intptr == SSH_PROTO_UNKNOWN) - *intptr = value; - break; - - case sSubsystem: - if (options->num_subsystems >= MAX_SUBSYSTEMS) { - fatal("%s line %d: too many subsystems defined.", - filename, linenum); - } - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - if (!*activep) { - arg = strdelim(&cp); - break; - } - for (i = 0; i < options->num_subsystems; i++) - if (strcmp(arg, options->subsystem_name[i]) == 0) - fatal("%s line %d: Subsystem '%s' already defined.", - filename, linenum, arg); - options->subsystem_name[options->num_subsystems] = xstrdup(arg); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem command.", - filename, linenum); - options->subsystem_command[options->num_subsystems] = xstrdup(arg); - - /* - * Collect arguments (separate to executable), including the - * name of the executable, in a way that is easier to parse - * later. - */ - p = xstrdup(arg); - len = strlen(p) + 1; - while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { - len += 1 + strlen(arg); - p = xrealloc(p, len); - strlcat(p, " ", len); - strlcat(p, arg, len); - } - options->subsystem_args[options->num_subsystems] = p; - options->num_subsystems++; - break; - - case sMaxStartups: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing MaxStartups spec.", - filename, linenum); - if ((n = sscanf(arg, "%d:%d:%d", - &options->max_startups_begin, - &options->max_startups_rate, - &options->max_startups)) == 3) { - if (options->max_startups_begin > - options->max_startups || - options->max_startups_rate > 100 || - options->max_startups_rate < 1) - fatal("%s line %d: Illegal MaxStartups spec.", - filename, linenum); - } else if (n != 1) - fatal("%s line %d: Illegal MaxStartups spec.", - filename, linenum); - else - options->max_startups = options->max_startups_begin; - break; - - case sBanner: - charptr = &options->banner; - goto parse_filename; - /* - * These options can contain %X options expanded at - * connect time, so that you can specify paths like: - * - * AuthorizedKeysFile /etc/ssh_keys/%u - */ - case sAuthorizedKeysFile: - case sAuthorizedKeysFile2: - charptr = (opcode == sAuthorizedKeysFile) ? - &options->authorized_keys_file : - &options->authorized_keys_file2; - goto parse_filename; - - case sClientAliveInterval: - intptr = &options->client_alive_interval; - goto parse_time; - - case sClientAliveCountMax: - intptr = &options->client_alive_count_max; - goto parse_int; - - case sMaxAuthTries: - intptr = &options->max_auth_tries; - goto parse_int; - - case sMaxAuthTriesLog: - intptr = &options->max_auth_tries_log; - goto parse_int; - - case sLookupClientHostnames: - intptr = &options->lookup_client_hostnames; - goto parse_flag; - - case sUseOpenSSLEngine: - intptr = &options->use_openssl_engine; - goto parse_flag; - - case sChrootDirectory: - charptr = &options->chroot_directory; - - arg = strdelim(&cp); - if (arg == NULL || *arg == '\0') - fatal("%s line %d: missing directory name for " - "ChrootDirectory.", filename, linenum); - if (*activep && *charptr == NULL) - *charptr = xstrdup(arg); - break; - - case sPreUserauthHook: - charptr = &options->pre_userauth_hook; - goto parse_filename; - - case sMatch: - if (cmdline) - fatal("Match directive not supported as a command-line " - "option"); - value = match_cfg_line(&cp, linenum, user, host, address); - if (value < 0) - fatal("%s line %d: Bad Match condition", filename, - linenum); - *activep = value; - break; - - case sDeprecated: - log("%s line %d: Deprecated option %s", - filename, linenum, arg); - while (arg) - arg = strdelim(&cp); - break; - - case sPAMServicePrefix: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", - filename, linenum); - if (options->pam_service_name != NULL) - fatal("%s line %d: PAMServiceName and PAMServicePrefix " - "are mutually exclusive.", filename, linenum); - if (options->pam_service_prefix == NULL) - options->pam_service_prefix = xstrdup(arg); - break; - - case sPAMServiceName: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", - filename, linenum); - if (options->pam_service_prefix != NULL) - fatal("%s line %d: PAMServiceName and PAMServicePrefix " - "are mutually exclusive.", filename, linenum); - if (options->pam_service_name == NULL) - options->pam_service_name = xstrdup(arg); - break; - - default: - fatal("%s line %d: Missing handler for opcode %s (%d)", - filename, linenum, arg, opcode); - } - if ((arg = strdelim(&cp)) != NULL && *arg != '\0') - fatal("%s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); - return 0; -} - - -/* Reads the server configuration file. */ - -void -load_server_config(const char *filename, Buffer *conf) -{ - char line[1024], *cp; - FILE *f; - - debug2("%s: filename %s", __func__, filename); - if ((f = fopen(filename, "r")) == NULL) { - perror(filename); - exit(1); - } - buffer_clear(conf); - while (fgets(line, sizeof(line), f)) { - /* - * Trim out comments and strip whitespace - * NB - preserve newlines, they are needed to reproduce - * line numbers later for error messages - */ - if ((cp = strchr(line, '#')) != NULL) - memcpy(cp, "\n", 2); - cp = line + strspn(line, " \t\r"); - - buffer_append(conf, cp, strlen(cp)); - } - buffer_append(conf, "\0", 1); - fclose(f); - debug2("%s: done config len = %d", __func__, buffer_len(conf)); -} - -void -parse_server_match_config(ServerOptions *options, const char *user, - const char *host, const char *address) -{ - ServerOptions mo; - - initialize_server_options(&mo); - parse_server_config(&mo, "reprocess config", &cfg, user, host, address); - copy_set_server_options(options, &mo, 0); -} - - - -/* Helper macros */ -#define M_CP_INTOPT(n) do {\ - if (src->n != -1) \ - dst->n = src->n; \ -} while (0) -#define M_CP_STROPT(n) do {\ - if (src->n != NULL) { \ - if (dst->n != NULL) \ - xfree(dst->n); \ - dst->n = src->n; \ - } \ -} while(0) - -/* - * Copy any supported values that are set. - * - * If the preauth flag is set, we do not bother copying the the string or - * array values that are not used pre-authentication, because any that we - * do use must be explictly sent in mm_getpwnamallow(). - */ -void -copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) -{ - M_CP_INTOPT(password_authentication); - M_CP_INTOPT(gss_authentication); - M_CP_INTOPT(rsa_authentication); - M_CP_INTOPT(pubkey_authentication); - M_CP_INTOPT(hostbased_authentication); - M_CP_INTOPT(kbd_interactive_authentication); - M_CP_INTOPT(permit_root_login); - M_CP_INTOPT(permit_empty_passwd); - M_CP_INTOPT(allow_tcp_forwarding); - M_CP_INTOPT(gateway_ports); - M_CP_INTOPT(x11_display_offset); - M_CP_INTOPT(x11_forwarding); - M_CP_INTOPT(x11_use_localhost); - M_CP_INTOPT(max_auth_tries); - M_CP_STROPT(banner); - - if (preauth) - return; - M_CP_STROPT(chroot_directory); -} - -#undef M_CP_INTOPT -#undef M_CP_STROPT - -void -parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, - const char *user, const char *host, const char *address) -{ - int active, linenum, bad_options = 0; - char *cp, *obuf, *cbuf; - - debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); - - obuf = cbuf = xstrdup(buffer_ptr(conf)); - active = user ? 0 : 1; - linenum = 1; - while ((cp = strsep(&cbuf, "\n")) != NULL) { - if (process_server_config_line(options, cp, filename, - linenum++, &active, user, host, address) != 0) - bad_options++; - } - xfree(obuf); - if (bad_options > 0) - fatal("%s: terminating, %d bad configuration options", - filename, bad_options); -} - - -/* - * Note that "none" is a special path having the same affect on sshd - * configuration as not specifying ChrootDirectory at all. - */ -int -chroot_requested(char *chroot_directory) -{ - return (chroot_directory != NULL && - strcasecmp(chroot_directory, "none") != 0); -} diff --git a/usr/src/cmd/ssh/sshd/serverloop.c b/usr/src/cmd/ssh/sshd/serverloop.c deleted file mode 100644 index 3dae9b1840..0000000000 --- a/usr/src/cmd/ssh/sshd/serverloop.c +++ /dev/null @@ -1,1310 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Server main loop for handling the interactive session. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * SSH2 support by Markus Friedl. - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.104 2002/09/19 16:03:15 stevesk Exp $"); - -#include "xmalloc.h" -#include "packet.h" -#include "buffer.h" -#include "log.h" -#include "servconf.h" -#include "canohost.h" -#include "sshpty.h" -#include "channels.h" -#include "compat.h" -#include "ssh1.h" -#include "ssh2.h" -#include "auth.h" -#include "session.h" -#include "dispatch.h" -#include "auth-options.h" -#include "serverloop.h" -#include "misc.h" -#include "kex.h" - -#ifdef ALTPRIVSEP -#include "altprivsep.h" -#endif /* ALTPRIVSEP*/ - -extern ServerOptions options; - -/* XXX */ -extern Kex *xxx_kex; -static Authctxt *xxx_authctxt; - -static Buffer stdin_buffer; /* Buffer for stdin data. */ -static Buffer stdout_buffer; /* Buffer for stdout data. */ -static Buffer stderr_buffer; /* Buffer for stderr data. */ -static int fdin; /* Descriptor for stdin (for writing) */ -static int fdout; /* Descriptor for stdout (for reading); - May be same number as fdin. */ -static int fderr; /* Descriptor for stderr. May be -1. */ -static long stdin_bytes = 0; /* Number of bytes written to stdin. */ -static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ -static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ -static long fdout_bytes = 0; /* Number of stdout bytes read from program. */ -static int stdin_eof = 0; /* EOF message received from client. */ -static int fdout_eof = 0; /* EOF encountered reading from fdout. */ -static int fderr_eof = 0; /* EOF encountered readung from fderr. */ -static int fdin_is_tty = 0; /* fdin points to a tty. */ -static int connection_in; /* Connection to client (input). */ -static int connection_out; /* Connection to client (output). */ -static int connection_closed = 0; /* Connection to client closed. */ -static u_int buffer_high; /* "Soft" max buffer size. */ -static int client_alive_timeouts = 0; - -/* - * This SIGCHLD kludge is used to detect when the child exits. The server - * will exit after that, as soon as forwarded connections have terminated. - */ - -static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ - -/* prototypes */ -static void server_init_dispatch(void); - -/* - * we write to this pipe if a SIGCHLD is caught in order to avoid - * the race between select() and child_terminated - */ -static int notify_pipe[2]; -static void -notify_setup(void) -{ - if (pipe(notify_pipe) < 0) { - error("pipe(notify_pipe) failed %s", strerror(errno)); - } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) || - (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) { - error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno)); - (void) close(notify_pipe[0]); - (void) close(notify_pipe[1]); - } else { - set_nonblock(notify_pipe[0]); - set_nonblock(notify_pipe[1]); - return; - } - notify_pipe[0] = -1; /* read end */ - notify_pipe[1] = -1; /* write end */ -} -static void -notify_parent(void) -{ - if (notify_pipe[1] != -1) - (void) write(notify_pipe[1], "", 1); -} -static void -notify_prepare(fd_set *readset) -{ - if (notify_pipe[0] != -1) - FD_SET(notify_pipe[0], readset); -} -static void -notify_done(fd_set *readset) -{ - char c; - - if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) - while (read(notify_pipe[0], &c, 1) != -1) - debug2("notify_done: reading"); -} - -static void -sigchld_handler(int sig) -{ - int save_errno = errno; - debug("Received SIGCHLD."); - child_terminated = 1; -#ifndef _UNICOS - mysignal(SIGCHLD, sigchld_handler); -#endif - notify_parent(); - errno = save_errno; -} - -/* - * Make packets from buffered stderr data, and buffer it for sending - * to the client. - */ -static void -make_packets_from_stderr_data(void) -{ - int len; - - /* Send buffered stderr data to the client. */ - while (buffer_len(&stderr_buffer) > 0 && - packet_not_very_much_data_to_write()) { - len = buffer_len(&stderr_buffer); - if (packet_is_interactive()) { - if (len > 512) - len = 512; - } else { - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()) - len = packet_get_maxsize(); - } - packet_start(SSH_SMSG_STDERR_DATA); - packet_put_string(buffer_ptr(&stderr_buffer), len); - packet_send(); - buffer_consume(&stderr_buffer, len); - stderr_bytes += len; - } -} - -/* - * Make packets from buffered stdout data, and buffer it for sending to the - * client. - */ -static void -make_packets_from_stdout_data(void) -{ - int len; - - /* Send buffered stdout data to the client. */ - while (buffer_len(&stdout_buffer) > 0 && - packet_not_very_much_data_to_write()) { - len = buffer_len(&stdout_buffer); - if (packet_is_interactive()) { - if (len > 512) - len = 512; - } else { - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()) - len = packet_get_maxsize(); - } - packet_start(SSH_SMSG_STDOUT_DATA); - packet_put_string(buffer_ptr(&stdout_buffer), len); - packet_send(); - buffer_consume(&stdout_buffer, len); - stdout_bytes += len; - } -} - -static void -client_alive_check(void) -{ - static int had_channel = 0; - int id; - - id = channel_find_open(); - if (id == -1) { - if (!had_channel) - return; - packet_disconnect("No open channels after timeout!"); - } - had_channel = 1; - - /* timeout, check to see how many we have had */ - if (++client_alive_timeouts > options.client_alive_count_max) - packet_disconnect("Timeout, your session not responding."); - - /* - * send a bogus channel request with "wantreply", - * we should get back a failure - */ - channel_request_start(id, "keepalive@openssh.com", 1); - packet_send(); -} - -/* - * Sleep in select() until we can do something. This will initialize the - * select masks. Upon return, the masks will indicate which descriptors - * have data or can accept data. Optionally, a maximum time can be specified - * for the duration of the wait (0 = infinite). - */ -static void -wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, - int *nallocp, u_int max_time_milliseconds) -{ - struct timeval tv, *tvp; - int ret; - int client_alive_scheduled = 0; - - /* - * if using client_alive, set the max timeout accordingly, - * and indicate that this particular timeout was for client - * alive by setting the client_alive_scheduled flag. - * - * this could be randomized somewhat to make traffic - * analysis more difficult, but we're not doing it yet. - */ - if (compat20 && - max_time_milliseconds == 0 && options.client_alive_interval) { - client_alive_scheduled = 1; - max_time_milliseconds = options.client_alive_interval * 1000; - } - - /* Allocate and update select() masks for channel descriptors. */ - channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); - - if (compat20) { -#ifdef ALTPRIVSEP - int pipe_fd; - - if ((pipe_fd = altprivsep_get_pipe_fd()) != -1) { - *maxfdp = MAX(*maxfdp, pipe_fd); - FD_SET(altprivsep_get_pipe_fd(), *readsetp); - } -#endif /* ALTPRIVSEP */ -#if 0 - /* wrong: bad condition XXX */ - if (channel_not_very_much_buffered_data()) -#endif - FD_SET(connection_in, *readsetp); - } else { - /* - * Read packets from the client unless we have too much - * buffered stdin or channel data. - */ - if (buffer_len(&stdin_buffer) < buffer_high && - channel_not_very_much_buffered_data()) - FD_SET(connection_in, *readsetp); - /* - * If there is not too much data already buffered going to - * the client, try to get some more data from the program. - */ - if (packet_not_very_much_data_to_write()) { - if (!fdout_eof) - FD_SET(fdout, *readsetp); - if (!fderr_eof) - FD_SET(fderr, *readsetp); - } - /* - * If we have buffered data, try to write some of that data - * to the program. - */ - if (fdin != -1 && buffer_len(&stdin_buffer) > 0) - FD_SET(fdin, *writesetp); - } - notify_prepare(*readsetp); - - /* - * If we have buffered packet data going to the client, mark that - * descriptor. - */ - if (packet_have_data_to_write()) - FD_SET(connection_out, *writesetp); - - /* - * If child has terminated and there is enough buffer space to read - * from it, then read as much as is available and exit. - */ - if (child_terminated && packet_not_very_much_data_to_write()) - if (max_time_milliseconds == 0 || client_alive_scheduled) - max_time_milliseconds = 100; - - if (max_time_milliseconds == 0) - tvp = NULL; - else { - tv.tv_sec = max_time_milliseconds / 1000; - tv.tv_usec = 1000 * (max_time_milliseconds % 1000); - tvp = &tv; - } - - /* Wait for something to happen, or the timeout to expire. */ - ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); - - if (ret == -1) { - memset(*readsetp, 0, *nallocp); - memset(*writesetp, 0, *nallocp); - if (errno != EINTR) - error("select: %.100s", strerror(errno)); - } else if (ret == 0 && client_alive_scheduled) - client_alive_check(); - - notify_done(*readsetp); -} - -/* - * Processes input from the client and the program. Input data is stored - * in buffers and processed later. - */ -static void -process_input(fd_set * readset) -{ - int len; - char buf[16384]; - - /* Read and buffer any input data from the client. */ - if (FD_ISSET(connection_in, readset)) { - len = read(connection_in, buf, sizeof(buf)); - if (len == 0) { - if (packet_is_monitor()) { - debug("child closed the communication pipe"); - } else { - verbose("Connection closed by %.100s", - get_remote_ipaddr()); - } - connection_closed = 1; - if (compat20) - return; - fatal_cleanup(); - } else if (len < 0) { - if (errno != EINTR && errno != EAGAIN) { - verbose("Read error from remote host " - "%.100s: %.100s", - get_remote_ipaddr(), strerror(errno)); - fatal_cleanup(); - } - } else { - /* Buffer any received data. */ - packet_process_incoming(buf, len); - } - } - if (compat20) - return; - - /* Read and buffer any available stdout data from the program. */ - if (!fdout_eof && FD_ISSET(fdout, readset)) { - len = read(fdout, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) { - /* EMPTY */ - } else if (len <= 0) { - fdout_eof = 1; - } else { - buffer_append(&stdout_buffer, buf, len); - fdout_bytes += len; - } - } - /* Read and buffer any available stderr data from the program. */ - if (!fderr_eof && FD_ISSET(fderr, readset)) { - len = read(fderr, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) { - /* EMPTY */ - } else if (len <= 0) { - fderr_eof = 1; - } else { - buffer_append(&stderr_buffer, buf, len); - } - } -} - -/* - * Sends data from internal buffers to client program stdin. - */ -static void -process_output(fd_set * writeset) -{ - struct termios tio; - u_char *data; - u_int dlen; - int len; - - /* Write buffered data to program stdin. */ - if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { - data = buffer_ptr(&stdin_buffer); - dlen = buffer_len(&stdin_buffer); - len = write(fdin, data, dlen); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) { - /* EMPTY */ - } else if (len <= 0) { - if (fdin != fdout) - (void) close(fdin); - else - (void) shutdown(fdin, SHUT_WR); /* We will no longer send. */ - fdin = -1; - } else { - /* Successful write. */ - if (fdin_is_tty && dlen >= 1 && data[0] != '\r' && - tcgetattr(fdin, &tio) == 0 && - !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { - /* - * Simulate echo to reduce the impact of - * traffic analysis - */ - packet_send_ignore(len); - packet_send(); - } - /* Consume the data from the buffer. */ - buffer_consume(&stdin_buffer, len); - /* Update the count of bytes written to the program. */ - stdin_bytes += len; - } - } - /* Send any buffered packet data to the client. */ - if (FD_ISSET(connection_out, writeset)) - packet_write_poll(); -} - -/* - * Wait until all buffered output has been sent to the client. - * This is used when the program terminates. - */ -static void -drain_output(void) -{ - /* Send any buffered stdout data to the client. */ - if (buffer_len(&stdout_buffer) > 0) { - packet_start(SSH_SMSG_STDOUT_DATA); - packet_put_string(buffer_ptr(&stdout_buffer), - buffer_len(&stdout_buffer)); - packet_send(); - /* Update the count of sent bytes. */ - stdout_bytes += buffer_len(&stdout_buffer); - } - /* Send any buffered stderr data to the client. */ - if (buffer_len(&stderr_buffer) > 0) { - packet_start(SSH_SMSG_STDERR_DATA); - packet_put_string(buffer_ptr(&stderr_buffer), - buffer_len(&stderr_buffer)); - packet_send(); - /* Update the count of sent bytes. */ - stderr_bytes += buffer_len(&stderr_buffer); - } - /* Wait until all buffered data has been written to the client. */ - packet_write_wait(); -} - -static void -process_buffered_input_packets(void) -{ - dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL); -} - -/* - * Performs the interactive session. This handles data transmission between - * the client and the program. Note that the notion of stdin, stdout, and - * stderr in this function is sort of reversed: this function writes to - * stdin (of the child program), and reads from stdout and stderr (of the - * child program). - */ -void -server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) -{ - fd_set *readset = NULL, *writeset = NULL; - int max_fd = 0, nalloc = 0; - int wait_status; /* Status returned by wait(). */ - pid_t wait_pid; /* pid returned by wait(). */ - int waiting_termination = 0; /* Have displayed waiting close message. */ - u_int max_time_milliseconds; - u_int previous_stdout_buffer_bytes; - u_int stdout_buffer_bytes; - int type; - - debug("Entering interactive session."); - - /* Initialize the SIGCHLD kludge. */ - child_terminated = 0; - mysignal(SIGCHLD, sigchld_handler); - - /* Initialize our global variables. */ - fdin = fdin_arg; - fdout = fdout_arg; - fderr = fderr_arg; - - /* nonblocking IO */ - set_nonblock(fdin); - set_nonblock(fdout); - /* we don't have stderr for interactive terminal sessions, see below */ - if (fderr != -1) - set_nonblock(fderr); - - if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) - fdin_is_tty = 1; - - connection_in = packet_get_connection_in(); - connection_out = packet_get_connection_out(); - - notify_setup(); - - previous_stdout_buffer_bytes = 0; - - /* Set approximate I/O buffer size. */ - if (packet_is_interactive()) - buffer_high = 4096; - else - buffer_high = 64 * 1024; - -#if 0 - /* Initialize max_fd to the maximum of the known file descriptors. */ - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, fdin); - max_fd = MAX(max_fd, fdout); - if (fderr != -1) - max_fd = MAX(max_fd, fderr); -#endif - - /* Initialize Initialize buffers. */ - buffer_init(&stdin_buffer); - buffer_init(&stdout_buffer); - buffer_init(&stderr_buffer); - - /* - * If we have no separate fderr (which is the case when we have a pty - * - there we cannot make difference between data sent to stdout and - * stderr), indicate that we have seen an EOF from stderr. This way - * we don\'t need to check the descriptor everywhere. - */ - if (fderr == -1) - fderr_eof = 1; - - server_init_dispatch(); - - /* Main loop of the server for the interactive session mode. */ - for (;;) { - - /* Process buffered packets from the client. */ - process_buffered_input_packets(); - - /* - * If we have received eof, and there is no more pending - * input data, cause a real eof by closing fdin. - */ - if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { - if (fdin != fdout) - (void) close(fdin); - else - (void) shutdown(fdin, SHUT_WR); /* We will no longer send. */ - fdin = -1; - } - /* Make packets from buffered stderr data to send to the client. */ - make_packets_from_stderr_data(); - - /* - * Make packets from buffered stdout data to send to the - * client. If there is very little to send, this arranges to - * not send them now, but to wait a short while to see if we - * are getting more data. This is necessary, as some systems - * wake up readers from a pty after each separate character. - */ - max_time_milliseconds = 0; - stdout_buffer_bytes = buffer_len(&stdout_buffer); - if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 && - stdout_buffer_bytes != previous_stdout_buffer_bytes) { - /* try again after a while */ - max_time_milliseconds = 10; - } else { - /* Send it now. */ - make_packets_from_stdout_data(); - } - previous_stdout_buffer_bytes = buffer_len(&stdout_buffer); - - /* Send channel data to the client. */ - if (packet_not_very_much_data_to_write()) - channel_output_poll(); - - /* - * Bail out of the loop if the program has closed its output - * descriptors, and we have no more data to send to the - * client, and there is no pending buffered data. - */ - if (fdout_eof && fderr_eof && !packet_have_data_to_write() && - buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { - if (!channel_still_open()) - break; - if (!waiting_termination) { - const char *s = "Waiting for forwarded connections to terminate...\r\n"; - char *cp; - waiting_termination = 1; - buffer_append(&stderr_buffer, s, strlen(s)); - - /* Display list of open channels. */ - cp = channel_open_message(); - buffer_append(&stderr_buffer, cp, strlen(cp)); - xfree(cp); - } - } - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, fdin); - max_fd = MAX(max_fd, fdout); - max_fd = MAX(max_fd, fderr); - max_fd = MAX(max_fd, notify_pipe[0]); - - /* Sleep in select() until we can do something. */ - wait_until_can_do_something(&readset, &writeset, &max_fd, - &nalloc, max_time_milliseconds); - - /* Process any channel events. */ - channel_after_select(readset, writeset); - - /* Process input from the client and from program stdout/stderr. */ - process_input(readset); - - /* Process output to the client and to program stdin. */ - process_output(writeset); - } - if (readset) - xfree(readset); - if (writeset) - xfree(writeset); - - /* Cleanup and termination code. */ - - /* Wait until all output has been sent to the client. */ - drain_output(); - - debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.", - stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes); - - /* Free and clear the buffers. */ - buffer_free(&stdin_buffer); - buffer_free(&stdout_buffer); - buffer_free(&stderr_buffer); - - /* Close the file descriptors. */ - if (fdout != -1) - (void) close(fdout); - fdout = -1; - fdout_eof = 1; - if (fderr != -1) - (void) close(fderr); - fderr = -1; - fderr_eof = 1; - if (fdin != -1) - (void) close(fdin); - fdin = -1; - - channel_free_all(); - - /* We no longer want our SIGCHLD handler to be called. */ - mysignal(SIGCHLD, SIG_DFL); - - while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0) - if (errno != EINTR) - packet_disconnect("wait: %.100s", strerror(errno)); - if (wait_pid != pid) - error("Strange, wait returned pid %ld, expected %ld", - (long)wait_pid, (long)pid); - - /* Check if it exited normally. */ - if (WIFEXITED(wait_status)) { - /* Yes, normal exit. Get exit status and send it to the client. */ - debug("Command exited with status %d.", WEXITSTATUS(wait_status)); - packet_start(SSH_SMSG_EXITSTATUS); - packet_put_int(WEXITSTATUS(wait_status)); - packet_send(); - packet_write_wait(); - - /* - * Wait for exit confirmation. Note that there might be - * other packets coming before it; however, the program has - * already died so we just ignore them. The client is - * supposed to respond with the confirmation when it receives - * the exit status. - */ - do { - type = packet_read(); - } - while (type != SSH_CMSG_EXIT_CONFIRMATION); - - debug("Received exit confirmation."); - return; - } - /* Check if the program terminated due to a signal. */ - if (WIFSIGNALED(wait_status)) - packet_disconnect("Command terminated on signal %d.", - WTERMSIG(wait_status)); - - /* Some weird exit cause. Just exit. */ - packet_disconnect("wait returned status %04x.", wait_status); - /* NOTREACHED */ -} - -static void -collect_children(void) -{ - pid_t pid; - sigset_t oset, nset; - int status; - - /* block SIGCHLD while we check for dead children */ - (void) sigemptyset(&nset); - (void) sigaddset(&nset, SIGCHLD); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - if (child_terminated) { - while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || - (pid < 0 && errno == EINTR)) - if (pid > 0) - session_close_by_pid(pid, status); - child_terminated = 0; - } - (void) sigprocmask(SIG_SETMASK, &oset, NULL); -} - -#ifdef ALTPRIVSEP -/* - * For ALTPRIVSEP the wait_until_can_do_something function is very - * simple: select() on the read side of the pipe, and if there's packets - * to send, on the write side, and on the read side of the SIGCHLD - * handler pipe. That's it. - */ -static void -aps_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, - int *maxfdp, int *nallocp, u_int max_time_milliseconds) -{ - int ret; - - /* - * Use channel_prepare_select() to make the fd sets. - * - * This is cheating, really, since because the last argument in - * this call is '1' nothing related to channels will be done -- - * we're using this function only to callocate the fd sets. - */ - channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 1); - - if ((connection_in = packet_get_connection_in()) >= 0 && - !connection_closed) - FD_SET(connection_in, *readsetp); - - notify_prepare(*readsetp); - - if ((connection_out = packet_get_connection_out()) >= 0 && - packet_have_data_to_write() && !connection_closed) - FD_SET(connection_out, *writesetp); - - /* Wait for something to happen, or the timeout to expire. */ - ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL); - - if (ret == -1) { - memset(*readsetp, 0, *nallocp); - memset(*writesetp, 0, *nallocp); - if (errno != EINTR) - error("select: %.100s", strerror(errno)); - } - - notify_done(*readsetp); -} - -/* - * Slightly different than collect_children, aps_collect_child() has - * only the unprivileged sshd to wait for, no sessions, no channells, - * just one process. - */ -static int -aps_collect_child(pid_t child) -{ - pid_t pid; - sigset_t oset, nset; - int status; - - /* block SIGCHLD while we check for dead children */ - (void) sigemptyset(&nset); - (void) sigaddset(&nset, SIGCHLD); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - if (child_terminated) { - while ((pid = waitpid(child, &status, WNOHANG)) > 0 || - (pid < 0 && errno == EINTR)) - if (pid == child) { - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - return (1); - } - child_terminated = 0; - } - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - return (0); -} - -static int killed = 0; - -static void -aps_monitor_kill_handler(int sig) -{ - int save_errno = errno; - killed = 1; - notify_parent(); - mysignal(sig, aps_monitor_kill_handler); - errno = save_errno; -} - -static void -aps_monitor_sigchld_handler(int sig) -{ - int save_errno = errno; - debug("Monitor received SIGCHLD."); - child_terminated = 1; - mysignal(SIGCHLD, aps_monitor_sigchld_handler); - notify_parent(); - errno = save_errno; -} - -void -aps_monitor_loop(Authctxt *authctxt, pid_t child_pid) -{ - fd_set *readset = NULL, *writeset = NULL; - int max_fd, nalloc = 0; - - debug("Entering monitor loop."); - - /* - * Awful hack follows: fake compat20 == 1 to cause process_input() - * and process_output() to behave as they would for SSHv2 because that's - * the behaviour we need in SSHv2. - * - * This same hack is done in packet.c - */ - compat20 = 1; /* causes process_input/output() to ignore stdio */ - - mysignal(SIGHUP, aps_monitor_kill_handler); - mysignal(SIGINT, aps_monitor_kill_handler); - mysignal(SIGTERM, aps_monitor_kill_handler); - - child_terminated = 0; - mysignal(SIGCHLD, aps_monitor_sigchld_handler); - - connection_in = packet_get_connection_in(); - connection_out = packet_get_connection_out(); - - notify_setup(); - - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, notify_pipe[0]); - - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); - dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_MAX, - &dispatch_protocol_error); - dispatch_set(SSH2_PRIV_MSG_ALTPRIVSEP, &aps_input_altpriv_msg); - - for (;;) { - process_buffered_input_packets(); - - aps_wait_until_can_do_something(&readset, &writeset, &max_fd, - &nalloc, 0); - - if (aps_collect_child(child_pid)) - break; - - if (killed) { - /* fatal cleanups will kill child, audit logout */ - log("Monitor killed; exiting"); - fatal_cleanup(); - } - - /* - * Unlike server_loop2() we don't care if connection_closed - * since we still want to wait for the monitor's child. - */ - process_input(readset); - process_output(writeset); - } - - packet_close(); -} -#endif /* ALTPRIVSEP */ - -/* - * This server loop is for unprivileged child only. Our monitor runs its own - * aps_monitor_loop() funtion. - */ -void -server_loop2(Authctxt *authctxt) -{ - fd_set *readset = NULL, *writeset = NULL; - int rekeying = 0, max_fd, nalloc = 0; - - debug("Entering interactive session for SSH2."); - - mysignal(SIGCHLD, sigchld_handler); - child_terminated = 0; - connection_in = packet_get_connection_in(); - connection_out = packet_get_connection_out(); - - notify_setup(); - - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, notify_pipe[0]); - - xxx_authctxt = authctxt; - - server_init_dispatch(); - - for (;;) { - process_buffered_input_packets(); - - rekeying = (xxx_kex != NULL && !xxx_kex->done); - - if (!rekeying && packet_not_very_much_data_to_write()) - channel_output_poll(); - wait_until_can_do_something(&readset, &writeset, &max_fd, - &nalloc, 0); - - collect_children(); - - if (!rekeying) { - channel_after_select(readset, writeset); - if (packet_need_rekeying()) { - debug("rekey limit reached, need rekeying"); - xxx_kex->done = 0; - debug("poking the monitor to start " - "key re-exchange"); - altprivsep_start_rekex(); - } - } -#ifdef ALTPRIVSEP - else - altprivsep_process_input(readset); -#endif /* ALTPRIVSEP */ - - process_input(readset); - if (connection_closed) - break; - process_output(writeset); - } - collect_children(); - - if (readset) - xfree(readset); - if (writeset) - xfree(writeset); - - /* free all channels, no more reads and writes */ - channel_free_all(); - - /* free remaining sessions, e.g. remove wtmp entries */ - session_destroy_all(NULL); -} - -static void -server_input_channel_failure(int type, u_int32_t seq, void *ctxt) -{ - debug("Got CHANNEL_FAILURE for keepalive"); - /* - * reset timeout, since we got a sane answer from the client. - * even if this was generated by something other than - * the bogus CHANNEL_REQUEST we send for keepalives. - */ - client_alive_timeouts = 0; -} - -static void -server_input_stdin_data(int type, u_int32_t seq, void *ctxt) -{ - char *data; - u_int data_len; - - /* Stdin data from the client. Append it to the buffer. */ - /* Ignore any data if the client has closed stdin. */ - if (fdin == -1) - return; - data = packet_get_string(&data_len); - packet_check_eom(); - buffer_append(&stdin_buffer, data, data_len); - memset(data, 0, data_len); - xfree(data); -} - -static void -server_input_eof(int type, u_int32_t seq, void *ctxt) -{ - /* - * Eof from the client. The stdin descriptor to the - * program will be closed when all buffered data has - * drained. - */ - debug("EOF received for stdin."); - packet_check_eom(); - stdin_eof = 1; -} - -static void -server_input_window_size(int type, u_int32_t seq, void *ctxt) -{ - int row = packet_get_int(); - int col = packet_get_int(); - int xpixel = packet_get_int(); - int ypixel = packet_get_int(); - - debug("Window change received."); - packet_check_eom(); - if (fdin != -1) - pty_change_window_size(fdin, row, col, xpixel, ypixel); -} - -static Channel * -server_request_direct_tcpip(char *ctype) -{ - Channel *c; - int sock; - char *target, *originator; - int target_port, originator_port; - - target = packet_get_string(NULL); - target_port = packet_get_int(); - originator = packet_get_string(NULL); - originator_port = packet_get_int(); - packet_check_eom(); - - debug("server_request_direct_tcpip: originator %s port %d, target %s port %d", - originator, originator_port, target, target_port); - - /* XXX check permission */ - sock = channel_connect_to(target, target_port); - - xfree(target); - xfree(originator); - if (sock < 0) - return NULL; - c = channel_new(ctype, SSH_CHANNEL_CONNECTING, - sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, - CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); - return c; -} - -static Channel * -server_request_session(char *ctype) -{ - Channel *c; - - debug("input_session_request"); - packet_check_eom(); - /* - * A server session has no fd to read or write until a - * CHANNEL_REQUEST for a shell is made, so we set the type to - * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all - * CHANNEL_REQUEST messages is registered. - */ - c = channel_new(ctype, SSH_CHANNEL_LARVAL, - -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, - 0, xstrdup("server-session"), 1); - if (session_open(xxx_authctxt, c->self) != 1) { - debug("session open failed, free channel %d", c->self); - channel_free(c); - return NULL; - } - channel_register_cleanup(c->self, session_close_by_channel); - return c; -} - -static void -server_input_channel_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - char *ctype; - int rchan; - u_int rmaxpack, rwindow, len; - - ctype = packet_get_string(&len); - rchan = packet_get_int(); - rwindow = packet_get_int(); - rmaxpack = packet_get_int(); - - debug("server_input_channel_open: ctype %s rchan %d win %d max %d", - ctype, rchan, rwindow, rmaxpack); - - if (strcmp(ctype, "session") == 0) { - c = server_request_session(ctype); - } else if (strcmp(ctype, "direct-tcpip") == 0) { - c = server_request_direct_tcpip(ctype); - } - if (c != NULL) { - debug("server_input_channel_open: confirm %s", ctype); - c->remote_id = rchan; - c->remote_window = rwindow; - c->remote_maxpacket = rmaxpack; - if (c->type != SSH_CHANNEL_CONNECTING) { - packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - packet_send(); - } - } else { - debug("server_input_channel_open: failure %s", ctype); - packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(rchan); - packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); - if (!(datafellows & SSH_BUG_OPENFAILURE)) { - packet_put_utf8_cstring("open failed"); - packet_put_cstring(""); - } - packet_send(); - } - xfree(ctype); -} - -static void -server_input_global_request(int type, u_int32_t seq, void *ctxt) -{ - char *rtype; - int want_reply; - int success = 0; - - rtype = packet_get_string(NULL); - want_reply = packet_get_char(); - debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); - - /* -R style forwarding */ - if (strcmp(rtype, "tcpip-forward") == 0) { - struct passwd *pw; - char *listen_address; - u_short listen_port; - - pw = auth_get_user(); - if (pw == NULL) - fatal("server_input_global_request: no user"); - listen_address = packet_get_string(NULL); /* XXX currently ignored */ - listen_port = (u_short)packet_get_int(); - debug("server_input_global_request: tcpip-forward listen %s port %d", - listen_address, listen_port); - - /* check permissions */ - if (!options.allow_tcp_forwarding || - no_port_forwarding_flag -#ifndef NO_IPPORT_RESERVED_CONCEPT - || (listen_port < IPPORT_RESERVED && pw->pw_uid != 0) -#endif - ) { - success = 0; - packet_send_debug("Server has disabled port forwarding."); - } else { - /* Start listening on the port */ - success = channel_setup_remote_fwd_listener( - listen_address, listen_port, options.gateway_ports); - } - xfree(listen_address); - } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { - char *cancel_address; - u_short cancel_port; - - cancel_address = packet_get_string(NULL); - cancel_port = (u_short)packet_get_int(); - debug("%s: cancel-tcpip-forward addr %s port %d", __func__, - cancel_address, cancel_port); - - success = channel_cancel_rport_listener(cancel_address, - cancel_port); - xfree(cancel_address); - } - if (want_reply) { - packet_start(success ? - SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); - packet_send(); - packet_write_wait(); - } - xfree(rtype); -} - -static void -server_input_channel_req(int type, u_int32_t seq, void *ctxt) -{ - Channel *c; - int id, reply, success = 0; - char *rtype; - - id = packet_get_int(); - rtype = packet_get_string(NULL); - reply = packet_get_char(); - - debug("server_input_channel_req: channel %d request %s reply %d", - id, rtype, reply); - - if ((c = channel_lookup(id)) == NULL) - packet_disconnect("server_input_channel_req: " - "unknown channel %d", id); - if (!strcmp(rtype, "eow@openssh.com")) { - packet_check_eom(); - chan_rcvd_eow(c); - } else if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN) - success = session_input_channel_req(c, rtype); - if (reply) { - packet_start(success ? - SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(c->remote_id); - packet_send(); - } - xfree(rtype); -} - -static void -server_init_dispatch_20(void) -{ - debug("server_init_dispatch_20"); - dispatch_init(&dispatch_protocol_error); - dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); - dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); - dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); - dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open); - dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); - dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); - dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); - dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); - /* client_alive */ - dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_channel_failure); - /* rekeying */ - -#ifdef ALTPRIVSEP - /* unprivileged sshd has a kex packet handler that must not be reset */ - debug3("server_init_dispatch_20 -- should we dispatch_set(KEXINIT) here? %d && !%d", - packet_is_server(), packet_is_monitor()); - if (packet_is_server() && !packet_is_monitor()) { - debug3("server_init_dispatch_20 -- skipping dispatch_set(KEXINIT) in unpriv proc"); - dispatch_range(SSH2_MSG_KEXINIT, SSH2_MSG_TRANSPORT_MAX, - &altprivsep_rekey); - return; - } -#endif /* ALTPRIVSEP */ - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); -} -static void -server_init_dispatch_13(void) -{ - debug("server_init_dispatch_13"); - dispatch_init(NULL); - dispatch_set(SSH_CMSG_EOF, &server_input_eof); - dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data); - dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); - dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); - dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); -} -static void -server_init_dispatch_15(void) -{ - server_init_dispatch_13(); - debug("server_init_dispatch_15"); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose); -} -static void -server_init_dispatch(void) -{ - if (compat20) - server_init_dispatch_20(); - else if (compat13) - server_init_dispatch_13(); - else - server_init_dispatch_15(); -} diff --git a/usr/src/cmd/ssh/sshd/session.c b/usr/src/cmd/ssh/sshd/session.c deleted file mode 100644 index 871b06c758..0000000000 --- a/usr/src/cmd/ssh/sshd/session.c +++ /dev/null @@ -1,2641 +0,0 @@ -/* - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * SSH2 support by Markus Friedl. - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: session.c,v 1.150 2002/09/16 19:55:33 stevesk Exp $"); - -#ifdef HAVE_DEFOPEN -#include <deflt.h> -#include <ulimit.h> -#endif /* HAVE_DEFOPEN */ - -#ifdef HAVE_LIBGEN_H -#include <libgen.h> -#endif - -#include <priv.h> - -#include "ssh.h" -#include "ssh1.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "sshpty.h" -#include "packet.h" -#include "buffer.h" -#include "mpaux.h" -#include "uidswap.h" -#include "compat.h" -#include "channels.h" -#include "bufaux.h" -#include "auth.h" -#include "auth-options.h" -#include "pathnames.h" -#include "log.h" -#include "servconf.h" -#include "sshlogin.h" -#include "serverloop.h" -#include "canohost.h" -#include "session.h" -#include "tildexpand.h" -#include "misc.h" -#include "sftp.h" - -#ifdef USE_PAM -#include <security/pam_appl.h> -#endif /* USE_PAM */ - -#ifdef GSSAPI -#include "ssh-gss.h" -#endif - -#ifdef ALTPRIVSEP -#include "altprivsep.h" -#endif /* ALTPRIVSEP */ - -#ifdef HAVE_CYGWIN -#include <windows.h> -#include <sys/cygwin.h> -#define is_winnt (GetVersion() < 0x80000000) -#endif - -/* func */ - -Session *session_new(void); -void session_set_fds(Session *, int, int, int); -void session_pty_cleanup(void *); -void session_xauthfile_cleanup(void *s); -void session_proctitle(Session *); -int session_setup_x11fwd(Session *); -void do_exec_pty(Session *, const char *); -void do_exec_no_pty(Session *, const char *); -void do_exec(Session *, const char *); -void do_login(Session *, const char *); -void do_child(Session *, const char *); -void do_motd(void); -int check_quietlogin(Session *, const char *); - -static void do_authenticated1(Authctxt *); -static void do_authenticated2(Authctxt *); - -static int session_pty_req(Session *); -static int session_env_req(Session *s); -static void session_free_env(char ***envp); -static void safely_chroot(const char *path, uid_t uid); -static void drop_privs(uid_t uid); - -#ifdef USE_PAM -static void session_do_pam(Session *, int); -#endif /* USE_PAM */ - -/* import */ -extern ServerOptions options; -extern char *__progname; -extern int log_stderr; -extern int debug_flag; -extern u_int utmp_len; -extern void destroy_sensitive_data(void); - -#ifdef GSSAPI -extern Gssctxt *xxx_gssctxt; -#endif /* GSSAPI */ - -/* original command from peer. */ -const char *original_command = NULL; - -/* data */ -#define MAX_SESSIONS 10 -Session sessions[MAX_SESSIONS]; - -#define SUBSYSTEM_NONE 0 -#define SUBSYSTEM_EXT 1 -#define SUBSYSTEM_INT_SFTP 2 - -#ifdef HAVE_LOGIN_CAP -login_cap_t *lc; -#endif - -/* Name and directory of socket for authentication agent forwarding. */ -static char *auth_sock_name = NULL; -static char *auth_sock_dir = NULL; - -/* removes the agent forwarding socket */ - -static void -auth_sock_cleanup_proc(void *_pw) -{ - struct passwd *pw = _pw; - - if (auth_sock_name != NULL) { - temporarily_use_uid(pw); - unlink(auth_sock_name); - rmdir(auth_sock_dir); - auth_sock_name = NULL; - restore_uid(); - } -} - -static int -auth_input_request_forwarding(struct passwd * pw) -{ - Channel *nc; - int sock; - struct sockaddr_un sunaddr; - - if (auth_sock_name != NULL) { - error("authentication forwarding requested twice."); - return 0; - } - - /* Temporarily drop privileged uid for mkdir/bind. */ - temporarily_use_uid(pw); - - /* Allocate a buffer for the socket name, and format the name. */ - auth_sock_name = xmalloc(MAXPATHLEN); - auth_sock_dir = xmalloc(MAXPATHLEN); - strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); - - /* Create private directory for socket */ - if (mkdtemp(auth_sock_dir) == NULL) { - packet_send_debug("Agent forwarding disabled: " - "mkdtemp() failed: %.100s", strerror(errno)); - restore_uid(); - xfree(auth_sock_name); - xfree(auth_sock_dir); - auth_sock_name = NULL; - auth_sock_dir = NULL; - return 0; - } - snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld", - auth_sock_dir, (long) getpid()); - - /* delete agent socket on fatal() */ - fatal_add_cleanup(auth_sock_cleanup_proc, pw); - - /* Create the socket. */ - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - packet_disconnect("socket: %.100s", strerror(errno)); - - /* Bind it to the name. */ - memset(&sunaddr, 0, sizeof(sunaddr)); - sunaddr.sun_family = AF_UNIX; - strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); - - if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) - packet_disconnect("bind: %.100s", strerror(errno)); - - /* Restore the privileged uid. */ - restore_uid(); - - /* Start listening on the socket. */ - if (listen(sock, 5) < 0) - packet_disconnect("listen: %.100s", strerror(errno)); - - /* Allocate a channel for the authentication agent socket. */ - nc = channel_new("auth socket", - SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, - 0, xstrdup("auth socket"), 1); - strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); - return 1; -} - - -void -do_authenticated(Authctxt *authctxt) -{ - /* setup the channel layer */ - if (!no_port_forwarding_flag && options.allow_tcp_forwarding) - channel_permit_all_opens(); - - if (compat20) - do_authenticated2(authctxt); - else - do_authenticated1(authctxt); - - /* remove agent socket */ - if (auth_sock_name != NULL) - auth_sock_cleanup_proc(authctxt->pw); -#ifdef KRB4 - if (options.kerberos_ticket_cleanup) - krb4_cleanup_proc(authctxt); -#endif -#ifdef KRB5 - if (options.kerberos_ticket_cleanup) - krb5_cleanup_proc(authctxt); -#endif -} - -/* - * Prepares for an interactive session. This is called after the user has - * been successfully authenticated. During this message exchange, pseudo - * terminals are allocated, X11, TCP/IP, and authentication agent forwardings - * are requested, etc. - */ -static void -do_authenticated1(Authctxt *authctxt) -{ - Session *s; - char *command; - int success, type, screen_flag; - int enable_compression_after_reply = 0; - u_int proto_len, data_len, dlen, compression_level = 0; - - s = session_new(); - s->authctxt = authctxt; - s->pw = authctxt->pw; - - /* - * We stay in this loop until the client requests to execute a shell - * or a command. - */ - for (;;) { - success = 0; - - /* Get a packet from the client. */ - type = packet_read(); - - /* Process the packet. */ - switch (type) { - case SSH_CMSG_REQUEST_COMPRESSION: - compression_level = packet_get_int(); - packet_check_eom(); - if (compression_level < 1 || compression_level > 9) { - packet_send_debug("Received illegal compression level %d.", - compression_level); - break; - } - if (!options.compression) { - debug2("compression disabled"); - break; - } - /* Enable compression after we have responded with SUCCESS. */ - enable_compression_after_reply = 1; - success = 1; - break; - - case SSH_CMSG_REQUEST_PTY: - success = session_pty_req(s); - break; - - case SSH_CMSG_X11_REQUEST_FORWARDING: - s->auth_proto = packet_get_string(&proto_len); - s->auth_data = packet_get_string(&data_len); - - screen_flag = packet_get_protocol_flags() & - SSH_PROTOFLAG_SCREEN_NUMBER; - debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag); - - if (packet_remaining() == 4) { - if (!screen_flag) - debug2("Buggy client: " - "X11 screen flag missing"); - s->screen = packet_get_int(); - } else { - s->screen = 0; - } - packet_check_eom(); - success = session_setup_x11fwd(s); - if (!success) { - xfree(s->auth_proto); - xfree(s->auth_data); - s->auth_proto = NULL; - s->auth_data = NULL; - } - break; - - case SSH_CMSG_AGENT_REQUEST_FORWARDING: - if (no_agent_forwarding_flag || compat13) { - debug("Authentication agent forwarding not permitted for this authentication."); - break; - } - debug("Received authentication agent forwarding request."); - success = auth_input_request_forwarding(s->pw); - break; - - case SSH_CMSG_PORT_FORWARD_REQUEST: - if (no_port_forwarding_flag) { - debug("Port forwarding not permitted for this authentication."); - break; - } - if (!options.allow_tcp_forwarding) { - debug("Port forwarding not permitted."); - break; - } - debug("Received TCP/IP port forwarding request."); - channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports); - success = 1; - break; - - case SSH_CMSG_MAX_PACKET_SIZE: - if (packet_set_maxsize(packet_get_int()) > 0) - success = 1; - break; - -#if defined(AFS) || defined(KRB5) - case SSH_CMSG_HAVE_KERBEROS_TGT: - if (!options.kerberos_tgt_passing) { - verbose("Kerberos TGT passing disabled."); - } else { - char *kdata = packet_get_string(&dlen); - packet_check_eom(); - - /* XXX - 0x41, see creds_to_radix version */ - if (kdata[0] != 0x41) { -#ifdef KRB5 - krb5_data tgt; - tgt.data = kdata; - tgt.length = dlen; - - if (auth_krb5_tgt(s->authctxt, &tgt)) - success = 1; - else - verbose("Kerberos v5 TGT refused for %.100s", s->authctxt->user); -#endif /* KRB5 */ - } else { -#ifdef AFS - if (auth_krb4_tgt(s->authctxt, kdata)) - success = 1; - else - verbose("Kerberos v4 TGT refused for %.100s", s->authctxt->user); -#endif /* AFS */ - } - xfree(kdata); - } - break; -#endif /* AFS || KRB5 */ - -#ifdef AFS - case SSH_CMSG_HAVE_AFS_TOKEN: - if (!options.afs_token_passing || !k_hasafs()) { - verbose("AFS token passing disabled."); - } else { - /* Accept AFS token. */ - char *token = packet_get_string(&dlen); - packet_check_eom(); - - if (auth_afs_token(s->authctxt, token)) - success = 1; - else - verbose("AFS token refused for %.100s", - s->authctxt->user); - xfree(token); - } - break; -#endif /* AFS */ - - case SSH_CMSG_EXEC_SHELL: - case SSH_CMSG_EXEC_CMD: - if (type == SSH_CMSG_EXEC_CMD) { - command = packet_get_string(&dlen); - debug("Exec command '%.500s'", command); - do_exec(s, command); - xfree(command); - } else { - do_exec(s, NULL); - } - packet_check_eom(); - session_close(s); - return; - - default: - /* - * Any unknown messages in this phase are ignored, - * and a failure message is returned. - */ - log("Unknown packet type received after authentication: %d", type); - } - packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - - /* Enable compression now that we have replied if appropriate. */ - if (enable_compression_after_reply) { - enable_compression_after_reply = 0; - packet_start_compression(compression_level); - } - } -} - -/* - * This is called to fork and execute a command when we have no tty. This - * will call do_child from the child, and server_loop from the parent after - * setting up file descriptors and such. - */ -void -do_exec_no_pty(Session *s, const char *command) -{ - pid_t pid; - - int inout[2], err[2]; - /* Uses socket pairs to communicate with the program. */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 || - socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) - packet_disconnect("Could not create socket pairs: %.100s", - strerror(errno)); - if (s == NULL) - fatal("do_exec_no_pty: no session"); - - session_proctitle(s); - - /* Fork the child. */ - if ((pid = fork()) == 0) { - fatal_remove_all_cleanups(); - - /* Child. Reinitialize the log since the pid has changed. */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); - - /* - * Create a new session and process group since the 4.4BSD - * setlogin() affects the entire process group. - */ - if (setsid() < 0) - error("setsid failed: %.100s", strerror(errno)); - - /* - * Redirect stdin, stdout, and stderr. Stdin and stdout will - * use the same socket, as some programs (particularly rdist) - * seem to depend on it. - */ - close(inout[1]); - close(err[1]); - if (dup2(inout[0], 0) < 0) /* stdin */ - perror("dup2 stdin"); - if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */ - perror("dup2 stdout"); - if (s->is_subsystem) { - /* - * Redirect the subsystem's stderr to /dev/null. We might send it - * over to the other side but changing that might break existing - * SSH clients. - */ - close(err[0]); - if ((err[0] = open(_PATH_DEVNULL, O_WRONLY)) == -1) - fatal("Cannot open /dev/null: %.100s", strerror(errno)); - } - if (dup2(err[0], 2) < 0) /* stderr */ - perror("dup2 stderr"); - -#ifdef _UNICOS - cray_init_job(s->pw); /* set up cray jid and tmpdir */ -#endif - - /* Do processing for the child (exec command etc). */ - do_child(s, command); - /* NOTREACHED */ - } -#ifdef _UNICOS - signal(WJSIGNAL, cray_job_termination_handler); -#endif /* _UNICOS */ -#ifdef HAVE_CYGWIN - if (is_winnt) - cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); -#endif - if (pid < 0) - packet_disconnect("fork failed: %.100s", strerror(errno)); - - s->pid = pid; - /* Set interactive/non-interactive mode. */ - packet_set_interactive(s->display != NULL); - - /* We are the parent. Close the child sides of the socket pairs. */ - close(inout[0]); - close(err[0]); - - /* - * Enter the interactive session. Note: server_loop must be able to - * handle the case that fdin and fdout are the same. - */ - if (compat20) { - session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]); - if (s->is_subsystem) - close(err[1]); - /* Don't close channel before sending exit-status! */ - channel_set_wait_for_exit(s->chanid, 1); - } else { - server_loop(pid, inout[1], inout[1], err[1]); - /* server_loop has closed inout[1] and err[1]. */ - } -} - -/* - * This is called to fork and execute a command when we have a tty. This - * will call do_child from the child, and server_loop from the parent after - * setting up file descriptors, controlling tty, updating wtmp, utmp, - * lastlog, and other such operations. - */ -void -do_exec_pty(Session *s, const char *command) -{ - int fdout, ptyfd, ttyfd, ptymaster, pipe_fds[2]; - pid_t pid; - - if (s == NULL) - fatal("do_exec_pty: no session"); - ptyfd = s->ptyfd; - ttyfd = s->ttyfd; - -#ifdef USE_PAM - session_do_pam(s, 1); /* pam_open_session() */ -#endif /* USE_PAM */ - - /* - * This pipe lets sshd wait for child to exec or exit. This is - * particularly important for ALTPRIVSEP because the child is - * the one to call the monitor to request a record_login() and - * we don't want the child and the parent to compete for the - * monitor's attention. But this is generic code and doesn't - * hurt to have here even if ALTPRIVSEP is not used. - */ - if (pipe(pipe_fds) != 0) - packet_disconnect("pipe failed: %.100s", strerror(errno)); - - (void) fcntl(pipe_fds[0], F_SETFD, FD_CLOEXEC); - (void) fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC); - - /* Fork the child. */ - if ((pid = fork()) == 0) { - (void) close(pipe_fds[0]); - - fatal_remove_all_cleanups(); - - /* Child. Reinitialize the log because the pid has changed. */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); - /* Close the master side of the pseudo tty. */ - close(ptyfd); - - /* Make the pseudo tty our controlling tty. */ - pty_make_controlling_tty(&ttyfd, s->tty); - - /* Redirect stdin/stdout/stderr from the pseudo tty. */ - if (dup2(ttyfd, 0) < 0) - error("dup2 stdin: %s", strerror(errno)); - if (dup2(ttyfd, 1) < 0) - error("dup2 stdout: %s", strerror(errno)); - if (dup2(ttyfd, 2) < 0) - error("dup2 stderr: %s", strerror(errno)); - - /* Close the extra descriptor for the pseudo tty. */ - close(ttyfd); - - /* record login, etc. similar to login(1) */ - do_login(s, command); - - /* - * Close the pipe to the parent so it can re-enter its event - * loop and service the ptm; if enough debug messages get - * written to the pty before this happens there will be a - * deadlock. - */ - close(pipe_fds[1]); - - /* - * do_motd() was called originally in do_login(). However, - * when the /etc/motd file is large, a deadlock would happen, - * because - * - The child is blocked at fputs() to pty, when pty buffer - * is full. - * - The parent can not consume the pty buffer, because it is - * still blocked at read(pipe_fds[0]). - * - * To resolve the deadlock issue, we defer do_motd() after - * close(pipe_fds[1]). - */ - do_motd(); - - /* Do common processing for the child, such as execing the command. */ - do_child(s, command); - /* NOTREACHED */ - } - - /* Wait for child to exec() or exit() */ - (void) close(pipe_fds[1]); - (void) read(pipe_fds[0], &pipe_fds[1], sizeof(int)); - -#ifdef _UNICOS - signal(WJSIGNAL, cray_job_termination_handler); -#endif /* _UNICOS */ -#ifdef HAVE_CYGWIN - if (is_winnt) - cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); -#endif - if (pid < 0) - packet_disconnect("fork failed: %.100s", strerror(errno)); - s->pid = pid; - - /* Parent. Close the slave side of the pseudo tty. */ - close(ttyfd); - - /* - * Create another descriptor of the pty master side for use as the - * standard input. We could use the original descriptor, but this - * simplifies code in server_loop. The descriptor is bidirectional. - */ - fdout = dup(ptyfd); - if (fdout < 0) - packet_disconnect("dup #1 failed: %.100s", strerror(errno)); - - /* we keep a reference to the pty master */ - ptymaster = dup(ptyfd); - if (ptymaster < 0) - packet_disconnect("dup #2 failed: %.100s", strerror(errno)); - s->ptymaster = ptymaster; - - /* Enter interactive session. */ - packet_set_interactive(1); - if (compat20) { - session_set_fds(s, ptyfd, fdout, -1); - /* Don't close channel before sending exit-status! */ - channel_set_wait_for_exit(s->chanid, 1); - } else { - server_loop(pid, ptyfd, fdout, -1); - /* server_loop _has_ closed ptyfd and fdout. */ - } -} - -/* - * This is called to fork and execute a command. If another command is - * to be forced, execute that instead. - */ -void -do_exec(Session *s, const char *command) -{ - if (command) - s->command = xstrdup(command); - - if (forced_command) { - original_command = command; - command = forced_command; - debug("Forced command '%.900s'", command); - } - - if (s->ttyfd != -1) - do_exec_pty(s, command); - else - do_exec_no_pty(s, command); - - original_command = NULL; -} - - -/* administrative, login(1)-like work */ -void -do_login(Session *s, const char *command) -{ - char *time_string; -#ifndef ALTPRIVSEP - struct passwd * pw = s->pw; -#endif /* ALTPRIVSEP*/ - pid_t pid = getpid(); - - /* Record that there was a login on that tty from the remote host. */ -#ifdef ALTPRIVSEP - debug3("Recording SSHv2 channel login in utmpx/wtmpx"); - altprivsep_record_login(pid, s->tty); -#endif /* ALTPRIVSEP*/ - - if (check_quietlogin(s, command)) - return; - -#ifdef USE_PAM - print_pam_messages(); -#endif /* USE_PAM */ -#ifdef WITH_AIXAUTHENTICATE - if (aixloginmsg && *aixloginmsg) - printf("%s\n", aixloginmsg); -#endif /* WITH_AIXAUTHENTICATE */ - -#ifndef NO_SSH_LASTLOG - if (options.print_lastlog && s->last_login_time != 0) { - time_string = ctime(&s->last_login_time); - if (strchr(time_string, '\n')) - *strchr(time_string, '\n') = 0; - if (strcmp(s->hostname, "") == 0) - printf("Last login: %s\r\n", time_string); - else - printf("Last login: %s from %s\r\n", time_string, - s->hostname); - } -#endif /* NO_SSH_LASTLOG */ - -} - -/* - * Display the message of the day. - */ -void -do_motd(void) -{ - FILE *f; - char buf[256]; - - if (options.print_motd) { -#ifdef HAVE_LOGIN_CAP - f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", - "/etc/motd"), "r"); -#else - f = fopen("/etc/motd", "r"); -#endif - if (f) { - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stdout); - fclose(f); - } - } -} - - -/* - * Check for quiet login, either .hushlogin or command given. - */ -int -check_quietlogin(Session *s, const char *command) -{ - char buf[256]; - struct passwd *pw = s->pw; - struct stat st; - - /* Return 1 if .hushlogin exists or a command given. */ - if (command != NULL) - return 1; - snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); -#ifdef HAVE_LOGIN_CAP - if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0) - return 1; -#else - if (stat(buf, &st) >= 0) - return 1; -#endif - return 0; -} - -/* - * Sets the value of the given variable in the environment. If the variable - * already exists, its value is overriden. - */ -void -child_set_env(char ***envp, u_int *envsizep, const char *name, - const char *value) -{ - debug3("child_set_env(%s, %s)", name, value); - child_set_env_silent(envp, envsizep, name, value); -} - - -void -child_set_env_silent(char ***envp, u_int *envsizep, const char *name, - const char *value) -{ - u_int i, namelen; - char **env; - - /* - * Find the slot where the value should be stored. If the variable - * already exists, we reuse the slot; otherwise we append a new slot - * at the end of the array, expanding if necessary. - */ - env = *envp; - namelen = strlen(name); - for (i = 0; env[i]; i++) - if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') - break; - if (env[i]) { - /* Reuse the slot. */ - xfree(env[i]); - } else { - /* New variable. Expand if necessary. */ - if (i >= (*envsizep) - 1) { - if (*envsizep >= 1000) - fatal("child_set_env: too many env vars," - " skipping: %.100s", name); - (*envsizep) += 50; - env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *)); - } - /* Need to set the NULL pointer at end of array beyond the new slot. */ - env[i + 1] = NULL; - } - - /* Allocate space and format the variable in the appropriate slot. */ - env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); - snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); -} - -/* - * Reads environment variables from the given file and adds/overrides them - * into the environment. If the file does not exist, this does nothing. - * Otherwise, it must consist of empty lines, comments (line starts with '#') - * and assignments of the form name=value. No other forms are allowed. - */ -static void -read_environment_file(char ***env, u_int *envsize, - const char *filename) -{ - FILE *f; - char buf[4096]; - char *cp, *value; - u_int lineno = 0; - - f = fopen(filename, "r"); - if (!f) - return; - - while (fgets(buf, sizeof(buf), f)) { - if (++lineno > 1000) - fatal("Too many lines in environment file %s", filename); - for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '#' || *cp == '\n') - continue; - if (strchr(cp, '\n')) - *strchr(cp, '\n') = '\0'; - value = strchr(cp, '='); - if (value == NULL) { - fprintf(stderr, gettext("Bad line %u in %.100s\n"), - lineno, filename); - continue; - } - /* - * Replace the equals sign by nul, and advance value to - * the value string. - */ - *value = '\0'; - value++; - child_set_env(env, envsize, cp, value); - } - fclose(f); -} - -void copy_environment(char **source, char ***env, u_int *envsize) -{ - char *var_name, *var_val; - int i; - - if (source == NULL) - return; - - for(i = 0; source[i] != NULL; i++) { - var_name = xstrdup(source[i]); - if ((var_val = strstr(var_name, "=")) == NULL) { - xfree(var_name); - continue; - } - *var_val++ = '\0'; - - debug3("Copy environment: %s=%s", var_name, var_val); - child_set_env(env, envsize, var_name, var_val); - - xfree(var_name); - } -} - -#ifdef HAVE_DEFOPEN -static -void -deflt_do_setup_env(Session *s, const char *shell, char ***env, u_int *envsize) -{ - int flags; - char *ptr; - mode_t Umask = 022; - - if (defopen(_PATH_DEFAULT_LOGIN)) - return; - - /* Ignore case */ - flags = defcntl(DC_GETFLAGS, 0); - TURNOFF(flags, DC_CASE); - (void) defcntl(DC_SETFLAGS, flags); - - /* TZ & HZ */ - if ((ptr = defread("TIMEZONE=")) != NULL) - child_set_env(env, envsize, "TZ", ptr); - if ((ptr = defread("HZ=")) != NULL) - child_set_env(env, envsize, "HZ", ptr); - - /* PATH */ - if (s->pw->pw_uid != 0 && (ptr = defread("PATH=")) != NULL) - child_set_env(env, envsize, "PATH", ptr); - if (s->pw->pw_uid == 0 && (ptr = defread("SUPATH=")) != NULL) - child_set_env(env, envsize, "PATH", ptr); - - /* SHELL */ - if ((ptr = defread("ALTSHELL=")) != NULL) { - if (strcasecmp("YES", ptr) == 0) - child_set_env(env, envsize, "SHELL", shell); - else - child_set_env(env, envsize, "SHELL", ""); - } - - /* UMASK */ - if ((ptr = defread("UMASK=")) != NULL && - sscanf(ptr, "%lo", &Umask) == 1 && - Umask <= (mode_t)0777) - (void) umask(Umask); - else - (void) umask(022); - - /* ULIMIT */ - if ((ptr = defread("ULIMIT=")) != NULL && atol(ptr) > 0L && - ulimit(UL_SETFSIZE, atol(ptr)) < 0L) - error("Could not set ULIMIT to %ld from %s\n", atol(ptr), - _PATH_DEFAULT_LOGIN); - - (void) defopen(NULL); -} -#endif /* HAVE_DEFOPEN */ - -static char ** -do_setup_env(Session *s, const char *shell) -{ - char buf[256]; - char path_maildir[] = _PATH_MAILDIR; - u_int i, envsize, pm_len; - char **env; - struct passwd *pw = s->pw; - - /* Initialize the environment. */ - envsize = 100; - env = xmalloc(envsize * sizeof(char *)); - env[0] = NULL; - -#ifdef HAVE_CYGWIN - /* - * The Windows environment contains some setting which are - * important for a running system. They must not be dropped. - */ - copy_environment(environ, &env, &envsize); -#endif - -#ifdef GSSAPI - /* Allow any GSSAPI methods that we've used to alter - * the childs environment as they see fit - */ - ssh_gssapi_do_child(xxx_gssctxt, &env,&envsize); -#endif - - /* Set basic environment. */ - child_set_env(&env, &envsize, "USER", pw->pw_name); - child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); - child_set_env(&env, &envsize, "HOME", pw->pw_dir); -#ifdef HAVE_LOGIN_CAP - if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0) - child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); - else - child_set_env(&env, &envsize, "PATH", getenv("PATH")); -#else /* HAVE_LOGIN_CAP */ -# ifndef HAVE_CYGWIN - /* - * There's no standard path on Windows. The path contains - * important components pointing to the system directories, - * needed for loading shared libraries. So the path better - * remains intact here. - */ -# ifdef SUPERUSER_PATH - child_set_env(&env, &envsize, "PATH", - s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH); -# else - child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); -# endif /* SUPERUSER_PATH */ -# endif /* HAVE_CYGWIN */ -#endif /* HAVE_LOGIN_CAP */ - - pm_len = strlen(path_maildir); - if (path_maildir[pm_len - 1] == '/' && pm_len > 1) - path_maildir[pm_len - 1] = NULL; - snprintf(buf, sizeof buf, "%.200s/%.50s", - path_maildir, pw->pw_name); - child_set_env(&env, &envsize, "MAIL", buf); - - /* Normal systems set SHELL by default. */ - child_set_env(&env, &envsize, "SHELL", shell); - -#ifdef HAVE_DEFOPEN - deflt_do_setup_env(s, shell, &env, &envsize); -#endif /* HAVE_DEFOPEN */ - -#define PASS_ENV(x) \ - if (getenv(x)) \ - child_set_env(&env, &envsize, x, getenv(x)); - - if (getenv("TZ")) - child_set_env(&env, &envsize, "TZ", getenv("TZ")); - - if (s->auth_file != NULL) - child_set_env(&env, &envsize, "XAUTHORITY", s->auth_file); - - PASS_ENV("LANG") - PASS_ENV("LC_ALL") - PASS_ENV("LC_CTYPE") - PASS_ENV("LC_COLLATE") - PASS_ENV("LC_TIME") - PASS_ENV("LC_NUMERIC") - PASS_ENV("LC_MONETARY") - PASS_ENV("LC_MESSAGES") - -#undef PASS_ENV - - if (s->env != NULL) - copy_environment(s->env, &env, &envsize); - - /* Set custom environment options from RSA authentication. */ - while (custom_environment) { - struct envstring *ce = custom_environment; - char *str = ce->s; - - for (i = 0; str[i] != '=' && str[i]; i++) - ; - if (str[i] == '=') { - str[i] = 0; - child_set_env(&env, &envsize, str, str + i + 1); - } - custom_environment = ce->next; - xfree(ce->s); - xfree(ce); - } - - /* SSH_CLIENT deprecated */ - snprintf(buf, sizeof buf, "%.50s %d %d", - get_remote_ipaddr(), get_remote_port(), get_local_port()); - child_set_env(&env, &envsize, "SSH_CLIENT", buf); - - snprintf(buf, sizeof buf, "%.50s %d %.50s %d", - get_remote_ipaddr(), get_remote_port(), - get_local_ipaddr(packet_get_connection_in()), get_local_port()); - child_set_env(&env, &envsize, "SSH_CONNECTION", buf); - - if (s->ttyfd != -1) - child_set_env(&env, &envsize, "SSH_TTY", s->tty); - if (s->term) - child_set_env(&env, &envsize, "TERM", s->term); - if (s->display) - child_set_env(&env, &envsize, "DISPLAY", s->display); - if (original_command) - child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", - original_command); - -#ifdef _UNICOS - if (cray_tmpdir[0] != '\0') - child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir); -#endif /* _UNICOS */ - -#ifdef _AIX - { - char *cp; - - if ((cp = getenv("AUTHSTATE")) != NULL) - child_set_env(&env, &envsize, "AUTHSTATE", cp); - if ((cp = getenv("KRB5CCNAME")) != NULL) - child_set_env(&env, &envsize, "KRB5CCNAME", cp); - read_environment_file(&env, &envsize, "/etc/environment"); - } -#endif -#ifdef KRB4 - if (s->authctxt->krb4_ticket_file) - child_set_env(&env, &envsize, "KRBTKFILE", - s->authctxt->krb4_ticket_file); -#endif -#ifdef KRB5 - if (s->authctxt->krb5_ticket_file) - child_set_env(&env, &envsize, "KRB5CCNAME", - s->authctxt->krb5_ticket_file); -#endif -#ifdef USE_PAM - /* - * Pull in any environment variables that may have - * been set by PAM. - */ - { - char **p; - - p = fetch_pam_environment(s->authctxt); - copy_environment(p, &env, &envsize); - free_pam_environment(p); - } -#endif /* USE_PAM */ - - if (auth_sock_name != NULL) - child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, - auth_sock_name); - - /* read $HOME/.ssh/environment. */ - if (options.permit_user_env) { - snprintf(buf, sizeof buf, "%.200s/.ssh/environment", - strcmp(pw->pw_dir, "/") ? pw->pw_dir : ""); - read_environment_file(&env, &envsize, buf); - } - if (debug_flag) { - /* dump the environment */ - fprintf(stderr, gettext("Environment:\n")); - for (i = 0; env[i]; i++) - fprintf(stderr, " %.200s\n", env[i]); - } - return env; -} - -/* - * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found - * first in this order). - */ -static void -do_rc_files(Session *s, const char *shell) -{ - FILE *f = NULL; - char cmd[1024]; - int do_xauth; - struct stat st; - - do_xauth = - s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; - - /* ignore _PATH_SSH_USER_RC for subsystems */ - if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) { - snprintf(cmd, sizeof cmd, "%s -c '%s %s'", - shell, _PATH_BSHELL, _PATH_SSH_USER_RC); - if (debug_flag) - fprintf(stderr, "Running %s\n", cmd); - f = popen(cmd, "w"); - if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); - pclose(f); - } else - fprintf(stderr, "Could not run %s\n", - _PATH_SSH_USER_RC); - } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { - if (debug_flag) - fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, - _PATH_SSH_SYSTEM_RC); - f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); - if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); - pclose(f); - } else - fprintf(stderr, "Could not run %s\n", - _PATH_SSH_SYSTEM_RC); - } else if (do_xauth && options.xauth_location != NULL) { - /* Add authority data to .Xauthority if appropriate. */ - if (debug_flag) { - fprintf(stderr, - "Running %.500s add " - "%.100s %.100s %.100s\n", - options.xauth_location, s->auth_display, - s->auth_proto, s->auth_data); - } - snprintf(cmd, sizeof cmd, "%s -q -", - options.xauth_location); - f = popen(cmd, "w"); - if (f) { - fprintf(f, "add %s %s %s\n", - s->auth_display, s->auth_proto, - s->auth_data); - pclose(f); - } else { - fprintf(stderr, "Could not run %s\n", - cmd); - } - } -} - -/* Disallow logins if /etc/nologin exists. This does not apply to root. */ -static void -do_nologin(struct passwd *pw) -{ - FILE *f = NULL; - char buf[1024]; - struct stat sb; - - if (pw->pw_uid == 0) - return; - - if (stat(_PATH_NOLOGIN, &sb) == -1) - return; - - /* /etc/nologin exists. Print its contents if we can and exit. */ - log("User %.100s not allowed because %s exists.", pw->pw_name, - _PATH_NOLOGIN); - if ((f = fopen(_PATH_NOLOGIN, "r")) != NULL) { - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stderr); - fclose(f); - } - exit(254); -} - -/* Chroot into ChrootDirectory if the option is set. */ -void -chroot_if_needed(struct passwd *pw) -{ - char *chroot_path, *tmp; - - if (chroot_requested(options.chroot_directory)) { - tmp = tilde_expand_filename(options.chroot_directory, - pw->pw_uid); - chroot_path = percent_expand(tmp, "h", pw->pw_dir, - "u", pw->pw_name, (char *)NULL); - safely_chroot(chroot_path, pw->pw_uid); - free(tmp); - free(chroot_path); - } -} - -/* - * Chroot into a directory after checking it for safety: all path components - * must be root-owned directories with strict permissions. - */ -static void -safely_chroot(const char *path, uid_t uid) -{ - const char *cp; - char component[MAXPATHLEN]; - struct stat st; - - if (*path != '/') - fatal("chroot path does not begin at root"); - if (strlen(path) >= sizeof(component)) - fatal("chroot path too long"); - - /* - * Descend the path, checking that each component is a - * root-owned directory with strict permissions. - */ - for (cp = path; cp != NULL;) { - if ((cp = strchr(cp, '/')) == NULL) - strlcpy(component, path, sizeof(component)); - else { - cp++; - memcpy(component, path, cp - path); - component[cp - path] = '\0'; - } - - debug3("%s: checking '%s'", __func__, component); - - if (stat(component, &st) != 0) - fatal("%s: stat(\"%s\"): %s", __func__, - component, strerror(errno)); - if (st.st_uid != 0 || (st.st_mode & 022) != 0) - fatal("bad ownership or modes for chroot " - "directory %s\"%s\"", - cp == NULL ? "" : "component ", component); - if (!S_ISDIR(st.st_mode)) - fatal("chroot path %s\"%s\" is not a directory", - cp == NULL ? "" : "component ", component); - } - - if (chdir(path) == -1) - fatal("Unable to chdir to chroot path \"%s\": " - "%s", path, strerror(errno)); - if (chroot(path) == -1) - fatal("chroot(\"%s\"): %s", path, strerror(errno)); - if (chdir("/") == -1) - fatal("%s: chdir(/) after chroot: %s", - __func__, strerror(errno)); - verbose("Changed root directory to \"%s\"", path); -} - -static void -launch_login(struct passwd *pw, const char *hostname) -{ - /* Launch login(1). */ - - execl(LOGIN_PROGRAM, "login", "-h", hostname, -#ifdef xxxLOGIN_NEEDS_TERM - (s->term ? s->term : "unknown"), -#endif /* LOGIN_NEEDS_TERM */ -#ifdef LOGIN_NO_ENDOPT - "-p", "-f", pw->pw_name, (char *)NULL); -#else - "-p", "-f", "--", pw->pw_name, (char *)NULL); -#endif - - /* Login couldn't be executed, die. */ - - perror("login"); - exit(1); -} - -/* - * Performs common processing for the child, such as setting up the - * environment, closing extra file descriptors, setting the user and group - * ids, and executing the command or shell. - */ -#define ARGV_MAX 10 -void -do_child(Session *s, const char *command) -{ - extern char **environ; - char **env; - char *argv[ARGV_MAX]; - const char *shell, *shell0; - struct passwd *pw = s->pw; - - /* remove hostkey from the child's memory */ - destroy_sensitive_data(); - - do_nologin(pw); - chroot_if_needed(pw); - - /* - * Get the shell from the password data. An empty shell field is - * legal, and means /bin/sh. - */ - shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; -#ifdef HAVE_LOGIN_CAP - shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); -#endif - - env = do_setup_env(s, shell); - - /* - * Close the connection descriptors; note that this is the child, and - * the server will still have the socket open, and it is important - * that we do not shutdown it. Note that the descriptors cannot be - * closed before building the environment, as we call - * get_remote_ipaddr there. - */ - if (packet_get_connection_in() == packet_get_connection_out()) - close(packet_get_connection_in()); - else { - close(packet_get_connection_in()); - close(packet_get_connection_out()); - } - /* - * Close all descriptors related to channels. They will still remain - * open in the parent. - */ - /* XXX better use close-on-exec? -markus */ - channel_close_all(); - - /* - * Close any extra file descriptors. Note that there may still be - * descriptors left by system functions. They will be closed later. - */ - endpwent(); - - /* - * Must switch to the new environment variables so that .ssh/rc, - * /etc/ssh/sshrc, and xauth are run in the proper environment. - */ - environ = env; - - /* - * New environment has been installed. We need to update locale - * so that error messages beyond this point have the proper - * character encoding. - */ - (void) setlocale(LC_ALL, ""); - - /* - * Close any extra open file descriptors so that we don\'t have them - * hanging around in clients. Note that we want to do this after - * initgroups, because at least on Solaris 2.3 it leaves file - * descriptors open. - */ - closefrom(STDERR_FILENO + 1); - -#ifdef AFS - /* Try to get AFS tokens for the local cell. */ - if (k_hasafs()) { - char cell[64]; - - if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0) - krb_afslog(cell, 0); - - krb_afslog(0, 0); - } -#endif /* AFS */ - - /* Change current directory to the user's home directory. */ - if (chdir(pw->pw_dir) < 0) { - /* Suppress missing homedir warning for chroot case */ - if (!chroot_requested(options.chroot_directory)) - fprintf(stderr, "Could not chdir to home " - "directory %s: %s\n", pw->pw_dir, - strerror(errno)); - } - - do_rc_files(s, shell); - - /* restore SIGPIPE for child */ - signal(SIGPIPE, SIG_DFL); - - if (s->is_subsystem == SUBSYSTEM_INT_SFTP) { - int i; - char *p, *args; - extern int optind, optreset; - - /* This will set the E/P sets here, simulating exec(2). */ - drop_privs(pw->pw_uid); - - setproctitle("%s@internal-sftp-server", s->pw->pw_name); - args = xstrdup(command ? command : "sftp-server"); - - i = 0; - for ((p = strtok(args, " ")); p != NULL; (p = strtok(NULL, " "))) { - if (i < ARGV_MAX - 1) - argv[i++] = p; - } - - argv[i] = NULL; - optind = optreset = 1; - __progname = argv[0]; - exit(sftp_server_main(i, argv, s->pw)); - } - - /* Get the last component of the shell name. */ - if ((shell0 = strrchr(shell, '/')) != NULL) - shell0++; - else - shell0 = shell; - - /* - * If we have no command, execute the shell. In this case, the shell - * name to be passed in argv[0] is preceded by '-' to indicate that - * this is a login shell. - */ - if (!command) { - char argv0[256]; - - /* Start the shell. Set initial character to '-'. */ - argv0[0] = '-'; - - if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1) - >= sizeof(argv0) - 1) { - errno = EINVAL; - perror(shell); - exit(1); - } - - /* Execute the shell. */ - argv[0] = argv0; - argv[1] = NULL; - execve(shell, argv, env); - - /* Executing the shell failed. */ - perror(shell); - exit(1); - } - /* - * Execute the command using the user's shell. This uses the -c - * option to execute the command. - */ - argv[0] = (char *) shell0; - argv[1] = "-c"; - argv[2] = (char *) command; - argv[3] = NULL; - execve(shell, argv, env); - perror(shell); - exit(1); -} - -Session * -session_new(void) -{ - int i; - static int did_init = 0; - if (!did_init) { - debug("session_new: init"); - for (i = 0; i < MAX_SESSIONS; i++) { - sessions[i].used = 0; - } - did_init = 1; - } - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (! s->used) { - memset(s, 0, sizeof(*s)); - s->chanid = -1; - s->ptyfd = -1; - s->ttyfd = -1; - s->used = 1; - s->self = i; - s->env = NULL; - debug("session_new: session %d", i); - return s; - } - } - return NULL; -} - -static void -session_dump(void) -{ - int i; - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - debug("dump: used %d session %d %p channel %d pid %ld", - s->used, - s->self, - s, - s->chanid, - (long)s->pid); - } -} - -int -session_open(Authctxt *authctxt, int chanid) -{ - Session *s = session_new(); - debug("session_open: channel %d", chanid); - if (s == NULL) { - error("no more sessions"); - return 0; - } - s->authctxt = authctxt; - s->pw = authctxt->pw; - if (s->pw == NULL) - fatal("no user for session %d", s->self); - debug("session_open: session %d: link with channel %d", s->self, chanid); - s->chanid = chanid; - return 1; -} - -#ifndef lint -Session * -session_by_tty(char *tty) -{ - int i; - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { - debug("session_by_tty: session %d tty %s", i, tty); - return s; - } - } - debug("session_by_tty: unknown tty %.100s", tty); - session_dump(); - return NULL; -} -#endif /* lint */ - -static Session * -session_by_channel(int id) -{ - int i; - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (s->used && s->chanid == id) { - debug("session_by_channel: session %d channel %d", i, id); - return s; - } - } - debug("session_by_channel: unknown channel %d", id); - session_dump(); - return NULL; -} - -static Session * -session_by_pid(pid_t pid) -{ - int i; - debug("session_by_pid: pid %ld", (long)pid); - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (s->used && s->pid == pid) - return s; - } - error("session_by_pid: unknown pid %ld", (long)pid); - session_dump(); - return NULL; -} - -static int -session_window_change_req(Session *s) -{ - s->col = packet_get_int(); - s->row = packet_get_int(); - s->xpixel = packet_get_int(); - s->ypixel = packet_get_int(); - packet_check_eom(); - pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); - return 1; -} - -static int -session_pty_req(Session *s) -{ - u_int len; - int n_bytes; - - if (no_pty_flag) { - debug("Allocating a pty not permitted for this authentication."); - return 0; - } - if (s->ttyfd != -1) { - packet_disconnect("Protocol error: you already have a pty."); - return 0; - } - /* Get the time and hostname when the user last logged in. */ - if (options.print_lastlog) { - s->hostname[0] = '\0'; - s->last_login_time = get_last_login_time(s->pw->pw_uid, - s->pw->pw_name, s->hostname, sizeof(s->hostname)); - - /* - * PAM may update the last login date. - * - * Ideally PAM would also show the last login date as a - * PAM_TEXT_INFO conversation message, and then we could just - * always force the use of keyboard-interactive just so we can - * pass any such PAM prompts and messages from the account and - * session stacks, but skip pam_authenticate() if other userauth - * has succeeded and the user's password isn't expired. - * - * Unfortunately this depends on support for keyboard- - * interactive in the client, and support for lastlog messages - * in some PAM module. - * - * As it is Solaris updates the lastlog in PAM, but does - * not show the lastlog date in PAM. If and when this state of - * affairs changes this hack can be reconsidered, and, maybe, - * removed. - * - * So we're stuck with a crude hack: get the lastlog - * time before calling pam_open_session() and store it - * in the Authctxt and then use it here once. After - * that, if the client opens any more pty sessions we'll - * show the last lastlog entry since userauth. - */ - if (s->authctxt != NULL && s->authctxt->last_login_time > 0) { - s->last_login_time = s->authctxt->last_login_time; - (void) strlcpy(s->hostname, - s->authctxt->last_login_host, - sizeof(s->hostname)); - s->authctxt->last_login_time = 0; - s->authctxt->last_login_host[0] = '\0'; - } - } - - s->term = packet_get_string(&len); - - if (compat20) { - s->col = packet_get_int(); - s->row = packet_get_int(); - } else { - s->row = packet_get_int(); - s->col = packet_get_int(); - } - s->xpixel = packet_get_int(); - s->ypixel = packet_get_int(); - - if (strcmp(s->term, "") == 0) { - xfree(s->term); - s->term = NULL; - } - - /* Allocate a pty and open it. */ - debug("Allocating pty."); - if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) { - if (s->term) - xfree(s->term); - s->term = NULL; - s->ptyfd = -1; - s->ttyfd = -1; - error("session_pty_req: session %d alloc failed", s->self); - return 0; - } - debug("session_pty_req: session %d alloc %s", s->self, s->tty); - - /* for SSH1 the tty modes length is not given */ - if (!compat20) - n_bytes = packet_remaining(); - tty_parse_modes(s->ttyfd, &n_bytes); - - /* - * Add a cleanup function to clear the utmp entry and record logout - * time in case we call fatal() (e.g., the connection gets closed). - */ - fatal_add_cleanup(session_pty_cleanup, (void *)s); - pty_setowner(s->pw, s->tty); - - /* Set window size from the packet. */ - pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); - - packet_check_eom(); - session_proctitle(s); - return 1; -} - -static int -session_subsystem_req(Session *s) -{ - struct stat st; - u_int len; - int success = 0; - char *prog, *cmd, *subsys = packet_get_string(&len); - u_int i; - - packet_check_eom(); - log("subsystem request for %.100s", subsys); - - for (i = 0; i < options.num_subsystems; i++) { - if (strcmp(subsys, options.subsystem_name[i]) == 0) { - prog = options.subsystem_command[i]; - cmd = options.subsystem_args[i]; - if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) { - s->is_subsystem = SUBSYSTEM_INT_SFTP; - /* - * We must stat(2) the subsystem before we chroot in - * order to be able to send a proper error message. - */ - } else if (chroot_requested(options.chroot_directory)) { - char chdirsub[MAXPATHLEN]; - - strlcpy(chdirsub, options.chroot_directory, - sizeof (chdirsub)); - strlcat(chdirsub, "/", sizeof (chdirsub)); - strlcat(chdirsub, prog, sizeof (chdirsub)); - if (stat(chdirsub, &st) < 0) { - error("subsystem: cannot stat %s under " - "chroot directory %s: %s", prog, - options.chroot_directory, - strerror(errno)); - if (strcmp(subsys, "sftp") == 0) - error("subsystem: please see " - "the Subsystem option in " - "sshd_config(4) for an " - "explanation of '%s'.", - INTERNAL_SFTP_NAME); - break; - } - } else if (stat(prog, &st) < 0) { - error("subsystem: cannot stat %s: %s", prog, - strerror(errno)); - break; - } else { - s->is_subsystem = SUBSYSTEM_EXT; - } - debug("subsystem: exec() %s", cmd); - do_exec(s, cmd); - success = 1; - break; - } - } - - if (!success) - log("subsystem request for %.100s failed, subsystem not found", - subsys); - - xfree(subsys); - return success; -} - -/* - * Serve "x11-req" channel request for X11 forwarding for the current session - * channel. - */ -static int -session_x11_req(Session *s) -{ - int success, fd; - char xauthdir[] = "/tmp/ssh-xauth-XXXXXX"; - - s->single_connection = packet_get_char(); - s->auth_proto = packet_get_string(NULL); - s->auth_data = packet_get_string(NULL); - s->screen = packet_get_int(); - packet_check_eom(); - - success = session_setup_x11fwd(s); - if (!success) { - xfree(s->auth_proto); - xfree(s->auth_data); - s->auth_proto = NULL; - s->auth_data = NULL; - return (success); - } - - /* - * Create per session X authority file so that different sessions - * don't contend for one common file. The reason for this is that - * xauth(1) locking doesn't work too well over network filesystems. - * - * If mkdtemp() or open() fails then s->auth_file remains NULL which - * means that we won't set XAUTHORITY variable in child's environment - * and xauth(1) will use the default location for the authority file. - */ - if (mkdtemp(xauthdir) != NULL) { - s->auth_file = xmalloc(MAXPATHLEN); - snprintf(s->auth_file, MAXPATHLEN, "%s/xauthfile", - xauthdir); - /* - * we don't want that "creating new authority file" message to - * be printed by xauth(1) so we must create that file - * beforehand. - */ - if ((fd = open(s->auth_file, O_CREAT | O_EXCL | O_RDONLY, - S_IRUSR | S_IWUSR)) == -1) { - error("failed to create the temporary X authority " - "file %s: %.100s; will use the default one", - s->auth_file, strerror(errno)); - xfree(s->auth_file); - s->auth_file = NULL; - if (rmdir(xauthdir) == -1) { - error("cannot remove xauth directory %s: %.100s", - xauthdir, strerror(errno)); - } - } else { - close(fd); - debug("temporary X authority file %s created", - s->auth_file); - - /* - * add a cleanup function to remove the temporary - * xauth file in case we call fatal() (e.g., the - * connection gets closed). - */ - fatal_add_cleanup(session_xauthfile_cleanup, (void *)s); - } - } - else { - error("failed to create a directory for the temporary X " - "authority file: %.100s; will use the default xauth file", - strerror(errno)); - } - - return (success); -} - -static int -session_shell_req(Session *s) -{ - packet_check_eom(); - do_exec(s, NULL); - return 1; -} - -static int -session_exec_req(Session *s) -{ - u_int len; - char *command = packet_get_string(&len); - packet_check_eom(); - do_exec(s, command); - xfree(command); - return 1; -} - -static int -session_auth_agent_req(Session *s) -{ - static int called = 0; - packet_check_eom(); - if (no_agent_forwarding_flag) { - debug("session_auth_agent_req: no_agent_forwarding_flag"); - return 0; - } - if (called) { - return 0; - } else { - called = 1; - return auth_input_request_forwarding(s->pw); - } -} - -static int -session_loc_env_check(char *var, char *val) -{ - char *current; - int cat, ret; - - if (strcmp(var, "LANG") == 0) - cat = LC_ALL; - else if (strcmp(var, "LC_ALL") == 0) - cat = LC_ALL; - else if (strcmp(var, "LC_CTYPE") == 0) - cat = LC_CTYPE; - else if (strcmp(var, "LC_COLLATE") == 0) - cat = LC_COLLATE; - else if (strcmp(var, "LC_TIME") == 0) - cat = LC_TIME; - else if (strcmp(var, "LC_NUMERIC") == 0) - cat = LC_NUMERIC; - else if (strcmp(var, "LC_MONETARY") == 0) - cat = LC_MONETARY; - else if (strcmp(var, "LC_MESSAGES") == 0) - cat = LC_MESSAGES; - - current = setlocale(cat, NULL); - - ret = (setlocale(cat, val) != NULL); - (void) setlocale(cat, current); - return (ret); -} - -static int -session_env_req(Session *s) -{ - Channel *c; - char *var, *val, *e; - char **p; - size_t len; - int ret = 0; - - /* Get var/val from the rest of this packet */ - var = packet_get_string(NULL); - val = packet_get_string(NULL); - - /* - * We'll need the channel ID for the packet_send_debug messages, - * so get it now. - */ - if ((c = channel_lookup(s->chanid)) == NULL) - goto done; /* shouldn't happen! */ - - debug2("Received request for environment variable %s=%s", var, val); - - /* For now allow only LANG and LC_* */ - if (strcmp(var, "LANG") != 0 && strncmp(var, "LC_", 3) != 0) { - debug2("Rejecting request for environment variable %s", var); - goto done; - } - - if (!session_loc_env_check(var, val)) { - packet_send_debug(gettext("Missing locale support for %s=%s"), - var, val); - goto done; - } - - packet_send_debug(gettext("Channel %d set: %s=%s"), c->remote_id, - var, val); - - /* - * Always append new environment variables without regard to old - * ones being overriden. The way these are actually added to - * the environment of the session process later settings - * override earlier ones; see copy_environment(). - */ - if (s->env == NULL) { - char **env; - - env = xmalloc(sizeof (char **) * 2); - memset(env, 0, sizeof (char **) * 2); - - s->env = env; - p = env; - } else { - for (p = s->env; *p != NULL ; p++); - - s->env = xrealloc(s->env, (p - s->env + 2) * sizeof (char **)); - - for (p = s->env; *p != NULL ; p++); - } - - len = snprintf(NULL, 0, "%s=%s", var, val); - e = xmalloc(len + 1); - (void) snprintf(e, len + 1, "%s=%s", var, val); - - (*p++) = e; - *p = NULL; - - ret = 1; - -done: - xfree(var); - xfree(val); - - return (ret); -} - -static void -session_free_env(char ***envp) -{ - char **env, **p; - - if (envp == NULL || *envp == NULL) - return; - - env = *envp; - - *envp = NULL; - - for (p = env; *p != NULL; p++) - xfree(*p); - - xfree(env); -} - -int -session_input_channel_req(Channel *c, const char *rtype) -{ - int success = 0; - Session *s; - - if ((s = session_by_channel(c->self)) == NULL) { - log("session_input_channel_req: no session %d req %.100s", - c->self, rtype); - return 0; - } - debug("session_input_channel_req: session %d req %s", s->self, rtype); - - /* - * a session is in LARVAL state until a shell, a command - * or a subsystem is executed - */ - if (c->type == SSH_CHANNEL_LARVAL) { - if (strcmp(rtype, "shell") == 0) { - success = session_shell_req(s); - } else if (strcmp(rtype, "exec") == 0) { - success = session_exec_req(s); - } else if (strcmp(rtype, "pty-req") == 0) { - success = session_pty_req(s); - } else if (strcmp(rtype, "x11-req") == 0) { - success = session_x11_req(s); - } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { - success = session_auth_agent_req(s); - } else if (strcmp(rtype, "subsystem") == 0) { - success = session_subsystem_req(s); - } else if (strcmp(rtype, "env") == 0) { - success = session_env_req(s); - } - } - if (strcmp(rtype, "window-change") == 0) { - success = session_window_change_req(s); - } - return success; -} - -void -session_set_fds(Session *s, int fdin, int fdout, int fderr) -{ - if (!compat20) - fatal("session_set_fds: called for proto != 2.0"); - /* - * now that have a child and a pipe to the child, - * we can activate our channel and register the fd's - */ - if (s->chanid == -1) - fatal("no channel for session %d", s->self); - channel_set_fds(s->chanid, - fdout, fdin, fderr, - fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1, - CHAN_SES_WINDOW_DEFAULT); -} - -/* - * Function to perform pty cleanup. Also called if we get aborted abnormally - * (e.g., due to a dropped connection). - */ -void -session_pty_cleanup2(void *session) -{ - Session *s = session; - - if (s == NULL) { - error("session_pty_cleanup: no session"); - return; - } - if (s->ttyfd == -1) - return; - - debug("session_pty_cleanup: session %d release %s", s->self, s->tty); - -#ifdef USE_PAM - session_do_pam(s, 0); -#endif /* USE_PAM */ - - /* Record that the user has logged out. */ - if (s->pid != 0) { - debug3("Recording SSHv2 channel logout in utmpx/wtmpx"); -#ifdef ALTPRIVSEP - altprivsep_record_logout(s->pid); -#endif /* ALTPRIVSEP */ - } - - /* Release the pseudo-tty. */ - if (getuid() == 0) - pty_release(s->tty); - - /* - * Close the server side of the socket pairs. We must do this after - * the pty cleanup, so that another process doesn't get this pty - * while we're still cleaning up. - */ - if (close(s->ptymaster) < 0) - error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); - - /* unlink pty from session */ - s->ttyfd = -1; -} - -void -session_pty_cleanup(void *session) -{ - session_pty_cleanup2(session); -} - -/* - * We use a different temporary X authority file per every session so we - * should remove those files when fatal() is called. - */ -void -session_xauthfile_cleanup(void *session) -{ - Session *s = session; - - if (s == NULL) { - error("session_xauthfile_cleanup: no session"); - return; - } - - debug("session_xauthfile_cleanup: session %d removing %s", s->self, - s->auth_file); - - if (unlink(s->auth_file) == -1) { - error("session_xauthfile_cleanup: cannot remove xauth file: " - "%.100s", strerror(errno)); - return; - } - - /* dirname() will modify s->auth_file but that's ok */ - if (rmdir(dirname(s->auth_file)) == -1) { - error("session_xauthfile_cleanup: " - "cannot remove xauth directory: %.100s", strerror(errno)); - return; - } -} - -static char * -sig2name(int sig) -{ -#define SSH_SIG(x) if (sig == SIG ## x) return #x - SSH_SIG(ABRT); - SSH_SIG(ALRM); - SSH_SIG(FPE); - SSH_SIG(HUP); - SSH_SIG(ILL); - SSH_SIG(INT); - SSH_SIG(KILL); - SSH_SIG(PIPE); - SSH_SIG(QUIT); - SSH_SIG(SEGV); - SSH_SIG(TERM); - SSH_SIG(USR1); - SSH_SIG(USR2); -#undef SSH_SIG - return "SIG@openssh.com"; -} - -static void -session_exit_message(Session *s, int status) -{ - Channel *c; - - if ((c = channel_lookup(s->chanid)) == NULL) - fatal("session_exit_message: session %d: no channel %d", - s->self, s->chanid); - debug("session_exit_message: session %d channel %d pid %ld", - s->self, s->chanid, (long)s->pid); - - if (WIFEXITED(status)) { - channel_request_start(s->chanid, "exit-status", 0); - packet_put_int(WEXITSTATUS(status)); - packet_send(); - } else if (WIFSIGNALED(status)) { - channel_request_start(s->chanid, "exit-signal", 0); - packet_put_cstring(sig2name(WTERMSIG(status))); -#ifdef WCOREDUMP - packet_put_char(WCOREDUMP(status)); -#else /* WCOREDUMP */ - packet_put_char(0); -#endif /* WCOREDUMP */ - packet_put_cstring(""); - packet_put_cstring(""); - packet_send(); - } else { - /* Some weird exit cause. Just exit. */ - packet_disconnect("wait returned status %04x.", status); - } - - /* Ok to close channel now */ - channel_set_wait_for_exit(s->chanid, 0); - - /* disconnect channel */ - debug("session_exit_message: release channel %d", s->chanid); - channel_cancel_cleanup(s->chanid); - /* - * emulate a write failure with 'chan_write_failed', nobody will be - * interested in data we write. - * Note that we must not call 'chan_read_failed', since there could - * be some more data waiting in the pipe. - */ - if (c->ostate != CHAN_OUTPUT_CLOSED) - chan_write_failed(c); - s->chanid = -1; -} - -void -session_close(Session *s) -{ - debug("session_close: session %d pid %ld", s->self, (long)s->pid); - if (s->ttyfd != -1) { - fatal_remove_cleanup(session_pty_cleanup, (void *)s); - session_pty_cleanup(s); - } - if (s->auth_file != NULL) { - fatal_remove_cleanup(session_xauthfile_cleanup, (void *)s); - session_xauthfile_cleanup(s); - xfree(s->auth_file); - } - if (s->term) - xfree(s->term); - if (s->display) - xfree(s->display); - if (s->auth_display) - xfree(s->auth_display); - if (s->auth_data) - xfree(s->auth_data); - if (s->auth_proto) - xfree(s->auth_proto); - if (s->command) - xfree(s->command); - session_free_env(&s->env); - s->used = 0; - session_proctitle(s); -} - -void -session_close_by_pid(pid_t pid, int status) -{ - Session *s = session_by_pid(pid); - if (s == NULL) { - debug("session_close_by_pid: no session for pid %ld", - (long)pid); - return; - } - if (s->chanid != -1) - session_exit_message(s, status); - session_close(s); -} - -/* - * This is called when a channel dies before the session 'child' itself dies. - * It can happen for example if we exit from an interactive shell before we - * exit from forwarded X11 applications. - */ -void -session_close_by_channel(int id, void *arg) -{ - Session *s = session_by_channel(id); - if (s == NULL) { - debug("session_close_by_channel: no session for id %d", id); - return; - } - debug("session_close_by_channel: channel %d child %ld", - id, (long)s->pid); - if (s->pid != 0) { - debug("session_close_by_channel: channel %d: has child", id); - /* - * delay detach of session, but release pty, since - * the fd's to the child are already closed - */ - if (s->ttyfd != -1) { - fatal_remove_cleanup(session_pty_cleanup, (void *)s); - session_pty_cleanup(s); - } - return; - } - /* detach by removing callback */ - channel_cancel_cleanup(s->chanid); - s->chanid = -1; - session_close(s); -} - -void -session_destroy_all(void (*closefunc)(Session *)) -{ - int i; - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (s->used) { - if (closefunc != NULL) - closefunc(s); - else - session_close(s); - } - } -} - -static char * -session_tty_list(void) -{ - static char buf[1024]; - int i; - buf[0] = '\0'; - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (s->used && s->ttyfd != -1) { - if (buf[0] != '\0') - strlcat(buf, ",", sizeof buf); - strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf); - } - } - if (buf[0] == '\0') - strlcpy(buf, "notty", sizeof buf); - return buf; -} - -void -session_proctitle(Session *s) -{ - if (s->pw == NULL) - error("no user for session %d", s->self); - else - setproctitle("%s@%s", s->pw->pw_name, session_tty_list()); -} - -int -session_setup_x11fwd(Session *s) -{ - struct stat st; - char display[512], auth_display[512]; - char hostname[MAXHOSTNAMELEN]; - - if (no_x11_forwarding_flag) { - packet_send_debug("X11 forwarding disabled in user configuration file."); - return 0; - } - if (!options.x11_forwarding) { - debug("X11 forwarding disabled in server configuration file."); - return 0; - } - if (!options.xauth_location || - (stat(options.xauth_location, &st) == -1)) { - packet_send_debug("No xauth program; cannot forward with spoofing."); - return 0; - } - if (s->display != NULL) { - debug("X11 display already set."); - return 0; - } - if (x11_create_display_inet(options.x11_display_offset, - options.x11_use_localhost, s->single_connection, - &s->display_number) == -1) { - debug("x11_create_display_inet failed."); - return 0; - } - - /* Set up a suitable value for the DISPLAY variable. */ - if (gethostname(hostname, sizeof(hostname)) < 0) - fatal("gethostname: %.100s", strerror(errno)); - /* - * auth_display must be used as the displayname when the - * authorization entry is added with xauth(1). This will be - * different than the DISPLAY string for localhost displays. - */ - if (options.x11_use_localhost) { - snprintf(display, sizeof display, "localhost:%u.%u", - s->display_number, s->screen); - snprintf(auth_display, sizeof auth_display, "unix:%u.%u", - s->display_number, s->screen); - s->display = xstrdup(display); - s->auth_display = xstrdup(auth_display); - } else { -#ifdef IPADDR_IN_DISPLAY - struct hostent *he; - struct in_addr my_addr; - - he = gethostbyname(hostname); - if (he == NULL) { - error("Can't get IP address for X11 DISPLAY."); - packet_send_debug("Can't get IP address for X11 DISPLAY."); - return 0; - } - memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr)); - snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr), - s->display_number, s->screen); -#else - snprintf(display, sizeof display, "%.400s:%u.%u", hostname, - s->display_number, s->screen); -#endif - s->display = xstrdup(display); - s->auth_display = xstrdup(display); - } - - return 1; -} - -#ifdef USE_PAM -int session_do_pam_conv(int, struct pam_message **, - struct pam_response **, void *); - -static struct pam_conv session_pam_conv = { - session_do_pam_conv, - NULL -}; - -static void -session_do_pam(Session *s, int do_open) -{ - int pam_retval; - char *where, *old_tty, *old_tty_copy = NULL; - struct pam_conv old_conv, *old_conv_ptr; - - if (!s || !s->authctxt || !s->authctxt->pam || !s->authctxt->pam->h) - return; - - /* Save current PAM item values */ - where = "getting PAM_CONV"; - pam_retval = pam_get_item(s->authctxt->pam->h, PAM_CONV, - (void **) &old_conv_ptr); - if (pam_retval != PAM_SUCCESS) - goto done; - old_conv = *old_conv_ptr; - - where = "getting PAM_TTY"; - pam_retval = pam_get_item(s->authctxt->pam->h, PAM_TTY, - (void **) &old_tty); - if (pam_retval != PAM_SUCCESS) - goto done; - old_tty_copy = xstrdup(old_tty); - - /* Change PAM_TTY and PAM_CONV items */ - where = "setting PAM_TTY"; - pam_retval = pam_set_item(s->authctxt->pam->h, PAM_TTY, s->tty); - if (pam_retval != PAM_SUCCESS) - goto done; - - where = "setting PAM_CONV"; - session_pam_conv.appdata_ptr = s; - pam_retval = pam_set_item(s->authctxt->pam->h, - PAM_CONV, &session_pam_conv); - if (pam_retval != PAM_SUCCESS) - goto done; - - /* Call pam_open/close_session() */ - if (do_open) { - where = "calling pam_open_session()"; - pam_retval = pam_open_session(s->authctxt->pam->h, 0); - } - else { - where = "calling pam_close_session()"; - pam_retval = pam_close_session(s->authctxt->pam->h, 0); - } - - /* Reset PAM_TTY and PAM_CONV items to previous values */ - where = "setting PAM_TTY"; - pam_retval = pam_set_item(s->authctxt->pam->h, PAM_TTY, old_tty_copy); - if (pam_retval != PAM_SUCCESS) - goto done; - - where = "setting PAM_CONV"; - pam_retval = pam_set_item(s->authctxt->pam->h, PAM_CONV, &old_conv); - if (pam_retval != PAM_SUCCESS) - goto done; - - session_pam_conv.appdata_ptr = NULL; - -done: - if (old_tty_copy) - xfree(old_tty_copy); - - if (pam_retval == PAM_SUCCESS) - return; - - /* fatal()? probably not... */ - log("PAM failed[%d] while %s: %s", pam_retval, where, - PAM_STRERROR(s->authctxt->pam->h, pam_retval)); -} - -int -session_do_pam_conv(int num_prompts, - struct pam_message **prompts, - struct pam_response **resp, - void *app_data) -{ - Session *s = (Session *) app_data; - - struct pam_response *reply; - int count; - char *prompt; - - if (channel_lookup(s->chanid) == NULL) - return PAM_CONV_ERR; - - /* PAM will free this later */ - reply = xmalloc(num_prompts * sizeof(*reply)); - - (void) memset(reply, 0, num_prompts * sizeof(*reply)); - for (count = 0; count < num_prompts; count++) { - switch(PAM_MSG_MEMBER(prompts, count, msg_style)) { - case PAM_TEXT_INFO: - /* Write to stdout of channel */ - prompt = PAM_MSG_MEMBER(prompts, count, msg); - if (prompt != NULL && s->ttyfd != -1) { - debug2("session_do_pam_conv: text info " - "prompt: %s", prompt); - (void) write(s->ttyfd, prompt, strlen(prompt)); - (void) write(s->ttyfd, "\n", 1); - } - reply[count].resp = xstrdup(""); - reply[count].resp_retcode = PAM_SUCCESS; - break; - case PAM_ERROR_MSG: - /* Write to stderr of channel */ - prompt = PAM_MSG_MEMBER(prompts, count, msg); - if (prompt != NULL && s->ttyfd != -1) { - debug2("session_do_pam_conv: error " - "prompt: %s", prompt); - (void) write(s->ttyfd, prompt, strlen(prompt)); - (void) write(s->ttyfd, "\n", 1); - } - reply[count].resp = xstrdup(""); - reply[count].resp_retcode = PAM_SUCCESS; - break; - case PAM_PROMPT_ECHO_ON: - case PAM_PROMPT_ECHO_OFF: - /* - * XXX Someday add support for echo on/off prompts - * here on sessions with ttys. - */ - default: - xfree(reply); - return PAM_CONV_ERR; - } - } - - *resp = reply; - - return PAM_SUCCESS; -} -#endif /* USE_PAM */ - -static void -do_authenticated2(Authctxt *authctxt) -{ - server_loop2(authctxt); -} - -/* - * Drop the privileges. We need this for the in-process SFTP server only. For - * the shell and the external subsystem the exec(2) call will do the P = E = I - * assignment itself. Never change the privileges if the connecting user is - * root. See privileges(5) if the terminology used here is not known to you. - */ -static void -drop_privs(uid_t uid) -{ - priv_set_t *priv_inherit; - - /* If root is connecting we are done. */ - if (uid == 0) - return; - - if ((priv_inherit = priv_allocset()) == NULL) - fatal("priv_allocset: %s", strerror(errno)); - if (getppriv(PRIV_INHERITABLE, priv_inherit) != 0) - fatal("getppriv: %s", strerror(errno)); - - /* - * This will limit E as well. Note that before this P was a - * superset of I, see permanently_set_uid(). - */ - if (setppriv(PRIV_SET, PRIV_PERMITTED, priv_inherit) == -1) - fatal("setppriv: %s", strerror(errno)); - - priv_freeset(priv_inherit); - - /* - * By manipulating the P set above we entered a PA mode which we - * do not need to retain in. - */ - if (setpflags(PRIV_AWARE, 0) == -1) - fatal("setpflags: %s", strerror(errno)); -} diff --git a/usr/src/cmd/ssh/sshd/sshd.c b/usr/src/cmd/ssh/sshd/sshd.c deleted file mode 100644 index 3be0890a8c..0000000000 --- a/usr/src/cmd/ssh/sshd/sshd.c +++ /dev/null @@ -1,2051 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This program is the ssh daemon. It listens for connections from clients, - * and performs authentication, executes use commands or shell, and forwards - * information to/from the application to the user client over an encrypted - * connection. This can also handle forwarding of X11, TCP/IP, and - * authentication agent connections. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * SSH2 implementation: - * Privilege Separation: - * - * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. - * Copyright (c) 2002 Niels Provos. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.260 2002/09/27 10:42:09 mickey Exp $"); - -#include <openssl/dh.h> -#include <openssl/bn.h> -#include <openssl/md5.h> - -#include <openssl/rand.h> - -#include "ssh.h" -#include "ssh1.h" -#include "ssh2.h" -#include "xmalloc.h" -#include "rsa.h" -#include "sshpty.h" -#include "packet.h" -#include "mpaux.h" -#include "log.h" -#include "servconf.h" -#include "uidswap.h" -#include "compat.h" -#include "buffer.h" -#include "cipher.h" -#include "kex.h" -#include "key.h" -#include "dh.h" -#include "myproposal.h" -#include "authfile.h" -#include "pathnames.h" -#include "atomicio.h" -#include "canohost.h" -#include "auth.h" -#include "misc.h" -#include "dispatch.h" -#include "channels.h" -#include "session.h" -#include "g11n.h" -#include "sshlogin.h" -#include "xlist.h" -#include "engine.h" - -#ifdef HAVE_BSM -#include "bsmaudit.h" -#endif /* HAVE_BSM */ - -#ifdef ALTPRIVSEP -#include "altprivsep.h" -#endif /* ALTPRIVSEP */ - -#ifdef HAVE_SOLARIS_CONTRACTS -#include <sys/ctfs.h> -#include <sys/contract.h> -#include <sys/contract/process.h> -#include <libcontract.h> -#endif /* HAVE_SOLARIS_CONTRACTS */ - -#ifdef GSSAPI -#include "ssh-gss.h" -#endif /* GSSAPI */ - -#ifdef LIBWRAP -#include <tcpd.h> -#include <syslog.h> -#ifndef lint -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING; -#endif /* lint */ -#endif /* LIBWRAP */ - -#ifndef O_NOCTTY -#define O_NOCTTY 0 -#endif - -#ifdef HAVE___PROGNAME -extern char *__progname; -#else -char *__progname; -#endif - -/* Server configuration options. */ -ServerOptions options; - -/* Name of the server configuration file. */ -static char *config_file_name = _PATH_SERVER_CONFIG_FILE; - -/* - * Flag indicating whether IPv4 or IPv6. This can be set on the command line. - * Default value is AF_UNSPEC means both IPv4 and IPv6. - */ -#ifdef IPV4_DEFAULT -int IPv4or6 = AF_INET; -#else -int IPv4or6 = AF_UNSPEC; -#endif - -/* - * Debug mode flag. This can be set on the command line. If debug - * mode is enabled, extra debugging output will be sent to the system - * log, the daemon will not go to background, and will exit after processing - * the first connection. - */ -int debug_flag = 0; - -/* Flag indicating that the daemon should only test the configuration and keys. */ -static int test_flag = 0; - -/* Flag indicating that the daemon is being started from inetd. */ -static int inetd_flag = 0; - -/* Flag indicating that sshd should not detach and become a daemon. */ -static int no_daemon_flag = 0; - -/* debug goes to stderr unless inetd_flag is set */ -int log_stderr = 0; - -/* Saved arguments to main(). */ -static char **saved_argv; -static int saved_argc; - -/* - * The sockets that the server is listening; this is used in the SIGHUP - * signal handler. - */ -#define MAX_LISTEN_SOCKS 16 -static int listen_socks[MAX_LISTEN_SOCKS]; -static int num_listen_socks = 0; - -/* - * the client's version string, passed by sshd2 in compat mode. if != NULL, - * sshd will skip the version-number exchange - */ -static char *client_version_string = NULL; -static char *server_version_string = NULL; - -/* for rekeying XXX fixme */ -Kex *xxx_kex; - -/* - * Any really sensitive data in the application is contained in this - * structure. The idea is that this structure could be locked into memory so - * that the pages do not get written into swap. However, there are some - * problems. The private key contains BIGNUMs, and we do not (in principle) - * have access to the internals of them, and locking just the structure is - * not very useful. Currently, memory locking is not implemented. - */ -static struct { - Key *server_key; /* ephemeral server key */ - Key *ssh1_host_key; /* ssh1 host key */ - Key **host_keys; /* all private host keys */ - int have_ssh1_key; - int have_ssh2_key; - u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; -} sensitive_data; - -/* - * Flag indicating whether the RSA server key needs to be regenerated. - * Is set in the SIGALRM handler and cleared when the key is regenerated. - */ -static volatile sig_atomic_t key_do_regen = 0; - -/* 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; - -/* session identifier, used by RSA-auth */ -u_char session_id[16]; - -/* same for ssh2 */ -u_char *session_id2 = NULL; -int session_id2_len = 0; - -/* record remote hostname or ip */ -u_int utmp_len = MAXHOSTNAMELEN; - -/* options.max_startup sized array of fd ints */ -static int *startup_pipes = NULL; -static int startup_pipe = -1; /* in child */ - -/* sshd_config buffer */ -Buffer cfg; - -#ifdef GSSAPI -static gss_OID_set mechs = GSS_C_NULL_OID_SET; -#endif /* GSSAPI */ - -/* Prototypes for various functions defined later in this file. */ -void destroy_sensitive_data(void); -static void demote_sensitive_data(void); - -static void do_ssh1_kex(void); -static void do_ssh2_kex(void); - -/* - * Close all listening sockets - */ -static void -close_listen_socks(void) -{ - int i; - - for (i = 0; i < num_listen_socks; i++) - (void) close(listen_socks[i]); - num_listen_socks = -1; -} - -static void -close_startup_pipes(void) -{ - int i; - - if (startup_pipes) - for (i = 0; i < options.max_startups; i++) - if (startup_pipes[i] != -1) - (void) close(startup_pipes[i]); -} - -/* - * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; - * the effect is to reread the configuration file (and to regenerate - * the server key). - */ -static void -sighup_handler(int sig) -{ - int save_errno = errno; - - received_sighup = 1; - (void) signal(SIGHUP, sighup_handler); - errno = save_errno; -} - -/* - * Called from the main program after receiving SIGHUP. - * Restarts the server. - */ -static void -sighup_restart(void) -{ - log("Received SIGHUP; restarting."); - close_listen_socks(); - close_startup_pipes(); - (void) execv(saved_argv[0], saved_argv); - log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], - strerror(errno)); - exit(1); -} - -/* - * Generic signal handler for terminating signals in the master daemon. - */ -static void -sigterm_handler(int sig) -{ - received_sigterm = sig; -} - -/* - * SIGCHLD handler. This is called whenever a child dies. This will then - * reap any zombies left by exited children. - */ -static void -main_sigchld_handler(int sig) -{ - int save_errno = errno; - pid_t pid; - int status; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || - (pid < 0 && errno == EINTR)) - ; - - (void) signal(SIGCHLD, main_sigchld_handler); - errno = save_errno; -} - -/* - * Signal handler for the alarm after the login grace period has expired. This - * is for the (soon-to-be) unprivileged child only. The monitor gets an event on - * the communication pipe and exits as well. - */ -static void -grace_alarm_handler(int sig) -{ - /* Log error and exit. */ - fatal("Timeout before authentication for %.200s", get_remote_ipaddr()); -} - -#ifdef HAVE_SOLARIS_CONTRACTS -static int contracts_fd = -1; -void -contracts_pre_fork() -{ - const char *during = "opening process contract template"; - - /* - * Failure should not be treated as fatal on the theory that - * it's better to start with children in the same contract as - * the master listener than not at all. - */ - - if (contracts_fd == -1) { - if ((contracts_fd = open64(CTFS_ROOT "/process/template", - O_RDWR)) == -1) - goto cleanup; - - during = "setting sundry contract terms"; - if ((errno = ct_pr_tmpl_set_param(contracts_fd, CT_PR_PGRPONLY))) - goto cleanup; - - if ((errno = ct_tmpl_set_informative(contracts_fd, CT_PR_EV_HWERR))) - goto cleanup; - - if ((errno = ct_pr_tmpl_set_fatal(contracts_fd, CT_PR_EV_HWERR))) - goto cleanup; - - if ((errno = ct_tmpl_set_critical(contracts_fd, 0))) - goto cleanup; - } - - during = "setting active template"; - if ((errno = ct_tmpl_activate(contracts_fd))) - goto cleanup; - - debug3("Set active contract"); - return; - -cleanup: - if (contracts_fd != -1) - (void) close(contracts_fd); - - contracts_fd = -1; - - if (errno) - debug2("Error while trying to set up active contract" - " template: %s while %s", strerror(errno), during); -} - -void -contracts_post_fork_child() -{ - /* Clear active template so fork() creates no new contracts. */ - - if (contracts_fd == -1) - return; - - if ((errno = (ct_tmpl_clear(contracts_fd)))) - debug2("Error while trying to clear active contract template" - " (child): %s", strerror(errno)); - else - debug3("Cleared active contract template (child)"); - - (void) close(contracts_fd); - - contracts_fd = -1; -} - -void -contracts_post_fork_parent(int fork_succeeded) -{ - char path[PATH_MAX]; - int cfd, n; - ct_stathdl_t st; - ctid_t latest; - - /* Clear active template, abandon latest contract. */ - if (contracts_fd == -1) - return; - - if ((errno = ct_tmpl_clear(contracts_fd))) - debug2("Error while clearing active contract template: %s", - strerror(errno)); - else - debug3("Cleared active contract template (parent)"); - - if (!fork_succeeded) - return; - - if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1) { - debug2("Error while getting latest contract: %s", - strerror(errno)); - return; - } - - if ((errno = ct_status_read(cfd, CTD_COMMON, &st)) != 0) { - debug2("Error while getting latest contract ID: %s", - strerror(errno)); - (void) close(cfd); - return; - } - - latest = ct_status_get_id(st); - ct_status_free(st); - (void) close(cfd); - - n = snprintf(path, PATH_MAX, CTFS_ROOT "/all/%ld/ctl", latest); - - if (n >= PATH_MAX) { - debug2("Error while opening the latest contract ctl file: %s", - strerror(ENAMETOOLONG)); - return; - } - - if ((cfd = open64(path, O_WRONLY)) == -1) { - debug2("Error while opening the latest contract ctl file: %s", - strerror(errno)); - return; - } - - if ((errno = ct_ctl_abandon(cfd))) - debug2("Error while abandoning latest contract: %s", - strerror(errno)); - else - debug3("Abandoned latest contract"); - - (void) close(cfd); -} -#endif /* HAVE_SOLARIS_CONTRACTS */ - -/* - * Signal handler for the key regeneration alarm. Note that this - * alarm only occurs in the daemon waiting for connections, and it does not - * do anything with the private key or random state before forking. - * Thus there should be no concurrency control/asynchronous execution - * problems. - */ -static void -generate_ephemeral_server_key(void) -{ - u_int32_t rnd = 0; - int i; - - verbose("Generating %s%d bit RSA key.", - sensitive_data.server_key ? "new " : "", options.server_key_bits); - if (sensitive_data.server_key != NULL) - key_free(sensitive_data.server_key); - sensitive_data.server_key = key_generate(KEY_RSA1, - options.server_key_bits); - verbose("RSA key generation complete."); - - for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { - if (i % 4 == 0) - rnd = arc4random(); - sensitive_data.ssh1_cookie[i] = rnd & 0xff; - rnd >>= 8; - } - arc4random_stir(); -} - -static void -key_regeneration_alarm(int sig) -{ - int save_errno = errno; - - (void) signal(SIGALRM, SIG_DFL); - errno = save_errno; - key_do_regen = 1; -} - -static void -sshd_exchange_identification(int sock_in, int sock_out) -{ - int i, mismatch; - int remote_major, remote_minor; - int major, minor; - char *s; - char buf[256]; /* Must not be larger than remote_version. */ - char remote_version[256]; /* Must be at least as big as buf. */ - - if ((options.protocol & SSH_PROTO_1) && - (options.protocol & SSH_PROTO_2)) { - major = PROTOCOL_MAJOR_1; - minor = 99; - } else if (options.protocol & SSH_PROTO_2) { - major = PROTOCOL_MAJOR_2; - minor = PROTOCOL_MINOR_2; - } else { - major = PROTOCOL_MAJOR_1; - minor = PROTOCOL_MINOR_1; - } - (void) snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); - server_version_string = xstrdup(buf); - - if (client_version_string == NULL) { - /* Send our protocol version identification. */ - if (atomicio(write, sock_out, server_version_string, - strlen(server_version_string)) - != strlen(server_version_string)) { - log("Could not write ident string to %s", get_remote_ipaddr()); - fatal_cleanup(); - } - - /* Read other sides version identification. */ - (void) memset(buf, 0, sizeof(buf)); - for (i = 0; i < sizeof(buf) - 1; i++) { - if (atomicio(read, sock_in, &buf[i], 1) != 1) { - log("Did not receive identification string from %s", - get_remote_ipaddr()); - fatal_cleanup(); - } - if (buf[i] == '\r') { - buf[i] = 0; - /* Kludge for F-Secure Macintosh < 1.0.2 */ - if (i == 12 && - strncmp(buf, "SSH-1.5-W1.0", 12) == 0) - break; - continue; - } - if (buf[i] == '\n') { - buf[i] = 0; - break; - } - } - buf[sizeof(buf) - 1] = 0; - client_version_string = xstrdup(buf); - } - - /* - * Check that the versions match. In future this might accept - * several versions and set appropriate flags to handle them. - */ - if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) != 3) { - s = "Protocol mismatch.\n"; - (void) atomicio(write, sock_out, s, strlen(s)); - (void) close(sock_in); - (void) close(sock_out); - log("Bad protocol version identification '%.100s' from %s", - client_version_string, get_remote_ipaddr()); - fatal_cleanup(); - } - debug("Client protocol version %d.%d; client software version %.100s", - remote_major, remote_minor, remote_version); - - compat_datafellows(remote_version); - - if (datafellows & SSH_BUG_PROBE) { - log("probed from %s with %s. Don't panic.", - get_remote_ipaddr(), client_version_string); - fatal_cleanup(); - } - - if (datafellows & SSH_BUG_SCANNER) { - log("scanned from %s with %s. Don't panic.", - get_remote_ipaddr(), client_version_string); - fatal_cleanup(); - } - - mismatch = 0; - switch (remote_major) { - case 1: - if (remote_minor == 99) { - if (options.protocol & SSH_PROTO_2) - enable_compat20(); - else - mismatch = 1; - break; - } - if (!(options.protocol & SSH_PROTO_1)) { - mismatch = 1; - break; - } - if (remote_minor < 3) { - packet_disconnect("Your ssh version is too old and " - "is no longer supported. Please install a newer version."); - } else if (remote_minor == 3) { - /* note that this disables agent-forwarding */ - enable_compat13(); - } - break; - case 2: - if (options.protocol & SSH_PROTO_2) { - enable_compat20(); - break; - } - /* FALLTHROUGH */ - default: - mismatch = 1; - break; - } - chop(server_version_string); - debug("Local version string %.200s", server_version_string); - - if (mismatch) { - s = "Protocol major versions differ.\n"; - (void) atomicio(write, sock_out, s, strlen(s)); - (void) close(sock_in); - (void) close(sock_out); - log("Protocol major versions differ for %s: %.200s vs. %.200s", - get_remote_ipaddr(), - server_version_string, client_version_string); - fatal_cleanup(); - } -} - -/* Destroy the host and server keys. They will no longer be needed. */ -void -destroy_sensitive_data(void) -{ - int i; - - if (sensitive_data.server_key) { - key_free(sensitive_data.server_key); - sensitive_data.server_key = NULL; - } - for (i = 0; i < options.num_host_key_files; i++) { - if (sensitive_data.host_keys[i]) { - key_free(sensitive_data.host_keys[i]); - sensitive_data.host_keys[i] = NULL; - } - } - sensitive_data.ssh1_host_key = NULL; - (void) memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); -} - -/* Demote private to public keys for network child */ -static void -demote_sensitive_data(void) -{ - Key *tmp; - int i; - - if (sensitive_data.server_key) { - tmp = key_demote(sensitive_data.server_key); - key_free(sensitive_data.server_key); - sensitive_data.server_key = tmp; - } - - for (i = 0; i < options.num_host_key_files; i++) { - if (sensitive_data.host_keys[i]) { - tmp = key_demote(sensitive_data.host_keys[i]); - key_free(sensitive_data.host_keys[i]); - sensitive_data.host_keys[i] = tmp; - if (tmp->type == KEY_RSA1) - sensitive_data.ssh1_host_key = tmp; - } - } - - /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ -} - -static char * -list_hostkey_types(void) -{ - Buffer b; - char *p; - int i; - - buffer_init(&b); - for (i = 0; i < options.num_host_key_files; i++) { - Key *key = sensitive_data.host_keys[i]; - if (key == NULL) - continue; - switch (key->type) { - case KEY_RSA: - case KEY_DSA: - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - p = key_ssh_name(key); - buffer_append(&b, p, strlen(p)); - break; - } - } - buffer_append(&b, "\0", 1); - p = xstrdup(buffer_ptr(&b)); - buffer_free(&b); - debug("list_hostkey_types: %s", p); - return p; -} - -#ifdef lint -static -#endif /* lint */ -Key * -get_hostkey_by_type(int type) -{ - int i; - - for (i = 0; i < options.num_host_key_files; i++) { - Key *key = sensitive_data.host_keys[i]; - if (key != NULL && key->type == type) - return key; - } - return NULL; -} - -#ifdef lint -static -#endif /* lint */ -Key * -get_hostkey_by_index(int ind) -{ - if (ind < 0 || ind >= options.num_host_key_files) - return (NULL); - return (sensitive_data.host_keys[ind]); -} - -#ifdef lint -static -#endif /* lint */ -int -get_hostkey_index(Key *key) -{ - int i; - - for (i = 0; i < options.num_host_key_files; i++) { - if (key == sensitive_data.host_keys[i]) - return (i); - } - return (-1); -} - -/* - * returns 1 if connection should be dropped, 0 otherwise. - * dropping starts at connection #max_startups_begin with a probability - * of (max_startups_rate/100). the probability increases linearly until - * all connections are dropped for startups > max_startups - */ -static int -drop_connection(int startups) -{ - double p, r; - - if (startups < options.max_startups_begin) - return 0; - if (startups >= options.max_startups) - return 1; - if (options.max_startups_rate == 100) - return 1; - - p = 100 - options.max_startups_rate; - p *= startups - options.max_startups_begin; - p /= (double) (options.max_startups - options.max_startups_begin); - p += options.max_startups_rate; - p /= 100.0; - r = arc4random() / (double) UINT_MAX; - - debug("drop_connection: p %g, r %g", p, r); - return (r < p) ? 1 : 0; -} - -static void -usage(void) -{ - (void) fprintf(stderr, gettext("sshd version %s\n"), SSH_VERSION); - (void) fprintf(stderr, - gettext("Usage: %s [options]\n" - "Options:\n" - " -f file Configuration file (default %s)\n" - " -d Debugging mode (multiple -d means more " - "debugging)\n" - " -i Started from inetd\n" - " -D Do not fork into daemon mode\n" - " -t Only test configuration file and keys\n" - " -q Quiet (no logging)\n" - " -p port Listen on the specified port (default: 22)\n" - " -k seconds Regenerate server key every this many seconds " - "(default: 3600)\n" - " -g seconds Grace period for authentication (default: 600)\n" - " -b bits Size of server RSA key (default: 768 bits)\n" - " -h file File from which to read host key (default: %s)\n" - " -4 Use IPv4 only\n" - " -6 Use IPv6 only\n" - " -o option Process the option as if it was read from " - "a configuration file.\n"), - __progname, _PATH_SERVER_CONFIG_FILE, _PATH_HOST_KEY_FILE); - exit(1); -} - -/* - * Main program for the daemon. - */ -int -main(int ac, char **av) -{ - extern char *optarg; - extern int optind; - int opt, j, i, fdsetsz, sock_in = 0, sock_out = 0, newsock = -1, on = 1; - pid_t pid; - socklen_t fromlen; - fd_set *fdset; - struct sockaddr_storage from; - const char *remote_ip; - int remote_port; - FILE *f; - struct addrinfo *ai; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; - int listen_sock, maxfd; - int startup_p[2]; - int startups = 0; - Authctxt *authctxt = NULL; - Key *key; - int ret, key_used = 0; -#ifdef HAVE_BSM - au_id_t auid = AU_NOAUDITID; -#endif /* HAVE_BSM */ - int mpipe; - - __progname = get_progname(av[0]); - - (void) g11n_setlocale(LC_ALL, ""); - - init_rng(); - - /* Save argv. */ - saved_argc = ac; - saved_argv = av; - - /* Initialize configuration options to their default values. */ - initialize_server_options(&options); - - /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) { - switch (opt) { - case '4': - IPv4or6 = AF_INET; - break; - case '6': - IPv4or6 = AF_INET6; - break; - case 'f': - config_file_name = optarg; - break; - case 'd': - if (0 == debug_flag) { - debug_flag = 1; - options.log_level = SYSLOG_LEVEL_DEBUG1; - } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { - options.log_level++; - } else { - (void) fprintf(stderr, - gettext("Debug level too high.\n")); - exit(1); - } - break; - case 'D': - no_daemon_flag = 1; - break; - case 'e': - log_stderr = 1; - break; - case 'i': - inetd_flag = 1; - break; - case 'Q': - /* ignored */ - break; - case 'q': - options.log_level = SYSLOG_LEVEL_QUIET; - break; - case 'b': - options.server_key_bits = atoi(optarg); - break; - case 'p': - options.ports_from_cmdline = 1; - if (options.num_ports >= MAX_PORTS) { - (void) fprintf(stderr, gettext("too many ports.\n")); - exit(1); - } - options.ports[options.num_ports++] = a2port(optarg); - if (options.ports[options.num_ports-1] == 0) { - (void) fprintf(stderr, gettext("Bad port number.\n")); - exit(1); - } - break; - case 'g': - if ((options.login_grace_time = convtime(optarg)) == -1) { - (void) fprintf(stderr, - gettext("Invalid login grace time.\n")); - exit(1); - } - break; - case 'k': - if ((options.key_regeneration_time = convtime(optarg)) == -1) { - (void) fprintf(stderr, - gettext("Invalid key regeneration " - "interval.\n")); - exit(1); - } - break; - case 'h': - if (options.num_host_key_files >= MAX_HOSTKEYS) { - (void) fprintf(stderr, - gettext("too many host keys.\n")); - exit(1); - } - options.host_key_files[options.num_host_key_files++] = optarg; - break; - case 'V': - client_version_string = optarg; - /* only makes sense with inetd_flag, i.e. no listen() */ - inetd_flag = 1; - break; - case 't': - test_flag = 1; - break; - case 'o': - if (process_server_config_line(&options, optarg, - "command-line", 0, NULL, NULL, NULL, NULL) != 0) - exit(1); - break; - case '?': - default: - usage(); - break; - } - } - - /* - * There is no need to use the PKCS#11 engine in the master SSH process. - */ - SSLeay_add_all_algorithms(); - seed_rng(); - channel_set_af(IPv4or6); - - /* - * Force logging to stderr until we have loaded the private host - * key (unless started from inetd) - */ - log_init(__progname, - options.log_level == SYSLOG_LEVEL_NOT_SET ? - SYSLOG_LEVEL_INFO : options.log_level, - options.log_facility == SYSLOG_FACILITY_NOT_SET ? - SYSLOG_FACILITY_AUTH : options.log_facility, - !inetd_flag); - -#ifdef _UNICOS - /* Cray can define user privs drop all prives now! - * Not needed on PRIV_SU systems! - */ - drop_cray_privs(); -#endif - - /* Fetch our configuration */ - buffer_init(&cfg); - load_server_config(config_file_name, &cfg); - parse_server_config(&options, config_file_name, &cfg, NULL, NULL, NULL); - - /* - * ChallengeResponseAuthentication is deprecated for protocol 2 which is - * the default setting on Solaris. Warn the user about it. Note that - * ChallengeResponseAuthentication is on by default but the option is - * not set until fill_default_server_options() is called. If the option - * is already set now, the user must have set it manually. - */ - if ((options.protocol & SSH_PROTO_2) && - !(options.protocol & SSH_PROTO_1) && - options.challenge_response_authentication != -1) { - log("ChallengeResponseAuthentication has been " - "deprecated for the SSH Protocol 2. You should use " - "KbdInteractiveAuthentication instead (which defaults to " - "\"yes\")."); - } - - /* - * While PAMAuthenticationViaKbdInt was not documented, it was - * previously set in our default sshd_config and also the only way to - * switch off the keyboard-interactive authentication. To maintain - * backward compatibility, if PAMAuthenticationViaKbdInt is manually set - * to "no" and KbdInteractiveAuthentication is not set, switch off the - * keyboard-interactive authentication method as before. As with the - * challenge response auth situation dealt above, we have not called - * fill_default_server_options() yet so if KbdInteractiveAuthentication - * is already set to 1 here the admin must have set it manually and we - * will honour it. - */ - if (options.kbd_interactive_authentication != 1 && - options.pam_authentication_via_kbd_int == 0) { - options.kbd_interactive_authentication = 0; - } - - /* Fill in default values for those options not explicitly set. */ - fill_default_server_options(&options); - - utmp_len = options.lookup_client_hostnames ? utmp_len : 0; - - /* Check that there are no remaining arguments. */ - if (optind < ac) { - (void) fprintf(stderr, gettext("Extra argument %s.\n"), av[optind]); - exit(1); - } - - debug("sshd version %.100s", SSH_VERSION); - - /* load private host keys */ - if (options.num_host_key_files > 0) - sensitive_data.host_keys = - xmalloc(options.num_host_key_files * sizeof(Key *)); - for (i = 0; i < options.num_host_key_files; i++) - sensitive_data.host_keys[i] = NULL; - sensitive_data.server_key = NULL; - sensitive_data.ssh1_host_key = NULL; - sensitive_data.have_ssh1_key = 0; - sensitive_data.have_ssh2_key = 0; - - for (i = 0; i < options.num_host_key_files; i++) { - key = key_load_private(options.host_key_files[i], "", NULL); - sensitive_data.host_keys[i] = key; - if (key == NULL) { - error("Could not load host key: %s", - options.host_key_files[i]); - sensitive_data.host_keys[i] = NULL; - continue; - } - switch (key->type) { - case KEY_RSA1: - sensitive_data.ssh1_host_key = key; - sensitive_data.have_ssh1_key = 1; - break; - case KEY_RSA: - case KEY_DSA: - sensitive_data.have_ssh2_key = 1; - break; - } - debug("private host key: #%d type %d %s", i, key->type, - key_type(key)); - } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - log("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; - } - if ((options.protocol & SSH_PROTO_2) && - !sensitive_data.have_ssh2_key) { -#ifdef GSSAPI - if (options.gss_keyex) - ssh_gssapi_server_mechs(&mechs); - - if (mechs == GSS_C_NULL_OID_SET) { - log("Disabling protocol version 2. Could not load host" - "key or GSS-API mechanisms"); - options.protocol &= ~SSH_PROTO_2; - } -#else - log("Disabling protocol version 2. Could not load host key"); - options.protocol &= ~SSH_PROTO_2; -#endif /* GSSAPI */ - } - if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { - log("sshd: no hostkeys available -- exiting."); - exit(1); - } - - /* Check certain values for sanity. */ - if (options.protocol & SSH_PROTO_1) { - if (options.server_key_bits < 512 || - options.server_key_bits > 32768) { - (void) fprintf(stderr, gettext("Bad server key size.\n")); - exit(1); - } - /* - * Check that server and host key lengths differ sufficiently. This - * is necessary to make double encryption work with rsaref. Oh, I - * hate software patents. I dont know if this can go? Niels - */ - if (options.server_key_bits > - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - - SSH_KEY_BITS_RESERVED && options.server_key_bits < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + - SSH_KEY_BITS_RESERVED) { - options.server_key_bits = - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + - SSH_KEY_BITS_RESERVED; - debug("Forcing server key to %d bits to make it differ from host key.", - options.server_key_bits); - } - } - - /* Configuration looks good, so exit if in test mode. */ - if (test_flag) - exit(0); - - /* - * Clear out any supplemental groups we may have inherited. This - * prevents inadvertent creation of files with bad modes (in the - * portable version at least, it's certainly possible for PAM - * to create a file, and we can't control the code in every - * module which might be used). - */ - if (setgroups(0, NULL) < 0) - debug("setgroups() failed: %.200s", strerror(errno)); - - /* Initialize the log (it is reinitialized below in case we forked). */ - if (debug_flag && !inetd_flag) - log_stderr = 1; - log_init(__progname, options.log_level, options.log_facility, log_stderr); - - /* - * Solaris 9 and systems upgraded from it may have the Ciphers option - * explicitly set to "aes128-cbc,blowfish-cbc,3des-cbc" in the - * sshd_config. Since the default server cipher list completely changed - * since then we rather notify the administator on startup. We do this - * check after log_init() so that the message goes to syslogd and not to - * stderr (unless the server is in the debug mode). Note that since - * Solaris 10 we no longer ship sshd_config with explicit settings for - * Ciphers or MACs. Do not try to augment the cipher list here since - * that might end up in a very confusing situation. - */ -#define OLD_DEFAULT_CIPHERS_LIST "aes128-cbc,blowfish-cbc,3des-cbc" - if (options.ciphers != NULL && - strcmp(options.ciphers, OLD_DEFAULT_CIPHERS_LIST) == 0) { - notice("Old default value \"%s\" for the \"Ciphers\" " - "option found in use. In general it is prudent to let " - "the server choose the defaults unless your environment " - "specifically needs an explicit setting. See " - "sshd_config(4) for more information.", - OLD_DEFAULT_CIPHERS_LIST); - } - -#ifdef HAVE_BSM - (void) setauid(&auid); -#endif /* HAVE_BSM */ - - /* - * If not in debugging mode, and not started from inetd, disconnect - * from the controlling terminal, and fork. The original process - * exits. - */ - if (!(debug_flag || inetd_flag || no_daemon_flag)) { -#ifdef TIOCNOTTY - int fd; -#endif /* TIOCNOTTY */ - if (daemon(0, 0) < 0) - fatal("daemon() failed: %.200s", strerror(errno)); - - /* Disconnect from the controlling tty. */ -#ifdef TIOCNOTTY - fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); - if (fd >= 0) { - (void) ioctl(fd, TIOCNOTTY, NULL); - (void) close(fd); - } -#endif /* TIOCNOTTY */ - } - /* Reinitialize the log (because of the fork above). */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); - - /* Initialize the random number generator. */ - arc4random_stir(); - - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - (void) chdir("/"); - - /* ignore SIGPIPE */ - (void) signal(SIGPIPE, SIG_IGN); - - /* Start listening for a socket, unless started from inetd. */ - if (inetd_flag) { - int s1; - s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */ - (void) dup(s1); - sock_in = dup(0); - sock_out = dup(1); - startup_pipe = -1; - /* we need this later for setting audit context */ - newsock = sock_in; - /* - * We intentionally do not close the descriptors 0, 1, and 2 - * as our code for setting the descriptors won\'t work if - * ttyfd happens to be one of those. - */ - debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); - if (options.protocol & SSH_PROTO_1) - generate_ephemeral_server_key(); - } else { - for (ai = options.listen_addrs; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) - continue; - if (num_listen_socks >= MAX_LISTEN_SOCKS) - fatal("Too many listen sockets. " - "Enlarge MAX_LISTEN_SOCKS"); - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, - ntop, sizeof(ntop), strport, sizeof(strport), - NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("getnameinfo failed"); - continue; - } - /* Create socket for listening. */ - listen_sock = socket(ai->ai_family, SOCK_STREAM, 0); - if (listen_sock < 0) { - /* kernel may not support ipv6 */ - verbose("socket: %.100s", strerror(errno)); - continue; - } - if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) { - error("listen_sock O_NONBLOCK: %s", strerror(errno)); - (void) close(listen_sock); - continue; - } - /* - * Set socket options. - * Allow local port reuse in TIME_WAIT. - */ - if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)) == -1) - error("setsockopt SO_REUSEADDR: %s", strerror(errno)); - - debug("Bind to port %s on %s.", strport, ntop); - - /* Bind the socket to the desired port. */ - if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { - if (!ai->ai_next) - error("Bind to port %s on %s failed: %.200s.", - strport, ntop, strerror(errno)); - (void) close(listen_sock); - continue; - } - listen_socks[num_listen_socks] = listen_sock; - num_listen_socks++; - - /* Start listening on the port. */ - log("Server listening on %s port %s.", ntop, strport); - if (listen(listen_sock, 5) < 0) - fatal("listen: %.100s", strerror(errno)); - - } - freeaddrinfo(options.listen_addrs); - - if (!num_listen_socks) - fatal("Cannot bind any address."); - - if (options.protocol & SSH_PROTO_1) - generate_ephemeral_server_key(); - - /* - * Arrange to restart on SIGHUP. The handler needs - * listen_sock. - */ - (void) signal(SIGHUP, sighup_handler); - - (void) signal(SIGTERM, sigterm_handler); - (void) signal(SIGQUIT, sigterm_handler); - - /* Arrange SIGCHLD to be caught. */ - (void) signal(SIGCHLD, main_sigchld_handler); - - /* Write out the pid file after the sigterm handler is setup */ - if (!debug_flag) { - /* - * Record our pid in /var/run/sshd.pid to make it - * easier to kill the correct sshd. We don't want to - * do this before the bind above because the bind will - * fail if there already is a daemon, and this will - * overwrite any old pid in the file. - */ - f = fopen(options.pid_file, "wb"); - if (f) { - (void) fprintf(f, "%ld\n", (long) getpid()); - (void) fclose(f); - } - } - - /* setup fd set for listen */ - fdset = NULL; - maxfd = 0; - for (i = 0; i < num_listen_socks; i++) - if (listen_socks[i] > maxfd) - maxfd = listen_socks[i]; - /* pipes connected to unauthenticated childs */ - startup_pipes = xmalloc(options.max_startups * sizeof(int)); - for (i = 0; i < options.max_startups; i++) - startup_pipes[i] = -1; - - /* - * Stay listening for connections until the system crashes or - * the daemon is killed with a signal. - */ - for (;;) { - if (received_sighup) - sighup_restart(); - if (fdset != NULL) - xfree(fdset); - fdsetsz = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask); - fdset = (fd_set *)xmalloc(fdsetsz); - (void) memset(fdset, 0, fdsetsz); - - for (i = 0; i < num_listen_socks; i++) - FD_SET(listen_socks[i], fdset); - for (i = 0; i < options.max_startups; i++) - if (startup_pipes[i] != -1) - FD_SET(startup_pipes[i], fdset); - - /* Wait in select until there is a connection. */ - ret = select(maxfd+1, fdset, NULL, NULL, NULL); - if (ret < 0 && errno != EINTR) - error("select: %.100s", strerror(errno)); - if (received_sigterm) { - log("Received signal %d; terminating.", - (int) received_sigterm); - close_listen_socks(); - (void) unlink(options.pid_file); - exit(255); - } - if (key_used && key_do_regen) { - generate_ephemeral_server_key(); - key_used = 0; - key_do_regen = 0; - } - if (ret < 0) - continue; - - for (i = 0; i < options.max_startups; i++) - if (startup_pipes[i] != -1 && - FD_ISSET(startup_pipes[i], fdset)) { - /* - * the read end of the pipe is ready - * if the child has closed the pipe - * after successful authentication - * or if the child has died - */ - (void) close(startup_pipes[i]); - startup_pipes[i] = -1; - startups--; - } - for (i = 0; i < num_listen_socks; i++) { - if (!FD_ISSET(listen_socks[i], fdset)) - continue; - fromlen = sizeof(from); - newsock = accept(listen_socks[i], (struct sockaddr *)&from, - &fromlen); - if (newsock < 0) { - if (errno != EINTR && errno != EWOULDBLOCK) - error("accept: %.100s", strerror(errno)); - continue; - } - if (fcntl(newsock, F_SETFL, 0) < 0) { - error("newsock del O_NONBLOCK: %s", strerror(errno)); - (void) close(newsock); - continue; - } - if (drop_connection(startups) == 1) { - debug("drop connection #%d", startups); - (void) close(newsock); - continue; - } - if (pipe(startup_p) == -1) { - (void) close(newsock); - continue; - } - - for (j = 0; j < options.max_startups; j++) - if (startup_pipes[j] == -1) { - startup_pipes[j] = startup_p[0]; - if (maxfd < startup_p[0]) - maxfd = startup_p[0]; - startups++; - break; - } - - /* - * Got connection. Fork a child to handle it, unless - * we are in debugging mode. - */ - if (debug_flag) { - /* - * In debugging mode. Close the listening - * socket, and start processing the - * connection without forking. - */ - debug("Server will not fork when running in debugging mode."); - close_listen_socks(); - sock_in = newsock; - sock_out = newsock; - startup_pipe = -1; - pid = getpid(); - break; - } else { - /* - * Normal production daemon. Fork, and have - * the child process the connection. The - * parent continues listening. - */ -#ifdef HAVE_SOLARIS_CONTRACTS - /* - * Setup Solaris contract template so - * the child process is in a different - * process contract than the parent; - * prevents established connections from - * being killed when the sshd master - * listener service is stopped. - */ - contracts_pre_fork(); -#endif /* HAVE_SOLARIS_CONTRACTS */ - if ((pid = fork()) == 0) { - /* - * Child. Close the listening and max_startup - * sockets. Start using the accepted socket. - * Reinitialize logging (since our pid has - * changed). We break out of the loop to handle - * the connection. - */ -#ifdef HAVE_SOLARIS_CONTRACTS - contracts_post_fork_child(); -#endif /* HAVE_SOLARIS_CONTRACTS */ - xfree(fdset); - startup_pipe = startup_p[1]; - close_startup_pipes(); - close_listen_socks(); - sock_in = newsock; - sock_out = newsock; - log_init(__progname, options.log_level, options.log_facility, log_stderr); - break; - } - - /* Parent. Stay in the loop. */ - if (pid < 0) - error("fork: %.100s", strerror(errno)); - else - debug("Forked child %ld.", (long)pid); - -#ifdef HAVE_SOLARIS_CONTRACTS - contracts_post_fork_parent((pid > 0)); -#endif /* HAVE_SOLARIS_CONTRACTS */ - } - - (void) close(startup_p[1]); - - /* Mark that the key has been used (it was "given" to the child). */ - if ((options.protocol & SSH_PROTO_1) && - key_used == 0) { - /* Schedule server key regeneration alarm. */ - (void) signal(SIGALRM, key_regeneration_alarm); - (void) alarm(options.key_regeneration_time); - key_used = 1; - } - - arc4random_stir(); - - /* - * Close the accepted socket since the child - * will now take care of the new connection. - */ - (void) close(newsock); - } - /* child process check (or debug mode) */ - if (num_listen_socks < 0) - break; - } - } - - /* - * This is the child processing a new connection, the SSH master process - * stays in the ( ; ; ) loop above. - */ -#ifdef HAVE_BSM - audit_sshd_settid(newsock); -#endif - /* - * Create a new session and process group since the 4.4BSD - * setlogin() affects the entire process group. We don't - * want the child to be able to affect the parent. - */ -#if 0 - /* XXX: this breaks Solaris */ - if (!debug_flag && !inetd_flag && setsid() < 0) - error("setsid: %.100s", strerror(errno)); -#endif - - /* - * Disable the key regeneration alarm. We will not regenerate the - * key since we are no longer in a position to give it to anyone. We - * will not restart on SIGHUP since it no longer makes sense. - */ - (void) alarm(0); - (void) signal(SIGALRM, SIG_DFL); - (void) signal(SIGHUP, SIG_DFL); - (void) signal(SIGTERM, SIG_DFL); - (void) signal(SIGQUIT, SIG_DFL); - (void) signal(SIGCHLD, SIG_DFL); - (void) signal(SIGINT, SIG_DFL); - - /* Set keepalives if requested. */ - if (options.keepalives && - setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, - sizeof(on)) < 0) - debug2("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); - - /* - * Register our connection. This turns encryption off because we do - * not have a key. - */ - packet_set_connection(sock_in, sock_out); - - remote_port = get_remote_port(); - remote_ip = get_remote_ipaddr(); - -#ifdef LIBWRAP - /* Check whether logins are denied from this host. */ - { - struct request_info req; - - (void) request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); - fromhost(&req); - - if (!hosts_access(&req)) { - debug("Connection refused by tcp wrapper"); - refuse(&req); - /* NOTREACHED */ - fatal("libwrap refuse returns"); - } - } -#endif /* LIBWRAP */ - - /* Log the connection. */ - verbose("Connection from %.500s port %d", remote_ip, remote_port); - - sshd_exchange_identification(sock_in, sock_out); - /* - * Check that the connection comes from a privileged port. - * Rhosts-Authentication only makes sense from privileged - * programs. Of course, if the intruder has root access on his local - * machine, he can connect from any port. So do not use these - * authentication methods from machines that you do not trust. - */ - if (options.rhosts_authentication && - (remote_port >= IPPORT_RESERVED || - remote_port < IPPORT_RESERVED / 2)) { - debug("Rhosts Authentication disabled, " - "originating port %d not trusted.", remote_port); - options.rhosts_authentication = 0; - } -#if defined(KRB4) && !defined(KRB5) - if (!packet_connection_is_ipv4() && - options.kerberos_authentication) { - debug("Kerberos Authentication disabled, only available for IPv4."); - options.kerberos_authentication = 0; - } -#endif /* KRB4 && !KRB5 */ -#ifdef AFS - /* If machine has AFS, set process authentication group. */ - if (k_hasafs()) { - k_setpag(); - k_unlog(); - } -#endif /* AFS */ - - packet_set_nonblocking(); - - /* - * Start the monitor. That way both processes will have their own - * PKCS#11 sessions. See the PKCS#11 standard for more information on - * fork safety and packet.c for information about forking with the - * engine. - * - * Note that the monitor stays in the function while the child is the - * only one that returns. - */ - altprivsep_start_and_do_monitor(options.use_openssl_engine, - inetd_flag, newsock, startup_pipe); - - /* - * We don't want to listen forever unless the other side successfully - * authenticates itself. So we set up an alarm which is cleared after - * successful authentication. A limit of zero indicates no limit. Note - * that we don't set the alarm in debugging mode; it is just annoying to - * have the server exit just when you are about to discover the bug. - */ - (void) signal(SIGALRM, grace_alarm_handler); - if (!debug_flag) - (void) alarm(options.login_grace_time); - - /* - * The child is about to start the first key exchange while the monitor - * stays in altprivsep_start_and_do_monitor() function. - */ - (void) pkcs11_engine_load(options.use_openssl_engine); - - /* perform the key exchange */ - /* authenticate user and start session */ - if (compat20) { - do_ssh2_kex(); - authctxt = do_authentication2(); - } else { - do_ssh1_kex(); - authctxt = do_authentication(); - } - - /* Authentication complete */ - (void) alarm(0); - /* we no longer need an alarm handler */ - (void) signal(SIGALRM, SIG_DFL); - - if (startup_pipe != -1) { - (void) close(startup_pipe); - startup_pipe = -1; - } - - /* ALTPRIVSEP Child */ - - /* - * Drop privileges, access to privileged resources. - * - * Destroy private host keys, if any. - * - * No need to release any GSS credentials -- sshd only acquires - * creds to determine what mechs it can negotiate then releases - * them right away and uses GSS_C_NO_CREDENTIAL to accept - * contexts. - */ - debug2("Unprivileged server process dropping privileges"); - permanently_set_uid(authctxt->pw, options.chroot_directory); - destroy_sensitive_data(); - - /* Just another safety check. */ - if (getuid() != authctxt->pw->pw_uid || - geteuid() != authctxt->pw->pw_uid) { - fatal("Failed to set uids to %u.", (u_int)authctxt->pw->pw_uid); - } - - ssh_gssapi_server_mechs(NULL); /* release cached mechs list */ - packet_set_server(); - - /* now send the authentication context to the monitor */ - altprivsep_send_auth_context(authctxt); - - mpipe = altprivsep_get_pipe_fd(); - if (fcntl(mpipe, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %.100s", strerror(errno)); - -#ifdef HAVE_BSM - fatal_remove_cleanup( - (void (*)(void *))audit_failed_login_cleanup, - (void *)authctxt); -#endif /* HAVE_BSM */ - - if (compat20) { - debug3("setting handler to forward re-key packets to the monitor"); - dispatch_range(SSH2_MSG_KEXINIT, SSH2_MSG_TRANSPORT_MAX, - &altprivsep_rekey); - } - - /* Logged-in session. */ - do_authenticated(authctxt); - - /* The connection has been terminated. */ - verbose("Closing connection to %.100s", remote_ip); - - packet_close(); - -#ifdef USE_PAM - finish_pam(authctxt); -#endif /* USE_PAM */ - - return (0); -} - -/* - * Decrypt session_key_int using our private server key and private host key - * (key with larger modulus first). - */ -int -ssh1_session_key(BIGNUM *session_key_int) -{ - int rsafail = 0; - - if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { - /* Server key has bigger modulus. */ - if (BN_num_bits(sensitive_data.server_key->rsa->n) < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), - BN_num_bits(sensitive_data.server_key->rsa->n), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) <= 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) <= 0) - rsafail++; - } else { - /* Host key has bigger modulus (or they are equal). */ - if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < - BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - BN_num_bits(sensitive_data.server_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) < 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) < 0) - rsafail++; - } - return (rsafail); -} -/* - * SSH1 key exchange - */ -static void -do_ssh1_kex(void) -{ - int i, len; - int rsafail = 0; - BIGNUM *session_key_int; - u_char session_key[SSH_SESSION_KEY_LENGTH]; - u_char cookie[8]; - u_int cipher_type, auth_mask, protocol_flags; - u_int32_t rnd = 0; - - /* - * Generate check bytes that the client must send back in the user - * packet in order for it to be accepted; this is used to defy ip - * spoofing attacks. Note that this only works against somebody - * doing IP spoofing from a remote machine; any machine on the local - * network can still see outgoing packets and catch the random - * cookie. This only affects rhosts authentication, and this is one - * of the reasons why it is inherently insecure. - */ - for (i = 0; i < 8; i++) { - if (i % 4 == 0) - rnd = arc4random(); - cookie[i] = rnd & 0xff; - rnd >>= 8; - } - - /* - * Send our public key. We include in the packet 64 bits of random - * data that must be matched in the reply in order to prevent IP - * spoofing. - */ - packet_start(SSH_SMSG_PUBLIC_KEY); - for (i = 0; i < 8; i++) - packet_put_char(cookie[i]); - - /* Store our public server RSA key. */ - packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n)); - packet_put_bignum(sensitive_data.server_key->rsa->e); - packet_put_bignum(sensitive_data.server_key->rsa->n); - - /* Store our public host RSA key. */ - packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); - packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e); - packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n); - - /* Put protocol flags. */ - packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); - - /* Declare which ciphers we support. */ - packet_put_int(cipher_mask_ssh1(0)); - - /* Declare supported authentication types. */ - auth_mask = 0; - if (options.rhosts_authentication) - auth_mask |= 1 << SSH_AUTH_RHOSTS; - if (options.rhosts_rsa_authentication) - auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA; - if (options.rsa_authentication) - auth_mask |= 1 << SSH_AUTH_RSA; -#if defined(KRB4) || defined(KRB5) - if (options.kerberos_authentication) - auth_mask |= 1 << SSH_AUTH_KERBEROS; -#endif -#if defined(AFS) || defined(KRB5) - if (options.kerberos_tgt_passing) - auth_mask |= 1 << SSH_PASS_KERBEROS_TGT; -#endif -#ifdef AFS - if (options.afs_token_passing) - auth_mask |= 1 << SSH_PASS_AFS_TOKEN; -#endif - if (options.challenge_response_authentication == 1) - auth_mask |= 1 << SSH_AUTH_TIS; - if (options.password_authentication) - auth_mask |= 1 << SSH_AUTH_PASSWORD; - packet_put_int(auth_mask); - - /* Send the packet and wait for it to be sent. */ - packet_send(); - packet_write_wait(); - - debug("Sent %d bit server key and %d bit host key.", - BN_num_bits(sensitive_data.server_key->rsa->n), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); - - /* Read clients reply (cipher type and session key). */ - packet_read_expect(SSH_CMSG_SESSION_KEY); - - /* Get cipher type and check whether we accept this. */ - cipher_type = packet_get_char(); - - if (!(cipher_mask_ssh1(0) & (1 << cipher_type))) { - packet_disconnect("Warning: client selects unsupported cipher."); - } - - /* Get check bytes from the packet. These must match those we - sent earlier with the public key packet. */ - for (i = 0; i < 8; i++) { - if (cookie[i] != packet_get_char()) { - packet_disconnect("IP Spoofing check bytes do not match."); - } - } - - debug("Encryption type: %.200s", cipher_name(cipher_type)); - - /* Get the encrypted integer. */ - if ((session_key_int = BN_new()) == NULL) - fatal("do_ssh1_kex: BN_new failed"); - packet_get_bignum(session_key_int); - - protocol_flags = packet_get_int(); - packet_set_protocol_flags(protocol_flags); - packet_check_eom(); - - /* Decrypt session_key_int using host/server keys */ - rsafail = ssh1_session_key(session_key_int); - - /* - * Extract session key from the decrypted integer. The key is in the - * least significant 256 bits of the integer; the first byte of the - * key is in the highest bits. - */ - if (!rsafail) { - (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); - len = BN_num_bytes(session_key_int); - if (len < 0 || len > sizeof(session_key)) { - error("do_connection: bad session key len from %s: " - "session_key_int %d > sizeof(session_key) %lu", - get_remote_ipaddr(), len, (u_long)sizeof(session_key)); - rsafail++; - } else { - (void) memset(session_key, 0, sizeof(session_key)); - (void) BN_bn2bin(session_key_int, - session_key + sizeof(session_key) - len); - - compute_session_id(session_id, cookie, - sensitive_data.ssh1_host_key->rsa->n, - sensitive_data.server_key->rsa->n); - /* - * Xor the first 16 bytes of the session key with the - * session id. - */ - for (i = 0; i < 16; i++) - session_key[i] ^= session_id[i]; - } - } - if (rsafail) { - int bytes = BN_num_bytes(session_key_int); - u_char *buf = xmalloc(bytes); - MD5_CTX md; - - log("do_connection: generating a fake encryption key"); - (void) BN_bn2bin(session_key_int, buf); - MD5_Init(&md); - MD5_Update(&md, buf, bytes); - MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); - MD5_Final(session_key, &md); - MD5_Init(&md); - MD5_Update(&md, session_key, 16); - MD5_Update(&md, buf, bytes); - MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); - MD5_Final(session_key + 16, &md); - (void) memset(buf, 0, bytes); - xfree(buf); - for (i = 0; i < 16; i++) - session_id[i] = session_key[i] ^ session_key[i + 16]; - } - /* Destroy the private and public keys. No longer. */ - destroy_sensitive_data(); - - /* Destroy the decrypted integer. It is no longer needed. */ - BN_clear_free(session_key_int); - - /* Set the session key. From this on all communications will be encrypted. */ - packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type); - - /* Destroy our copy of the session key. It is no longer needed. */ - (void) memset(session_key, 0, sizeof(session_key)); - - debug("Received session key; encryption turned on."); - - /* Send an acknowledgment packet. Note that this packet is sent encrypted. */ - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); -} - -/* - * Prepare for SSH2 key exchange. - */ -Kex * -prepare_for_ssh2_kex(void) -{ - Kex *kex; - Kex_hook_func kex_hook = NULL; - char **locales; - static char **myproposal; - - myproposal = my_srv_proposal; - - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); - myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); - - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - } - if (!options.compression) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; - } - - /* - * Prepare kex algs / hostkey algs (excluding GSS, which is - * handled in the kex hook. - * - * XXX This should probably move to the kex hook as well, where - * all non-constant kex offer material belongs. - */ - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); - - /* If we have no host key algs we can't offer KEXDH/KEX_DH_GEX */ - if (myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] == NULL || - *myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] == '\0') - myproposal[PROPOSAL_KEX_ALGS] = ""; - - if ((locales = g11n_getlocales()) != NULL) { - /* Solaris 9 SSH expects a list of locales */ - if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) - myproposal[PROPOSAL_LANG_STOC] = xjoin(locales, ','); - else - myproposal[PROPOSAL_LANG_STOC] = - g11n_locales2langs(locales); - } - - if (locales != NULL) - g11n_freelist(locales); - - if ((myproposal[PROPOSAL_LANG_STOC] != NULL) && - (strcmp(myproposal[PROPOSAL_LANG_STOC], "")) != 0) - myproposal[PROPOSAL_LANG_CTOS] = - xstrdup(myproposal[PROPOSAL_LANG_STOC]); - -#ifdef GSSAPI - if (options.gss_keyex) - kex_hook = ssh_gssapi_server_kex_hook; -#endif /* GSSAPI */ - - kex = kex_setup(NULL, myproposal, kex_hook); - - /* - * Note that the my_srv_proposal variable (ie., myproposal) is staticly - * initialized with "" for the language fields; we must not xfree such - * strings. - */ - if (myproposal[PROPOSAL_LANG_STOC] != NULL && - strcmp(myproposal[PROPOSAL_LANG_STOC], "") != 0) - xfree(myproposal[PROPOSAL_LANG_STOC]); - if (myproposal[PROPOSAL_LANG_CTOS] != NULL && - strcmp(myproposal[PROPOSAL_LANG_STOC], "") != 0) - xfree(myproposal[PROPOSAL_LANG_CTOS]); - - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; -#ifdef GSSAPI - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -#endif /* GSSAPI */ - kex->server = 1; - kex->client_version_string = client_version_string; - kex->server_version_string = server_version_string; - kex->load_host_key = &get_hostkey_by_type; - kex->host_key_index = &get_hostkey_index; - - xxx_kex = kex; - return (kex); -} - -/* - * Do SSH2 key exchange. - */ -static void -do_ssh2_kex(void) -{ - Kex *kex; - - kex = prepare_for_ssh2_kex(); - kex_start(kex); - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); - - if (kex->name) { - xfree(kex->name); - kex->name = NULL; - } - session_id2 = kex->session_id; - session_id2_len = kex->session_id_len; - -#ifdef DEBUG_KEXDH - /* send 1st encrypted/maced/compressed message */ - packet_start(SSH2_MSG_IGNORE); - packet_put_cstring("markus"); - packet_send(); - packet_write_wait(); -#endif - debug("KEX done"); -} diff --git a/usr/src/cmd/ssh/sshd/sshlogin.c b/usr/src/cmd/ssh/sshd/sshlogin.c deleted file mode 100644 index c21877355c..0000000000 --- a/usr/src/cmd/ssh/sshd/sshlogin.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * This file performs some of the things login(1) normally does. We cannot - * easily use something like login -p -h host -f user, because there are - * several different logins around, and it is hard to determined what kind of - * login the current system has. Also, we want to be able to execute commands - * on a tty. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * Copyright (c) 1999 Theo de Raadt. All rights reserved. - * Copyright (c) 1999 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: sshlogin.c,v 1.5 2002/08/29 15:57:25 stevesk Exp $"); - -#include "loginrec.h" -#include "log.h" -#include "buffer.h" -#include "servconf.h" -#include "canohost.h" -#include "packet.h" - -extern u_int utmp_len; -extern ServerOptions options; - -/* - * Returns the time when the user last logged in. Returns 0 if the - * information is not available. This must be called before record_login. - * The host the user logged in from will be returned in buf. - */ -u_long -get_last_login_time(uid_t uid, const char *logname, - char *buf, u_int bufsize) -{ - struct logininfo li; - - (void) login_get_lastlog(&li, uid); - (void) strlcpy(buf, li.hostname, bufsize); - return li.tv_sec; -} - -/* - * Records that the user has logged in. If only these parts of operating - * systems were more standardized. - */ -void -record_login(pid_t pid, const char *ttyname, const char *progname, - const char *user) -{ - struct logininfo *li; - static int initialized = 0; - static socklen_t fromlen; - static struct sockaddr_storage from; - static const char *remote_name_or_ip; - - if (pid == 0) - pid = getpid(); - /* - * Get IP address of client. If the connection is not a socket, let - * the address be 0.0.0.0. - */ - if (!initialized) { - (void) memset(&from, 0, sizeof(from)); - if (packet_connection_is_on_socket()) { - fromlen = sizeof(from); - if (getpeername(packet_get_connection_in(), - (struct sockaddr *) &from, &fromlen) < 0) { - debug("getpeername: %.100s", strerror(errno)); - fatal_cleanup(); - } - } - remote_name_or_ip = get_remote_name_or_ip(utmp_len, - options.verify_reverse_mapping); - - initialized = 1; - } - - li = login_alloc_entry(pid, user, remote_name_or_ip, ttyname, progname); - login_set_addr(li, (struct sockaddr*) &from, sizeof(struct sockaddr)); - (void) login_login(li); - login_free_entry(li); -} - -/* Records that the user has logged out. */ -void -record_logout(pid_t pid, const char *ttyname, const char *progname, - const char *user) -{ - struct logininfo *li; - - li = login_alloc_entry(pid, user, NULL, ttyname, progname); - (void) login_logout(li); - login_free_entry(li); -} diff --git a/usr/src/cmd/ssh/sshd/sshpty.c b/usr/src/cmd/ssh/sshd/sshpty.c deleted file mode 100644 index b421798cb5..0000000000 --- a/usr/src/cmd/ssh/sshd/sshpty.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Author: Tatu Ylonen <ylo@cs.hut.fi> - * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland - * All rights reserved - * Allocating a pseudo-terminal, and making it the controlling tty. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" -RCSID("$OpenBSD: sshpty.c,v 1.7 2002/06/24 17:57:20 deraadt Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef HAVE_UTIL_H -# include <util.h> -#endif /* HAVE_UTIL_H */ - -#include "sshpty.h" -#include "log.h" -#include "misc.h" - -/* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */ -#if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY) -#undef HAVE_DEV_PTMX -#endif - -#ifdef HAVE_PTY_H -# include <pty.h> -#endif -#if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) -# include <sys/stropts.h> -#endif - -#ifndef O_NOCTTY -#define O_NOCTTY 0 -#endif - -/* - * Allocates and opens a pty. Returns 0 if no pty could be allocated, or - * nonzero if a pty was successfully allocated. On success, open file - * descriptors for the pty and tty sides and the name of the tty side are - * returned (the buffer must be able to hold at least 64 characters). - */ - -int -pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) -{ -#if defined(HAVE_OPENPTY) || defined(BSD4_4) - /* openpty(3) exists in OSF/1 and some other os'es */ - char *name; - int i; - - i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); - if (i < 0) { - error("openpty: %.100s", strerror(errno)); - return 0; - } - name = ttyname(*ttyfd); - if (!name) - fatal("openpty returns device for which ttyname fails."); - - strlcpy(namebuf, name, namebuflen); /* possible truncation */ - return 1; -#else /* HAVE_OPENPTY */ -#ifdef HAVE__GETPTY - /* - * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more - * pty's automagically when needed - */ - char *slave; - - slave = _getpty(ptyfd, O_RDWR, 0622, 0); - if (slave == NULL) { - error("_getpty: %.100s", strerror(errno)); - return 0; - } - strlcpy(namebuf, slave, namebuflen); - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("%.200s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } - return 1; -#else /* HAVE__GETPTY */ -#if defined(HAVE_DEV_PTMX) - /* - * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 - * also has bsd-style ptys, but they simply do not work.) - */ - int ptm; - char *pts; - mysig_t old_signal; - - ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); - if (ptm < 0) { - error("/dev/ptmx: %.100s", strerror(errno)); - return 0; - } - old_signal = mysignal(SIGCHLD, SIG_DFL); - if (grantpt(ptm) < 0) { - error("grantpt: %.100s", strerror(errno)); - return 0; - } - mysignal(SIGCHLD, old_signal); - if (unlockpt(ptm) < 0) { - error("unlockpt: %.100s", strerror(errno)); - return 0; - } - pts = ptsname(ptm); - if (pts == NULL) - error("Slave pty side name could not be obtained."); - strlcpy(namebuf, pts, namebuflen); - *ptyfd = ptm; - - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("%.100s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } -#ifndef HAVE_CYGWIN - /* - * Push the appropriate streams modules, as described in Solaris pts(7). - * HP-UX pts(7) doesn't have ttcompat module. - */ - if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) - error("ioctl I_PUSH ptem: %.100s", strerror(errno)); - if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) - error("ioctl I_PUSH ldterm: %.100s", strerror(errno)); -#ifndef __hpux - if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) - error("ioctl I_PUSH ttcompat: %.100s", strerror(errno)); -#endif -#endif - return 1; -#else /* HAVE_DEV_PTMX */ -#ifdef HAVE_DEV_PTS_AND_PTC - /* AIX-style pty code. */ - const char *name; - - *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY); - if (*ptyfd < 0) { - error("Could not open /dev/ptc: %.100s", strerror(errno)); - return 0; - } - name = ttyname(*ptyfd); - if (!name) - fatal("Open of /dev/ptc returns device for which ttyname fails."); - strlcpy(namebuf, name, namebuflen); - *ttyfd = open(name, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("Could not open pty slave side %.100s: %.100s", - name, strerror(errno)); - close(*ptyfd); - return 0; - } - return 1; -#else /* HAVE_DEV_PTS_AND_PTC */ -#ifdef _UNICOS - char buf[64]; - int i; - int highpty; - -#ifdef _SC_CRAY_NPTY - highpty = sysconf(_SC_CRAY_NPTY); - if (highpty == -1) - highpty = 128; -#else - highpty = 128; -#endif - - for (i = 0; i < highpty; i++) { - snprintf(buf, sizeof(buf), "/dev/pty/%03d", i); - *ptyfd = open(buf, O_RDWR|O_NOCTTY); - if (*ptyfd < 0) - continue; - snprintf(namebuf, namebuflen, "/dev/ttyp%03d", i); - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); - if (*ttyfd < 0) { - error("%.100s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } - return 1; - } - return 0; -#else - /* BSD-style pty code. */ - char buf[64]; - int i; - const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const char *ptyminors = "0123456789abcdef"; - int num_minors = strlen(ptyminors); - int num_ptys = strlen(ptymajors) * num_minors; - struct termios tio; - - for (i = 0; i < num_ptys; i++) { - snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], - ptyminors[i % num_minors]); - snprintf(namebuf, namebuflen, "/dev/tty%c%c", - ptymajors[i / num_minors], ptyminors[i % num_minors]); - - *ptyfd = open(buf, O_RDWR | O_NOCTTY); - if (*ptyfd < 0) { - /* Try SCO style naming */ - snprintf(buf, sizeof buf, "/dev/ptyp%d", i); - snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); - *ptyfd = open(buf, O_RDWR | O_NOCTTY); - if (*ptyfd < 0) - continue; - } - - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("%.100s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } - /* set tty modes to a sane state for broken clients */ - if (tcgetattr(*ptyfd, &tio) < 0) - log("Getting tty modes for pty failed: %.100s", strerror(errno)); - else { - tio.c_lflag |= (ECHO | ISIG | ICANON); - tio.c_oflag |= (OPOST | ONLCR); - tio.c_iflag |= ICRNL; - - /* Set the new modes for the terminal. */ - if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) - log("Setting tty modes for pty failed: %.100s", strerror(errno)); - } - - return 1; - } - return 0; -#endif /* CRAY */ -#endif /* HAVE_DEV_PTS_AND_PTC */ -#endif /* HAVE_DEV_PTMX */ -#endif /* HAVE__GETPTY */ -#endif /* HAVE_OPENPTY */ -} - -/* Releases the tty. Its ownership is returned to root, and permissions to 0666. */ - -void -pty_release(const char *ttyname) -{ - if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0) - error("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno)); - if (chmod(ttyname, (mode_t) 0666) < 0) - error("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno)); -} - -/* Makes the tty the processes controlling tty and sets it to sane modes. */ - -void -pty_make_controlling_tty(int *ttyfd, const char *ttyname) -{ - int fd; -#ifdef USE_VHANGUP - void *old; -#endif /* USE_VHANGUP */ - -#ifdef _UNICOS - if (setsid() < 0) - error("setsid: %.100s", strerror(errno)); - - fd = open(ttyname, O_RDWR|O_NOCTTY); - if (fd != -1) { - mysignal(SIGHUP, SIG_IGN); - ioctl(fd, TCVHUP, (char *)NULL); - mysignal(SIGHUP, SIG_DFL); - setpgid(0, 0); - close(fd); - } else { - error("Failed to disconnect from controlling tty."); - } - - debug("Setting controlling tty using TCSETCTTY."); - ioctl(*ttyfd, TCSETCTTY, NULL); - fd = open("/dev/tty", O_RDWR); - if (fd < 0) - error("%.100s: %.100s", ttyname, strerror(errno)); - close(*ttyfd); - *ttyfd = fd; -#else /* _UNICOS */ - - /* First disconnect from the old controlling tty. */ -#ifdef TIOCNOTTY - fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); - if (fd >= 0) { - (void) ioctl(fd, TIOCNOTTY, NULL); - close(fd); - } -#endif /* TIOCNOTTY */ - if (setsid() < 0) - error("setsid: %.100s", strerror(errno)); - - /* - * Verify that we are successfully disconnected from the controlling - * tty. - */ - fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); - if (fd >= 0) { - error("Failed to disconnect from controlling tty."); - close(fd); - } - /* Make it our controlling tty. */ -#ifdef TIOCSCTTY - debug("Setting controlling tty using TIOCSCTTY."); - if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) - error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); -#endif /* TIOCSCTTY */ -#ifdef HAVE_NEWS4 - if (setpgrp(0,0) < 0) - error("SETPGRP %s",strerror(errno)); -#endif /* HAVE_NEWS4 */ -#ifdef USE_VHANGUP - old = mysignal(SIGHUP, SIG_IGN); - vhangup(); - mysignal(SIGHUP, old); -#endif /* USE_VHANGUP */ - fd = open(ttyname, O_RDWR); - if (fd < 0) { - error("%.100s: %.100s", ttyname, strerror(errno)); - } else { -#ifdef USE_VHANGUP - close(*ttyfd); - *ttyfd = fd; -#else /* USE_VHANGUP */ - close(fd); -#endif /* USE_VHANGUP */ - } - /* Verify that we now have a controlling tty. */ - fd = open(_PATH_TTY, O_WRONLY); - if (fd < 0) - error("open /dev/tty failed - could not set controlling tty: %.100s", - strerror(errno)); - else - close(fd); -#endif /* _UNICOS */ -} - -/* Changes the window size associated with the pty. */ - -void -pty_change_window_size(int ptyfd, int row, int col, - int xpixel, int ypixel) -{ - struct winsize w; - - w.ws_row = row; - w.ws_col = col; - w.ws_xpixel = xpixel; - w.ws_ypixel = ypixel; - (void) ioctl(ptyfd, TIOCSWINSZ, &w); -} - -void -pty_setowner(struct passwd *pw, const char *ttyname) -{ - struct group *grp; - gid_t gid; - mode_t mode; - struct stat st; - - /* Determine the group to make the owner of the tty. */ - grp = getgrnam("tty"); - if (grp) { - gid = grp->gr_gid; - mode = S_IRUSR | S_IWUSR | S_IWGRP; - } else { - gid = pw->pw_gid; - mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH; - } - - /* - * Change owner and mode of the tty as required. - * Warn but continue if filesystem is read-only and the uids match/ - * tty is owned by root. - */ - if (stat(ttyname, &st)) - fatal("stat(%.100s) failed: %.100s", ttyname, - strerror(errno)); - - if (st.st_uid != pw->pw_uid || st.st_gid != gid) { - if (chown(ttyname, pw->pw_uid, gid) < 0) { - if (errno == EROFS && - (st.st_uid == pw->pw_uid || st.st_uid == 0)) - error("chown(%.100s, %u, %u) failed: %.100s", - ttyname, (u_int)pw->pw_uid, (u_int)gid, - strerror(errno)); - else - fatal("chown(%.100s, %u, %u) failed: %.100s", - ttyname, (u_int)pw->pw_uid, (u_int)gid, - strerror(errno)); - } - } - - if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) { - if (chmod(ttyname, mode) < 0) { - if (errno == EROFS && - (st.st_mode & (S_IRGRP | S_IROTH)) == 0) - error("chmod(%.100s, 0%o) failed: %.100s", - ttyname, (int)mode, strerror(errno)); - else - fatal("chmod(%.100s, 0%o) failed: %.100s", - ttyname, (int)mode, strerror(errno)); - } - } -} diff --git a/usr/src/cmd/stat/Makefile b/usr/src/cmd/stat/Makefile index 34149b2b37..faffc6a437 100644 --- a/usr/src/cmd/stat/Makefile +++ b/usr/src/cmd/stat/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2011, 2012, Joyent, Inc. All rights reserved. # Use is subject to license terms. # # cmd/stat/Makefile @@ -27,7 +27,14 @@ include ../Makefile.cmd -SUBDIRS= arcstat iostat mpstat vmstat fsstat kstat +SUBDIRS= arcstat \ + fsstat \ + iostat \ + kstat \ + mpstat \ + vfsstat \ + vmstat \ + ziostat all := TARGET = all install := TARGET = install diff --git a/usr/src/cmd/stat/arcstat/Makefile b/usr/src/cmd/stat/arcstat/Makefile index 6ae60a8d3d..a98e2fee7e 100644 --- a/usr/src/cmd/stat/arcstat/Makefile +++ b/usr/src/cmd/stat/arcstat/Makefile @@ -11,6 +11,7 @@ # # Copyright 2014 Adam Stevko. All rights reserved. +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # include $(SRC)/cmd/Makefile.cmd diff --git a/usr/src/cmd/stat/arcstat/arcstat.pl b/usr/src/cmd/stat/arcstat/arcstat.pl index 8f13221910..8f13221910 100755..100644 --- a/usr/src/cmd/stat/arcstat/arcstat.pl +++ b/usr/src/cmd/stat/arcstat/arcstat.pl diff --git a/usr/src/cmd/ssh/etc/ssh-askpass b/usr/src/cmd/stat/vfsstat/Makefile index f2735a9103..04b5085243 100644 --- a/usr/src/cmd/ssh/etc/ssh-askpass +++ b/usr/src/cmd/stat/vfsstat/Makefile @@ -1,4 +1,3 @@ -#! /usr/bin/ksh # # CDDL HEADER START # @@ -19,13 +18,24 @@ # # CDDL HEADER END # - -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # -prompt=$(echo $1 | sed s/_/__/g) -ICON=/usr/share/pixmaps/blueprint-keyring.png -exec /usr/bin/zenity --entry --title "ssh-askpass" \ - --text="$prompt" --hide-text --window-icon=$ICON +include $(SRC)/cmd/Makefile.cmd + +PROG= vfsstat + +.KEEP_STATE: + +all: $(PROG) + +install: all .WAIT $(ROOTPROG) + +clean: + +$(ROOTBINPROG): $(PROG) + $(INS.file) + +lint: + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/stat/vfsstat/vfsstat.pl b/usr/src/cmd/stat/vfsstat/vfsstat.pl new file mode 100644 index 0000000000..a3780b8e63 --- /dev/null +++ b/usr/src/cmd/stat/vfsstat/vfsstat.pl @@ -0,0 +1,227 @@ +#!/usr/perl5/bin/perl -w +# +# 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) 2011 Joyent, Inc. +# +# vfsstat - report VFS statistics per zone +# +# USAGE: vfsstat [-hIMrzZ] [interval [count]] +# -h # help +# -I # print results per interval (where applicable) +# -M # print results in MB/s +# -r # print data in comma-separated format +# -z # hide zones with no VFS activity +# -Z # print data for all zones +# +# eg, vfsstat # print summary since zone boot +# vfsstat 1 # print continually every 1 second +# vfsstat 1 5 # print 5 times, every 1 second +# +# NOTES: +# +# - The calculations and output fields emulate those from iostat(1M) as closely +# as possible. When only one zone is actively performing disk I/O, the +# results from iostat(1M) in the global zone and vfsstat in the local zone +# should be almost identical. Note that many VFS read operations are handled +# by the ARC, so vfsstat and iostat(1M) will be similar only when most +# requests are missing in the ARC. +# +# - As with iostat(1M), a result of 100% for VFS read and write utilization does +# not mean that the syscall layer is fully saturated. Instead, that +# measurement just shows that at least one operation was pending over the last +# quanta of time examined. Since the VFS layer can process more than one +# operation concurrently, this measurement will frequently be 100% but the VFS +# layer can still accept additional requests. +# +# - This script is based on Brendan Gregg's K9Toolkit examples: +# +# http://www.brendangregg.com/k9toolkit.html +# + +use Getopt::Std; +use Sun::Solaris::Kstat; +my $Kstat = Sun::Solaris::Kstat->new(); + +# Process command line args +usage() if defined $ARGV[0] and $ARGV[0] eq "--help"; +getopts('hIMrzZ') or usage(); +usage() if defined $main::opt_h; +$main::opt_h = 0; + +my $USE_MB = defined $main::opt_M ? $main::opt_M : 0; +my $USE_INTERVAL = defined $main::opt_I ? $main::opt_I : 0; +my $USE_COMMA = defined $main::opt_r ? $main::opt_r : 0; +my $HIDE_ZEROES = defined $main::opt_z ? $main::opt_z : 0; +my $ALL_ZONES = defined $main::opt_Z ? $main::opt_Z : 0; + +my ($interval, $count); +if ( defined($ARGV[0]) ) { + $interval = $ARGV[0]; + $count = defined ($ARGV[1]) ? $ARGV[1] : 2**32; + usage() if ($interval == 0); +} else { + $interval = 1; + $count = 1; +} + +my $HEADER_FMT = $USE_COMMA ? + "r/%s,w/%s,%sr/%s,%sw/%s,ractv,wactv,read_t,writ_t,%%r,%%w," . + "d/%s,del_t,zone\n" : + " r/%s w/%s %sr/%s %sw/%s ractv wactv read_t writ_t " . + "%%r %%w d/%s del_t zone\n"; +my $DATA_FMT = $USE_COMMA ? + "%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%d,%d,%.1f,%.1f,%s,%d\n" : + "%5.1f %5.1f %5.1f %5.1f %5.1f %5.1f %6.1f %6.1f %3d %3d " . + "%5.1f %6.1f %s (%d)\n"; + +my $BYTES_PREFIX = $USE_MB ? "M" : "k"; +my $BYTES_DIVISOR = $USE_MB ? 1024 * 1024 : 1024; +my $INTERVAL_SUFFIX = $USE_INTERVAL ? "i" : "s"; +my $NANOSEC = 1000000000; + +my @fields = ( 'reads', 'writes', 'nread', 'nwritten', 'rtime', 'wtime', + 'rlentime', 'wlentime', 'delay_cnt', 'delay_time', 'snaptime' ); + +chomp(my $curzone = (`/sbin/zonename`)); + +my %old = (); +my $rows_printed = 0; + +for (my $ii = 0; $ii < $count; $ii++) { + # Read list of visible zones and their zone IDs + my @zones = (); + my %zoneids = (); + my $zoneadm = `zoneadm list -p | cut -d: -f1,2`; + @lines = split(/\n/, $zoneadm); + foreach $line (@lines) { + @tok = split(/:/, $line); + $zoneids->{$tok[1]} = $tok[0]; + push(@zones, $tok[1]); + } + + $Kstat->update(); + + # Print the column header every 20 rows + if ($rows_printed == 0 || $ALL_ZONES) { + printf($HEADER_FMT, $INTERVAL_SUFFIX, $INTERVAL_SUFFIX, + $BYTES_PREFIX, $INTERVAL_SUFFIX, $BYTES_PREFIX, + $INTERVAL_SUFFIX, $INTERVAL_SUFFIX); + } + + $rows_printed = $rows_printed >= 20 ? 0 : $rows_printed + 1; + + foreach $zone (@zones) { + if ((!$ALL_ZONES) && ($zone ne $curzone)) { + next; + } + + if (! defined $old->{$zone}) { + $old->{$zone} = (); + foreach $field (@fields) { $old->{$zone}->{$field} = 0; } + } + + # + # Kstats have a 30-character limit (KSTAT_STRLEN) on their + # names, so if the zone name exceeds that limit, use the first + # 30 characters. + # + my $trimmed_zone = substr($zone, 0, 30); + my $zoneid = $zoneids->{$zone}; + + print_stats($zone, $zoneid, + $Kstat->{'zone_vfs'}{$zoneid}{$trimmed_zone}, $old->{$zone}); + } + + sleep ($interval); +} + +exit(0); + +sub print_stats { + my $zone = $_[0]; + my $zoneid = $_[1]; + my $data = $_[2]; + my $old = $_[3]; + + my $etime = $data->{'snaptime'} - + ($old->{'snaptime'} > 0 ? $old->{'snaptime'} : $data->{'crtime'}); + + # Calculate basic statistics + my $rate_divisor = $USE_INTERVAL ? 1 : $etime; + my $reads = ($data->{'reads'} - $old->{'reads'}) / $rate_divisor; + my $writes = ($data->{'writes'} - $old->{'writes'}) / $rate_divisor; + my $nread = ($data->{'nread'} - $old->{'nread'}) / + $rate_divisor / $BYTES_DIVISOR; + my $nwritten = ($data->{'nwritten'} - $old->{'nwritten'}) / + $rate_divisor / $BYTES_DIVISOR; + + # Calculate transactions per second + my $r_tps = ($data->{'reads'} - $old->{'reads'}) / $etime; + my $w_tps = ($data->{'writes'} - $old->{'writes'}) / $etime; + + # Calculate average length of active queue + my $r_actv = (($data->{'rlentime'} - $old->{'rlentime'}) / $NANOSEC) / + $etime; + my $w_actv = (($data->{'wlentime'} - $old->{'wlentime'}) / $NANOSEC) / + $etime; + + # Calculate average service time + # multiply by 1000 to convert to usecs for conssistency with del_t + my $read_t = ($r_tps > 0 ? $r_actv * (1000 / $r_tps) : 0.0) * 1000; + my $writ_t = ($w_tps > 0 ? $w_actv * (1000 / $w_tps) : 0.0) * 1000; + + # Calculate I/O throttle delay metrics + my $delays = $data->{'delay_cnt'} - $old->{'delay_cnt'}; + my $d_tps = $delays / $etime; + my $del_t = $delays > 0 ? + ($data->{'delay_time'} - $old->{'delay_time'}) / $delays : 0.0; + + # Calculate the % time the VFS layer is active + my $r_b_pct = ((($data->{'rtime'} - $old->{'rtime'}) / $NANOSEC) / + $etime) * 100; + my $w_b_pct = ((($data->{'wtime'} - $old->{'wtime'}) / $NANOSEC) / + $etime) * 100; + + if (! $HIDE_ZEROES || $reads != 0.0 || $writes != 0.0 || + $nread != 0.0 || $nwritten != 0.0) { + printf($DATA_FMT, $reads, $writes, $nread, $nwritten, $r_actv, + $w_actv, $read_t, $writ_t, $r_b_pct, $w_b_pct, + $d_tps, $del_t, substr($zone, 0, 8), $zoneid); + } + + # Save current calculations for next loop + foreach (@fields) { $old->{$_} = $data->{$_}; } +} + +sub usage { + print STDERR <<END; +USAGE: vfsstat [-hIMrzZ] [interval [count]] + eg, vfsstat # print summary since zone boot + vfsstat 1 # print continually every 1 second + vfsstat 1 5 # print 5 times, every 1 second + vfsstat -I # print results per interval (where applicable) + vfsstat -M # print results in MB/s + vfsstat -r # print results in comma-separated format + vfsstat -z # hide zones with no VFS activity + vfsstat -Z # print results for all zones +END + exit 1; +} diff --git a/usr/src/cmd/stat/ziostat/Makefile b/usr/src/cmd/stat/ziostat/Makefile new file mode 100644 index 0000000000..c338b59678 --- /dev/null +++ b/usr/src/cmd/stat/ziostat/Makefile @@ -0,0 +1,41 @@ +# +# 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) 2011, Joyent, Inc. All rights reserved. +# + +include $(SRC)/cmd/Makefile.cmd + +PROG= ziostat + +.KEEP_STATE: + +all: $(PROG) + +install: all .WAIT $(ROOTPROG) + +clean: + +$(ROOTBINPROG): $(PROG) + $(INS.file) + +lint: + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/stat/ziostat/ziostat.pl b/usr/src/cmd/stat/ziostat/ziostat.pl new file mode 100755 index 0000000000..cf95d2f5a5 --- /dev/null +++ b/usr/src/cmd/stat/ziostat/ziostat.pl @@ -0,0 +1,204 @@ +#!/usr/perl5/bin/perl -w +# +# 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) 2011 Joyent, Inc. +# +# ziostat - report I/O statistics per zone +# +# USAGE: ziostat [-hIMrzZ] [interval [count]] +# -h # help +# -I # print results per interval (where applicable) +# -M # print results in MB/s +# -r # print data in comma-separated format +# -z # hide zones with no ZFS I/O activity +# -Z # print data for all zones +# +# eg, ziostat # print summary since zone boot +# ziostat 1 # print continually every 1 second +# ziostat 1 5 # print 5 times, every 1 second +# +# NOTES: +# +# - The calculations and output fields emulate those from iostat(1M) as closely +# as possible. When only one zone is actively performing disk I/O, the +# results from iostat(1M) in the global zone and ziostat in the local zone +# should be almost identical. +# +# - As with iostat(1M), a result of 100% for disk utilization does not mean that +# the disk is fully saturated. Instead, that measurement just shows that at +# least one operation was pending over the last quanta of time examined. +# Since disk devices can process more than one operation concurrently, this +# measurement will frequently be 100% but the disk can still offer higher +# performance. +# +# - This script is based on Brendan Gregg's K9Toolkit examples: +# +# http://www.brendangregg.com/k9toolkit.html +# + +use Getopt::Std; +use Sun::Solaris::Kstat; +my $Kstat = Sun::Solaris::Kstat->new(); + +# Process command line args +usage() if defined $ARGV[0] and $ARGV[0] eq "--help"; +getopts('hIMrzZ') or usage(); +usage() if defined $main::opt_h; +$main::opt_h = 0; + +my $USE_MB = defined $main::opt_M ? $main::opt_M : 0; +my $USE_INTERVAL = defined $main::opt_I ? $main::opt_I : 0; +my $USE_COMMA = defined $main::opt_r ? $main::opt_r : 0; +my $HIDE_ZEROES = defined $main::opt_z ? $main::opt_z : 0; +my $ALL_ZONES = defined $main::opt_Z ? $main::opt_Z : 0; + +my ($interval, $count); +if ( defined($ARGV[0]) ) { + $interval = $ARGV[0]; + $count = defined ($ARGV[1]) ? $ARGV[1] : 2**32; + usage() if ($interval == 0); +} else { + $interval = 1; + $count = 1; +} + +my $HEADER_FMT = $USE_COMMA ? + "r/%s,%sr/%s,actv,wsvc_t,asvc_t,%%b,zone\n" : + " r/%s %sr/%s actv wsvc_t asvc_t %%b zone\n"; +my $DATA_FMT = $USE_COMMA ? + "%.1f,%.1f,%.1f,%.1f,%.1f,%d,%s,%d\n" : + " %6.1f %6.1f %6.1f %6.1f %6.1f %3d %s (%d)\n"; + +my $BYTES_PREFIX = $USE_MB ? "M" : "k"; +my $BYTES_DIVISOR = $USE_MB ? 1024 * 1024 : 1024; +my $INTERVAL_SUFFIX = $USE_INTERVAL ? "i" : "s"; +my $NANOSEC = 1000000000; + +my @fields = ( 'reads', 'nread', 'waittime', 'rtime', 'rlentime', 'snaptime' ); + +chomp(my $curzone = (`/sbin/zonename`)); + +# Read list of visible zones and their zone IDs +my @zones = (); +my %zoneids = (); +my $zoneadm = `zoneadm list -p | cut -d: -f1,2`; +@lines = split(/\n/, $zoneadm); +foreach $line (@lines) { + @tok = split(/:/, $line); + $zoneids->{$tok[1]} = $tok[0]; + push(@zones, $tok[1]); +} + +my %old = (); +my $rows_printed = 0; + +$Kstat->update(); + +for (my $ii = 0; $ii < $count; $ii++) { + # Print the column header every 20 rows + if ($rows_printed == 0 || $ALL_ZONES) { + printf($HEADER_FMT, $INTERVAL_SUFFIX, $BYTES_PREFIX, + $INTERVAL_SUFFIX, $INTERVAL_SUFFIX); + } + + $rows_printed = $rows_printed >= 20 ? 0 : $rows_printed + 1; + + foreach $zone (@zones) { + if ((!$ALL_ZONES) && ($zone ne $curzone)) { + next; + } + + if (! defined $old->{$zone}) { + $old->{$zone} = (); + foreach $field (@fields) { $old->{$zone}->{$field} = 0; } + } + + # + # Kstats have a 30-character limit (KSTAT_STRLEN) on their + # names, so if the zone name exceeds that limit, use the first + # 30 characters. + # + my $trimmed_zone = substr($zone, 0, 30); + my $zoneid = $zoneids->{$zone}; + + print_stats($zone, $zoneid, + $Kstat->{'zone_zfs'}{$zoneid}{$trimmed_zone}, $old->{$zone}); + } + + sleep ($interval); + $Kstat->update(); +} + +sub print_stats { + my $zone = $_[0]; + my $zoneid = $_[1]; + my $data = $_[2]; + my $old = $_[3]; + + my $etime = $data->{'snaptime'} - + ($old->{'snaptime'} > 0 ? $old->{'snaptime'} : $data->{'crtime'}); + + # Calculate basic statistics + my $rate_divisor = $USE_INTERVAL ? 1 : $etime; + my $reads = ($data->{'reads'} - $old->{'reads'}) / $rate_divisor; + my $nread = ($data->{'nread'} - $old->{'nread'}) / + $rate_divisor / $BYTES_DIVISOR; + + # Calculate overall transactions per second + my $ops = $data->{'reads'} - $old->{'reads'}; + my $tps = $ops / $etime; + + # Calculate average length of disk run queue + my $actv = (($data->{'rlentime'} - $old->{'rlentime'}) / $NANOSEC) / + $etime; + + # Calculate average disk wait and service times + my $wsvc = $ops > 0 ? (($data->{'waittime'} - $old->{'waittime'}) / + 1000000) / $ops : 0.0; + my $asvc = $tps > 0 ? $actv * (1000 / $tps) : 0.0; + + # Calculate the % time the disk run queue is active + my $b_pct = ((($data->{'rtime'} - $old->{'rtime'}) / $NANOSEC) / + $etime) * 100; + + if (! $HIDE_ZEROES || $reads != 0.0 || $nread != 0.0 ) { + printf($DATA_FMT, $reads, $nread, $actv, $wsvc, $asvc, + $b_pct, substr($zone, 0, 8), $zoneid); + } + + # Save current calculations for next loop + foreach (@fields) { $old->{$_} = $data->{$_}; } +} + +sub usage { + print STDERR <<END; +USAGE: ziostat [-hIMrzZ] [interval [count]] + eg, ziostat # print summary since zone boot + ziostat 1 # print continually every 1 second + ziostat 1 5 # print 5 times, every 1 second + ziostat -I # print results per interval (where applicable) + ziostat -M # print results in MB/s + ziostat -r # print results in comma-separated format + ziostat -z # hide zones with no ZFS I/O activity + ziostat -Z # print results for all zones +END + exit 1; +} diff --git a/usr/src/cmd/svc/configd/rc_node.c b/usr/src/cmd/svc/configd/rc_node.c index 3cc30e3e67..149f2a6cb5 100644 --- a/usr/src/cmd/svc/configd/rc_node.c +++ b/usr/src/cmd/svc/configd/rc_node.c @@ -23,6 +23,9 @@ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ /* * rc_node.c - In-memory SCF object management diff --git a/usr/src/cmd/svc/milestone/net-routing-setup b/usr/src/cmd/svc/milestone/net-routing-setup index 6ab1a6c7f0..b4ee7d39ac 100644 --- a/usr/src/cmd/svc/milestone/net-routing-setup +++ b/usr/src/cmd/svc/milestone/net-routing-setup @@ -21,11 +21,15 @@ # # # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. # This script configures IP routing. . /lib/svc/share/smf_include.sh +set -o xtrace + # # In a shared-IP zone we need this service to be up, but all of the work # it tries to do is irrelevant (and will actually lead to the service @@ -156,7 +160,8 @@ fi # however, as persistent daemon state is now controlled by SMF. # ipv4_routing_set=`/usr/bin/svcprop -p routeadm/ipv4-routing-set $SMF_FMRI` -if [ -z "$defrouters" ]; then +smartos_param=`/usr/bin/bootparams | grep "^smartos"` +if [ -z "$defrouters" ] && [ "$smartos_param" != "" ]; then # # Set default value for ipv4-routing to enabled. If routeadm -e/-d # has not yet been run by the administrator, we apply this default. @@ -210,5 +215,21 @@ if [ -f /etc/inet/static_routes ]; then done fi +# +# Read /etc/inet/static_routes.vmadm and add each route. +# +if [ -f /etc/inet/static_routes.vmadm ]; then + echo "Adding vmadm persistent routes:" + /usr/bin/egrep -v "^(#|$)" /etc/inet/static_routes.vmadm | while read line; do + /usr/sbin/route add $line + done +fi + +# +# Log the result +# +echo "Routing setup complete:" +/usr/bin/netstat -rn + # Clear exit status. exit $SMF_EXIT_OK diff --git a/usr/src/cmd/svc/milestone/network-location.xml b/usr/src/cmd/svc/milestone/network-location.xml index aad337f42f..709e9df8f3 100644 --- a/usr/src/cmd/svc/milestone/network-location.xml +++ b/usr/src/cmd/svc/milestone/network-location.xml @@ -106,7 +106,7 @@ --> <dependency name='manifest-import' - grouping='require_all' + grouping='optional_all' restart_on='none' type='service'> <service_fmri value='svc:/system/manifest-import:default' /> diff --git a/usr/src/cmd/svc/milestone/network-routing-setup.xml b/usr/src/cmd/svc/milestone/network-routing-setup.xml index b34d578e2a..85a74756da 100644 --- a/usr/src/cmd/svc/milestone/network-routing-setup.xml +++ b/usr/src/cmd/svc/milestone/network-routing-setup.xml @@ -40,11 +40,19 @@ <!-- loopback/physical network configuration is required --> <dependency - name='network' - grouping='optional_all' + name='loopback' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/network/loopback' /> + </dependency> + + <dependency + name='physical' + grouping='require_all' restart_on='none' type='service'> - <service_fmri value='svc:/milestone/network' /> + <service_fmri value='svc:/network/physical' /> </dependency> <!-- usr filesystem required to run routing-related commands --> diff --git a/usr/src/cmd/svc/milestone/network.xml b/usr/src/cmd/svc/milestone/network.xml index 75b5578f44..48386ebf73 100644 --- a/usr/src/cmd/svc/milestone/network.xml +++ b/usr/src/cmd/svc/milestone/network.xml @@ -54,6 +54,14 @@ <service_fmri value='svc:/network/physical' /> </dependency> + <dependency + name='routing-setup' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/network/routing-setup' /> + </dependency> + <exec_method type='method' name='start' diff --git a/usr/src/cmd/svc/milestone/single-user.xml b/usr/src/cmd/svc/milestone/single-user.xml index 8797f13c47..579ecb5ddd 100644 --- a/usr/src/cmd/svc/milestone/single-user.xml +++ b/usr/src/cmd/svc/milestone/single-user.xml @@ -68,7 +68,7 @@ <dependency name='manifests' - grouping='require_all' + grouping='optional_all' restart_on='none' type='service'> <service_fmri value='svc:/system/manifest-import' /> diff --git a/usr/src/cmd/svc/shell/smf_include.sh b/usr/src/cmd/svc/shell/smf_include.sh index d0dc387246..02c9532763 100644 --- a/usr/src/cmd/svc/shell/smf_include.sh +++ b/usr/src/cmd/svc/shell/smf_include.sh @@ -22,6 +22,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2012 Joyent, Inc. All rights reserved. # smf_present () { @@ -234,7 +235,12 @@ smf_kill_contract() { # SMF_EXIT_ERR_OTHER, although not defined, encompasses all non-zero # exit status values. # +# The SMF_EXIT_NODAEMON exit status should be used when a method does not +# need to run any persistent process. This indicates success, abandons the +# contract, and allows dependencies to be met. +# SMF_EXIT_OK=0 +SMF_EXIT_NODAEMON=94 SMF_EXIT_ERR_FATAL=95 SMF_EXIT_ERR_CONFIG=96 SMF_EXIT_MON_DEGRADE=97 diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c index c831c99301..5a4e933220 100644 --- a/usr/src/cmd/svc/startd/graph.c +++ b/usr/src/cmd/svc/startd/graph.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2015, Syneto S.R.L. All rights reserved. */ @@ -142,6 +143,8 @@ #include <assert.h> #include <errno.h> #include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> #include <fm/libfmevent.h> #include <libscf.h> #include <libscf_priv.h> @@ -4876,6 +4879,20 @@ vertex_subgraph_dependencies_shutdown(scf_handle_t *h, graph_vertex_t *v, was_up = up_state(old_state); now_up = up_state(v->gv_state); + if (halting != -1 && old_state == RESTARTER_STATE_DISABLED && + v->gv_state != RESTARTER_STATE_DISABLED) { + /* + * We're halting and we have a svc which is transitioning to + * offline in parallel. This leads to a race condition where + * gt_enter_offline might re-enable the svc after we disabled + * it. Since we're halting, we want to ensure no svc ever + * transitions out of the disabled state. In this case, modify + * the flags to keep us on the halting path. + */ + was_up = 0; + now_up = 0; + } + if (!was_up && now_up) { ++non_subgraph_svcs; } else if (was_up && !now_up) { @@ -6828,6 +6845,7 @@ repository_event_thread(void *unused) char *fmri = startd_alloc(max_scf_fmri_size); char *pg_name = startd_alloc(max_scf_value_size); int r; + int fd; h = libscf_handle_create_bound_loop(); @@ -6850,6 +6868,14 @@ retry: goto retry; } + if ((fd = open("/etc/svc/volatile/startd.ready", O_RDONLY | O_CREAT, + S_IRUSR)) < 0) { + log_error(LOG_WARNING, "Couldn't create startd.ready file\n", + SCF_GROUP_FRAMEWORK, scf_strerror(scf_error())); + } else { + (void) close(fd); + } + /*CONSTCOND*/ while (1) { ssize_t res; diff --git a/usr/src/cmd/svc/startd/method.c b/usr/src/cmd/svc/startd/method.c index cc9ce6768c..c3cd0144c1 100644 --- a/usr/src/cmd/svc/startd/method.c +++ b/usr/src/cmd/svc/startd/method.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011 Joyent Inc. + * Copyright 2012 Joyent, Inc. All rights reserved. */ /* @@ -100,34 +100,18 @@ static uint_t method_events[] = { * method_record_start(restarter_inst_t *) * Record a service start for rate limiting. Place the current time * in the circular array of instance starts. + * + * Save the critical_failure_period and critical_failure_allowed with either + * the defaults or the svc properties startd/critical_failure_count and + * startd/critical_failure_period. + * ri_crit_fail_allowed is capped at RINST_START_TIMES. */ static void method_record_start(restarter_inst_t *inst) { - int index = inst->ri_start_index++ % RINST_START_TIMES; - - inst->ri_start_time[index] = gethrtime(); -} - -/* - * method_rate_critical(restarter_inst_t *) - * Return true if the average start interval is less than the permitted - * interval. The implicit interval defaults to RINST_FAILURE_RATE_NS and - * RINST_START_TIMES but may be overridden with the svc properties - * startd/critical_failure_count and startd/critical_failure_period - * which represent the number of failures to consider and the amount of - * time in seconds in which that number may occur, respectively. Note that - * this time is measured as of the transition to 'enabled' rather than wall - * clock time. - * Implicit success if insufficient measurements for an average exist. - */ -int -method_rate_critical(restarter_inst_t *inst) -{ + int index; + uint_t critical_failure_allowed = RINST_START_TIMES; hrtime_t critical_failure_period; - uint_t critical_failure_count = RINST_START_TIMES; - uint_t n = inst->ri_start_index; - hrtime_t avg_ns = 0; uint64_t scf_fr, scf_st; scf_propvec_t *prop = NULL; scf_propvec_t restart_critical[] = { @@ -151,17 +135,48 @@ method_rate_critical(restarter_inst_t *inst) * in seconds but tracked in ns */ critical_failure_period = (hrtime_t)scf_fr * NANOSEC; - critical_failure_count = (uint_t)scf_st; + critical_failure_allowed = (uint_t)scf_st; + + if (critical_failure_allowed > RINST_START_TIMES) + critical_failure_allowed = RINST_START_TIMES; + if (critical_failure_allowed < 1) + critical_failure_allowed = 1; + } - if (inst->ri_start_index < critical_failure_count) + + inst->ri_crit_fail_allowed = critical_failure_allowed; + inst->ri_crit_fail_period = critical_failure_period; + + index = inst->ri_start_index++ % critical_failure_allowed; + inst->ri_start_time[index] = gethrtime(); +} + +/* + * method_rate_critical(restarter_inst_t *) + * Return true if the number of failures within the interval + * ri_crit_fail_period exceeds ri_crit_fail_allowed. The allowed failure + * count defaults to RINST_START_TIMES and the implicit interval defaults + * to RINST_FAILURE_RATE_NS but may be overridden with the svc properties + * startd/critical_failure_count and startd/critical_failure_period which + * represent the acceptable number of failures and the amount of time in + * seconds in which that number may occur, respectively. Note that this time + * is measured as of the transition to 'enabled' rather than wall clock + * time. Implicitly not critical if insufficient failures have occured. + */ +int +method_rate_critical(restarter_inst_t *inst) +{ + uint_t n = inst->ri_start_index; + uint_t fail_allowed = inst->ri_crit_fail_allowed; + hrtime_t diff_ns; + + if (n < fail_allowed) return (0); - avg_ns = - (inst->ri_start_time[(n - 1) % critical_failure_count] - - inst->ri_start_time[n % critical_failure_count]) / - (critical_failure_count - 1); + diff_ns = inst->ri_start_time[(n - 1) % fail_allowed] - + inst->ri_start_time[n % fail_allowed]; - return (avg_ns < critical_failure_period); + return (diff_ns < inst->ri_crit_fail_period); } /* @@ -989,7 +1004,8 @@ method_run(restarter_inst_t **instp, int type, int *exit_code) goto contract_out; } - if (!WIFEXITED(ret_status)) { + if (!WIFEXITED(ret_status) && + WEXITSTATUS(ret_status) != SMF_EXIT_NODAEMON) { /* * If method didn't exit itself (it was killed by an * external entity, etc.), consider the entire @@ -1018,7 +1034,7 @@ method_run(restarter_inst_t **instp, int type, int *exit_code) } *exit_code = WEXITSTATUS(ret_status); - if (*exit_code != 0) { + if (*exit_code != 0 && *exit_code != SMF_EXIT_NODAEMON) { log_error(LOG_WARNING, "%s: Method \"%s\" failed with exit status %d.\n", inst->ri_i.i_fmri, method, WEXITSTATUS(ret_status)); @@ -1027,6 +1043,7 @@ method_run(restarter_inst_t **instp, int type, int *exit_code) log_instance(inst, B_TRUE, "Method \"%s\" exited with status " "%d.", mname, *exit_code); + /* Note: we will take this path for SMF_EXIT_NODAEMON */ if (*exit_code != 0) goto contract_out; @@ -1073,7 +1090,10 @@ assured_kill: } contract_out: - /* Abandon contracts for transient methods & methods that fail. */ + /* + * Abandon contracts for transient methods, methods that exit with + * SMF_EXIT_NODAEMON & methods that fail. + */ transient = method_is_transient(inst, type); if ((transient || *exit_code != 0 || result != 0) && (restarter_is_kill_method(method) < 0)) @@ -1169,7 +1189,7 @@ retry: r = method_run(&inst, info->sf_method_type, &exit_code); - if (r == 0 && exit_code == 0) { + if (r == 0 && (exit_code == 0 || exit_code == SMF_EXIT_NODAEMON)) { /* Success! */ assert(inst->ri_i.i_next_state != RESTARTER_STATE_NONE); @@ -1187,6 +1207,12 @@ retry: else method_remove_contract(inst, B_TRUE, B_TRUE); } + + /* + * For methods that exit with SMF_EXIT_NODAEMON, we already + * called method_remove_contract in method_run. + */ + /* * We don't care whether the handle was rebound because this is * the last thing we do with it. diff --git a/usr/src/cmd/svc/startd/startd.h b/usr/src/cmd/svc/startd/startd.h index c1062e45e0..e204fb829f 100644 --- a/usr/src/cmd/svc/startd/startd.h +++ b/usr/src/cmd/svc/startd/startd.h @@ -405,7 +405,7 @@ typedef enum { #define RINST_RETAKE_MASK 0x0f000000 -#define RINST_START_TIMES 5 /* failures to consider */ +#define RINST_START_TIMES 10 /* up to 10 fails to consider */ #define RINST_FAILURE_RATE_NS 600000000000LL /* 1 failure/10 minutes */ #define RINST_WT_SVC_FAILURE_RATE_NS NANOSEC /* 1 failure/second */ @@ -427,6 +427,8 @@ typedef struct restarter_inst { hrtime_t ri_start_time[RINST_START_TIMES]; uint_t ri_start_index; /* times started */ + uint_t ri_crit_fail_allowed; + hrtime_t ri_crit_fail_period; uu_list_node_t ri_link; pthread_mutex_t ri_lock; diff --git a/usr/src/cmd/svc/svcadm/Makefile b/usr/src/cmd/svc/svcadm/Makefile index cc0cc160bf..1a6a0dd35c 100644 --- a/usr/src/cmd/svc/svcadm/Makefile +++ b/usr/src/cmd/svc/svcadm/Makefile @@ -21,6 +21,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2012, Joyent, Inc. All rights reserved. # PROG = svcadm @@ -49,7 +50,11 @@ $(PROG): $(OBJS) $(POFILE): $(POFILES) cat $(POFILES) > $(POFILE) -install: all $(ROOTUSRSBINPROG) +install: all $(ROOTSBINPROG) $(ROOTUSRSBINPROG) + +$(ROOTUSRSBINPROG): + -$(RM) $@ + -$(SYMLINK) ../../sbin/$(PROG) $@ clean: $(RM) $(OBJS) diff --git a/usr/src/cmd/svc/svcs/Makefile b/usr/src/cmd/svc/svcs/Makefile index 0e9fc52652..2ea89818c0 100644 --- a/usr/src/cmd/svc/svcs/Makefile +++ b/usr/src/cmd/svc/svcs/Makefile @@ -34,7 +34,7 @@ include ../../Makefile.cmd include ../../Makefile.ctf POFILE = $(PROG)_all.po -LDLIBS += -lcontract -lscf -luutil -lumem -lnvpair -lzonecfg +LDLIBS += -lcontract -lscf -luutil -lumem -lnvpair -lzonecfg -lsasl CPPFLAGS += -I ../common lint := LINTFLAGS = -mux diff --git a/usr/src/cmd/svc/svcs/explain.c b/usr/src/cmd/svc/svcs/explain.c index 42fca80172..eed9733abc 100644 --- a/usr/src/cmd/svc/svcs/explain.c +++ b/usr/src/cmd/svc/svcs/explain.c @@ -200,6 +200,7 @@ static char *emsg_invalid_dep; extern scf_handle_t *h; extern char *g_zonename; +extern char *g_zonealias; /* ARGSUSED */ static int @@ -2000,6 +2001,9 @@ print_service(inst_t *svcp, int verbose) if (g_zonename != NULL) (void) printf(gettext(" Zone: %s\n"), g_zonename); + if (g_zonealias != NULL) + (void) printf(gettext(" Alias: %s\n"), g_zonealias); + stime = svcp->stime.tv_sec; tmp = localtime(&stime); diff --git a/usr/src/cmd/svc/svcs/svcs.c b/usr/src/cmd/svc/svcs/svcs.c index c54f4bd12d..b4882d1776 100644 --- a/usr/src/cmd/svc/svcs/svcs.c +++ b/usr/src/cmd/svc/svcs/svcs.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -59,6 +59,7 @@ #include <sys/ctfs.h> #include <sys/stat.h> +#include <sasl/saslutil.h> #include <assert.h> #include <errno.h> #include <fcntl.h> @@ -134,6 +135,9 @@ static int first_paragraph = 1; /* For -l mode. */ static char *common_name_buf; /* Sized for maximal length value. */ char *locale; /* Current locale. */ char *g_zonename; /* zone being operated upon */ +char *g_zonealias; /* alias for zone, if any */ +static char g_aliasdec[MAXPATHLEN / 4 * 3]; /* decoded zone alias buffer */ +static char g_aliasbuf[MAXPATHLEN]; /* base64 encoded zone alias buffer */ /* * Pathname storage for path generated from the fmri. @@ -240,7 +244,25 @@ ht_free(void) static void ht_init(void) { - assert(ht_buckets == NULL); + if (ht_buckets != NULL) { + /* + * If we already have a hash table (e.g., because we are + * processing multiple zones), destroy it before creating + * a new one. + */ + struct ht_elem *elem, *next; + int i; + + for (i = 0; i < ht_buckets_num; i++) { + for (elem = ht_buckets[i]; elem != NULL; elem = next) { + next = elem->next; + free((char *)elem->fmri); + free(elem); + } + } + + free(ht_buckets); + } ht_buckets_num = 8; ht_buckets = safe_malloc(sizeof (*ht_buckets) * ht_buckets_num); @@ -553,7 +575,7 @@ get_restarter_time_prop(scf_instance_t *inst, const char *pname, int r; r = inst_get_single_val(inst, SCF_PG_RESTARTER, pname, SCF_TYPE_TIME, - tvp, NULL, ok_if_empty ? EMPTY_OK : 0, 0, 1); + tvp, 0, ok_if_empty ? EMPTY_OK : 0, 0, 1); return (r == 0 ? 0 : -1); } @@ -1650,7 +1672,7 @@ sprint_stime(char **buf, scf_walkinfo_t *wip) SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0); } else { r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP, - SCF_TYPE_TIME, &tv, NULL, 0); + SCF_TYPE_TIME, &tv, 0, 0); } if (r != 0) { @@ -1702,7 +1724,7 @@ sortkey_stime(char *buf, int reverse, scf_walkinfo_t *wip) SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0); else r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP, - SCF_TYPE_TIME, &tv, NULL, 0); + SCF_TYPE_TIME, &tv, 0, 0); if (r == 0) { int64_t sec; @@ -2514,7 +2536,7 @@ print_detailed(void *unused, scf_walkinfo_t *wip) gettext("next_state"), buf); if (pg_get_single_val(rpg, SCF_PROPERTY_STATE_TIMESTAMP, - SCF_TYPE_TIME, &tv, NULL, 0) == 0) { + SCF_TYPE_TIME, &tv, 0, 0) == 0) { stime = tv.tv_sec; tmp = localtime(&stime); for (tbsz = 50; ; tbsz *= 2) { @@ -3663,6 +3685,24 @@ again: assert(opt_zone == NULL || zids == NULL); if (opt_zone == NULL) { + zone_status_t status; + + if (zone_getattr(zids[zent], ZONE_ATTR_STATUS, + &status, sizeof (status)) < 0 || + status != ZONE_IS_RUNNING) { + /* + * If this zone is not running or we cannot + * get its status, we do not want to attempt + * to bind an SCF handle to it, lest we + * accidentally interfere with a zone that + * is not yet running by looking up a door + * to its svc.configd (which could potentially + * block a mount with an EBUSY). + */ + zent++; + goto nextzone; + } + if (getzonenamebyid(zids[zent++], zonename, sizeof (zonename)) < 0) { uu_warn(gettext("could not get name for " @@ -3685,18 +3725,46 @@ again: uu_die(gettext("invalid zone '%s'\n"), g_zonename); scf_value_destroy(zone); + + /* + * On SmartOS, there may be a base64-encoded string attribute + * named 'alias' associated with this zone. This alias is + * useful, so we attempt to make it available when we are + * displaying -xZ output. If it's not available or not + * decodable, we just ignore it. + */ + if (g_zonename != NULL) { + unsigned len; + struct zone_attrtab zattrs; + zone_dochandle_t zhdl = zonecfg_init_handle(); + + bzero(&zattrs, sizeof (zattrs)); + (void) strcpy(zattrs.zone_attr_name, "alias"); + + if (zhdl != NULL && + zonecfg_get_handle(g_zonename, zhdl) == Z_OK && + zonecfg_lookup_attr(zhdl, &zattrs) == Z_OK && + zonecfg_get_attr_string(&zattrs, g_aliasbuf, + sizeof (g_aliasbuf)) == Z_OK && + sasl_decode64(g_aliasbuf, strlen(g_aliasbuf), + g_aliasdec, sizeof (g_aliasdec), &len) == SASL_OK) { + g_aliasdec[len] = '\0'; + g_zonealias = g_aliasdec; + } else { + g_zonealias = NULL; + } + zonecfg_fini_handle(zhdl); + } } if (scf_handle_bind(h) == -1) { if (g_zonename != NULL) { - uu_warn(gettext("Could not bind to repository " + if (show_zones) + goto nextzone; + + uu_die(gettext("Could not bind to repository " "server for zone %s: %s\n"), g_zonename, scf_strerror(scf_error())); - - if (!show_zones) - return (UU_EXIT_FATAL); - - goto nextzone; } uu_die(gettext("Could not bind to repository server: %s. " @@ -3755,7 +3823,7 @@ again: if (opt_mode == 'L') { if ((err = scf_walk_fmri(h, argc, argv, SCF_WALK_MULTIPLE, - print_log, NULL, &exit_status, uu_warn)) != 0) { + print_log, NULL, errarg, errfunc)) != 0) { uu_warn(gettext("failed to iterate over " "instances: %s\n"), scf_strerror(err)); exit_status = UU_EXIT_FATAL; diff --git a/usr/src/cmd/svr4pkg/pkgadd/Makefile b/usr/src/cmd/svr4pkg/pkgadd/Makefile index 66e6abb737..b1b4168a7c 100644 --- a/usr/src/cmd/svr4pkg/pkgadd/Makefile +++ b/usr/src/cmd/svr4pkg/pkgadd/Makefile @@ -35,7 +35,7 @@ ROOTLINKS= $(ROOTUSRSBIN)/pkgask include $(SRC)/cmd/svr4pkg/Makefile.svr4pkg LDLIBS += -lpkg -linstzones -ladm -LDLIBS += -lcrypto -lwanboot +LDLIBS += -lsunw_crypto -lwanboot .KEEP_STATE: diff --git a/usr/src/cmd/svr4pkg/pkgadm/Makefile b/usr/src/cmd/svr4pkg/pkgadm/Makefile index 620e32cf0d..c4970c3b91 100644 --- a/usr/src/cmd/svr4pkg/pkgadm/Makefile +++ b/usr/src/cmd/svr4pkg/pkgadm/Makefile @@ -35,7 +35,7 @@ OBJS= addcert.o \ include $(SRC)/cmd/svr4pkg/Makefile.svr4pkg -LDLIBS += -lpkg -ladm -lcrypto -lgen +LDLIBS += -lpkg -ladm -lsunw_crypto -lgen .KEEP_STATE: all: $(PROG) diff --git a/usr/src/cmd/tail/Makefile b/usr/src/cmd/tail/Makefile index 293920cfd1..e660cedf2d 100644 --- a/usr/src/cmd/tail/Makefile +++ b/usr/src/cmd/tail/Makefile @@ -21,6 +21,7 @@ OBJS= forward.o misc.o read.o reverse.o tail.o SRCS= $(OBJS:%.o=%.c) include ../Makefile.cmd +include ../Makefile.ctf CLOBBERFILES= $(PROG) CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 @@ -43,6 +44,10 @@ $(PROG): $(OBJS) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) +%.o: %.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + install: all .WAIT $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTXPG4PROG): diff --git a/usr/src/cmd/tar/tar.c b/usr/src/cmd/tar/tar.c index ae96ff27c7..46e6e38612 100644 --- a/usr/src/cmd/tar/tar.c +++ b/usr/src/cmd/tar/tar.c @@ -21,7 +21,7 @@ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Milan Jurik. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -124,13 +124,6 @@ int utimes(const char *path, const struct timeval timeval_ptr[]); #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) -/* -DDEBUG ONLY for debugging */ -#ifdef DEBUG -#undef DEBUG -#define DEBUG(a, b, c)\ - (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c) -#endif - #define TBLOCK 512 /* tape block size--should be universal */ #ifdef BSIZE @@ -482,7 +475,7 @@ static int checkupdate(char *arg); static int checkw(char c, char *name); static int cmp(char *b, char *s, int n); static int defset(char *arch); -static int endtape(void); +static boolean_t endtape(void); static int is_in_table(file_list_t *table[], char *str); static int notsame(void); static int is_prefix(char *s1, char *s2); @@ -558,6 +551,8 @@ static char *add_suffix(); static void wait_pid(pid_t); static void verify_compress_opt(const char *t); static void detect_compress(void); +static void dlog(const char *, ...); +static boolean_t should_enable_debug(void); static struct stat stbuf; @@ -633,7 +628,7 @@ static int extno; /* number of extent: starts at 1 */ static int extotal; /* total extents in this file */ static off_t extsize; /* size of current extent during extraction */ static ushort_t Oumask = 0; /* old umask value */ -static int is_posix; /* true if archive we're reading is POSIX-conformant */ +static boolean_t is_posix; /* true if archive is POSIX-conformant */ static const char *magic_type = "ustar"; static size_t xrec_size = 8 * PATH_MAX; /* extended rec initial size */ static char *xrec_ptr; @@ -645,6 +640,8 @@ static u_longlong_t xhdr_flgs; /* Bits set determine which items */ /* need to be in extended header. */ static pid_t comp_pid = 0; +static boolean_t debug_output = B_FALSE; + #define _X_DEVMAJOR 0x1 #define _X_DEVMINOR 0x2 #define _X_GID 0x4 @@ -736,6 +733,8 @@ main(int argc, char *argv[]) if (argc < 2) usage(); + debug_output = should_enable_debug(); + tfile = NULL; if ((myname = strdup(argv[0])) == NULL) { (void) fprintf(stderr, gettext( @@ -1193,6 +1192,49 @@ main(int argc, char *argv[]) return (1); } +static boolean_t +should_enable_debug(void) +{ + const char *val; + const char *truth[] = { + "true", + "1", + "yes", + "y", + "please", + NULL + }; + unsigned int i; + + if ((val = getenv("DEBUG_TAR")) == NULL) { + return (B_FALSE); + } + + for (i = 0; truth[i] != NULL; i++) { + if (strcmp(val, truth[i]) == 0) { + return (B_TRUE); + } + } + + return (B_FALSE); +} + +/*PRINTFLIKE1*/ +static void +dlog(const char *format, ...) +{ + va_list ap; + + if (!debug_output) { + return; + } + + va_start(ap, format); + (void) fprintf(stderr, "tar: DEBUG: "); + (void) vfprintf(stderr, format, ap); + va_end(ap); +} + static void usage(void) { @@ -1427,13 +1469,26 @@ dorep(char *argv[]) * 1 if EOT, tape position unaffected */ -static int +static boolean_t endtape(void) { - if (dblock.dbuf.name[0] == '\0') { /* null header = EOT */ - return (1); - } else - return (0); + if (dblock.dbuf.name[0] != '\0') { + /* + * The name field is populated. + */ + return (B_FALSE); + } + + if (is_posix && dblock.dbuf.prefix[0] != '\0') { + /* + * This is a ustar/POSIX archive, and although the name + * field is empty the prefix field is not. + */ + return (B_FALSE); + } + + dlog("endtape(): found null header; EOT\n"); + return (B_TRUE); } /* @@ -1471,9 +1526,11 @@ top: is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0); sp->st_mode = Gen.g_mode; - if (is_posix && (sp->st_mode & S_IFMT) == 0) + if (is_posix && (sp->st_mode & S_IFMT) == 0) { switch (dblock.dbuf.typeflag) { - case '0': case 0: case _XATTR_HDRTYPE: + case '0': + case 0: + case _XATTR_HDRTYPE: sp->st_mode |= S_IFREG; break; case '1': /* hard link */ @@ -1498,6 +1555,7 @@ top: sp->st_mode |= S_IFREG; break; } + } if ((dblock.dbuf.typeflag == 'X') || (dblock.dbuf.typeflag == 'L')) { Xhdrflag = 1; /* Currently processing extended header */ @@ -1605,7 +1663,7 @@ top: * The tape directory entry must be in dblock.dbuf. This * routine just eats the number of blocks computed from the * directory size entry; the tape must be (logically) positioned - * right after thee directory info. + * right after the directory info. */ static void @@ -1615,6 +1673,18 @@ passtape(void) char buf[TBLOCK]; /* + * Print some debugging information about the directory entry + * we are skipping over: + */ + dlog("passtape: typeflag \"%c\"\n", dblock.dbuf.typeflag); + if (dblock.dbuf.name[0] != '\0') { + dlog("passtape: name \"%s\"\n", dblock.dbuf.name); + } + if (is_posix && dblock.dbuf.prefix[0] != '\0') { + dlog("passtape: prefix \"%s\"\n", dblock.dbuf.prefix); + } + + /* * Types link(1), sym-link(2), char special(3), blk special(4), * directory(5), and FIFO(6) do not have data blocks associated * with them so just skip reading the data block. @@ -1625,6 +1695,8 @@ passtape(void) return; blocks = TBLOCKS(stbuf.st_size); + dlog("passtape: block count %" FMT_blkcnt_t "\n", blocks); + /* if operating on disk, seek instead of reading */ if (NotTape) seekdisk(blocks); @@ -2070,11 +2142,9 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, (void) writetbuf((char *)&dblock, 1); } if (vflag) { -#ifdef DEBUG - if (NotTape) - DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), - 0); -#endif + if (NotTape) { + dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos)); + } if (filetype == XATTR_FILE && Hiddendir) { (void) fprintf(vfile, gettext("a %s attribute %s "), @@ -2083,12 +2153,13 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, } else { (void) fprintf(vfile, "a %s/ ", longname); } - if (NotTape) + if (NotTape) { (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", K(blocks)); - else + } else { (void) fprintf(vfile, gettext("%" FMT_blkcnt_t " tape blocks\n"), blocks); + } } /* @@ -2270,20 +2341,16 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, } newvol(); /* not worth it--just get new volume */ } -#ifdef DEBUG - DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, + dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, blocks); -#endif if (build_dblock(name, tchar, '0', filetype, &stbuf, stbuf.st_dev, prefix) != 0) { goto out; } if (vflag) { -#ifdef DEBUG - if (NotTape) - DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), - 0); -#endif + if (NotTape) { + dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos)); + } (void) fprintf(vfile, "a %s%s%s%s ", longname, rw_sysattr ? gettext(" system") : "", (filetype == XATTR_FILE) ? gettext( @@ -2367,23 +2434,19 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, } newvol(); } -#ifdef DEBUG - DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, + dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, blocks); -#endif if (vflag) { -#ifdef DEBUG - if (NotTape) - DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), - 0); -#endif - if (NotTape) + if (NotTape) { + dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos)); + (void) fprintf(vfile, gettext("a %s %" FMT_blkcnt_t "K\n "), longname, K(blocks)); - else + } else { (void) fprintf(vfile, gettext( "a %s %" FMT_blkcnt_t " tape blocks\n"), longname, blocks); + } } if (build_dblock(name, tchar, '6', filetype, &stbuf, stbuf.st_dev, prefix) != 0) @@ -2418,23 +2481,19 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, } newvol(); } -#ifdef DEBUG - DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, + dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, blocks); -#endif if (vflag) { -#ifdef DEBUG - if (NotTape) - DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), - 0); -#endif - if (NotTape) + if (NotTape) { + dlog("seek = %" FMT_blkcnt_t "K\t", K(tapepos)); + (void) fprintf(vfile, gettext("a %s %" FMT_blkcnt_t "K\n"), longname, K(blocks)); - else + } else { (void) fprintf(vfile, gettext("a %s %" FMT_blkcnt_t " tape blocks\n"), longname, blocks); + } } if (build_dblock(name, tchar, '3', filetype, &stbuf, stbuf.st_rdev, prefix) != 0) @@ -2469,16 +2528,13 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, } newvol(); } -#ifdef DEBUG - DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, + dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, blocks); -#endif if (vflag) { -#ifdef DEBUG - if (NotTape) - DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), - 0); -#endif + if (NotTape) { + dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos)); + } + (void) fprintf(vfile, "a %s ", longname); if (NotTape) (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", @@ -4790,9 +4846,7 @@ newvol(void) int c; if (dumping) { -#ifdef DEBUG - DEBUG("newvol called with 'dumping' set\n", 0, 0); -#endif + dlog("newvol called with 'dumping' set\n"); putempty((blkcnt_t)2); /* 2 EOT marks */ closevol(); flushtape(); @@ -4825,10 +4879,8 @@ newvol(void) "tar: cannot reopen %s (%s)\n"), dumping ? gettext("output") : gettext("input"), usefile); -#ifdef DEBUG - DEBUG("update=%d, usefile=%s ", update, usefile); - DEBUG("mt=%d, [%s]\n", mt, strerror(errno)); -#endif + dlog("update=%d, usefile=%s ", update, usefile); + dlog("mt=%d, [%s]\n", mt, strerror(errno)); done(2); } @@ -5013,9 +5065,7 @@ seekdisk(blkcnt_t blocks) #endif tapepos += blocks; -#ifdef DEBUG - DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); -#endif + dlog("seekdisk(%" FMT_blkcnt_t ") called\n", blocks); if (recno + blocks <= nblock) { recno += blocks; return; @@ -5026,10 +5076,8 @@ seekdisk(blkcnt_t blocks) recno = nblock; /* so readtape() reads next time through */ #if SYS_BLOCK > TBLOCK nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); -#ifdef DEBUG - DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", + dlog("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", nxb, seekval); -#endif if (nxb && nxb > seekval) /* don't seek--we'll read */ goto noseek; seekval -= nxb; /* don't seek quite so far */ @@ -5043,9 +5091,7 @@ seekdisk(blkcnt_t blocks) /* read those extra blocks */ noseek: if (nxb) { -#ifdef DEBUG - DEBUG("reading extra blocks\n", 0, 0); -#endif + dlog("reading extra blocks\n", 0, 0); if (read(mt, tbuf, TBLOCK*nblock) < 0) { (void) fprintf(stderr, gettext( "tar: read error while skipping file\n")); @@ -5217,10 +5263,8 @@ static void backtape(void) { struct mtop mtcmd; -#ifdef DEBUG - DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, + dlog("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, nblock); -#endif /* * Backup to the position in the archive where the record * currently sitting in the tbuf buffer is situated. @@ -5278,9 +5322,7 @@ backtape(void) static void flushtape(void) { -#ifdef DEBUG - DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); -#endif + dlog("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno); if (recno > 0) { /* anything buffered? */ if (NotTape) { #if SYS_BLOCK > TBLOCK @@ -5293,20 +5335,16 @@ flushtape(void) * boundary. */ if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { -#ifdef DEBUG - DEBUG("flushtape() %d rounding blocks\n", i, 0); -#endif + dlog("flushtape() %d rounding blocks\n", i); recno += i; /* round up to even SYS_BLOCK */ } #endif if (recno > nblock) recno = nblock; } -#ifdef DEBUG - DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t + dlog("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); -#endif if (write(mt, tbuf, (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { (void) fprintf(stderr, gettext( @@ -5436,12 +5474,10 @@ defset(char *arch) else NotTape = (blocklim != 0); (void) defopen(NULL); -#ifdef DEBUG - DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); - DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", + dlog("defset: archive='%s'; usefile='%s'\n", arch, usefile); + dlog("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", nblock, blocklim); - DEBUG("defset: not tape = %d\n", NotTape, 0); -#endif + dlog("defset: not tape = %d\n", NotTape); return (TRUE); } @@ -5752,6 +5788,9 @@ top: if (endtape()) { if (Bflag) { + ssize_t sz; + size_t extra_blocks = 0; + /* * Logically at EOT - consume any extra blocks * so that write to our stdin won't fail and @@ -5760,10 +5799,13 @@ top: * will produce a bogus error message from "dd". */ - while (read(mt, tbuf, TBLOCK*nblock) > 0) { - /* empty body */ + while ((sz = read(mt, tbuf, TBLOCK*nblock)) > 0) { + extra_blocks += sz; } + dlog("wantit(): %d bytes of extra blocks\n", + extra_blocks); } + dlog("wantit(): at end of tape.\n"); return (-1); } @@ -8016,11 +8058,9 @@ put_link(char *name, char *longname, char *component, char *longattrname, */ if (vflag) { -#ifdef DEBUG if (NotTape) - DEBUG("seek = %" FMT_blkcnt_t - "K\t", K(tapepos), 0); -#endif + dlog("seek = %" FMT_blkcnt_t + "K\n", K(tapepos)); if (filetype == XATTR_FILE) { (void) fprintf(vfile, gettext( "a %s attribute %s link to " diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c index 069268dc05..303b652b91 100644 --- a/usr/src/cmd/truss/codes.c +++ b/usr/src/cmd/truss/codes.c @@ -23,7 +23,7 @@ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. * Copyright (c) 2014, OmniTI Computer Consulting, Inc. All rights reserved. */ @@ -108,7 +108,7 @@ #include "proto.h" #define FCNTLMIN F_DUPFD -#define FCNTLMAX F_BADFD +#define FCNTLMAX F_FLOCKW const char *const FCNTLname[] = { "F_DUPFD", "F_GETFD", @@ -156,7 +156,15 @@ const char *const FCNTLname[] = { "F_SHARE_NBMAND", "F_SETLK64_NBMAND", NULL, /* 45 */ - "F_BADFD" + "F_BADFD", + "F_OFD_GETLK", + "F_OFD_SETLK", + "F_OFD_SETLKW", + NULL, /* 50 */ + NULL, /* 51 */ + NULL, /* 52 */ + "F_FLOCK", + "F_FLOCKW" }; #define SYSFSMIN GETFSIND @@ -703,6 +711,8 @@ const struct ioc { /* /dev/poll ioctl() control codes */ { (uint_t)DP_POLL, "DP_POLL", NULL }, { (uint_t)DP_ISPOLLED, "DP_ISPOLLED", NULL }, + { (uint_t)DP_PPOLL, "DP_PPOLL", NULL }, + { (uint_t)DP_EPOLLCOMPAT, "DP_EPOLLCOMPAT", NULL }, /* the old /proc ioctl() control codes */ #define PIOC ('q'<<8) { (uint_t)(PIOC|1), "PIOCSTATUS", NULL }, diff --git a/usr/src/cmd/truss/expound.c b/usr/src/cmd/truss/expound.c index 915ec4626b..6bfa2fd86f 100644 --- a/usr/src/cmd/truss/expound.c +++ b/usr/src/cmd/truss/expound.c @@ -23,6 +23,7 @@ * Copyright 2012 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright 2015 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -1872,6 +1873,11 @@ show_fcntl(private_t *pri) case F_FREESP: case F_ALLOCSP: case F_SETLK_NBMAND: + case F_OFD_GETLK: + case F_OFD_SETLK: + case F_OFD_SETLKW: + case F_FLOCK: + case F_FLOCKW: if (data_model == PR_MODEL_LP64) show_flock64(pri, offset); else @@ -1883,6 +1889,11 @@ show_fcntl(private_t *pri) case 27: /* F_FREESP64 */ case 28: /* F_ALLOCSP64 */ case 44: /* F_SETLK64_NBMAND */ + case 50: /* F_OFD_GETLK64 */ + case 51: /* F_OFD_SETLK64 */ + case 52: /* F_OFD_SETLKW64 */ + case 55: /* F_FLOCK64 */ + case 56: /* F_FLOCKW64 */ show_flock64(pri, offset); break; #else /* _LP64 */ @@ -1900,6 +1911,11 @@ show_fcntl(private_t *pri) case F_FREESP64: case F_ALLOCSP64: case F_SETLK64_NBMAND: + case F_OFD_GETLK64: + case F_OFD_SETLK64: + case F_OFD_SETLKW64: + case F_FLOCK64: + case F_FLOCKW64: show_flock64(pri, offset); break; #endif /* _LP64 */ diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c index 6c884386b0..ff896f5da4 100644 --- a/usr/src/cmd/truss/print.c +++ b/usr/src/cmd/truss/print.c @@ -845,6 +845,7 @@ prt_mad(private_t *pri, int raw, long val) /* print madvise() argument */ case MADV_ACCESS_DEFAULT: s = "MADV_ACCESS_DEFAULT"; break; case MADV_ACCESS_LWP: s = "MADV_ACCESS_LWP"; break; case MADV_ACCESS_MANY: s = "MADV_ACCESS_MANY"; break; + case MADV_PURGE: s = "MADV_PURGE"; break; } } @@ -872,7 +873,9 @@ prt_mc4(private_t *pri, int raw, long val) /* print memcntl() (4th) argument */ return; case MC_SYNC: - if ((val & ~(MS_SYNC|MS_ASYNC|MS_INVALIDATE)) == 0) { + if ((val & + ~(MS_SYNC|MS_ASYNC|MS_INVALIDATE|MS_INVALCURPROC)) + == 0) { *(s = pri->code_buf) = '\0'; if (val & MS_SYNC) (void) strlcat(s, "|MS_SYNC", CBSIZE); @@ -881,6 +884,9 @@ prt_mc4(private_t *pri, int raw, long val) /* print memcntl() (4th) argument */ if (val & MS_INVALIDATE) (void) strlcat(s, "|MS_INVALIDATE", CBSIZE); + if (val & MS_INVALCURPROC) + (void) strlcat(s, "|MS_INVALCURPROC", + CBSIZE); } break; @@ -1997,6 +2003,8 @@ udp_optname(private_t *pri, long val) case UDP_EXCLBIND: return ("UDP_EXCLBIND"); case UDP_RCVHDR: return ("UDP_RCVHDR"); case UDP_NAT_T_ENDPOINT: return ("UDP_NAT_T_ENDPOINT"); + case UDP_SRCPORT_HASH: return ("UDP_SRCPORT_HASH"); + case UDP_SND_TO_CONNECTED: return ("UDP_SND_TO_CONNECTED"); default: (void) snprintf(pri->code_buf, sizeof (pri->code_buf), "0x%lx", @@ -2445,7 +2453,10 @@ prt_zga(private_t *pri, int raw, long val) case ZONE_ATTR_BOOTARGS: s = "ZONE_ATTR_BOOTARGS"; break; case ZONE_ATTR_BRAND: s = "ZONE_ATTR_BRAND"; break; case ZONE_ATTR_FLAGS: s = "ZONE_ATTR_FLAGS"; break; - case ZONE_ATTR_PHYS_MCAP: s = "ZONE_ATTR_PHYS_MCAP"; break; + case ZONE_ATTR_DID: s = "ZONE_ATTR_DID"; break; + case ZONE_ATTR_PMCAP_NOVER: s = "ZONE_ATTR_PMCAP_NOVER"; break; + case ZONE_ATTR_PMCAP_PAGEOUT: s = "ZONE_ATTR_PMCAP_PAGEOUT"; + break; } } diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c index febd7d71f5..8c736a7044 100644 --- a/usr/src/cmd/truss/systable.c +++ b/usr/src/cmd/truss/systable.c @@ -29,6 +29,9 @@ /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */ +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> @@ -1716,9 +1719,10 @@ const char * const afcodes[] = { "POLICY", /* 29 */ "RDS", /* 30 */ "TRILL", /* 31 */ - "PACKET" /* 32 */ + "PACKET", /* 32 */ + "LX_NETLINK" /* 33 */ }; -#if MAX_AFCODES != 33 +#if MAX_AFCODES != 34 #error Need to update address-family table #endif diff --git a/usr/src/cmd/varpd/Makefile b/usr/src/cmd/varpd/Makefile new file mode 100644 index 0000000000..215f23d29e --- /dev/null +++ b/usr/src/cmd/varpd/Makefile @@ -0,0 +1,74 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +PROG= varpd +OBJS = varpd.o +SRCS = $(OBJS:%.o=../%.c) +SVCMETHOD = svc-varpd +MANIFEST = varpd.xml +ROOTLIBVARPD = $(ROOTLIB)/varpd +ROOTLIBVARPDPROG= $(PROG:%=$(ROOTLIBVARPD)/%) + + +include ../Makefile.cmd +include ../Makefile.ctf + +ROOTMANIFESTDIR= $(ROOTSVCNETWORK) + +CLEANFILES += $(OBJS) +CPPFLAGS += -D_REENTRANT +CFLAGS += $(CCVERBOSE) +LDLIBS += -lvarpd -lumem -lscf +$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG + +# +# Our debug only umem related functions cause lint to get confused. +# +LINTFLAGS += -erroff=E_NAME_DEF_NOT_USED2 + +C99MODE= -xc99=%all +C99LMODE= -Xc99=%all + +.KEEP_STATE: + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +clean: + -$(RM) $(CLEANFILES) + +lint: lint_PROG + +%.o: ../%.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + +check: $(CHKMANIFEST) + +clobber: clean + $(RM) $(PROG) + +install: $(PROG) $(ROOTLIBVARPDPROG) $(ROOTMANIFEST) $(ROOTSVCMETHOD) + +$(ROOTLIBVARPD): + $(INS.dir) + +$(ROOTLIBVARPD)/%: % $(ROOTLIBVARPD) + $(INS.file) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/cmd/varpd/svc-varpd b/usr/src/cmd/varpd/svc-varpd new file mode 100644 index 0000000000..c7483a033e --- /dev/null +++ b/usr/src/cmd/varpd/svc-varpd @@ -0,0 +1,32 @@ +#!/usr/bin/sh +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +. /lib/svc/share/smf_include.sh + +# +# For the time being, we're going to manually make sure that the +# overlay driver is loaded. We probably shouldn't do that in the long +# run, but it helps for bootstrapping +# +add_drv overlay 2>/dev/null + +/usr/lib/varpd/varpd +if [ $? = 0 ]; then + exit $SMF_EXIT_OK +else + exit $SMF_EXIT_ERR_FATAL +fi diff --git a/usr/src/cmd/varpd/varpd.c b/usr/src/cmd/varpd/varpd.c new file mode 100644 index 0000000000..8131604537 --- /dev/null +++ b/usr/src/cmd/varpd/varpd.c @@ -0,0 +1,526 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015 Joyent, Inc. + */ + +/* + * virtual arp daemon -- varpd + * + * The virtual arp daemon is the user land counterpart to the overlay driver. To + * truly understand its purpose and how it fits into things, you should read the + * overlay big theory statement in uts/common/io/overlay/overlay.c. + * + * varod's purpose it to provide a means for looking up the destination on the + * underlay network for a host on an overlay network and to also be a door + * server such that dladm(1M) via libdladm can configure and get useful status + * information. The heavy lifting is all done by libvarpd and the various lookup + * plugins. + * + * When varpd first starts up, we take of chdiring into /var/run/varpd, which is + * also where we create /var/run/varpd.door, our door server. After that we + * daemonize and only after we daemonize do we go ahead and load plugins. The + * reason that we don't load plugins before daemonizing is that they could very + * well be creating threads and thus lose them all. In general, we want to make + * things easier on our children and not require them to be fork safe. + * + * Once it's spun up, the main varpd thread sits in sigsuspend and really just + * hangs out waiting for something, libvarpd handles everything else. + */ + +#include <libvarpd.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <libgen.h> +#include <stdarg.h> +#include <stdlib.h> +#include <paths.h> +#include <limits.h> +#include <sys/corectl.h> +#include <signal.h> +#include <strings.h> +#include <sys/wait.h> +#include <unistd.h> +#include <thread.h> +#include <priv.h> +#include <libscf.h> + +#define VARPD_EXIT_REQUESTED 0 +#define VARPD_EXIT_FATAL 1 +#define VARPD_EXIT_USAGE 2 + +#define VARPD_RUNDIR "/var/run/varpd" +#define VARPD_DEFAULT_DOOR "/var/run/varpd/varpd.door" + +#define VARPD_PG "varpd" +#define VARPD_PROP_INC "include_path" + +static varpd_handle_t *varpd_handle; +static const char *varpd_pname; +static volatile boolean_t varpd_exit = B_FALSE; + +/* + * Debug builds are automatically wired up for umem debugging. + */ +#ifdef DEBUG +const char * +_umem_debug_init() +{ + return ("default,verbose"); +} + +const char * +_umem_logging_init(void) +{ + return ("fail,contents"); +} +#endif /* DEBUG */ + +static void +varpd_vwarn(FILE *out, const char *fmt, va_list ap) +{ + int error = errno; + + (void) fprintf(out, "%s: ", varpd_pname); + (void) vfprintf(out, fmt, ap); + + if (fmt[strlen(fmt) - 1] != '\n') + (void) fprintf(out, ": %s\n", strerror(error)); +} + +static void +varpd_fatal(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + varpd_vwarn(stderr, fmt, ap); + va_end(ap); + + exit(VARPD_EXIT_FATAL); +} + +static void +varpd_dfatal(int dfd, const char *fmt, ...) +{ + int status = VARPD_EXIT_FATAL; + va_list ap; + + va_start(ap, fmt); + varpd_vwarn(stdout, fmt, ap); + va_end(ap); + + /* Take a single shot at this */ + (void) write(dfd, &status, sizeof (status)); + exit(status); +} + +/* ARGSUSED */ +static int +varpd_plugin_walk_cb(varpd_handle_t *vph, const char *name, void *unused) +{ + (void) printf("loaded %s!\n", name); + return (0); +} + +static int +varpd_dir_setup(void) +{ + int fd; + + if (mkdir(VARPD_RUNDIR, 0700) != 0) { + if (errno != EEXIST) + varpd_fatal("failed to create %s: %s", VARPD_RUNDIR, + strerror(errno)); + } + + fd = open(VARPD_RUNDIR, O_RDONLY); + if (fd < 0) + varpd_fatal("failed to open %s: %s", VARPD_RUNDIR, + strerror(errno)); + + if (fchown(fd, UID_NETADM, GID_NETADM) != 0) + varpd_fatal("failed to chown %s: %s\n", VARPD_RUNDIR, + strerror(errno)); + + return (fd); +} + +/* + * Because varpd is generally run under SMF, we opt to keep its stdout and + * stderr to be whatever our parent set them up to be. + */ +static void +varpd_fd_setup(void) +{ + int dupfd; + + closefrom(STDERR_FILENO + 1); + dupfd = open(_PATH_DEVNULL, O_RDONLY); + if (dupfd < 0) + varpd_fatal("failed to open %s: %s", _PATH_DEVNULL, + strerror(errno)); + if (dup2(dupfd, STDIN_FILENO) == -1) + varpd_fatal("failed to dup out stdin: %s", strerror(errno)); +} + +/* + * We borrow fmd's daemonization style. Basically, the parent waits for the + * child to successfully set up a door and recover all of the old configurations + * before we say that we're good to go. + */ +static int +varpd_daemonize(int dirfd) +{ + char path[PATH_MAX]; + struct rlimit rlim; + sigset_t set, oset; + int estatus, pfds[2]; + pid_t child; + priv_set_t *pset; + + /* + * Set a per-process core path to be inside of /var/run/varpd. Make sure + * that we aren't limited in our dump size. + */ + (void) snprintf(path, sizeof (path), + "/var/run/varpd/core.%s.%%p", varpd_pname); + (void) core_set_process_path(path, strlen(path) + 1, getpid()); + + rlim.rlim_cur = RLIM_INFINITY; + rlim.rlim_max = RLIM_INFINITY; + (void) setrlimit(RLIMIT_CORE, &rlim); + + /* + * Claim as many file descriptors as the system will let us. + */ + if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { + rlim.rlim_cur = rlim.rlim_max; + (void) setrlimit(RLIMIT_NOFILE, &rlim); + } + + /* + * chdir /var/run/varpd + */ + if (fchdir(dirfd) != 0) + varpd_fatal("failed to chdir to %s", VARPD_RUNDIR); + + + /* + * At this point block all signals going in so we don't have the parent + * mistakingly exit when the child is running, but never block SIGABRT. + */ + if (sigfillset(&set) != 0) + abort(); + if (sigdelset(&set, SIGABRT) != 0) + abort(); + if (sigprocmask(SIG_BLOCK, &set, &oset) != 0) + abort(); + + /* + * Do the fork+setsid dance. + */ + if (pipe(pfds) != 0) + varpd_fatal("failed to create pipe for daemonizing"); + + if ((child = fork()) == -1) + varpd_fatal("failed to fork for daemonizing"); + + if (child != 0) { + /* We'll be exiting shortly, so allow for silent failure */ + (void) close(pfds[1]); + if (read(pfds[0], &estatus, sizeof (estatus)) == + sizeof (estatus)) + _exit(estatus); + + if (waitpid(child, &estatus, 0) == child && WIFEXITED(estatus)) + _exit(WEXITSTATUS(estatus)); + + _exit(VARPD_EXIT_FATAL); + } + + /* + * Drop privileges here. + * + * We should make sure we keep around PRIV_NET_PRIVADDR and + * PRIV_SYS_DLCONFIG, but drop everything else; however, keep basic + * privs and have our child drop them. + * + * We should also run as netadm:netadm and drop all of our groups. + */ + if (setgroups(0, NULL) != 0) + abort(); + if (setgid(GID_NETADM) == -1 || seteuid(UID_NETADM) == -1) + abort(); + if ((pset = priv_allocset()) == NULL) + abort(); + priv_basicset(pset); + if (priv_delset(pset, PRIV_PROC_EXEC) == -1 || + priv_delset(pset, PRIV_PROC_INFO) == -1 || + priv_delset(pset, PRIV_PROC_FORK) == -1 || + priv_delset(pset, PRIV_PROC_SESSION) == -1 || + priv_delset(pset, PRIV_FILE_LINK_ANY) == -1 || + priv_addset(pset, PRIV_SYS_DL_CONFIG) == -1 || + priv_addset(pset, PRIV_NET_PRIVADDR) == -1) { + abort(); + } + /* + * Remove privs from the permitted set. That will cause them to be + * removed from the effective set. We want to make sure that in the case + * of a vulnerability, something can't get back in here and wreak more + * havoc. But if we want non-basic privs in the effective set, we have + * to request them explicitly. + */ + if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) == -1) + abort(); + if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pset) == -1) + abort(); + + priv_freeset(pset); + + if (close(pfds[0]) != 0) + abort(); + if (setsid() == -1) + abort(); + if (sigprocmask(SIG_SETMASK, &oset, NULL) != 0) + abort(); + (void) umask(0022); + + return (pfds[1]); +} + +static int +varpd_setup_lookup_threads(void) +{ + int ret; + long i, ncpus = sysconf(_SC_NPROCESSORS_ONLN) * 2 + 1; + + if (ncpus <= 0) + abort(); + for (i = 0; i < ncpus; i++) { + thread_t thr; + + ret = thr_create(NULL, 0, + (void *(*)(void *))libvarpd_overlay_lookup_run, + varpd_handle, THR_DETACHED | THR_DAEMON, &thr); + if (ret != 0) + return (ret); + } + + return (0); +} + +static void +varpd_cleanup(void) +{ + varpd_exit = B_TRUE; +} + +/* + * Load default information from SMF and apply any of if necessary. We recognize + * the following properties: + * + * varpd/include_path Treat these as a series of -i options. + * + * If we're not under SMF, just move on. + */ +static void +varpd_load_smf(int dfd) +{ + char *fmri, *inc; + scf_simple_prop_t *prop; + + if ((fmri = getenv("SMF_FMRI")) == NULL) + return; + + if ((prop = scf_simple_prop_get(NULL, fmri, VARPD_PG, + VARPD_PROP_INC)) == NULL) + return; + + while ((inc = scf_simple_prop_next_astring(prop)) != NULL) { + int err = libvarpd_plugin_load(varpd_handle, inc); + if (err != 0) { + varpd_dfatal(dfd, "failed to load from %s: %s\n", + inc, strerror(err)); + } + } + + scf_simple_prop_free(prop); +} + +/* + * There are a bunch of things we need to do to be a proper daemon here. + * + * o Ensure that /var/run/varpd exists or create it + * o make stdin /dev/null (stdout?) + * o Ensure any other fds that we somehow inherited are closed, eg. + * closefrom() + * o Properly daemonize + * o Mask all signals except sigabrt before creating our first door -- all + * other doors will inherit from that. + * o Have the main thread sigsuspend looking for most things that are + * actionable... + */ +int +main(int argc, char *argv[]) +{ + int err, c, dirfd, dfd, i; + const char *doorpath = VARPD_DEFAULT_DOOR; + sigset_t set; + struct sigaction act; + int nincpath = 0, nextincpath = 0; + char **incpath = NULL; + + varpd_pname = basename(argv[0]); + + /* + * We want to clean up our file descriptors before we do anything else + * as we can't assume that libvarpd won't open file descriptors, etc. + */ + varpd_fd_setup(); + + if ((err = libvarpd_create(&varpd_handle)) != 0) { + varpd_fatal("failed to open a libvarpd handle"); + return (1); + } + + while ((c = getopt(argc, argv, ":i:d:")) != -1) { + switch (c) { + case 'i': + if (nextincpath == nincpath) { + if (nincpath == 0) + nincpath = 16; + else + nincpath *= 2; + incpath = realloc(incpath, sizeof (char *) * + nincpath); + if (incpath == NULL) { + (void) fprintf(stderr, "failed to " + "allocate memory for the %dth " + "-I option: %s\n", nextincpath + 1, + strerror(errno)); + } + + } + incpath[nextincpath] = optarg; + nextincpath++; + break; + case 'd': + doorpath = optarg; + break; + default: + (void) fprintf(stderr, "unknown option: %c\n", c); + return (1); + } + } + + dirfd = varpd_dir_setup(); + + (void) libvarpd_plugin_walk(varpd_handle, varpd_plugin_walk_cb, NULL); + + dfd = varpd_daemonize(dirfd); + + /* + * Now that we're in the child, go ahead and load all of our plug-ins. + * We do this, in part, because these plug-ins may need threads of their + * own and fork won't preserve those and we'd rather the plug-ins don't + * have to learn about fork-handlers. + */ + for (i = 0; i < nextincpath; i++) { + err = libvarpd_plugin_load(varpd_handle, incpath[i]); + if (err != 0) { + varpd_dfatal(dfd, "failed to load from %s: %s\n", + incpath[i], strerror(err)); + } + } + + varpd_load_smf(dfd); + + if ((err = libvarpd_persist_enable(varpd_handle, VARPD_RUNDIR)) != 0) + varpd_dfatal(dfd, "failed to enable varpd persistence: %s\n", + strerror(err)); + + if ((err = libvarpd_persist_restore(varpd_handle)) != 0) + varpd_dfatal(dfd, "failed to enable varpd persistence: %s\n", + strerror(err)); + + /* + * The ur-door thread will inherit from this signal mask. So set it to + * what we want before doing anything else. In addition, so will our + * threads that handle varpd lookups. + */ + if (sigfillset(&set) != 0) + varpd_dfatal(dfd, "failed to fill a signal set..."); + + if (sigdelset(&set, SIGABRT) != 0) + varpd_dfatal(dfd, "failed to unmask SIGABRT"); + + if (sigprocmask(SIG_BLOCK, &set, NULL) != 0) + varpd_dfatal(dfd, "failed to set our door signal mask"); + + if ((err = varpd_setup_lookup_threads()) != 0) + varpd_dfatal(dfd, "failed to create lookup threads: %s\n", + strerror(err)); + + if ((err = libvarpd_door_server_create(varpd_handle, doorpath)) != 0) + varpd_dfatal(dfd, "failed to create door server at %s: %s\n", + doorpath, strerror(err)); + + /* + * At this point, finish up signal intialization and finally go ahead, + * notify the parent that we're okay, and enter the sigsuspend loop. + */ + bzero(&act, sizeof (struct sigaction)); + act.sa_handler = varpd_cleanup; + if (sigfillset(&act.sa_mask) != 0) + varpd_dfatal(dfd, "failed to fill sigaction mask"); + act.sa_flags = 0; + if (sigaction(SIGHUP, &act, NULL) != 0) + varpd_dfatal(dfd, "failed to register HUP handler"); + if (sigdelset(&set, SIGHUP) != 0) + varpd_dfatal(dfd, "failed to remove HUP from mask"); + if (sigaction(SIGQUIT, &act, NULL) != 0) + varpd_dfatal(dfd, "failed to register QUIT handler"); + if (sigdelset(&set, SIGQUIT) != 0) + varpd_dfatal(dfd, "failed to remove QUIT from mask"); + if (sigaction(SIGINT, &act, NULL) != 0) + varpd_dfatal(dfd, "failed to register INT handler"); + if (sigdelset(&set, SIGINT) != 0) + varpd_dfatal(dfd, "failed to remove INT from mask"); + if (sigaction(SIGTERM, &act, NULL) != 0) + varpd_dfatal(dfd, "failed to register TERM handler"); + if (sigdelset(&set, SIGTERM) != 0) + varpd_dfatal(dfd, "failed to remove TERM from mask"); + + err = 0; + (void) write(dfd, &err, sizeof (err)); + (void) close(dfd); + + for (;;) { + if (sigsuspend(&set) == -1) + if (errno == EFAULT) + abort(); + if (varpd_exit == B_TRUE) + break; + } + + libvarpd_door_server_destroy(varpd_handle); + libvarpd_destroy(varpd_handle); + + return (VARPD_EXIT_REQUESTED); +} diff --git a/usr/src/cmd/varpd/varpd.xml b/usr/src/cmd/varpd/varpd.xml new file mode 100644 index 0000000000..8ea855b438 --- /dev/null +++ b/usr/src/cmd/varpd/varpd.xml @@ -0,0 +1,60 @@ +<?xml version="1.0"?> +<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> +<!-- +This file and its contents are supplied under the terms of the +Common Development and Distribution License ("CDDL"), version 1.0. +You may only use this file in accordance with the terms of version +1.0 of the CDDL. + +A full copy of the text of the CDDL should have accompanied this +source. A copy of the CDDL is also available via the Internet at +http://www.illumos.org/license/CDDL. + +Copyright 2015, Joyent, Inc. +--> + +<service_bundle type="manifest" name="illumos:varpd" > + + <service name="network/varpd" type="service" version="1" > + + <create_default_instance enabled="true" /> + + <single_instance/> + + <dependency name="varpd-network-physical" + grouping="require_all" + restart_on="none" + type="service"> + <service_fmri value="svc:/network/physical:default" /> + </dependency> + + <exec_method + type="method" + name="start" + exec="/lib/svc/method/svc-varpd" + timeout_seconds="60" /> + + <exec_method + type="method" + name="stop" + exec=":kill" + timeout_seconds="10" /> + + <property_group name='varpd' type='application'> + <property name='include_path' type='astring'> + <astring_list> + <value_node value='/usr/lib/varpd'/> + </astring_list> + </property> + </property_group> + + <stability value='Unstable' /> + + <template> + <common_name> + <loctext xml:lang="C">virutal ARP daemon + </loctext> + </common_name> + </template> + </service> +</service_bundle> diff --git a/usr/src/cmd/vi/port/Makefile b/usr/src/cmd/vi/port/Makefile index 268dd752a6..8e223d98e8 100644 --- a/usr/src/cmd/vi/port/Makefile +++ b/usr/src/cmd/vi/port/Makefile @@ -75,6 +75,9 @@ $(XPG6) := CFLAGS += -DXPG4 -DXPG6 -I$(SRC)/lib/libc/inc CPPFLAGS += -DUSG -DSTDIO -DVMUNIX -DTABS=8 -DSINGLE -DTAG_STACK +# vi intentionally uses foo[-1] as a sentinal value to q*column() +$(__GNUC4)CERRWARN += -_gcc=-Wno-array-bounds + # vi maintains its own versions of various routines from libc and libcurses, # so localize all symbols to avoid name space collisions. LDFLAGS += $(MAPFILE.NGB:%=-M%) diff --git a/usr/src/cmd/vi/port/ex_cmdsub.c b/usr/src/cmd/vi/port/ex_cmdsub.c index 0260d334fe..00bdcefccb 100644 --- a/usr/src/cmd/vi/port/ex_cmdsub.c +++ b/usr/src/cmd/vi/port/ex_cmdsub.c @@ -1735,7 +1735,7 @@ char *prompt; /* In ex mode, let the system hassle with setting no echo */ if (!inopen) - return (unsigned char *)getpass(prompt); + return (unsigned char *)getpass((const char *)prompt); viprintf("%s", prompt); flush(); for (p=pbuf; (c = getkey())!='\n' && c!=EOF && c!='\r';) { if (p < &pbuf[8]) diff --git a/usr/src/cmd/vndadm/Makefile b/usr/src/cmd/vndadm/Makefile new file mode 100644 index 0000000000..aa9c22d296 --- /dev/null +++ b/usr/src/cmd/vndadm/Makefile @@ -0,0 +1,65 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +PROG= vndadm +OBJS = vndadm.o +SRCS = $(OBJS:%.o=../%.c) + + +include ../Makefile.cmd +include ../Makefile.ctf + +CLEANFILES += $(OBJS) +CFLAGS += $(CCVERBOSE) +LDLIBS += -lvnd +LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2 +C99MODE= -xc99=%all +C99LMODE= -Xc99=%all + +all := TARGET += all +clean := TARGET += clean +clobber := TARGET += clobber +install := TARGET += install +lint := TARGET += lint + +SUBDIRS = test + +.KEEP_STATE: + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +clean: $(SUBDIRS) + -$(RM) $(CLEANFILES) + +lint: lint_PROG $(SUBDIRS) + +%.o: ../%.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + +clobber: clean $(SUBDIRS) + $(RM) $(PROG) + +install: $(PROG) $(ROOTUSRSBINPROG) $(SUBDIRS) + + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/cmd/vndadm/test/Makefile b/usr/src/cmd/vndadm/test/Makefile new file mode 100644 index 0000000000..12ef2c3a3c --- /dev/null +++ b/usr/src/cmd/vndadm/test/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +SUBDIRS = scripts tst + +include Makefile.subdirs +include Makefile.com diff --git a/usr/src/cmd/vndadm/test/Makefile.com b/usr/src/cmd/vndadm/test/Makefile.com new file mode 100644 index 0000000000..cb096952ca --- /dev/null +++ b/usr/src/cmd/vndadm/test/Makefile.com @@ -0,0 +1,43 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +include $(SRC)/Makefile.master +include $(SRC)/cmd/Makefile.cmd + +# +# Force c99 for everything +# +C99MODE= -xc99=%all +C99LMODE= -Xc99=%all + +# +# Deal with odd lint bits. +# +LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2 + +# +# Install related definitions +# +ROOTOPTPKG = $(ROOT)/opt/vndtest +ROOTBIN = $(ROOTOPTPKG)/bin +ROOTTST = $(ROOTOPTPKG)/tst +ROOTTSTDIR = $(ROOTTST)/$(TSTDIR) +ROOTTSTEXES = $(EXETESTS:%=$(ROOTTSTDIR)/%) +ROOTTSTSH = $(SHTESTS:%=$(ROOTTSTDIR)/%) +ROOTOUT = $(OUTFILES:%=$(ROOTTSTDIR)/%) +ROOTTESTS = $(ROOTTSTEXES) $(ROOTTSTSH) $(ROOTOUT) +FILEMODE = 0555 +LDLIBS = $(LDLIBS.cmd) +LINTEXE = $(EXETESTS:%.exe=%.exe.ln) diff --git a/usr/src/cmd/vndadm/test/Makefile.subdirs b/usr/src/cmd/vndadm/test/Makefile.subdirs new file mode 100644 index 0000000000..957448c23b --- /dev/null +++ b/usr/src/cmd/vndadm/test/Makefile.subdirs @@ -0,0 +1,29 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +.KEEP_STATE: + +all := TARGET += all +clean := TARGET += clean +clobber := TARGET += clobber +install := TARGET += install +lint := TARGET += lint + +all clean clobber install lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/cmd/vndadm/test/Makefile.targ b/usr/src/cmd/vndadm/test/Makefile.targ new file mode 100644 index 0000000000..bcbd3c8f35 --- /dev/null +++ b/usr/src/cmd/vndadm/test/Makefile.targ @@ -0,0 +1,59 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +$(ROOTOPTPKG): + $(INS.dir) + +$(ROOTBIN): $(ROOTOPTPKG) + $(INS.dir) + +$(ROOTBIN)/%: %.ksh $(ROOTBIN) + $(INS.rename) + +$(ROOTTST): $(ROOTOPTPKG) + $(INS.dir) + +$(ROOTTSTDIR): $(ROOTTST) + $(INS.dir) + +$(ROOTTSTDIR)/%.ksh: %.ksh $(ROOTTSTDIR) + $(INS.file) + +$(ROOTTSTDIR)/%.out: %.out $(ROOTTSTDIR) + $(INS.file) + +%.o: %.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + +%.exe: %.o $(SUPOBJS) + $(LINK.c) -o $@ $< $(SUPOBJS) $(LDLIBS) + $(POST_PROCESS) + +$(ROOTTSTDIR)/%.exe: %.exe $(ROOTTSTDIR) + $(INS.file) + +all: install + +%.exe.ln: %.c $(SUPOBJS) + $(LINT.c) $< $(LDLIBS) + +lint: $(LINTEXE) + +clean: + -$(RM) *.o $(CLEANFILES) + +clobber: clean + -$(RM) $(CLOBBERFILES) diff --git a/usr/src/cmd/vndadm/test/scripts/Makefile b/usr/src/cmd/vndadm/test/scripts/Makefile new file mode 100644 index 0000000000..d0f58918f9 --- /dev/null +++ b/usr/src/cmd/vndadm/test/scripts/Makefile @@ -0,0 +1,28 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +include ../Makefile.com + +SRCS = vndtest +SCRIPTS = $(SRCS:%=$(ROOTBIN)/%) + +SCRIPTS := FILEMODE = 0555 +CLOBBERFILES = $(SCRIPTS) + +install: $(SCRIPTS) + +lint: + +include ../Makefile.targ diff --git a/usr/src/cmd/vndadm/test/scripts/vndtest.ksh b/usr/src/cmd/vndadm/test/scripts/vndtest.ksh new file mode 100755 index 0000000000..1167a64802 --- /dev/null +++ b/usr/src/cmd/vndadm/test/scripts/vndtest.ksh @@ -0,0 +1,300 @@ +#!/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# vnd test suite driver +# +unalias -a + +vt_arg0=$(basename $0) +vt_root="$(dirname $0)/.." +vt_ksh="/usr/bin/ksh" +vt_outdir= +vt_keep= +vt_all= +vt_tests= +vt_stub= +vt_vnics="vndtest1 vndtest2 vndtest3 vndtest4 vndtest5" +vt_tnum=0 +vt_tfail=0 +vt_tsuc=0 + +function usage +{ + typeset msg="$*" + [[ -z "$msg" ]] || echo "$msg" 2>&1 + cat <<USAGE >&2 +Usage: $vt_arg0 [ -o dir ] [ -k ] [ -a | test ... ] + + -o dir Sets 'dir' as the output directory + -a Runs all tests, ignores tests passed in + -k Keep output from all tests, not just failures + -m mdb binary to test +USAGE + exit 2 +} + +function fatal +{ + typeset msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "$vt_arg0: $msg" >&2 + exit 1 +} + +function setup_outdir +{ + vt_outdir="$vt_outdir/$vt_arg0.$$" + mkdir -p $vt_outdir || fatal "failed to make output dir $vt_outdir" +} + +function setup_etherstub +{ + vt_ether="vndstub$$" + + dladm create-etherstub -t $vt_ether || \ + fatal "failed to create etherstub" +} + +function cleanup_vnd +{ + typeset over=$1 + typeset vnddevs vn + + vnddevs=$(vndadm list -p -d: -o datalink,name) + [[ $? -eq 0 ]] || fatal "failed to list vnics" + for v in $vnddevs; do + vn=$(echo $v | awk 'BEGIN{ FS=":"} + { if ($1 == targ) { print $2 } }' targ=$over) + [[ -z "$vn" ]] && continue + vndadm destroy $vn || fatal "failed to destroy $vn" + done +} + +function create_vnics +{ + for n in $vt_vnics; do + dladm create-vnic -t -l $vt_ether $n || fatal \ + "failed to create vnic $n over $vt_ether" + done +} + +function cleanup_vnics +{ + typeset nics vn + + nics=$(dladm show-vnic -p -o over,link) + [[ $? -eq 0 ]] || fatal "failed to list vnics" + for n in $nics; do + vn=$(echo $n | awk 'BEGIN{ FS=":"} + { if ($1 == targ) { print $2 } }' targ=$vt_ether ) + [[ -z "$vn" ]] && continue + cleanup_vnd $vn + # + # There may or may not be an IP device on our nics... + # + ifconfig $vn down unplumb 2>/dev/null || /bin/true + dladm delete-vnic $vn || fatal "failed to delete vnic $n" + done + +} + +function cleanup_etherstub +{ + cleanup_vnics + dladm delete-etherstub -t $vt_ether || \ + fatal "failed to delete etherstub" +} + +function run_single +{ + typeset name=$1 + typeset expect base ext exe command odir res reason + typeset iserr + + [[ -z "$name" ]] && fail "missing test to run" + base=${name##*/} + ext=${base##*.} + expect=${base%%.*} + odir="$vt_outdir/current" + [[ -z "$ext" ]] && fatal "found test without ext: $name" + [[ -z "$expect" ]] && fatal "found test without prefix: $name" + + [[ "$expect" == "create" || "$expect" == "ecreate" ]] && create_vnics + if [[ "$expect" == "err" || "$expect" == "ecreate" ]]; then + iserr="yup" + else + iserr="" + fi + + case "$ext" in + "ksh") + command="$vt_ksh ./$base" + ;; + "exe") + command="./$base" + ;; + "out") + # + # This is the file format for checking output against. + # + return 0 + ;; + *) + echo "skipping test $name (unknown extensino)" + return 0 + ;; + esac + + echo "Executing test $name ... \c" + mkdir -p "$odir" >/dev/null || fatal "can't make output directory" + cd $(dirname $name) || fatal "failed to enter test directory" + $command $vt_vnics > "$odir/stdout" 2>"$odir/stderr" + res=$? + cd - > /dev/null || fatal "failed to leave test directory" + + if [[ -f "$name.out" ]] && \ + ! diff "$name.out" "$odir/stdout" >/dev/null; then + cp $name.out $odir/$base.out + reason="stdout mismatch" + elif [[ -n "$iserr" && $res -eq 0 ]]; then + reason="test exited $res, not non-zero" + elif [[ -z "$iserr" && $res -ne 0 ]]; then + reason="test exited $res, not zero" + fi + + if [[ -n "$reason" ]]; then + echo "$reason" + ((vt_tfail++)) + mv "$odir" "$vt_outdir/failure.$vt_tfail" || fatal \ + "failed to move test output directory" + cp "$name" "$vt_outdir/failure.$vt_tfail/$(basename $name)" || \ + fatal "failed to copy test into output directory" + else + echo "passed" + ((vt_tsuc++)) + mv "$odir" "$vt_outdir/success.$vt_tsuc" || fatal \ + "failed to move test directory" + fi + + [[ "$expect" == "create" || "$expect" == "ecreate" ]] && cleanup_vnics + + ((vt_tnum++)) +} + +function run_all +{ + typeset tests t dir + + cd $vt_root || fatal "failed to enter root test directory" + tests=$(ls -1 */*/@(ecreate|create|tst|err).*.@(ksh|exe)) + cd - > /dev/null + for t in $tests; do + run_single $t + done +} + +function welcome +{ + cat <<WELCOME +Starting tests... +output directory: $vt_outdir +WELCOME +} + +function cleanup +{ + [[ -n "$vt_keep" ]] && return + rm -rf "$vt_outdir"/success.* || fatal \ + "failed to remove successful test cases" + if [[ $vt_tfail -eq 0 ]]; then + rmdir "$vt_outdir" || fatal \ + "failed to remove test output directory" + fi +} + +function goodbye +{ + cat <<EOF + +------------- +Results +------------- + +Tests passed: $vt_tsuc +Tests failed: $vt_tfail +Tests ran: $vt_tnum + +EOF + if [[ $vt_tfail -eq 0 ]]; then + echo "Congrats, vnd isn't completely broken, the tests pass". + else + echo "Some tests failed, you have some work to do." + fi +} + +while getopts ":ahko:m:" c $@; do + case "$c" in + a) + vt_all="y" + ;; + k) + vt_keep="y" + ;; + o) + vt_outdir="$OPTARG" + ;; + h) + usage + ;; + :) + usage "option requires an argument -- $OPTARG" + ;; + *) + usage "invalid option -- $OPTARG" + ;; + esac +done + +shift $((OPTIND-1)) + +[[ $(zonename) != "global" ]] && fatal "vndtest only runs in the global zone" + +[[ -z "$vt_all" && $# == 0 ]] && usage "no tests to run" + +[[ -z "$vt_outdir" ]] && vt_outdir="$PWD" + +setup_outdir +setup_etherstub +welcome + +if [[ ! -z "$vt_all" ]]; then + run_all +else + for t in $@; do + [[ -f $t ]] || fatal "cannot find test $t" + run_single $t + done +fi + +cleanup_etherstub +goodbye +cleanup + +# +# Exit 1 if we have tests that return non-zero +# +[[ $vt_tfai -eq 0 ]] diff --git a/usr/src/cmd/vndadm/test/tst/Makefile b/usr/src/cmd/vndadm/test/tst/Makefile new file mode 100644 index 0000000000..9b1ba29429 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +SUBDIRS = cmd dld ioctl lib + +include ../Makefile.subdirs diff --git a/usr/src/cmd/vndadm/test/tst/cmd/Makefile b/usr/src/cmd/vndadm/test/tst/cmd/Makefile new file mode 100644 index 0000000000..1ca20bf749 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/Makefile @@ -0,0 +1,34 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +TSTDIR = cmd +COMMONSH = cmd.common.ksh +SHTESTS = $(COMMONSH) \ + create.list.ksh \ + create.sdev.ksh \ + create.setbuf.ksh \ + ecreate.destroy.ksh \ + ecreate.setbadprop.ksh \ + ecreate.setbadvalue.ksh \ + ecreate.setbuftoobig.ksh \ + ecreate.setrdonlyprop.ksh + +OUTFILES = create.list.ksh.out + +include ../../Makefile.com + +install: $(ROOTTESTS) + +include ../../Makefile.targ diff --git a/usr/src/cmd/vndadm/test/tst/cmd/cmd.common.ksh b/usr/src/cmd/vndadm/test/tst/cmd/cmd.common.ksh new file mode 100644 index 0000000000..31e4e8bf5c --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/cmd.common.ksh @@ -0,0 +1,33 @@ +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Common ksh-based utilities +# + +vt_arg0=$(basename $0) + +function fatal +{ + typeset msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "$vt_arg0: $msg" >&2 + exit 1 +} + +[[ -z "$1" ]] && fatal "missing required vnic" +[[ -z "$2" ]] && fatal "missing required vnic" +[[ -z "$3" ]] && fatal "missing required vnic" diff --git a/usr/src/cmd/vndadm/test/tst/cmd/create.list.ksh b/usr/src/cmd/vndadm/test/tst/cmd/create.list.ksh new file mode 100644 index 0000000000..fdec9a85be --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/create.list.ksh @@ -0,0 +1,30 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Basic device listing +# + +. ./cmd.common.ksh + +# +# Use what we hope is a relatively unique name +# +cl_name="triforceofcourage0" +vndadm create -l $1 $cl_name || fatal "failed to create vnd device" +vndadm list -p -o name,zone $cl_name +vndadm list -p -d: -o zone,name $cl_name +vndadm destroy $cl_name || fatal "failed to destroy vnd device" diff --git a/usr/src/cmd/vndadm/test/tst/cmd/create.list.ksh.out b/usr/src/cmd/vndadm/test/tst/cmd/create.list.ksh.out new file mode 100644 index 0000000000..d208b38aab --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/create.list.ksh.out @@ -0,0 +1,2 @@ +triforceofcourage0 global +global:triforceofcourage0 diff --git a/usr/src/cmd/vndadm/test/tst/cmd/create.sdev.ksh b/usr/src/cmd/vndadm/test/tst/cmd/create.sdev.ksh new file mode 100644 index 0000000000..b816ade1de --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/create.sdev.ksh @@ -0,0 +1,25 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Verify that our sdev links exist +# + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd" +[[ -c /dev/vnd/$1 ]] || fatal "missing link" +[[ -c /dev/vnd/zone/$(zonename)/$1 ]] || fatal "missing per-zone link" diff --git a/usr/src/cmd/vndadm/test/tst/cmd/create.setbuf.ksh b/usr/src/cmd/vndadm/test/tst/cmd/create.setbuf.ksh new file mode 100644 index 0000000000..d50edbead4 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/create.setbuf.ksh @@ -0,0 +1,34 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Set and validate the buffer size properties. Valiate that we can set +# the value using the various number analogues, eg. 1024K, etc. +# +set -o pipefail + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd device" +vndadm set $1 rxbuf=1M +cur=$(vndadm get -p $1 rxbuf | nawk '{ print $4 }') +[[ $? -eq 0 ]] || fatal "failed to get rxbuf" +[[ $cur -eq 1048576 ]] || fatal "rxbuf is $cur, not 1M" + +vndadm set $1 txbuf=1024K +cur=$(vndadm get -p $1 rxbuf | nawk '{ print $4 }') +[[ $? -eq 0 ]] || fatal "failed to get txbuf" +[[ $cur -eq 1048576 ]] || fatal "txbuf is $cur, not 1M" diff --git a/usr/src/cmd/vndadm/test/tst/cmd/ecreate.destroy.ksh b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.destroy.ksh new file mode 100644 index 0000000000..e3c4931018 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.destroy.ksh @@ -0,0 +1,25 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure that destroy on a previously destroyed link fails +# + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd device" +vndadm destroy $1 || fatal "failed to destroy vnd device" +vndadm destroy $1 diff --git a/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbadprop.ksh b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbadprop.ksh new file mode 100644 index 0000000000..30c27575b1 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbadprop.ksh @@ -0,0 +1,24 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure that we can't set a non-existant proprety +# + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd device" +vndadm set $1 ganon=ganondorf diff --git a/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbadvalue.ksh b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbadvalue.ksh new file mode 100644 index 0000000000..056b24a817 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbadvalue.ksh @@ -0,0 +1,24 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure that we can't set something to a garbage value +# + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd device" +vndadm set $1 rxbuf=hello diff --git a/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbuftoobig.ksh b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbuftoobig.ksh new file mode 100644 index 0000000000..551e20461c --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setbuftoobig.ksh @@ -0,0 +1,24 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure that we can't set a buffer value to a ridiculous size +# + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd device" +vndadm set $1 rxsize=1T diff --git a/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setrdonlyprop.ksh b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setrdonlyprop.ksh new file mode 100644 index 0000000000..4beb53e227 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/cmd/ecreate.setrdonlyprop.ksh @@ -0,0 +1,24 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure that we can't set a read only property. +# + +. ./cmd.common.ksh + +vndadm create $1 || fatal "failed to bring up vnd device" +vndadm set $1 mintu=100 diff --git a/usr/src/cmd/vndadm/test/tst/dld/Makefile b/usr/src/cmd/vndadm/test/tst/dld/Makefile new file mode 100644 index 0000000000..3088812630 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/dld/Makefile @@ -0,0 +1,27 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +TSTDIR = dld +COMMONSH = dld.common.ksh +SHTESTS = $(COMMONSH) \ + ecreate.ipfirst.ksh \ + ecreate.vndfirst.ksh \ + create.reuse.ksh + +include ../../Makefile.com + +install: $(ROOTTESTS) + +include ../../Makefile.targ diff --git a/usr/src/cmd/vndadm/test/tst/dld/create.reuse.ksh b/usr/src/cmd/vndadm/test/tst/dld/create.reuse.ksh new file mode 100644 index 0000000000..bc2ffde7f6 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/dld/create.reuse.ksh @@ -0,0 +1,31 @@ +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure that we can reuse a data link +# + +. ./dld.common.ksh + +dld_nic=$1 +[[ -z "$1" ]] && fatal "missing required vnic" + +vndadm create $dld_nic || fatal "failed to bring up vnd" +vndadm destroy $dld_nic || fatal "failed to bring down vnd" +ifconfig $dld_nic plumb up || fatal "failed to bring up IP" +ifconfig $dld_nic down unplumb || fatal "failed to bring down IP" +vndadm create $dld_nic || fatal "failed to bring up vnd" +vndadm destroy $dld_nic || fatal "failed to bring down vnd" diff --git a/usr/src/cmd/vndadm/test/tst/dld/dld.common.ksh b/usr/src/cmd/vndadm/test/tst/dld/dld.common.ksh new file mode 100644 index 0000000000..7a2e0a8e2b --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/dld/dld.common.ksh @@ -0,0 +1,29 @@ +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Common ksh-based utilities +# + +vt_arg0=$(basename $0) + +function fatal +{ + typeset msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "$vt_arg0: $msg" >&2 + exit 1 +} diff --git a/usr/src/cmd/vndadm/test/tst/dld/ecreate.ipfirst.ksh b/usr/src/cmd/vndadm/test/tst/dld/ecreate.ipfirst.ksh new file mode 100644 index 0000000000..e6409781cb --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/dld/ecreate.ipfirst.ksh @@ -0,0 +1,27 @@ +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure vnd fails to come up when IP is up +# + +. ./dld.common.ksh + +dld_nic=$1 +[[ -z "$1" ]] && fatal "missing required vnic" + +ifconfig $dld_nic plumb up || fatal "failed to bring up IP" +vndadm create $dld_nic diff --git a/usr/src/cmd/vndadm/test/tst/dld/ecreate.vndfirst.ksh b/usr/src/cmd/vndadm/test/tst/dld/ecreate.vndfirst.ksh new file mode 100644 index 0000000000..ee7a13c09c --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/dld/ecreate.vndfirst.ksh @@ -0,0 +1,27 @@ +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Make sure IP fails to come up when vnd is up +# + +. ./dld.common.ksh + +dld_nic=$1 +[[ -z "$1" ]] && fatal "missing required vnic" + +vndadm create $dld_nic || fatal "failed to bring up vnd" +ifconfig $dld_nic plumb up diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/Makefile b/usr/src/cmd/vndadm/test/tst/ioctl/Makefile new file mode 100644 index 0000000000..fe074f32b0 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/Makefile @@ -0,0 +1,49 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +TSTDIR = ioctl +EXETESTS = \ + create.attach.exe \ + create.attachnolink.exe \ + create.badlinkname.exe \ + create.doublelink.exe \ + create.gioctlattach.exe \ + create.link.exe \ + create.linkexists.exe \ + create.ngioctlfault.exe \ + create.nopriv1.exe \ + create.nopriv2.exe \ + create.nopriv3.exe \ + create.nopriv4.exe \ + create.olink.exe \ + create.olinknopriv.exe \ + create.rmenolink.exe \ + tst.attachrdonly.exe \ + tst.basicopenctl.exe \ + tst.badioctl.exe \ + tst.gioctlfault.exe \ + tst.gioctlnattach.exe \ + tst.openctlbadflags.exe +SHTESTS = \ + tst.iocsize.ksh +SUPBOBJS = + +CLOBBERFILES = $(EXETESTS) + +include ../../Makefile.com + +install: $(ROOTTESTS) + +include ../../Makefile.targ diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.attach.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.attach.c new file mode 100644 index 0000000000..d7bca5cce3 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.attach.c @@ -0,0 +1,63 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Simply attach a nic + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.attachnolink.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.attachnolink.c new file mode 100644 index 0000000000..43c6c99af5 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.attachnolink.c @@ -0,0 +1,67 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Try to attach to a non-existant vnic + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + /* + * All datalink names have numbers, so we can pick a datalink which + * doesn't exist by not using numbers... + */ + (void) strlcpy(via.via_name, "enolink", VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == -1); + assert(via.via_errno == VND_E_NODATALINK); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.badlinkname.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.badlinkname.c new file mode 100644 index 0000000000..e3a067d5ce --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.badlinkname.c @@ -0,0 +1,119 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Test that we can't link a nic with invalid names + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +static const char *names[] = { + /* Reserved names */ + "ctl", + "zone", + /* Invalid characters */ + "The fight of the century", + "Link/Ganon", + "happens@7pm", + "#testing", + "asdf!!", + "power&courage&wisdom", + "over9000?", + "you're", + "100$", + "(function", + "x)", + "2^128", + "1++", + "No.", + "99%", + "*****", + "r|m", + "=0", + "`p0", + "goodbye~", + "however;", + "\"hesaid", + "shesaid\'", + /* emoji pile of poo */ + "\xF0\x9F\x92\xA9", + NULL +}; + +int +main(int argc, const char *argv[]) +{ + int fd, ret, i; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + vnd_ioc_unlink_t viu; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + for (i = 0; names[i] != NULL; i++) { + (void) strlcpy(vil.vil_name, names[i], VND_NAMELEN); + (void) fprintf(stderr, "Trying to create [%s]\n", names[i]); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == -1); + assert(vil.vil_errno == VND_E_BADNAME); + } + + /* Finally, the missing null terminator */ + for (i = 0; i < VND_NAMELEN; i++) + vil.vil_name[i] = 'a'; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == -1); + assert(vil.vil_errno == VND_E_BADNAME); + + viu.viu_errno = 0; + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(ret == -1); + assert(viu.viu_errno == VND_E_NOTLINKED); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.doublelink.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.doublelink.c new file mode 100644 index 0000000000..dcf4f311e9 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.doublelink.c @@ -0,0 +1,82 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Link a nic, first should work, second will fail. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + vnd_ioc_unlink_t viu; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == 0); + assert(vil.vil_errno == 0); + + (void) strlcpy(vil.vil_name, "dup", VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == -1); + assert(vil.vil_errno == VND_E_LINKED); + viu.viu_errno = 0; + + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(ret == 0); + assert(viu.viu_errno == 0); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.gioctlattach.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.gioctlattach.c new file mode 100644 index 0000000000..3d6f43377b --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.gioctlattach.c @@ -0,0 +1,69 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Ensure that we can't run global ioctls on an attached handle + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + via.via_name[0] = 'a'; + via.via_name[1] = '\0'; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == -1); + assert(via.via_errno == VND_E_ATTACHED); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.link.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.link.c new file mode 100644 index 0000000000..16569d58cd --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.link.c @@ -0,0 +1,76 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Link a nic + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + vnd_ioc_unlink_t viu; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == 0); + assert(vil.vil_errno == 0); + + viu.viu_errno = 0; + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(ret == 0); + assert(viu.viu_errno == 0); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.linkexists.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.linkexists.c new file mode 100644 index 0000000000..4e3be0db5d --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.linkexists.c @@ -0,0 +1,90 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Try to create two devices with the same link name. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, fd2, ret; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + vnd_ioc_unlink_t viu; + + if (argc < 3) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + fd2 = open(VND_PATH, O_RDWR); + assert(fd2 > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(via.via_name, argv[2], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd2, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(vil.vil_name, "dup", VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == 0); + assert(vil.vil_errno == 0); + + (void) strlcpy(vil.vil_name, "dup", VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd2, VND_IOC_LINK, &vil); + assert(ret == -1); + assert(vil.vil_errno == VND_E_LINKEXISTS); + + viu.viu_errno = 0; + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(ret == 0); + assert(viu.viu_errno == 0); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.ngioctlfault.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.ngioctlfault.c new file mode 100644 index 0000000000..bf174f1a8f --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.ngioctlfault.c @@ -0,0 +1,96 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Pass bad addresses to all of our non-global ioctls + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +static int requests[] = { + VND_IOC_LINK, + VND_IOC_UNLINK, + VND_IOC_GETRXBUF, + VND_IOC_SETRXBUF, + VND_IOC_GETTXBUF, + VND_IOC_SETTXBUF, + VND_IOC_GETMINTU, + VND_IOC_GETMAXTU, + VND_IOC_GETMAXBUF, + -1 +}; + +int +main(int argc, const char *argv[]) +{ + int fd, ret, i; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + vnd_ioc_unlink_t viu; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == 0); + assert(vil.vil_errno == 0); + + for (i = 0; requests[i] != -1; i++) { + ret = ioctl(fd, requests[i], (void *)(uintptr_t)i); + assert(ret == -1); + assert(errno == EFAULT); + } + + + viu.viu_errno = 0; + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(ret == 0); + assert(viu.viu_errno == 0); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv1.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv1.c new file mode 100644 index 0000000000..6d5ad0eec2 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv1.c @@ -0,0 +1,69 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to attach a device without PRIV_NET_CONFIG + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <priv.h> +#include <string.h> +#include <unistd.h> +#include <stropts.h> +#include <stdio.h> +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + priv_set_t *ps; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + ps = priv_allocset(); + assert(ps != NULL); + assert(priv_addset(ps, PRIV_SYS_NET_CONFIG) == 0); + assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); + + fd = open(VND_PATH, O_RDWR); + assert(fd >= 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == -1); + assert(errno == EPERM); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv2.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv2.c new file mode 100644 index 0000000000..6b38f159a0 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv2.c @@ -0,0 +1,69 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to attach a device without PRIV_NET_RAWACCESS + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <priv.h> +#include <unistd.h> +#include <stropts.h> +#include <string.h> +#include <stdio.h> +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + priv_set_t *ps; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + ps = priv_allocset(); + assert(ps != NULL); + assert(priv_addset(ps, PRIV_NET_RAWACCESS) == 0); + assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); + + fd = open(VND_PATH, O_RDWR); + assert(fd >= 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == -1); + assert(errno == EPERM); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv3.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv3.c new file mode 100644 index 0000000000..a8c43fc46d --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv3.c @@ -0,0 +1,70 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to attach a device without PRIV_NET_CONFIG and PRIV_NET_RAWACCESS + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <priv.h> +#include <unistd.h> +#include <stropts.h> +#include <string.h> +#include <stdio.h> +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + priv_set_t *ps; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + ps = priv_allocset(); + assert(ps != NULL); + assert(priv_addset(ps, PRIV_SYS_NET_CONFIG) == 0); + assert(priv_addset(ps, PRIV_NET_RAWACCESS) == 0); + assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); + + fd = open(VND_PATH, O_RDWR); + assert(fd >= 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == -1); + assert(errno == EPERM); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv4.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv4.c new file mode 100644 index 0000000000..aed0204544 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv4.c @@ -0,0 +1,75 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to link a device without PRIV_NET_CONFIG + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <priv.h> +#include <unistd.h> +#include <stropts.h> +#include <string.h> +#include <stdio.h> +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + priv_set_t *ps; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd >= 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + + ps = priv_allocset(); + assert(ps != NULL); + assert(priv_addset(ps, PRIV_SYS_NET_CONFIG) == 0); + assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); + + (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == -1); + assert(errno == EPERM); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv5.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv5.c new file mode 100644 index 0000000000..2db8ecc95f --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.nopriv5.c @@ -0,0 +1,77 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to open a device without PRIV_NET_RAWACCESS + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <priv.h> +#include <unistd.h> +#include <stropts.h> +#include <string.h> +#include <stdio.h> +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, fd2, ret; + priv_set_t *ps; + char *path; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd >= 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + + ps = priv_allocset(); + assert(ps != NULL); + assert(priv_addset(ps, PRIV_SYS_NET_RAWACCESS) == 0); + assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); + + (void) asprintf(&path, "/dev/vnd/%s", argv[1]); + assert(path != NULL); + fd2 = open(path, O_RDWR); + assert(fd2 == -1); + assert(errno == EPERM); + + free(path); + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.olink.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.olink.c new file mode 100644 index 0000000000..0f9292bbae --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.olink.c @@ -0,0 +1,77 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Open a /dev/vnd/%s link + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + char *path; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == 0); + assert(vil.vil_errno == 0); + + ret = asprintf(&path, "/dev/vnd/%s", argv[1]); + assert(ret != -1); + + ret = open(path, O_RDONLY); + assert(ret > 0); + assert(close(ret) == 0); + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.olinknopriv.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.olinknopriv.c new file mode 100644 index 0000000000..338218e751 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.olinknopriv.c @@ -0,0 +1,83 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to open a /dev/vnd/%s without PRIV_NET_RAWACCESS + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> +#include <priv.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + char *path; + priv_set_t *ps; + vnd_ioc_attach_t via; + vnd_ioc_link_t vil; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); + vil.vil_errno = 0; + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(ret == 0); + assert(vil.vil_errno == 0); + + ret = asprintf(&path, "/dev/vnd/%s", argv[1]); + assert(ret != -1); + + ps = priv_allocset(); + assert(ps != NULL); + assert(priv_addset(ps, PRIV_NET_RAWACCESS) == 0); + assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); + + ret = open(path, O_RDWR); + assert(ret == -1); + assert(errno == EPERM); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/create.rmenolink.c b/usr/src/cmd/vndadm/test/tst/ioctl/create.rmenolink.c new file mode 100644 index 0000000000..d44e6512a7 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/create.rmenolink.c @@ -0,0 +1,69 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Verify that unlink fails when we're not linked. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + vnd_ioc_unlink_t viu; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == 0); + assert(via.via_errno == 0); + + viu.viu_errno = 0; + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(ret == -1); + assert(viu.viu_errno == VND_E_NOTLINKED); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.attachrdonly.c b/usr/src/cmd/vndadm/test/tst/ioctl/tst.attachrdonly.c new file mode 100644 index 0000000000..29def6182d --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.attachrdonly.c @@ -0,0 +1,63 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Fail to attach when /dev/vnd/ctl is opened read only. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + vnd_ioc_attach_t via; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= VND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open(VND_PATH, O_RDONLY); + assert(fd > 0); + + (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); + via.via_zoneid = 0; + via.via_errno = 0; + + ret = ioctl(fd, VND_IOC_ATTACH, &via); + assert(ret == -1); + assert(errno == EBADF); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.badioctl.c b/usr/src/cmd/vndadm/test/tst/ioctl/tst.badioctl.c new file mode 100644 index 0000000000..f26722f035 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.badioctl.c @@ -0,0 +1,79 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Throw a bunch of bad ioctls at us and make sure that we get ENOTTY. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <unistd.h> +#include <stropts.h> +#include <limits.h> +#include <assert.h> + +/* + * We're including a bunch of bad header files that have ioctl numbers that we + * know we shouldn't. + */ +#include <sys/ipd.h> +#include <sys/dtrace.h> + +#define VND_PATH "/dev/vnd/ctl" + +/* + * A series of bad requests + */ +static int requests[] = { + 0, + 1, + 42, + 169, + 4096, + INT_MAX, + IPDIOC_CORRUPT, + IPDIOC_REMOVE, + DTRACEIOC_CONF, + DTRACEIOC_REPLICATE, + -1 +}; + +int +main(void) +{ + int fd, i; + + fd = open(VND_PATH, O_RDONLY); + if (fd < 0) { + (void) fprintf(stderr, "failed to open %s read only: %s\n", + VND_PATH, strerror(errno)); + return (1); + } + + for (i = 0; requests[i] != -1; i++) { + int ret; + ret = ioctl(fd, requests[i], NULL); + assert(ret == -1); + assert(errno == ENOTTY); + } + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.basicopenctl.c b/usr/src/cmd/vndadm/test/tst/ioctl/tst.basicopenctl.c new file mode 100644 index 0000000000..852ad5550f --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.basicopenctl.c @@ -0,0 +1,76 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Ensure that we can do a basic open of the device for read, write, and + * read/write. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <unistd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(void) +{ + int fd; + + fd = open(VND_PATH, O_RDONLY); + if (fd < 0) { + (void) fprintf(stderr, "failed to open %s read only: %s\n", + VND_PATH, strerror(errno)); + return (1); + } + + if (close(fd) != 0) { + (void) fprintf(stderr, "failed to close vnd fd: %s\n", + strerror(errno)); + return (1); + } + + fd = open(VND_PATH, O_RDWR); + if (fd < 0) { + (void) fprintf(stderr, "failed to open %s read/write: %s\n", + VND_PATH, strerror(errno)); + return (1); + } + + if (close(fd) != 0) { + (void) fprintf(stderr, "failed to close vnd fd: %s\n", + strerror(errno)); + return (1); + } + + fd = open(VND_PATH, O_WRONLY); + if (fd < 0) { + (void) fprintf(stderr, "failed to open %s write only: %s\n", + VND_PATH, strerror(errno)); + return (1); + } + + if (close(fd) != 0) { + (void) fprintf(stderr, "failed to close vnd fd: %s\n", + strerror(errno)); + return (1); + } + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.gioctlfault.c b/usr/src/cmd/vndadm/test/tst/ioctl/tst.gioctlfault.c new file mode 100644 index 0000000000..b581b5dd4c --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.gioctlfault.c @@ -0,0 +1,78 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Pass pointers to arbitrary addresses and make sure we properly get EFAULT for + * all the global ioctls. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <unistd.h> +#include <stropts.h> +#include <limits.h> +#include <assert.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(void) +{ + int fd, ret; + vnd_ioc_attach_t *via; + vnd_ioc_list_t *vil; + vnd_ioc_buf_t *vib; + + fd = open(VND_PATH, O_RDWR); + if (fd < 0) { + (void) fprintf(stderr, "failed to open %s r/w: %s\n", VND_PATH, + strerror(errno)); + return (1); + } + + via = (vnd_ioc_attach_t *)(uintptr_t)23; + vil = (vnd_ioc_list_t *)(uintptr_t)42; + vib = (vnd_ioc_buf_t *)(uintptr_t)169; + + ret = ioctl(fd, VND_IOC_ATTACH, NULL); + assert(ret == -1); + assert(errno == EFAULT); + ret = ioctl(fd, VND_IOC_LIST, NULL); + assert(ret == -1); + assert(errno == EFAULT); + ret = ioctl(fd, VND_IOC_GETMAXBUF, NULL); + assert(ret == -1); + assert(errno == EFAULT); + + ret = ioctl(fd, VND_IOC_ATTACH, via); + assert(ret == -1); + assert(errno == EFAULT); + ret = ioctl(fd, VND_IOC_LIST, vil); + assert(ret == -1); + assert(errno == EFAULT); + ret = ioctl(fd, VND_IOC_GETMAXBUF, vib); + assert(ret == -1); + assert(errno == EFAULT); + + assert(close(fd) == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.gioctlnattach.c b/usr/src/cmd/vndadm/test/tst/ioctl/tst.gioctlnattach.c new file mode 100644 index 0000000000..98acffa194 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.gioctlnattach.c @@ -0,0 +1,100 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Here we test that all the ioctls which require us to be on a local device + * fail to work. Specifically, the errno should be VND_E_NOTATTACHED + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <unistd.h> +#include <stropts.h> +#include <limits.h> +#include <assert.h> +#include <stdlib.h> + +#include <sys/vnd.h> + +#define VND_PATH "/dev/vnd/ctl" + +static int vib_ioc[] = { + VND_IOC_GETRXBUF, + VND_IOC_SETRXBUF, + VND_IOC_GETTXBUF, + VND_IOC_SETTXBUF, + VND_IOC_GETMINTU, + VND_IOC_GETMAXTU, + -1 +}; + +int +main(void) +{ + int fd, ret, i; + vnd_ioc_link_t vil; + vnd_ioc_unlink_t viu; + vnd_ioc_buf_t vib; + frameio_t *fio; + char buf[1]; + + fd = open(VND_PATH, O_RDWR); + if (fd < 0) { + (void) fprintf(stderr, "failed to open %s r/w: %s\n", VND_PATH, + strerror(errno)); + return (1); + } + + bzero(&vil, sizeof (vnd_ioc_link_t)); + vil.vil_name[0] = 'a'; + bzero(&viu, sizeof (vnd_ioc_unlink_t)); + bzero(&vib, sizeof (vnd_ioc_buf_t)); + fio = malloc(sizeof (frameio_t) + sizeof (framevec_t)); + assert(fio != NULL); + fio->fio_version = FRAMEIO_CURRENT_VERSION; + fio->fio_nvpf = 1; + fio->fio_nvecs = 1; + fio->fio_vecs[0].fv_buf = buf; + fio->fio_vecs[0].fv_buflen = 1; + + ret = ioctl(fd, VND_IOC_LINK, &vil); + assert(vil.vil_errno == VND_E_NOTATTACHED); + ret = ioctl(fd, VND_IOC_UNLINK, &viu); + assert(viu.viu_errno == VND_E_NOTLINKED); + + for (i = 0; vib_ioc[i] != -1; i++) { + bzero(&vib, sizeof (vib)); + ret = ioctl(fd, vib_ioc[i], &vib); + assert(vib.vib_errno == VND_E_NOTATTACHED); + } + + /* The frameio ioctls only use standard errnos */ + ret = ioctl(fd, VND_IOC_FRAMEIO_READ, fio); + assert(ret == -1); + assert(errno == ENXIO); + ret = ioctl(fd, VND_IOC_FRAMEIO_WRITE, fio); + assert(ret == -1); + assert(errno == ENXIO); + + free(fio); + assert(close(fd) == 0); + + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.iocsize.ksh b/usr/src/cmd/vndadm/test/tst/ioctl/tst.iocsize.ksh new file mode 100644 index 0000000000..9b30043d47 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.iocsize.ksh @@ -0,0 +1,54 @@ +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Ensure structure sizes for both ILP32 and LP64 are the same +# + +vt_arg0=$(basename $0) +vt_structs="vnd_ioc_attach_t vnd_ioc_link_t vnd_ioc_unlink_t" +vt_structs="$vt_structs vnd_ioc_nonblock_t vnd_ioc_buf_t vnd_ioc_info_t" + +vt_t32="/tmp/vnd.iocsize.32.$$" +vt_t64="/tmp/vnd.iocsize.64.$$" + +function fatal +{ + typeset msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "$vt_arg0: $msg" >&2 + exit 1 +} + +function dump_types +{ + typeset file=$1 + typeset lib=$2 + typeset t + + for t in $vn_structs; do + mdb -e \'::print -at $t\' $lib >> $file || fatal \ + "failed to dump type $t from $lib" + done +} + +rm -f $vt_t32 $vt_t64 || fatal "failed to cleanup old temp files" +touch $vt_t32 $vt_t64 || fatal "failed to create temp files" + +dump_types $vt_t32 /usr/lib/libvnd.so.1 +dump_types $vt_t64 /usr/lib/64/libvnd.so.1 + +diff $vt_t32 $vt_t64 diff --git a/usr/src/cmd/vndadm/test/tst/ioctl/tst.openctlbadflags.c b/usr/src/cmd/vndadm/test/tst/ioctl/tst.openctlbadflags.c new file mode 100644 index 0000000000..65e48029b7 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/ioctl/tst.openctlbadflags.c @@ -0,0 +1,88 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Make sure that we can't open the vnd control device with invalid flags. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> + +#define VND_PATH "/dev/vnd/ctl" + +int +main(void) +{ + int fd; + + fd = open(VND_PATH, O_RDONLY | O_EXCL); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_EXCL!"); + return (1); + } + + fd = open(VND_PATH, O_RDWR | O_EXCL); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_EXCL!"); + return (1); + } + + fd = open(VND_PATH, O_WRONLY | O_EXCL); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_EXCL!"); + return (1); + } + + fd = open(VND_PATH, O_RDONLY | O_NDELAY); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_NDELAY!"); + return (1); + } + + fd = open(VND_PATH, O_RDWR | O_NDELAY); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_NDELAY!"); + return (1); + } + + fd = open(VND_PATH, O_WRONLY | O_NDELAY); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_NDELAY!"); + return (1); + } + + fd = open(VND_PATH, O_RDONLY | O_NDELAY | O_EXCL); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_NDELAY | O_EXCL!"); + return (1); + } + + fd = open(VND_PATH, O_RDWR | O_NDELAY | O_EXCL); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_NDELAY | O_EXCL!"); + return (1); + } + + fd = open(VND_PATH, O_WRONLY | O_NDELAY | O_EXCL); + if (fd != -1) { + (void) fprintf(stderr, "somehow opened vnd O_NDELAY | O_EXCL!"); + return (1); + } + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/Makefile b/usr/src/cmd/vndadm/test/tst/lib/Makefile new file mode 100644 index 0000000000..d7a1ed8fa5 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/Makefile @@ -0,0 +1,44 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +TSTDIR = lib +EXETESTS = \ + create.basic.exe \ + create.badlink.exe \ + create.badpropid.exe \ + create.badpropsize.exe \ + create.badzone.exe \ + create.enomem.exe \ + create.frameioeagain.exe \ + create.open.exe \ + create.propiter.exe \ + create.proprdonly.exe \ + err.badclose.exe \ + tst.badopen.exe \ + tst.strerror.exe \ + tst.strsyserror.exe +OUTFILES = tst.strerror.exe.out +SHTESTS = +SUPBOBJS = + +CLOBBERFILES = $(EXETESTS) + +include ../../Makefile.com + +LDLIBS += -lvnd + +install: $(ROOTTESTS) + +include ../../Makefile.targ diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.badlink.c b/usr/src/cmd/vndadm/test/tst/lib/create.badlink.c new file mode 100644 index 0000000000..aefec3ed44 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.badlink.c @@ -0,0 +1,39 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Make sure that we can't create something in the context of a datalink that + * doesn't exist. + */ + +#include <assert.h> +#include <stdio.h> +#include <libvnd.h> + +int +main(void) +{ + int syserr; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + + vhp = vnd_create(NULL, "foobar", "foobar", &vnderr, &syserr); + (void) printf("%d, %d\n", vnderr, syserr); + assert(vhp == NULL); + assert(vnderr == VND_E_NODATALINK); + assert(syserr == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.badpropid.c b/usr/src/cmd/vndadm/test/tst/lib/create.badpropid.c new file mode 100644 index 0000000000..15334fa31c --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.badpropid.c @@ -0,0 +1,76 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Make sure that we can't get and set nonexisting properties. + */ + +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr, ret; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + ret = vnd_prop_get(vhp, VND_PROP_MAX, NULL, 0); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_BADPROP); + assert(vnd_syserrno(vhp) == 0); + + ret = vnd_prop_get(vhp, VND_PROP_MAX + 5, NULL, 0); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_BADPROP); + assert(vnd_syserrno(vhp) == 0); + + ret = vnd_prop_set(vhp, VND_PROP_MAX, NULL, 0); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_BADPROP); + assert(vnd_syserrno(vhp) == 0); + + ret = vnd_prop_set(vhp, VND_PROP_MAX + 5, NULL, 0); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_BADPROP); + assert(vnd_syserrno(vhp) == 0); + + ret = vnd_prop_writeable(VND_PROP_MAX, NULL); + assert(ret == -1); + + ret = vnd_prop_writeable(VND_PROP_MAX + 5, NULL); + assert(ret == -1); + + vnd_close(vhp); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.badpropsize.c b/usr/src/cmd/vndadm/test/tst/lib/create.badpropsize.c new file mode 100644 index 0000000000..d5fefd3764 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.badpropsize.c @@ -0,0 +1,63 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Validate that we can't set properties with bogus sizes. + */ + +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <limits.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr, ret, i; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + for (i = 0; i < VND_PROP_MAX; i++) { + ret = vnd_prop_get(vhp, i, NULL, INT32_MAX); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_BADPROPSIZE); + assert(vnd_syserrno(vhp) == 0); + + ret = vnd_prop_set(vhp, i, NULL, INT32_MAX); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_BADPROPSIZE); + assert(vnd_syserrno(vhp) == 0); + } + + vnd_close(vhp); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.badzone.c b/usr/src/cmd/vndadm/test/tst/lib/create.badzone.c new file mode 100644 index 0000000000..30f9612963 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.badzone.c @@ -0,0 +1,43 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Make sure that we can't create something in the context of a zone that + * doesn't exist. + */ + +#include <assert.h> +#include <sys/zone.h> +#include <string.h> +#include <libvnd.h> + +int +main(void) +{ + int syserr; + vnd_errno_t vnderr; + char zname[ZONENAME_MAX+4]; + vnd_handle_t *vhp; + + (void) memset(zname, 'a', sizeof (zname)); + zname[ZONENAME_MAX+3] = '\0'; + + vhp = vnd_create(zname, "foobar", "foobar", &vnderr, &syserr); + assert(vhp == NULL); + assert(vnderr == VND_E_NOZONE); + assert(syserr == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.basic.c b/usr/src/cmd/vndadm/test/tst/lib/create.basic.c new file mode 100644 index 0000000000..5335f8cbb4 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.basic.c @@ -0,0 +1,49 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Simple create and destroy. + */ + +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + vnd_close(vhp); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.enomem.c b/usr/src/cmd/vndadm/test/tst/lib/create.enomem.c new file mode 100644 index 0000000000..9203e369ae --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.enomem.c @@ -0,0 +1,91 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Verify that we can't allocate a handle when in an ENOMEM situation. + */ + +#include <procfs.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/sysmacros.h> +#include <assert.h> +#include <strings.h> + +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int fd; + int syserr; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + pstatus_t status; + void *addr; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + fd = open("/proc/self/status", O_RDONLY); + if (fd < 0) + exit(1); + if (read(fd, &status, sizeof (status)) != sizeof (status)) + exit(1); + + addr = mmap((caddr_t)P2ROUNDUP(status.pr_brkbase + + status.pr_brksize, 0x1000), 0x1000, + PROT_READ, MAP_ANON | MAP_FIXED | MAP_PRIVATE, -1, 0); + if (addr == (void *)-1) { + perror("mmap"); + exit(1); + } + + /* malloc an approximate size of the vnd_handle_t */ + for (;;) { + void *buf; + + buf = malloc(8); + if (buf == NULL) + break; + } + + for (;;) { + void *buf; + + buf = malloc(4); + if (buf == NULL) + break; + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp == NULL); + assert(vnderr == VND_E_NOMEM); + assert(syserr == 0); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.frameioeagain.c b/usr/src/cmd/vndadm/test/tst/lib/create.frameioeagain.c new file mode 100644 index 0000000000..6cb14fb7df --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.frameioeagain.c @@ -0,0 +1,80 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Create a datalink, set it to non-blocking mode and ensure that we get EAGAIN + * from frame I/O calls. Note that if this test is not plumbed up over an + * etherstub, then it is likely that other traffic will appear on the device and + * this will fail. Note that the test suite always creates these devices over an + * etherstub. + */ + +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr, ret, fd; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + frameio_t *fio; + char buf[1520]; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + fd = vnd_pollfd(vhp); + ret = fcntl(fd, F_SETFL, O_NONBLOCK); + assert(ret == 0); + + fio = malloc(sizeof (frameio_t) + + sizeof (framevec_t)); + assert(fio != NULL); + fio->fio_version = FRAMEIO_CURRENT_VERSION; + fio->fio_nvpf = 1; + fio->fio_nvecs = 1; + + fio->fio_vecs[0].fv_buf = buf; + fio->fio_vecs[0].fv_buflen = sizeof (buf); + + ret = vnd_frameio_read(vhp, fio); + (void) printf("%d, %d\n", ret, errno); + assert(ret == -1); + assert(errno == EAGAIN); + + vnd_close(vhp); + free(fio); + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.open.c b/usr/src/cmd/vndadm/test/tst/lib/create.open.c new file mode 100644 index 0000000000..9cb1d7e40e --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.open.c @@ -0,0 +1,56 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Make sure we can open a created datalink. + */ + +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr; + vnd_errno_t vnderr; + vnd_handle_t *vhp, *vhp2; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + vhp2 = vnd_open(NULL, argv[1], &vnderr, &syserr); + assert(vhp2 != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + vnd_close(vhp2); + vnd_close(vhp); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.propiter.c b/usr/src/cmd/vndadm/test/tst/lib/create.propiter.c new file mode 100644 index 0000000000..a0b46180f7 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.propiter.c @@ -0,0 +1,79 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Ensure that vnd_prop_iter sees all props; + */ + +#include <stdio.h> +#include <strings.h> +#include <stdlib.h> +#include <assert.h> +#include <libvnd.h> + +static boolean_t *g_props; + +/* ARGSUSED */ +static int +prop_cb(vnd_handle_t *vhp, vnd_prop_t prop, void *unused) +{ + assert(prop < VND_PROP_MAX); + g_props[prop] = B_TRUE; + + return (0); +} + +int +main(int argc, const char *argv[]) +{ + int syserr, i, ret; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + g_props = malloc(sizeof (boolean_t) * VND_PROP_MAX); + if (g_props == NULL) { + (void) fprintf(stderr, "failed to alloc memory for %d " + "boolean_t\n", VND_PROP_MAX); + return (1); + } + for (i = 0; i < VND_PROP_MAX; i++) + g_props[i] = B_FALSE; + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + ret = vnd_prop_iter(vhp, prop_cb, NULL); + assert(ret == 0); + + for (i = 0; i < VND_PROP_MAX; i++) + assert(g_props[i] == B_TRUE); + + free(g_props); + vnd_close(vhp); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/create.proprdonly.c b/usr/src/cmd/vndadm/test/tst/lib/create.proprdonly.c new file mode 100644 index 0000000000..18b1f7d58d --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/create.proprdonly.c @@ -0,0 +1,63 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Validate that we can't set read only properties + */ + +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <limits.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr, ret; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + vnd_prop_buf_t vpb; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_create(NULL, argv[1], argv[1], &vnderr, &syserr); + assert(vhp != NULL); + assert(vnderr == 0); + assert(syserr == 0); + + ret = vnd_prop_get(vhp, VND_PROP_MINTU, &vpb, + sizeof (vnd_prop_buf_t)); + assert(ret == 0); + + ret = vnd_prop_set(vhp, VND_PROP_MINTU, &vpb, + sizeof (vnd_prop_buf_t)); + assert(ret == -1); + assert(vnd_errno(vhp) == VND_E_PROPRDONLY); + assert(vnd_syserrno(vhp) == 0); + + vnd_close(vhp); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/err.badclose.c b/usr/src/cmd/vndadm/test/tst/lib/err.badclose.c new file mode 100644 index 0000000000..8c832506a0 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/err.badclose.c @@ -0,0 +1,33 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * This program should segfault. + */ + +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <libvnd.h> + +int +main(void) +{ + vnd_handle_t *vhp = (void *)0x42; + vnd_close(vhp); + /* This should not be reached */ + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/tst.badopen.c b/usr/src/cmd/vndadm/test/tst/lib/tst.badopen.c new file mode 100644 index 0000000000..4f67ce79ed --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/tst.badopen.c @@ -0,0 +1,49 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Make sure we can't open a vnd device that doesn't exist + */ + +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <assert.h> +#include <libvnd.h> + +int +main(int argc, const char *argv[]) +{ + int syserr; + vnd_errno_t vnderr; + vnd_handle_t *vhp; + + if (argc < 2) { + (void) fprintf(stderr, "missing arguments...\n"); + return (1); + } + + if (strlen(argv[1]) >= LIBVND_NAMELEN) { + (void) fprintf(stderr, "vnic name too long...\n"); + return (1); + } + + vhp = vnd_open(NULL, argv[1], &vnderr, &syserr); + assert(vhp == NULL); + assert(vnderr == VND_E_SYS); + assert(syserr == ENOENT); + + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/tst.strerror.c b/usr/src/cmd/vndadm/test/tst/lib/tst.strerror.c new file mode 100644 index 0000000000..a99a9ecbf6 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/tst.strerror.c @@ -0,0 +1,30 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Verify that all the error strings we care about match what we expect. + */ + +#include <stdio.h> +#include <libvnd.h> + +int +main(void) +{ + int i; + for (i = 0; i <= VND_E_UNKNOWN + 1; i++) + (void) printf("[%s]\n", vnd_strerror(i)); + return (0); +} diff --git a/usr/src/cmd/vndadm/test/tst/lib/tst.strerror.exe.out b/usr/src/cmd/vndadm/test/tst/lib/tst.strerror.exe.out new file mode 100644 index 0000000000..83dbcdfdb4 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/tst.strerror.exe.out @@ -0,0 +1,37 @@ +[no error] +[not enough memory available] +[no such datalink] +[datalink not of type DL_ETHER] +[unknown dlpi failure] +[DL_ATTACH_REQ failed] +[DL_BIND_REQ failed] +[DL_PROMISCON_REQ failed] +[DLD_CAPAB_DIRECT enable failed] +[bad datalink capability] +[bad datalink subcapability] +[bad dld version] +[failed to create kstats] +[no such vnd link] +[netstack doesn't exist] +[device already associated] +[device already attached] +[device already linked] +[invalid name] +[permission denied] +[no such zone] +[failed to initialize vnd stream module] +[device not attached] +[device not linked] +[another device has the same link name] +[failed to create minor node] +[requested buffer size is too large] +[requested buffer size is too small] +[unable to obtain exclusive access to dlpi link, link busy] +[DLD direct capability not supported over data link] +[invalid property size] +[invalid property] +[property is read only] +[unexpected system error] +[capabilities invalid, pass-through module detected] +[unknown error] +[unknown error] diff --git a/usr/src/cmd/vndadm/test/tst/lib/tst.strsyserror.c b/usr/src/cmd/vndadm/test/tst/lib/tst.strsyserror.c new file mode 100644 index 0000000000..b95e6372e4 --- /dev/null +++ b/usr/src/cmd/vndadm/test/tst/lib/tst.strsyserror.c @@ -0,0 +1,50 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Verify that the error message from libvnd's strsyserrno is the same as the + * underlying strerror function's. It should be. We'll just check an assortment + * of errnos. + */ + +#include <stdio.h> +#include <string.h> +#include <libvnd.h> + +int +main(void) +{ + int i; + const char *vnd, *libc; + for (i = 0; i < 42; i++) { + vnd = vnd_strsyserror(i); + libc = strerror(i); + if ((vnd != NULL && libc == NULL) || + (vnd == NULL && libc != NULL)) { + (void) fprintf(stderr, "errno %d, vnd: %p, libc: %p", + i, (void *)vnd, (void *)libc); + return (1); + } + if (vnd != NULL && strcmp(vnd, libc) != 0) { + (void) fprintf(stderr, + "errno %d: libc and vnd disagree.\n", i); + (void) fprintf(stderr, "vnd: %s\n", vnd); + (void) fprintf(stderr, "libc: %s\n", libc); + return (1); + } + } + + return (0); +} diff --git a/usr/src/cmd/vndadm/vndadm.c b/usr/src/cmd/vndadm/vndadm.c new file mode 100644 index 0000000000..6811663696 --- /dev/null +++ b/usr/src/cmd/vndadm/vndadm.c @@ -0,0 +1,872 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +#include <errno.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> +#include <libgen.h> +#include <stdlib.h> +#include <unistd.h> +#include <zone.h> + +#include <libvnd.h> + +typedef int (*vndadm_print_t)(vnd_handle_t *, vnd_prop_t); +typedef int (*vndadm_parse_t)(char *, void **, size_t *); + +typedef struct vndadm_proptbl { + const char *vp_name; + vndadm_print_t vp_print; + vndadm_parse_t vp_parse; +} vndadm_proptbl_t; + +/* + * Forwards + */ +static int usage(const char *, ...); +static int vndadm_print_size(vnd_handle_t *, vnd_prop_t); +static int vndadm_print_number(vnd_handle_t *, vnd_prop_t); +static int vndadm_parse_size(char *, void **, size_t *); + +/* + * Globals + */ +static char *vnd_pname; + +static void +vnd_vwarn(vnd_errno_t verr, int syserr, const char *format, va_list alist) +{ + (void) fprintf(stderr, "%s: ", vnd_pname); + (void) vfprintf(stderr, format, alist); + if (strchr(format, '\n') == NULL) { + (void) fprintf(stderr, ": %s\n", verr != VND_E_SYS ? + vnd_strerror(verr) : vnd_strsyserror(syserr)); + } +} + +static void +vnd_libwarn(vnd_errno_t verr, int syserr, const char *format, ...) +{ + va_list alist; + + va_start(alist, format); + vnd_vwarn(verr, syserr, format, alist); + va_end(alist); +} + +static void +vnd_warn(const char *format, ...) +{ + va_list alist; + + va_start(alist, format); + vnd_vwarn(0, 0, format, alist); + va_end(alist); +} + +static vndadm_proptbl_t vndadm_propname_tbl[] = { + { "rxbuf", vndadm_print_size, + vndadm_parse_size }, /* VND_PROP_RXBUF */ + { "txbuf", vndadm_print_size, + vndadm_parse_size }, /* VND_PROP_TXBUF */ + { "maxsize", vndadm_print_size, NULL }, /* VND_PROP_MAXBUF */ + { "mintu", vndadm_print_number, NULL }, /* VND_PROP_MINTU */ + { "maxtu", vndadm_print_number, NULL }, /* VND_PROP_MAXTU */ + NULL /* VND_PROP_MAX */ +}; + +static const char * +vndadm_prop_to_name(vnd_prop_t prop) +{ + if (prop > VND_PROP_MAX) + return (NULL); + + return (vndadm_propname_tbl[prop].vp_name); +} + +static vnd_prop_t +vndadm_name_to_prop(const char *name) +{ + int i; + + for (i = 0; i < VND_PROP_MAX; i++) { + if (strcmp(name, vndadm_propname_tbl[i].vp_name) == 0) + return (i); + } + + return (VND_PROP_MAX); +} + +static int +vndadm_print_size(vnd_handle_t *vhp, vnd_prop_t prop) +{ + vnd_prop_buf_t buf; + + if (vnd_prop_get(vhp, prop, &buf, sizeof (buf)) != 0) { + vnd_libwarn(vnd_errno(vhp), vnd_syserrno(vhp), + "failed to get property %s", vndadm_prop_to_name(prop)); + return (1); + } + + (void) printf("%lld", buf.vpb_size); + return (0); +} + +static int +vndadm_print_number(vnd_handle_t *vhp, vnd_prop_t prop) +{ + vnd_prop_buf_t buf; + + if (vnd_prop_get(vhp, prop, &buf, sizeof (buf)) != 0) { + vnd_libwarn(vnd_errno(vhp), vnd_syserrno(vhp), + "failed to get property %s", vndadm_prop_to_name(prop)); + return (1); + } + + (void) printf("%lld", buf.vpb_size); + return (0); +} + +static int +vndadm_parse_size(char *str, void **bufp, size_t *sizep) +{ + char *end; + unsigned long long val, orig; + vnd_prop_buf_t *buf; + + errno = 0; + val = strtoull(str, &end, 10); + if (errno != 0) { + vnd_warn("%s: not a number\n", str); + return (1); + } + + orig = val; + switch (*end) { + case 'g': + case 'G': + val *= 1024; + if (val < orig) + goto overflow; + /*FALLTHRU*/ + case 'm': + case 'M': + val *= 1024; + if (val < orig) + goto overflow; + /*FALLTHRU*/ + case 'k': + case 'K': + val *= 1024; + if (val < orig) + goto overflow; + end++; + break; + default: + break; + } + + if (*end == 'b' || *end == 'B') + end++; + if (*end != '\0') { + vnd_warn("%s: not a number", str); + return (1); + } + + buf = malloc(sizeof (vnd_prop_buf_t)); + if (buf == NULL) { + vnd_warn("failed to allocate memory for setting a property"); + return (1); + } + + buf->vpb_size = val; + *bufp = buf; + *sizep = sizeof (vnd_prop_buf_t); + + return (0); + +overflow: + vnd_warn("value overflowed: %s\n", str); + return (1); +} + +static void +vndadm_create_usage(FILE *out) +{ + (void) fprintf(out, "\tcreate:\t\t[-z zonename] -l datalink name\n"); +} + +static int +vndadm_create(int argc, char *argv[]) +{ + int c, syserr; + vnd_errno_t vnderr; + const char *datalink = NULL; + const char *linkname = NULL; + const char *zonename = NULL; + vnd_handle_t *vhp; + + optind = 0; + while ((c = getopt(argc, argv, ":z:l:")) != -1) { + switch (c) { + case 'l': + datalink = optarg; + break; + case 'z': + zonename = optarg; + break; + case ':': + return (usage("-%c requires an operand\n", optopt)); + case '?': + return (usage("unknown option: -%c\n", optopt)); + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + return (usage("missing required link name\n")); + } else if (argc > 1) { + return (usage("create: too many arguments for link name, " + "pick one\n")); + } + linkname = argv[0]; + if (datalink == NULL) + datalink = linkname; + + vhp = vnd_create(zonename, datalink, linkname, &vnderr, &syserr); + if (vhp == NULL) { + vnd_libwarn(vnderr, syserr, + "failed to create datapath link %s", linkname); + return (1); + } + + vnd_close(vhp); + return (0); +} + +static void +vndadm_destroy_usage(FILE *out) +{ + (void) fprintf(out, "\tdestroy:\t[-z zonename] [link]...\n"); +} + +static int +vndadm_destroy(int argc, char *argv[]) +{ + vnd_handle_t *vhp; + int c, syserr; + vnd_errno_t vnderr; + const char *zonename = NULL; + + optind = 0; + while ((c = getopt(argc, argv, ":z:")) != -1) { + switch (c) { + case 'z': + zonename = optarg; + break; + case ':': + return (usage("-%c requires an operand\n", optopt)); + case '?': + return (usage("unknown option: -%c\n", optopt)); + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + if (argc != 1) { + return (usage("extraneous arguments\n")); + } + + vhp = vnd_open(zonename, argv[0], &vnderr, &syserr); + if (vhp == NULL) { + vnd_libwarn(vnderr, syserr, "failed to open link: %s", argv[0]); + return (1); + } + + if (vnd_unlink(vhp) != 0) { + vnd_libwarn(vnd_errno(vhp), vnd_syserrno(vhp), + "failed to destroy link %s", argv[0]); + return (1); + } + + vnd_close(vhp); + return (0); +} + +static void +vndadm_list_usage(FILE *out) +{ + (void) fprintf(out, "\tlist:\t\t[-p] [-d delim] [-o field,...] " + "[-z zonename] [link]...\n"); +} + +#define VNDADM_LIST_NFIELDS 3 + +typedef struct vndadm_list_cb { + int vsc_argc; + char **vsc_argv; + int vsc_found; + boolean_t vsc_parse; + const char *vsc_delim; + int vsc_order[VNDADM_LIST_NFIELDS]; + int vsc_last; + zoneid_t vsc_zid; +} vndadm_list_cb_t; + +typedef struct vndadm_list_field { + const char *vlf_name; + const char *vlf_header; + int vlf_size; + void (*vlf_print)(struct vndadm_list_field *, vnd_info_t *, boolean_t); + void (*vlf_parse)(struct vndadm_list_field *, vnd_info_t *, boolean_t); +} vndadm_list_field_t; + +static void +vlf_print_link(vndadm_list_field_t *vlfp, vnd_info_t *viip, + boolean_t last) +{ + if (last == B_TRUE) { + (void) printf("%s", viip->vi_name); + } else { + (void) printf("%-*s", vlfp->vlf_size, viip->vi_name); + } +} + +/* ARGSUSED */ +static void +vlf_parse_link(vndadm_list_field_t *vlfp, vnd_info_t *viip, + boolean_t last) +{ + (void) printf("%s", viip->vi_name); +} + +static void +vlf_print_datalink(vndadm_list_field_t *vlfp, vnd_info_t *viip, + boolean_t last) +{ + if (last == B_TRUE) { + (void) printf("%s", viip->vi_datalink); + } else { + (void) printf("%-*s", vlfp->vlf_size, viip->vi_datalink); + } +} + +/* ARGSUSED */ +static void +vlf_parse_datalink(vndadm_list_field_t *vlfp, vnd_info_t *viip, + boolean_t last) +{ + (void) printf("%s", viip->vi_datalink); +} + +static void +vlf_print_zone(vndadm_list_field_t *vlfp, vnd_info_t *viip, + boolean_t last) +{ + char buf[ZONENAME_MAX]; + + if (getzonenamebyid(viip->vi_zone, buf, sizeof (buf)) <= 0) + (void) strlcpy(buf, "<unknown>", sizeof (buf)); + + if (last == B_TRUE) { + (void) printf("%s", buf); + } else { + (void) printf("%-*s", vlfp->vlf_size, buf); + } +} + +/* ARGSUSED */ +static void +vlf_parse_zone(vndadm_list_field_t *vlfp, vnd_info_t *viip, + boolean_t last) +{ + char buf[ZONENAME_MAX]; + + if (getzonenamebyid(viip->vi_zone, buf, sizeof (buf)) <= 0) + (void) strlcpy(buf, "<unknown>", sizeof (buf)); + + (void) printf("%s", buf); +} + +static vndadm_list_field_t vlf_tbl[] = { + { "name", "NAME", 16, vlf_print_link, vlf_parse_link }, + { "datalink", "DATALINK", 16, vlf_print_datalink, vlf_parse_datalink }, + { "zone", "ZONENAME", 32, vlf_print_zone, vlf_parse_zone }, + { NULL } +}; + + +static int +vndadm_list_f(vnd_info_t *viip, void *arg) +{ + int i; + boolean_t found; + vndadm_list_cb_t *vscp = arg; + + if (vscp->vsc_zid != ALL_ZONES && vscp->vsc_zid != viip->vi_zone) + return (0); + + if (vscp->vsc_argc != 0) { + found = B_FALSE; + for (i = 0; i < vscp->vsc_argc; i++) { + if (strcmp(viip->vi_name, vscp->vsc_argv[i]) == 0) { + found = B_TRUE; + break; + } + } + if (found == B_FALSE) + return (0); + vscp->vsc_found++; + } + + for (i = 0; i < VNDADM_LIST_NFIELDS && vscp->vsc_order[i] != -1; i++) { + boolean_t last = i == vscp->vsc_last; + if (vscp->vsc_parse == B_TRUE) + vlf_tbl[vscp->vsc_order[i]].vlf_parse( + &vlf_tbl[vscp->vsc_order[i]], viip, last); + else + vlf_tbl[vscp->vsc_order[i]].vlf_print( + &vlf_tbl[vscp->vsc_order[i]], viip, last); + + if (last == B_FALSE) + (void) printf("%s", vscp->vsc_delim); + } + (void) printf("\n"); + + return (0); +} + +static int +vndadm_list(int argc, char *argv[]) +{ + int c, i, syserr; + vnd_errno_t vnderr; + boolean_t parse = B_FALSE; + const char *zonename = NULL, *delim = NULL; + char *fields = NULL; + vndadm_list_cb_t vsc; + + optind = 0; + while ((c = getopt(argc, argv, ":pd:o:z:")) != -1) { + switch (c) { + case 'p': + parse = B_TRUE; + break; + case 'd': + delim = optarg; + break; + case 'o': + fields = optarg; + break; + case 'z': + zonename = optarg; + break; + case ':': + return (usage("-%c requires an operand\n", optopt)); + case '?': + return (usage("unknown option: -%c\n", optopt)); + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + vsc.vsc_argc = argc; + vsc.vsc_argv = argv; + vsc.vsc_found = 0; + if (zonename != NULL) { + vsc.vsc_zid = getzoneidbyname(zonename); + if (vsc.vsc_zid == -1) { + vnd_warn("no such zone: %s\n", zonename); + return (1); + } + } else { + vsc.vsc_zid = ALL_ZONES; + } + + /* Sanity check parseable related stuff */ + if (delim != NULL && parse == B_FALSE) { + return (usage("-d cannot be used without -p\n")); + } + + if (parse == B_TRUE && fields == NULL) { + return (usage("-p cannot be used without -o\n")); + } + + /* validate our fields, if any */ + if (fields != NULL) { + char *c, *n; + int floc = 0; + + c = fields; + for (;;) { + if (floc >= VNDADM_LIST_NFIELDS) { + return (usage("too many fields specified " + "for -o\n")); + } + + n = strchr(c, ','); + if (n != NULL) + *n = '\0'; + + for (i = 0; i < VNDADM_LIST_NFIELDS; i++) { + if (strcasecmp(c, vlf_tbl[i].vlf_name) == 0) + break; + } + if (i == VNDADM_LIST_NFIELDS) { + vnd_warn("invalid field for -o: %s\nvalid " + "fields are:", c); + for (i = 0; i < VNDADM_LIST_NFIELDS; i++) + vnd_warn(" %s", vlf_tbl[i].vlf_name); + vnd_warn("\n"); + return (usage(NULL)); + } + vsc.vsc_order[floc] = i; + floc++; + + if (n == NULL) + break; + c = n + 1; + } + + vsc.vsc_last = floc - 1; + while (floc < VNDADM_LIST_NFIELDS) + vsc.vsc_order[floc++] = -1; + } else { + vsc.vsc_order[0] = 0; + vsc.vsc_order[1] = 1; + vsc.vsc_order[2] = 2; + } + + vsc.vsc_parse = parse; + vsc.vsc_delim = delim; + if (vsc.vsc_delim == NULL) + vsc.vsc_delim = " "; + + if (vsc.vsc_parse != B_TRUE) { + for (i = 0; i < VNDADM_LIST_NFIELDS && vsc.vsc_order[i] != -1; + i++) { + if (i + 1 == VNDADM_LIST_NFIELDS) { + (void) printf("%s\n", + vlf_tbl[vsc.vsc_order[i]].vlf_header); + continue; + } + (void) printf("%-*s ", + vlf_tbl[vsc.vsc_order[i]].vlf_size, + vlf_tbl[vsc.vsc_order[i]].vlf_header); + } + } + + if (vnd_walk(vndadm_list_f, &vsc, &vnderr, &syserr) != 0) { + vnd_libwarn(vnderr, syserr, "failed to walk vnd links"); + return (1); + } + + if (argc > 0 && vsc.vsc_found == 0) { + vnd_warn("no links matched requested names\n"); + return (1); + } + + return (0); +} + +typedef struct vndadm_get { + boolean_t vg_parse; + const char *vg_delim; + const char *vg_link; + int vg_argc; + char **vg_argv; +} vndadm_get_t; + +static int +vndadm_get_cb(vnd_handle_t *vhp, vnd_prop_t prop, void *arg) +{ + boolean_t writeable; + const char *perm; + vndadm_get_t *vgp = arg; + const char *name = vndadm_prop_to_name(prop); + + /* Verify if this is a prop we're supposed to print */ + if (vgp->vg_argc > 0) { + int i; + boolean_t found = B_FALSE; + for (i = 0; i < vgp->vg_argc; i++) { + if (strcmp(name, vgp->vg_argv[i]) == 0) { + found = B_TRUE; + break; + } + } + if (found == B_FALSE) + return (0); + } + + if (vnd_prop_writeable(prop, &writeable) != 0) + abort(); + + perm = writeable ? "rw" : "r-"; + + if (vgp->vg_parse == B_TRUE) { + (void) printf("%s%s%s%s%s%s", vgp->vg_link, vgp->vg_delim, + name, vgp->vg_delim, perm, vgp->vg_delim); + } else { + (void) printf("%-13s %-16s %-5s ", vgp->vg_link, name, perm); + } + + if (vndadm_propname_tbl[prop].vp_print != NULL) { + if (vndadm_propname_tbl[prop].vp_print(vhp, prop) != 0) + return (1); + } else { + (void) printf("-"); + } + (void) printf("\n"); + return (0); +} + +static int +vndadm_get(int argc, char *argv[]) +{ + vnd_handle_t *vhp; + boolean_t parse = B_FALSE; + vndadm_get_t vg; + int c, syserr; + vnd_errno_t vnderr; + const char *zonename = NULL, *delim = NULL; + + if (argc <= 0) { + return (usage("get requires a link name\n")); + } + + optind = 0; + while ((c = getopt(argc, argv, ":pd:z:")) != -1) { + switch (c) { + case 'p': + parse = B_TRUE; + break; + case 'd': + delim = optarg; + break; + case 'z': + zonename = optarg; + break; + case ':': + return (usage("-%c requires an operand\n", optopt)); + case '?': + return (usage("unknown option: -%c\n", optopt)); + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + return (usage("missing required link\n")); + } + + vhp = vnd_open(zonename, argv[0], &vnderr, &syserr); + if (vhp == NULL) { + vnd_libwarn(vnderr, syserr, "failed to open link: %s", argv[0]); + return (1); + } + + vg.vg_argc = argc - 1; + vg.vg_argv = argv + 1; + vg.vg_link = argv[0]; + vg.vg_parse = parse; + vg.vg_delim = delim != NULL ? delim : " "; + if (vg.vg_parse == B_FALSE) + (void) printf("%-13s %-16s %-5s %s\n", "LINK", "PROPERTY", + "PERM", "VALUE"); + + if (vnd_prop_iter(vhp, vndadm_get_cb, &vg) != 0) + return (1); + + return (0); +} + +static void +vndadm_get_usage(FILE *out) +{ + (void) fprintf(out, + "\tget:\t\t[-p] [-d delim] [-z zonename] link [prop]...\n"); +} + +static int +vndadm_set(int argc, char *argv[]) +{ + vnd_handle_t *vhp; + int c, i, syserr; + vnd_errno_t vnderr; + const char *zonename = NULL; + + optind = 0; + while ((c = getopt(argc, argv, ":z:")) != -1) { + switch (c) { + case 'z': + zonename = optarg; + break; + case ':': + return (usage("-%c requires an operand\n", optopt)); + case '?': + return (usage("unknown option: -%c\n", optopt)); + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + if (argc < 2) { + return (usage("missing arguments to set\n")); + } + + vhp = vnd_open(zonename, argv[0], &vnderr, &syserr); + if (vhp == NULL) { + vnd_libwarn(vnderr, syserr, "failed to open link: %s", argv[0]); + return (1); + } + + for (i = 1; i < argc; i++) { + char *eq, *key, *value; + boolean_t writeable; + vnd_prop_t prop; + void *buf; + size_t psize; + int ret; + + key = argv[i]; + eq = strchr(key, '='); + if (eq == NULL) { + vnd_warn("invalid property name=value: %s\n", key); + return (1); + } + *eq = '\0'; + value = eq + 1; + if (*value == '\0') { + vnd_warn("property value required for %s\n", key); + return (1); + } + prop = vndadm_name_to_prop(key); + if (prop == VND_PROP_MAX) { + vnd_warn("unknown property: %s\n", key); + return (1); + } + + if (vnd_prop_writeable(prop, &writeable) != 0) + abort(); + if (writeable != B_TRUE) { + vnd_warn("property %s is read-only\n", key); + return (1); + } + assert(vndadm_propname_tbl[prop].vp_parse != NULL); + + /* + * vp_parse functions should say what explicitly is invalid. We + * should indicate that the property failed. + */ + ret = vndadm_propname_tbl[prop].vp_parse(value, &buf, &psize); + if (ret != 0) { + vnd_warn("failed to set property %s\n", key); + return (1); + } + + ret = vnd_prop_set(vhp, prop, buf, psize); + free(buf); + if (ret != 0) { + vnd_libwarn(vnd_errno(vhp), vnd_syserrno(vhp), + "failed to set property %s", key); + return (1); + } + } + + return (0); +} + +static void +vndadm_set_usage(FILE *out) +{ + (void) fprintf(out, "\tset:\t\t[-z zonename] link prop=val...\n"); +} + +typedef struct vnd_cmdtab { + const char *vc_name; + int (*vc_op)(int, char *[]); + void (*vc_usage)(FILE *); +} vnd_cmdtab_t; + +static vnd_cmdtab_t vnd_tab[] = { + { "create", vndadm_create, vndadm_create_usage }, + { "destroy", vndadm_destroy, vndadm_destroy_usage }, + { "list", vndadm_list, vndadm_list_usage }, + { "get", vndadm_get, vndadm_get_usage }, + { "set", vndadm_set, vndadm_set_usage }, + { NULL, NULL } +}; + +static int +usage(const char *format, ...) +{ + vnd_cmdtab_t *tab; + const char *help = "usage: %s <subcommand> <args> ...\n"; + + if (format != NULL) { + va_list alist; + + va_start(alist, format); + (void) fprintf(stderr, "%s: ", vnd_pname); + (void) vfprintf(stderr, format, alist); + va_end(alist); + } + (void) fprintf(stderr, help, vnd_pname); + for (tab = vnd_tab; tab->vc_name != NULL; tab++) + tab->vc_usage(stderr); + + return (2); +} + +int +main(int argc, char *argv[]) +{ + vnd_cmdtab_t *tab; + + vnd_pname = basename(argv[0]); + if (argc < 2) { + return (usage(NULL)); + } + + for (tab = vnd_tab; tab->vc_name != NULL; tab++) { + if (strcmp(argv[1], tab->vc_name) == 0) { + argc -= 2; argv += 2; + assert(argc >= 0); + return (tab->vc_op(argc, argv)); + } + } + + return (usage("unknown sub-command '%s'\n", argv[1])); +} diff --git a/usr/src/cmd/vndstat/Makefile b/usr/src/cmd/vndstat/Makefile new file mode 100644 index 0000000000..c77eef3887 --- /dev/null +++ b/usr/src/cmd/vndstat/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +PROG= vndstat + +include ../Makefile.cmd + +LDLIBS += -lkstat + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + $(RM) $(PROG) + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/vndstat/vndstat.c b/usr/src/cmd/vndstat/vndstat.c new file mode 100644 index 0000000000..6f6c76fc12 --- /dev/null +++ b/usr/src/cmd/vndstat/vndstat.c @@ -0,0 +1,542 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ + +#include <sys/kstat.h> +#include <kstat.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <alloca.h> +#include <signal.h> +#include <sys/varargs.h> +#include <sys/int_limits.h> +#include <sys/sysmacros.h> + +#define KSTAT_FIELD_USEINSTANCE 0x01 +#define KSTAT_FIELD_NODELTA 0x02 +#define KSTAT_FIELD_FILLER 0x04 +#define KSTAT_FIELD_STRING 0x08 +#define KSTAT_FIELD_UNIT 0x10 +#define KSTAT_FIELD_LJUST 0x20 + +typedef struct kstat_field { + char *ksf_header; /* header for field */ + char *ksf_name; /* name of stat, if any */ + int ksf_width; /* width for field in output line */ + uint32_t ksf_flags; /* flags for this field, if any */ + char *ksf_suffix; /* optional suffix for units */ + int ksf_hint; /* index hint for field in kstat */ +} kstat_field_t; + +typedef struct kstat_instance { + char ksi_name[KSTAT_STRLEN]; /* name of the underlying kstat */ + int ksi_instance; /* instance identifer of this kstat */ + kstat_t *ksi_ksp; /* pointer to the kstat */ + uint64_t *ksi_data[2]; /* pointer to two generations of data */ + hrtime_t ksi_snaptime[2]; /* hrtime for data generations */ + int ksi_gen; /* current generation */ + struct kstat_instance *ksi_next; /* next in instance list */ +} kstat_instance_t; + +const char *g_cmd = "vndstat"; + +static void +kstat_nicenum(uint64_t num, char *buf, size_t buflen) +{ + uint64_t n = num; + int index = 0; + char u; + + while (n >= 1024) { + n /= 1024; + index++; + } + + u = " KMGTPE"[index]; + + if (index == 0) { + (void) snprintf(buf, buflen, "%llu", n); + } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { + /* + * If this is an even multiple of the base, always display + * without any decimal precision. + */ + (void) snprintf(buf, buflen, "%llu%c", n, u); + } else { + /* + * We want to choose a precision that reflects the best choice + * for fitting in 5 characters. This can get rather tricky when + * we have numbers that are very close to an order of magnitude. + * For example, when displaying 10239 (which is really 9.999K), + * we want only a single place of precision for 10.0K. We could + * develop some complex heuristics for this, but it's much + * easier just to try each combination in turn. + */ + int i; + for (i = 2; i >= 0; i--) { + if (snprintf(buf, buflen, "%.*f%c", i, + (double)num / (1ULL << 10 * index), u) <= 5) + break; + } + } +} + +static void +fatal(char *fmt, ...) +{ + va_list ap; + int error = errno; + + va_start(ap, fmt); + + (void) fprintf(stderr, "%s: ", g_cmd); + /*LINTED*/ + (void) vfprintf(stderr, fmt, ap); + + if (fmt[strlen(fmt) - 1] != '\n') + (void) fprintf(stderr, ": %s\n", strerror(error)); + + exit(EXIT_FAILURE); +} + +int +kstat_field_hint(kstat_t *ksp, kstat_field_t *field) +{ + kstat_named_t *nm = KSTAT_NAMED_PTR(ksp); + int i; + + assert(ksp->ks_type == KSTAT_TYPE_NAMED); + + for (i = 0; i < ksp->ks_ndata; i++) { + if (strcmp(field->ksf_name, nm[i].name) == 0) + return (field->ksf_hint = i); + } + + fatal("could not find field '%s' in %s:%d\n", + field->ksf_name, ksp->ks_name, ksp->ks_instance); + + return (0); +} + +int +kstat_instances_compare(const void *lhs, const void *rhs) +{ + kstat_instance_t *l = *((kstat_instance_t **)lhs); + kstat_instance_t *r = *((kstat_instance_t **)rhs); + int rval; + + if ((rval = strcmp(l->ksi_name, r->ksi_name)) != 0) + return (rval); + + if (l->ksi_instance < r->ksi_instance) + return (-1); + + if (l->ksi_instance > r->ksi_instance) + return (1); + + return (0); +} + +void +kstat_instances_update(kstat_ctl_t *kcp, kstat_instance_t **head, + boolean_t (*interested)(kstat_t *)) +{ + int ninstances = 0, i; + kstat_instance_t **sorted, *ksi, *next; + kstat_t *ksp; + kid_t kid; + + if ((kid = kstat_chain_update(kcp)) == 0 && *head != NULL) + return; + + if (kid == -1) + fatal("failed to update kstat chain"); + + for (ksi = *head; ksi != NULL; ksi = ksi->ksi_next) + ksi->ksi_ksp = NULL; + + for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) { + kstat_instance_t *last = NULL; + + if (!interested(ksp)) + continue; + + /* + * Now look to see if we have this instance and name. (Yes, + * this is a linear search; we're assuming that this list is + * modest in size.) + */ + for (ksi = *head; ksi != NULL; ksi = ksi->ksi_next) { + last = ksi; + + if (ksi->ksi_instance != ksp->ks_instance) + continue; + + if (strcmp(ksi->ksi_name, ksp->ks_name) != 0) + continue; + + ksi->ksi_ksp = ksp; + ninstances++; + break; + } + + if (ksi != NULL) + continue; + + if ((ksi = malloc(sizeof (kstat_instance_t))) == NULL) + fatal("could not allocate memory for stat instance"); + + bzero(ksi, sizeof (kstat_instance_t)); + (void) strlcpy(ksi->ksi_name, ksp->ks_name, KSTAT_STRLEN); + ksi->ksi_instance = ksp->ks_instance; + ksi->ksi_ksp = ksp; + ksi->ksi_next = NULL; + + if (last == NULL) { + assert(*head == NULL); + *head = ksi; + } else { + last->ksi_next = ksi; + } + + ninstances++; + } + + /* + * Now we know how many instances we have; iterate back over them, + * pruning the stale ones and adding the active ones to a holding + * array in which to sort them. + */ + sorted = (void *)alloca(ninstances * sizeof (kstat_instance_t *)); + ninstances = 0; + + for (ksi = *head; ksi != NULL; ksi = next) { + next = ksi->ksi_next; + + if (ksi->ksi_ksp == NULL) { + free(ksi); + } else { + sorted[ninstances++] = ksi; + } + } + + if (ninstances == 0) { + *head = NULL; + return; + } + + qsort(sorted, ninstances, sizeof (kstat_instance_t *), + kstat_instances_compare); + + *head = sorted[0]; + + for (i = 0; i < ninstances; i++) { + ksi = sorted[i]; + ksi->ksi_next = i < ninstances - 1 ? sorted[i + 1] : NULL; + } +} + +void +kstat_instances_read(kstat_ctl_t *kcp, kstat_instance_t *instances, + kstat_field_t *fields) +{ + kstat_instance_t *ksi; + int i, nfields; + + for (nfields = 0; fields[nfields].ksf_header != NULL; nfields++) + continue; + + for (ksi = instances; ksi != NULL; ksi = ksi->ksi_next) { + kstat_t *ksp = ksi->ksi_ksp; + + if (ksp == NULL) + continue; + + if (kstat_read(kcp, ksp, NULL) == -1) { + if (errno == ENXIO) { + /* + * Our kstat has been removed since the update; + * NULL it out to prevent us from trying to read + * it again (and to indicate that it should not + * be displayed) and drive on. + */ + ksi->ksi_ksp = NULL; + continue; + } + + fatal("failed to read kstat %s:%d", + ksi->ksi_name, ksi->ksi_instance); + } + + if (ksp->ks_type != KSTAT_TYPE_NAMED) { + fatal("%s:%d is not a named kstat", ksi->ksi_name, + ksi->ksi_instance); + } + + if (ksi->ksi_data[0] == NULL) { + size_t size = nfields * sizeof (uint64_t) * 2; + uint64_t *data; + + if ((data = malloc(size)) == NULL) + fatal("could not allocate memory"); + + bzero(data, size); + ksi->ksi_data[0] = data; + ksi->ksi_data[1] = &data[nfields]; + } + + for (i = 0; i < nfields; i++) { + kstat_named_t *nm = KSTAT_NAMED_PTR(ksp); + kstat_field_t *field = &fields[i]; + int hint = field->ksf_hint; + + if (field->ksf_name == NULL) + continue; + + if (hint < 0 || hint >= ksp->ks_ndata || + strcmp(field->ksf_name, nm[hint].name) != 0) { + hint = kstat_field_hint(ksp, field); + } + + if (field->ksf_flags & KSTAT_FIELD_STRING) + ksi->ksi_data[ksi->ksi_gen][i] = + (uint64_t)(uintptr_t) + nm[hint].value.str.addr.ptr; + else + ksi->ksi_data[ksi->ksi_gen][i] = + nm[hint].value.ui64; + } + + ksi->ksi_snaptime[ksi->ksi_gen] = ksp->ks_snaptime; + ksi->ksi_gen ^= 1; + } +} + +uint64_t +kstat_instances_delta(kstat_instance_t *ksi, int i) +{ + int gen = ksi->ksi_gen; + uint64_t delta = ksi->ksi_data[gen ^ 1][i] - ksi->ksi_data[gen][i]; + uint64_t tdelta = ksi->ksi_snaptime[gen ^ 1] - ksi->ksi_snaptime[gen]; + + return (((delta * (uint64_t)NANOSEC) + (tdelta / 2)) / tdelta); +} + +void +kstat_instances_print(kstat_instance_t *instances, kstat_field_t *fields, + boolean_t header) +{ + kstat_instance_t *ksi = instances; + int i, nfields; + + for (nfields = 0; fields[nfields].ksf_header != NULL; nfields++) + continue; + + if (header) { + for (i = 0; i < nfields; i++) { + if (fields[i].ksf_flags & KSTAT_FIELD_LJUST) { + (void) printf("%s%c", fields[i].ksf_header, + i < nfields - 1 ? ' ' : '\n'); + continue; + } + (void) printf("%*s%c", fields[i].ksf_width, + fields[i].ksf_header, i < nfields - 1 ? ' ' : '\n'); + } + } + + for (ksi = instances; ksi != NULL; ksi = ksi->ksi_next) { + if (ksi->ksi_snaptime[1] == 0 || ksi->ksi_ksp == NULL) + continue; + + for (i = 0; i < nfields; i++) { + char trailer = i < nfields - 1 ? ' ' : '\n'; + + if (fields[i].ksf_flags & KSTAT_FIELD_FILLER) { + (void) printf("%*s%c", fields[i].ksf_width, + fields[i].ksf_header, trailer); + continue; + } + + if (fields[i].ksf_flags & KSTAT_FIELD_STRING) { + (void) printf("%*s%c", fields[i].ksf_width, + (char *)(uintptr_t)ksi->ksi_data[ + ksi->ksi_gen ^ 1][i], + trailer); + continue; + } + + if (fields[i].ksf_flags & KSTAT_FIELD_UNIT) { + char buf[128]; + size_t flen = fields[i].ksf_width + 1; + const char *suffix = ""; + + if (fields[i].ksf_suffix != NULL) { + suffix = fields[i].ksf_suffix; + flen -= strlen(fields[i].ksf_suffix); + } + + kstat_nicenum(fields[i].ksf_flags & + KSTAT_FIELD_NODELTA ? + ksi->ksi_data[ksi->ksi_gen ^ 1][i] : + kstat_instances_delta(ksi, i), buf, + MIN(sizeof (buf), flen)); + (void) printf("%*s%s%c", flen - 1, buf, + suffix, trailer); + continue; + } + + (void) printf("%*lld%c", fields[i].ksf_width, + fields[i].ksf_flags & KSTAT_FIELD_USEINSTANCE ? + ksi->ksi_instance : + fields[i].ksf_flags & KSTAT_FIELD_NODELTA ? + ksi->ksi_data[ksi->ksi_gen ^ 1][i] : + kstat_instances_delta(ksi, i), trailer); + } + } +} + +static boolean_t +interested(kstat_t *ksp) +{ + const char *module = "vnd"; + const char *class = "net"; + + if (strcmp(ksp->ks_module, module) != 0) + return (B_FALSE); + + if (strcmp(ksp->ks_class, class) != 0) + return (B_FALSE); + + return (B_TRUE); +} + +/* BEGIN CSTYLED */ +char *g_usage = "Usage: vndstat [interval [count]]\n" + "\n" + " Displays statistics for active vnd devices, with one line per device.\n" + " All statistics are reported as per-second rates.\n" + "\n" + " The columns are as follows:\n" + "\n" + " zone => name of the zone with the device\n" + " name => name of the vnd device\n" + " rx => bytes received\n" + " tx => bytes transmitted\n" + " drops => number of dropped packets\n" + " txfc => number of transmit flow control events\n" + "\n"; +/* END CSTYLED */ + +void +usage() +{ + (void) fprintf(stderr, "%s", g_usage); + exit(EXIT_FAILURE); +} + +/*ARGSUSED*/ +void +intr(int sig) +{} + +/*ARGSUSED*/ +int +main(int argc, char **argv) +{ + kstat_ctl_t *kcp; + kstat_instance_t *instances = NULL; + int i = 0; + int interval = 1; + int count = INT32_MAX; + struct itimerval itimer; + struct sigaction act; + sigset_t set; + char *endp; + + kstat_field_t fields[] = { + { "name", "linkname", 6, KSTAT_FIELD_STRING }, + { "|", NULL, 1, KSTAT_FIELD_FILLER }, + { "rx B/s", "rbytes", 8, KSTAT_FIELD_UNIT, "B/s" }, + { "|", NULL, 1, KSTAT_FIELD_FILLER }, + { "tx B/s", "obytes", 8, KSTAT_FIELD_UNIT, "B/s" }, + { "|", NULL, 1, KSTAT_FIELD_FILLER }, + { "drops", "total_drops", 5 }, + { "txfc", "flowcontrol_events", 4 }, + { "|", NULL, 1, KSTAT_FIELD_FILLER }, + { "zone", "zonename", 36, + KSTAT_FIELD_STRING | KSTAT_FIELD_LJUST }, + { NULL } + }; + + if (argc > 1) { + interval = strtol(argv[1], &endp, 10); + + if (*endp != '\0' || interval <= 0) + usage(); + } + + if (argc > 2) { + count = strtol(argv[2], &endp, 10); + + if (*endp != '\0' || count <= 0) + usage(); + } + + if ((kcp = kstat_open()) == NULL) + fatal("could not open /dev/kstat"); + + (void) sigemptyset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = intr; + (void) sigaction(SIGALRM, &act, NULL); + + (void) sigemptyset(&set); + (void) sigaddset(&set, SIGALRM); + (void) sigprocmask(SIG_BLOCK, &set, NULL); + + bzero(&itimer, sizeof (itimer)); + itimer.it_value.tv_sec = interval; + itimer.it_interval.tv_sec = interval; + + if (setitimer(ITIMER_REAL, &itimer, NULL) != 0) { + fatal("could not set timer to %d second%s", interval, + interval == 1 ? "" : "s"); + } + + (void) sigemptyset(&set); + + for (;;) { + kstat_instances_update(kcp, &instances, interested); + kstat_instances_read(kcp, instances, fields); + + if (i++ > 0) { + kstat_instances_print(instances, fields, + instances != NULL && instances->ksi_next == NULL ? + (((i - 2) % 20) == 0) : B_TRUE); + } + + if (i > count) + break; + + (void) sigsuspend(&set); + } + + /*NOTREACHED*/ + return (0); +} diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c index 1ed01b4048..dadaf44126 100644 --- a/usr/src/cmd/zfs/zfs_main.c +++ b/usr/src/cmd/zfs/zfs_main.c @@ -225,7 +225,7 @@ get_usage(zfs_help_t idx) "<filesystem|volume>@<snap>[%<snap>][,...]\n" "\tdestroy <filesystem|volume>#<bookmark>\n")); case HELP_GET: - return (gettext("\tget [-rHp] [-d max] " + return (gettext("\tget [-crHp] [-d max] " "[-o \"all\" | field[,...]]\n" "\t [-t type[,...]] [-s source[,...]]\n" "\t <\"all\" | property[,...]> " @@ -580,7 +580,7 @@ finish_progress(char *done) } /* - * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol> + * zfs clone [-Fp] [-o prop=value] ... <snap> <fs | vol> * * Given an existing dataset, create a writable copy whose initial contents * are the same as the source. The newly created dataset maintains a @@ -588,12 +588,18 @@ finish_progress(char *done) * the clone exists. * * The '-p' flag creates all the non-existing ancestors of the target first. + * + * The '-F' flag retries the zfs_mount() operation as long as zfs_mount() is + * still returning EBUSY. Any callers which specify -F should be careful to + * ensure that no other process has a persistent hold on the mountpoint's + * directory. */ static int zfs_do_clone(int argc, char **argv) { zfs_handle_t *zhp = NULL; boolean_t parents = B_FALSE; + boolean_t keeptrying = B_FALSE; nvlist_t *props; int ret = 0; int c; @@ -602,8 +608,11 @@ zfs_do_clone(int argc, char **argv) nomem(); /* check options */ - while ((c = getopt(argc, argv, "o:p")) != -1) { + while ((c = getopt(argc, argv, "Fo:p")) != -1) { switch (c) { + case 'F': + keeptrying = B_TRUE; + break; case 'o': if (parseprop(props, optarg) != 0) return (1); @@ -664,9 +673,14 @@ zfs_do_clone(int argc, char **argv) clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET); if (clone != NULL) { - if (zfs_get_type(clone) != ZFS_TYPE_VOLUME) - if ((ret = zfs_mount(clone, NULL, 0)) == 0) + if (zfs_get_type(clone) != ZFS_TYPE_VOLUME) { + while ((ret = zfs_mount(clone, NULL, 0)) != 0) { + if (!keeptrying || errno != EBUSY) + break; + } + if (ret == 0) ret = zfs_share(clone); + } zfs_close(clone); } } @@ -890,12 +904,13 @@ badusage: } /* - * zfs destroy [-rRf] <fs, vol> + * zfs destroy [-rRfF] <fs, vol> * zfs destroy [-rRd] <snap> * * -r Recursively destroy all children * -R Recursively destroy all dependents, including clones * -f Force unmounting of any dependents + * -F Continue retrying on seeing EBUSY * -d If we can't destroy now, mark for deferred destruction * * Destroys the given dataset. By default, it will unmount any filesystems, @@ -905,6 +920,7 @@ badusage: typedef struct destroy_cbdata { boolean_t cb_first; boolean_t cb_force; + boolean_t cb_wait; boolean_t cb_recurse; boolean_t cb_error; boolean_t cb_doclones; @@ -988,13 +1004,18 @@ out: static int destroy_callback(zfs_handle_t *zhp, void *data) { - destroy_cbdata_t *cb = data; + destroy_cbdata_t *cbp = data; + struct timespec ts; + int err = 0; + + ts.tv_sec = 0; + ts.tv_nsec = 500 * (NANOSEC / MILLISEC); const char *name = zfs_get_name(zhp); - if (cb->cb_verbose) { - if (cb->cb_parsable) { + if (cbp->cb_verbose) { + if (cbp->cb_parsable) { (void) printf("destroy\t%s\n", name); - } else if (cb->cb_dryrun) { + } else if (cbp->cb_dryrun) { (void) printf(gettext("would destroy %s\n"), name); } else { @@ -1009,13 +1030,10 @@ destroy_callback(zfs_handle_t *zhp, void *data) */ if (strchr(zfs_get_name(zhp), '/') == NULL && zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { - zfs_close(zhp); - return (0); - } - if (cb->cb_dryrun) { - zfs_close(zhp); - return (0); + goto out; } + if (cbp->cb_dryrun) + goto out; /* * We batch up all contiguous snapshots (even of different @@ -1024,23 +1042,66 @@ destroy_callback(zfs_handle_t *zhp, void *data) * because we must delete a clone before its origin. */ if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) { - fnvlist_add_boolean(cb->cb_batchedsnaps, name); - } else { - int error = zfs_destroy_snaps_nvl(g_zfs, - cb->cb_batchedsnaps, B_FALSE); - fnvlist_free(cb->cb_batchedsnaps); - cb->cb_batchedsnaps = fnvlist_alloc(); - - if (error != 0 || - zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 || - zfs_destroy(zhp, cb->cb_defer_destroy) != 0) { - zfs_close(zhp); - return (-1); + fnvlist_add_boolean(cbp->cb_batchedsnaps, name); + goto out; + } + + if (cbp->cb_wait) + libzfs_print_on_error(g_zfs, B_FALSE); + + /* + * Unless instructed to retry on EBUSY, bail out on the first error. + * When retrying, try every 500ms until either succeeding or seeing a + * non-EBUSY error code. + */ + while ((err = zfs_destroy_snaps_nvl(g_zfs, + cbp->cb_batchedsnaps, B_FALSE)) != 0) { + if (cbp->cb_wait && libzfs_errno(g_zfs) == EZFS_BUSY) { + nanosleep(&ts, NULL); + continue; + } + (void) fprintf(stderr, "%s: %s\n", + libzfs_error_action(g_zfs), + libzfs_error_description(g_zfs)); + break; + } + + fnvlist_free(cbp->cb_batchedsnaps); + cbp->cb_batchedsnaps = fnvlist_alloc(); + + if (err != 0) + goto out; + + while ((err = zfs_unmount(zhp, NULL, + cbp->cb_force ? MS_FORCE : 0)) != 0) { + if (cbp->cb_wait && libzfs_errno(g_zfs) == EZFS_BUSY) { + (void) nanosleep(&ts, NULL); + continue; } + (void) fprintf(stderr, "%s: %s\n", + libzfs_error_action(g_zfs), + libzfs_error_description(g_zfs)); + break; } + if (err != 0) + goto out; + + while ((err = zfs_destroy(zhp, cbp->cb_defer_destroy)) != 0) { + if (cbp->cb_wait && libzfs_errno(g_zfs) == EZFS_BUSY) { + (void) nanosleep(&ts, NULL); + continue; + } + (void) fprintf(stderr, "%s: %s\n", + libzfs_error_action(g_zfs), + libzfs_error_description(g_zfs)); + break; + } + +out: + libzfs_print_on_error(g_zfs, B_TRUE); zfs_close(zhp); - return (0); + return (err); } static int @@ -1196,7 +1257,7 @@ zfs_do_destroy(int argc, char **argv) zfs_type_t type = ZFS_TYPE_DATASET; /* check options */ - while ((c = getopt(argc, argv, "vpndfrR")) != -1) { + while ((c = getopt(argc, argv, "vpndfFrR")) != -1) { switch (c) { case 'v': cb.cb_verbose = B_TRUE; @@ -1215,6 +1276,9 @@ zfs_do_destroy(int argc, char **argv) case 'f': cb.cb_force = B_TRUE; break; + case 'F': + cb.cb_wait = B_TRUE; + break; case 'r': cb.cb_recurse = B_TRUE; break; @@ -1585,8 +1649,11 @@ zfs_do_get(int argc, char **argv) cb.cb_type = ZFS_TYPE_DATASET; /* check options */ - while ((c = getopt(argc, argv, ":d:o:s:rt:Hp")) != -1) { + while ((c = getopt(argc, argv, ":d:o:s:rt:Hcp")) != -1) { switch (c) { + case 'c': + libzfs_set_cachedprops(g_zfs, B_TRUE); + break; case 'p': cb.cb_literal = B_TRUE; break; @@ -3016,6 +3083,7 @@ zfs_do_list(int argc, char **argv) int types = ZFS_TYPE_DATASET; boolean_t types_specified = B_FALSE; char *fields = NULL; + zprop_list_t *pl; list_cbdata_t cb = { 0 }; char *value; int limit = 0; @@ -3127,6 +3195,18 @@ zfs_do_list(int argc, char **argv) != 0) usage(B_FALSE); + /* + * The default set of properties contains only properties which can be + * retrieved from the set of cached properties. If any user-specfied + * properties cannot be retrieved from that set, unset the cachedprops + * flags on the ZFS handle. + */ + libzfs_set_cachedprops(g_zfs, B_TRUE); + for (pl = cb.cb_proplist; pl != NULL; pl = pl->pl_next) { + if (zfs_prop_cacheable(pl->pl_prop)) + libzfs_set_cachedprops(g_zfs, B_FALSE); + } + cb.cb_first = B_TRUE; ret = zfs_for_each(argc, argv, flags, types, sortcol, &cb.cb_proplist, diff --git a/usr/src/cmd/zlogin/zlogin.c b/usr/src/cmd/zlogin/zlogin.c index 296c32be01..c829459e50 100644 --- a/usr/src/cmd/zlogin/zlogin.c +++ b/usr/src/cmd/zlogin/zlogin.c @@ -22,11 +22,12 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2013 DEY Storage Systems, Inc. * Copyright (c) 2014 Gary Mills + * Copyright 2015 Joyent, Inc. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* - * zlogin provides three types of login which allow users in the global + * zlogin provides five types of login which allow users in the global * zone to access non-global zones. * * - "interactive login" is similar to rlogin(1); for example, the user could @@ -42,12 +43,22 @@ * In this mode, zlogin sets up pipes as the communication channel, and * 'su' is used to do the login setup work. * + * - "interactive command" is a combination of the above two modes where + * a command is provide like the non-interactive case, but the -i option is + * also provided to make things interactive. For example, the user could + * issue 'zlogin -i my-zone /bin/sh'. In this mode neither 'login -c' nor + * 'su root -c' is prepended to the command invocation. Because of this + * there will be no wtmpx login record within the zone. + * * - "console login" is the equivalent to accessing the tip line for a * zone. For example, the user can issue 'zlogin -C my-zone'. * In this mode, zlogin contacts the zoneadmd process via unix domain * socket. If zoneadmd is not running, it starts it. This allows the * console to be available anytime the zone is installed, regardless of * whether it is running. + * + * - "standalone-processs interactive" is specified with -I and connects to + * the zone's stdin, stdout and stderr zfd(7D) devices. */ #include <sys/socket.h> @@ -92,7 +103,8 @@ #include <auth_attr.h> #include <secdb.h> -static int masterfd; +static int masterfd = -1; +static int ctlfd = -1; static struct termios save_termios; static struct termios effective_termios; static int save_fd; @@ -101,12 +113,13 @@ static volatile int dead; static volatile pid_t child_pid = -1; static int interactive = 0; static priv_set_t *dropprivs; +static unsigned int connect_flags = 0; static int nocmdchar = 0; static int failsafe = 0; -static int disconnect = 0; static char cmdchar = '~'; static int quiet = 0; +static char zonebrand[MAXNAMELEN]; static int pollerr = 0; @@ -123,10 +136,12 @@ static boolean_t forced_login = B_FALSE; #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ #endif -#define SUPATH "/usr/bin/su" +#define SUPATH1 "/usr/bin/su" +#define SUPATH2 "/bin/su" #define FAILSAFESHELL "/sbin/sh" #define DEFAULTSHELL "/sbin/sh" #define DEF_PATH "/usr/sbin:/usr/bin" +#define LX_DEF_PATH "/bin:/usr/sbin:/usr/bin" #define CLUSTER_BRAND_NAME "cluster" @@ -153,7 +168,7 @@ static boolean_t forced_login = B_FALSE; static void usage(void) { - (void) fprintf(stderr, gettext("usage: %s [ -dnQCES ] [ -e cmdchar ] " + (void) fprintf(stderr, gettext("usage: %s [-dinCEINQS] [-e cmdchar] " "[-l user] zonename [command [args ...] ]\n"), pname); exit(2); } @@ -248,19 +263,11 @@ postfork_dropprivs() } } -/* - * Create the unix domain socket and call the zoneadmd server; handshake - * with it to determine whether it will allow us to connect. - */ static int -get_console_master(const char *zname) +connect_zone_sock(const char *zname, const char *suffix) { int sockfd = -1; struct sockaddr_un servaddr; - char clientid[MAXPATHLEN]; - char handshake[MAXPATHLEN], c; - int msglen; - int i = 0, err = 0; if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { zperror(gettext("could not create socket")); @@ -270,35 +277,44 @@ get_console_master(const char *zname) bzero(&servaddr, sizeof (servaddr)); servaddr.sun_family = AF_UNIX; (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path), - "%s/%s.console_sock", ZONES_TMPDIR, zname); - + "%s/%s.%s", ZONES_TMPDIR, zname, suffix); if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof (servaddr)) == -1) { - zperror(gettext("Could not connect to zone console")); - goto bad; + zperror(gettext("Could not connect to zone")); + close(sockfd); + return (-1); } - masterfd = sockfd; + return (sockfd); +} - msglen = snprintf(clientid, sizeof (clientid), "IDENT %lu %s %d\n", - getpid(), setlocale(LC_MESSAGES, NULL), disconnect); + +static int +handshake_zone_sock(int sockfd, unsigned int flags) +{ + char clientid[MAXPATHLEN]; + char handshake[MAXPATHLEN], c; + int msglen; + int i = 0, err = 0; + + msglen = snprintf(clientid, sizeof (clientid), "IDENT %s %u\n", + setlocale(LC_MESSAGES, NULL), flags); if (msglen >= sizeof (clientid) || msglen < 0) { zerror("protocol error"); - goto bad; + return (-1); } - if (write(masterfd, clientid, msglen) != msglen) { + if (write(sockfd, clientid, msglen) != msglen) { zerror("protocol error"); - goto bad; + return (-1); } - bzero(handshake, sizeof (handshake)); - /* * Take care not to accumulate more than our fill, and leave room for * the NUL at the end. */ - while ((err = read(masterfd, &c, 1)) == 1) { + bzero(handshake, sizeof (handshake)); + while ((err = read(sockfd, &c, 1)) == 1) { if (i >= (sizeof (handshake) - 1)) break; if (c == '\n') @@ -308,26 +324,48 @@ get_console_master(const char *zname) } /* - * If something went wrong during the handshake we bail; perhaps - * the server died off. + * If something went wrong during the handshake we bail. + * Perhaps the server died off. */ if (err == -1) { - zperror(gettext("Could not connect to zone console")); - goto bad; + zperror(gettext("Could not connect to zone")); + return (-1); } - if (strncmp(handshake, "OK", sizeof (handshake)) == 0) - return (0); + if (strncmp(handshake, "OK", sizeof (handshake)) != 0) { + zerror(gettext("Zone is already in use by process ID %s."), + handshake); + return (-1); + } - zerror(gettext("Console is already in use by process ID %s."), - handshake); -bad: - (void) close(sockfd); - masterfd = -1; - return (-1); + return (0); } - +static int +send_ctl_sock(const char *buf, size_t len) +{ + char rbuf[BUFSIZ]; + int i; + if (ctlfd == -1) { + return (-1); + } + if (write(ctlfd, buf, len) != len) { + return (-1); + } + /* read the response */ + for (i = 0; i < (BUFSIZ - 1); i++) { + char c; + if (read(ctlfd, &c, 1) != 1 || c == '\n' || c == '\0') { + break; + } + rbuf[i] = c; + } + rbuf[i+1] = '\0'; + if (strncmp("OK", rbuf, BUFSIZ) != 0) { + return (-1); + } + return (0); +} /* * Routines to handle pty creation upon zone entry and to shuttle I/O back * and forth between the two terminals. We also compute and store the @@ -516,8 +554,32 @@ sigwinch(int s) { struct winsize ws; - if (ioctl(0, TIOCGWINSZ, &ws) == 0) - (void) ioctl(masterfd, TIOCSWINSZ, &ws); + if (ioctl(0, TIOCGWINSZ, &ws) == 0) { + if (ctlfd != -1) { + char buf[BUFSIZ]; + snprintf(buf, sizeof (buf), "TIOCSWINSZ %hu %hu\n", + ws.ws_row, ws.ws_col); + (void) send_ctl_sock(buf, strlen(buf)); + } else { + (void) ioctl(masterfd, TIOCSWINSZ, &ws); + } + } +} + +/* + * Toggle zfd EOF mode and notify zoneadmd + */ +/*ARGSUSED*/ +static void +sigusr1(int s) +{ + connect_flags ^= ZLOGIN_ZFD_EOF; + if (ctlfd != -1) { + char buf[BUFSIZ]; + snprintf(buf, sizeof (buf), "SETFLAGS %u\n", + connect_flags); + (void) send_ctl_sock(buf, strlen(buf)); + } } static volatile int close_on_sig = -1; @@ -862,28 +924,28 @@ doio(int stdin_fd, int appin_fd, int stdout_fd, int stderr_fd, int sig_fd, break; } - /* event from master side stdout */ - if (pollfds[0].revents) { - if (pollfds[0].revents & + /* event from master side stderr */ + if (pollfds[1].revents) { + if (pollfds[1].revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { - if (process_output(stdout_fd, STDOUT_FILENO) + if (process_output(stderr_fd, STDERR_FILENO) != 0) break; } else { - pollerr = pollfds[0].revents; + pollerr = pollfds[1].revents; break; } } - /* event from master side stderr */ - if (pollfds[1].revents) { - if (pollfds[1].revents & + /* event from master side stdout */ + if (pollfds[0].revents) { + if (pollfds[0].revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { - if (process_output(stderr_fd, STDERR_FILENO) + if (process_output(stdout_fd, STDOUT_FILENO) != 0) break; } else { - pollerr = pollfds[1].revents; + pollerr = pollfds[0].revents; break; } } @@ -1053,7 +1115,7 @@ zone_login_cmd(brand_handle_t bh, const char *login) * but we're going to be very simplistic about it and break stuff * up based on spaces. We're not even going to support any kind * of quoting or escape characters. It's truly amazing that - * there is no library function in OpenSolaris to do this for us. + * there is no library function in Illumos to do this for us. */ /* @@ -1099,7 +1161,7 @@ zone_login_cmd(brand_handle_t bh, const char *login) * checks). */ static char ** -prep_args(brand_handle_t bh, const char *login, char **argv) +prep_args(brand_handle_t bh, char *zonename, const char *login, char **argv) { int argc = 0, a = 0, i, n = -1; char **new_argv; @@ -1112,35 +1174,105 @@ prep_args(brand_handle_t bh, const char *login, char **argv) argc++; for (i = 0; i < argc; i++) { - subshell_len += strlen(argv[i]) + 1; + /* + * Allocate enough space for the delimiter and 2 + * quotes which might be needed. + */ + subshell_len += strlen(argv[i]) + 3; } if ((subshell = calloc(1, subshell_len)) == NULL) return (NULL); + /* + * The handling of quotes in the following block may seem + * unusual, but it is done this way for backward compatibility. + * When running a command, zlogin is documented as: + * zlogin zonename command args + * However, some code has come to depend on the following usage: + * zlogin zonename 'command args' + * This relied on the fact that the single argument would be + * re-parsed within the zone and excuted as a command with an + * argument. To remain compatible with this (incorrect) usage, + * if there is only a single argument, it is not quoted, even + * if it has embedded spaces. + * + * Here are two examples which both need to work: + * 1) zlogin foo 'echo hello' + * This has a single argv member with a space in it but will + * not be quoted on the command passed into the zone. + * 2) zlogin foo bash -c 'echo hello' + * This has 3 argv members. The 3rd arg has a space and must + * be quoted on the command passed into the zone. + */ for (i = 0; i < argc; i++) { - (void) strcat(subshell, argv[i]); - (void) strcat(subshell, " "); + if (i > 0) + (void) strcat(subshell, " "); + + if (argc > 1 && (strchr(argv[i], ' ') != NULL || + strchr(argv[i], '\t') != NULL)) { + (void) strcat(subshell, "'"); + (void) strcat(subshell, argv[i]); + (void) strcat(subshell, "'"); + } else { + (void) strcat(subshell, argv[i]); + } } if (failsafe) { n = 4; - if ((new_argv = malloc(sizeof (char *) * n)) == NULL) - return (NULL); + } else { + n = 6; + } + if ((new_argv = malloc(sizeof (char *) * n)) == NULL) + return (NULL); + + if (failsafe) { new_argv[a++] = FAILSAFESHELL; + new_argv[a++] = "-c"; } else { - n = 5; - if ((new_argv = malloc(sizeof (char *) * n)) == NULL) + struct stat sb; + char zonepath[MAXPATHLEN]; + char supath[MAXPATHLEN]; + + /* + * We allocated an extra slot in case our login below + * is not 'root' but normally we don't take that code + * path. + */ + n--; + + if (zone_get_zonepath(zonename, zonepath, + sizeof (zonepath)) != Z_OK) { + zerror(gettext("unable to determine zone " + "path")); return (NULL); + } + + (void) snprintf(supath, sizeof (supath), "%s/root/%s", + zonepath, SUPATH1); + if (stat(supath, &sb) == 0) { + new_argv[a++] = SUPATH1; + } else { + (void) snprintf(supath, sizeof (supath), + "%s/root/%s", zonepath, SUPATH2); + if (stat(supath, &sb) == 0) { + new_argv[a++] = SUPATH2; + } else { + zerror(gettext("unable to find 'su' " + "command")); + return (NULL); + } + } - new_argv[a++] = SUPATH; if (strcmp(login, "root") != 0) { new_argv[a++] = "-"; n++; } new_argv[a++] = (char *)login; + new_argv[a++] = "-c"; } - new_argv[a++] = "-c"; + new_argv[a++] = subshell; new_argv[a++] = NULL; assert(a == n); @@ -1185,6 +1317,7 @@ prep_env() int e = 0, size = 1; char **new_env, *estr; char *term = getenv("TERM"); + char *path; size++; /* for $PATH */ if (term != NULL) @@ -1201,7 +1334,12 @@ prep_env() if ((new_env = malloc(sizeof (char *) * size)) == NULL) return (NULL); - if ((estr = add_env("PATH", DEF_PATH)) == NULL) + if (strcmp(zonebrand, "lx") == 0) + path = LX_DEF_PATH; + else + path = DEF_PATH; + + if ((estr = add_env("PATH", path)) == NULL) return (NULL); new_env[e++] = estr; @@ -1723,24 +1861,55 @@ get_username() return (nptr->pw_name); } +static boolean_t +zlog_mode_logging(char *zonename) +{ + boolean_t lm = B_FALSE; + zone_dochandle_t handle; + struct zone_attrtab attr; + + if ((handle = zonecfg_init_handle()) == NULL) + return (lm); + + if (zonecfg_get_handle(zonename, handle) != Z_OK) + goto done; + + if (zonecfg_setattrent(handle) != Z_OK) + goto done; + while (zonecfg_getattrent(handle, &attr) == Z_OK) { + if (strcmp("zlog-mode", attr.zone_attr_name) == 0) { + if (strncmp("log", attr.zone_attr_value, 3) == 0) + lm = B_TRUE; + break; + } + } + (void) zonecfg_endattrent(handle); + +done: + zonecfg_fini_handle(handle); + return (lm); +} + int main(int argc, char **argv) { - int arg, console = 0; + int arg, console = 0, imode = 0; + int estatus = 0; zoneid_t zoneid; zone_state_t st; char *login = "root"; + int iflag = 0; int lflag = 0; int nflag = 0; char *zonename = NULL; char **proc_args = NULL; char **new_args, **new_env; sigset_t block_cld; + siginfo_t si; char devroot[MAXPATHLEN]; char *slavename, slaveshortname[MAXPATHLEN]; priv_set_t *privset; int tmpl_fd; - char zonebrand[MAXNAMELEN]; char default_brand[MAXNAMELEN]; struct stat sb; char kernzone[ZONENAME_MAX]; @@ -1754,7 +1923,7 @@ main(int argc, char **argv) (void) getpname(argv[0]); username = get_username(); - while ((arg = getopt(argc, argv, "dnECR:Se:l:Q")) != EOF) { + while ((arg = getopt(argc, argv, "diNnECIR:Se:l:Q")) != EOF) { switch (arg) { case 'C': console = 1; @@ -1762,6 +1931,16 @@ main(int argc, char **argv) case 'E': nocmdchar = 1; break; + case 'I': + /* + * interactive mode is just a slight variation on the + * console mode. + */ + console = 1; + imode = 1; + /* The default is HUP, disconnect on EOF */ + connect_flags ^= ZLOGIN_ZFD_EOF; + break; case 'R': /* undocumented */ if (*optarg != '/') { zerror(gettext("root path must be absolute.")); @@ -1781,15 +1960,22 @@ main(int argc, char **argv) failsafe = 1; break; case 'd': - disconnect = 1; + connect_flags |= ZLOGIN_DISCONNECT; break; case 'e': set_cmdchar(optarg); break; + case 'i': + iflag = 1; + break; case 'l': login = optarg; lflag = 1; break; + case 'N': + /* NOHUP - do not send EOF */ + connect_flags ^= ZLOGIN_ZFD_EOF; + break; case 'n': nflag = 1; break; @@ -1800,6 +1986,12 @@ main(int argc, char **argv) if (console != 0) { + /* + * The only connect option in console mode is ZLOGIN_DISCONNECT + */ + if (imode == 0) + connect_flags &= ZLOGIN_DISCONNECT; + if (lflag != 0) { zerror(gettext( "-l may not be specified for console login")); @@ -1826,17 +2018,27 @@ main(int argc, char **argv) } + if (iflag != 0 && nflag != 0) { + zerror(gettext("-i and -n flags are incompatible")); + usage(); + } + if (failsafe != 0 && lflag != 0) { zerror(gettext("-l may not be specified for failsafe login")); usage(); } - if (!console && disconnect != 0) { + if (!console && (connect_flags & ZLOGIN_DISCONNECT) != 0) { zerror(gettext( "-d may only be specified with console login")); usage(); } + if (imode == 0 && (connect_flags & ZLOGIN_ZFD_EOF) != 0) { + zerror(gettext("-N may only be specified with -I")); + usage(); + } + if (optind == (argc - 1)) { /* * zone name, no process name; this should be an interactive @@ -1859,7 +2061,8 @@ main(int argc, char **argv) /* zone name and process name, and possibly some args */ zonename = argv[optind]; proc_args = &argv[optind + 1]; - interactive = 0; + if (iflag && isatty(STDIN_FILENO)) + interactive = 1; } else { usage(); } @@ -1945,10 +2148,16 @@ main(int argc, char **argv) } /* - * The console is a separate case from the rest of the code; handle - * it first. + * The console (or standalong interactive mode) is a separate case from + * the rest of the code; handle it first. */ if (console) { + int gz_stderr_fd = -1; + boolean_t set_raw = B_TRUE; + + if (imode && zlog_mode_logging(zonename)) + set_raw = B_FALSE; + /* * Ensure that zoneadmd for this zone is running. */ @@ -1958,15 +2167,49 @@ main(int argc, char **argv) /* * Make contact with zoneadmd. */ - if (get_console_master(zonename) == -1) - return (1); + if (!imode) { + masterfd = connect_zone_sock(zonename, "console_sock"); + if (masterfd == -1) { + return (1); + } + if (handshake_zone_sock(masterfd, + connect_flags) != 0) { + (void) close(masterfd); + return (1); + } + } else { + /* handshake with the control socket first */ + ctlfd = connect_zone_sock(zonename, "server_ctl"); + if (ctlfd == -1) { + return (1); + } + if (handshake_zone_sock(ctlfd, + connect_flags) != 0) { + (void) close(ctlfd); + return (1); + } + /* then open the io-related sockets */ + masterfd = connect_zone_sock(zonename, "server_out"); + gz_stderr_fd = connect_zone_sock(zonename, + "server_err"); + if (masterfd == -1 || gz_stderr_fd == -1) { + (void) close(ctlfd); + (void) close(masterfd); + (void) close(gz_stderr_fd); + return (1); + } + } - if (!quiet) - (void) printf( - gettext("[Connected to zone '%s' console]\n"), - zonename); + if (!quiet) { + if (imode) + (void) printf(gettext("[Connected to zone '%s' " + "interactively]\n"), zonename); + else + (void) printf(gettext("[Connected to zone '%s' " + "console]\n"), zonename); + } - if (set_tty_rawmode(STDIN_FILENO) == -1) { + if (set_raw && set_tty_rawmode(STDIN_FILENO) == -1) { reset_tty(); zperror(gettext("failed to set stdin pty to raw mode")); return (1); @@ -1975,15 +2218,25 @@ main(int argc, char **argv) (void) sigset(SIGWINCH, sigwinch); (void) sigwinch(0); + if (imode) { + /* Allow EOF mode toggling via SIGUSR1 */ + (void) sigset(SIGUSR1, sigusr1); + } + /* * Run the I/O loop until we get disconnected. */ - doio(masterfd, -1, masterfd, -1, -1, B_FALSE); + doio(masterfd, -1, masterfd, gz_stderr_fd, -1, B_FALSE); reset_tty(); - if (!quiet) - (void) printf( - gettext("\n[Connection to zone '%s' console " - "closed]\n"), zonename); + if (!quiet) { + if (imode) + (void) printf(gettext("\n[Interactive " + "connection to zone '%s' closed]\n"), + zonename); + else + (void) printf(gettext("\n[Connection to zone " + "'%s' console closed]\n"), zonename); + } return (0); } @@ -2051,11 +2304,23 @@ main(int argc, char **argv) return (1); } - if ((new_args = prep_args(bh, login, proc_args)) == NULL) { - zperror(gettext("could not assemble new arguments")); - brand_close(bh); - return (1); + /* + * The 'interactive' parameter (-i option) indicates that we're running + * a command interactively. In this case we skip prep_args so that we + * don't prepend the 'su root -c' preamble to the command invocation + * since the 'su' command typically will execute a setpgrp which will + * disassociate the actual command from the controlling terminal that + * we (zlogin) setup. + */ + if (!iflag) { + if ((new_args = prep_args(bh, zonename, login, proc_args)) + == NULL) { + zperror(gettext("could not assemble new arguments")); + brand_close(bh); + return (1); + } } + /* * Get the brand specific user_cmd. This command is used to get * a passwd(4) entry for login. @@ -2201,6 +2466,8 @@ main(int argc, char **argv) return (1); } + /* Note: we're now inside the zone, can't use gettext anymore */ + if (slavefd != STDERR_FILENO) (void) close(STDERR_FILENO); @@ -2242,8 +2509,18 @@ main(int argc, char **argv) /* * In failsafe mode, we don't use login(1), so don't try * setting up a utmpx entry. + * + * A branded zone may have very different utmpx semantics. + * At the moment, we only have two brand types: + * Illumos-like (native, sn1) and Linux. In the Illumos + * case, we know exactly how to do the necessary utmpx + * setup. Fortunately for us, the Linux /bin/login is + * prepared to deal with a non-initialized utmpx entry, so + * we can simply skip it. If future brands don't fall into + * either category, we'll have to add a per-brand utmpx + * setup hook. */ - if (!failsafe) + if (!failsafe && (strcmp(zonebrand, "lx") != 0)) if (setup_utmpx(slaveshortname) == -1) return (1); @@ -2252,13 +2529,17 @@ main(int argc, char **argv) * execute the brand's login program. */ if (setuid(0) == -1) { - zperror(gettext("insufficient privilege")); + zperror("insufficient privilege"); return (1); } - (void) execve(new_args[0], new_args, new_env); - zperror(gettext("exec failure")); - return (1); + if (iflag) { + (void) execve(proc_args[0], proc_args, new_env); + } else { + (void) execve(new_args[0], new_args, new_env); + } + zperror("exec failure"); + return (ENOEXEC); } (void) ct_tmpl_clear(tmpl_fd); @@ -2283,8 +2564,19 @@ main(int argc, char **argv) if (pollerr != 0) { (void) fprintf(stderr, gettext("Error: connection closed due " "to unexpected pollevents=0x%x.\n"), pollerr); - return (1); + return (EPIPE); } - return (0); + /* reap child and get its status */ + if (waitid(P_PID, child_pid, &si, WEXITED | WNOHANG) == -1) { + estatus = errno; + } else if (si.si_pid == 0) { + estatus = ECHILD; + } else if (si.si_code == CLD_EXITED) { + estatus = si.si_status; + } else { + estatus = ECONNABORTED; + } + + return (estatus); } diff --git a/usr/src/cmd/zoneadm/Makefile b/usr/src/cmd/zoneadm/Makefile index 2b01078aec..fba7809c71 100644 --- a/usr/src/cmd/zoneadm/Makefile +++ b/usr/src/cmd/zoneadm/Makefile @@ -21,14 +21,18 @@ # # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # PROG= zoneadm +SCRIPTS= MANIFEST= zones.xml resource-mgmt.xml SVCMETHOD= svc-zones svc-resource-mgmt include ../Makefile.cmd +include ../Makefile.ctf +ROOTUSRSBINSCRIPTS= $(SCRIPTS:%=$(ROOTUSRSBIN)/%) ROOTMANIFESTDIR= $(ROOTSVCSYSTEM) OBJS= zoneadm.o zfs.o @@ -42,13 +46,14 @@ CERRWARN += -_gcc=-Wno-uninitialized .KEEP_STATE: -all: $(PROG) +all: $(PROG) $(SCRIPTS) $(PROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) -install: all $(ROOTUSRSBINPROG) $(ROOTMANIFEST) $(ROOTSVCMETHOD) +install: all $(ROOTUSRSBINPROG) $(ROOTUSRSBINSCRIPTS) $(ROOTMANIFEST) \ + $(ROOTSVCMETHOD) check: $(PROG).c $(CHKMANIFEST) $(CSTYLE) -pP $(SRCS:%=%) @@ -58,7 +63,7 @@ $(POFILE): $(POFILES) $(CAT) $(POFILES) > $@ clean: - $(RM) $(OBJS) $(POFILES) + $(RM) $(OBJS) $(POFILES) $(SCRIPTS) lint: lint_SRCS diff --git a/usr/src/cmd/zoneadm/svc-zones b/usr/src/cmd/zoneadm/svc-zones index 9d307835bd..30d54f5272 100644 --- a/usr/src/cmd/zoneadm/svc-zones +++ b/usr/src/cmd/zoneadm/svc-zones @@ -32,7 +32,7 @@ shutdown_zones() { zoneadm list -p | nawk -F: '{ - if ($2 != "global") { + if (($5 != "lx") && ($2 != "global")) { print $2 } }' diff --git a/usr/src/cmd/zoneadm/zfs.c b/usr/src/cmd/zoneadm/zfs.c index d27b9c4678..78c165ffd1 100644 --- a/usr/src/cmd/zoneadm/zfs.c +++ b/usr/src/cmd/zoneadm/zfs.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -968,6 +968,7 @@ create_zfs_zonepath(char *zonepath) zfs_handle_t *zhp; char zfs_name[MAXPATHLEN]; nvlist_t *props = NULL; + int i; if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK) return; @@ -1004,9 +1005,20 @@ create_zfs_zonepath(char *zonepath) nvlist_free(props); - if (zfs_mount(zhp, NULL, 0) != 0) { + /* + * A monitoring tool might race with us and touch the mountpoint just + * as we're trying to mount, blocking the mount. We wait and retry a + * few times to workaround this race. + */ + for (i = 0; i < 5; i++) { + if (zfs_mount(zhp, NULL, 0) == 0) + break; (void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: " "%s\n"), zfs_name, libzfs_error_description(g_zfs)); + (void) sleep(1); + } + + if (i >= 5) { (void) zfs_destroy(zhp, B_FALSE); } else { if (chmod(zonepath, S_IRWXU) != 0) { diff --git a/usr/src/cmd/zoneadm/zoneadm.c b/usr/src/cmd/zoneadm/zoneadm.c index 6d80fcd8c3..70962d1ea3 100644 --- a/usr/src/cmd/zoneadm/zoneadm.c +++ b/usr/src/cmd/zoneadm/zoneadm.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015, Joyent Inc. All rights reserved. */ /* @@ -100,6 +101,7 @@ typedef struct zone_entry { char zroot[MAXPATHLEN]; char zuuid[UUID_PRINTABLE_STRING_LENGTH]; zone_iptype_t ziptype; + zoneid_t zdid; } zone_entry_t; #define CLUSTER_BRAND_NAME "cluster" @@ -442,6 +444,7 @@ zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) } if (!verbose) { char *cp, *clim; + char zdid[80]; if (!parsable) { (void) printf("%s\n", zent->zname); @@ -457,8 +460,12 @@ zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) (void) printf("%.*s\\:", clim - cp, cp); cp = clim + 1; } - (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand, - ip_type_str); + if (zent->zdid == -1) + zdid[0] = '\0'; + else + (void) snprintf(zdid, sizeof (zdid), "%d", zent->zdid); + (void) printf("%s:%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand, + ip_type_str, zdid); return; } if (zent->zstate_str != NULL) { @@ -553,6 +560,22 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) return (Z_OK); } + if ((handle = zonecfg_init_handle()) == NULL) { + zperror2(zent->zname, gettext("could not init handle")); + return (Z_ERR); + } + if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) { + zperror2(zent->zname, gettext("could not get handle")); + zonecfg_fini_handle(handle); + return (Z_ERR); + } + + if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) { + zperror2(zent->zname, gettext("could not get ip-type")); + zonecfg_fini_handle(handle); + return (Z_ERR); + } + /* * There is a race condition where the zone could boot while * we're walking the index file. In this case the zone state @@ -573,25 +596,11 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) zent->ziptype = ZS_EXCLUSIVE; else zent->ziptype = ZS_SHARED; - return (Z_OK); } } - if ((handle = zonecfg_init_handle()) == NULL) { - zperror2(zent->zname, gettext("could not init handle")); - return (Z_ERR); - } - if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) { - zperror2(zent->zname, gettext("could not get handle")); - zonecfg_fini_handle(handle); - return (Z_ERR); - } + zent->zdid = zonecfg_get_did(handle); - if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) { - zperror2(zent->zname, gettext("could not get ip-type")); - zonecfg_fini_handle(handle); - return (Z_ERR); - } zonecfg_fini_handle(handle); return (Z_OK); @@ -765,18 +774,22 @@ zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) * Retrieve a zone entry by name. Returns NULL if no such zone exists. */ static zone_entry_t * -lookup_running_zone(const char *str) +lookup_running_zone(const char *name) { - int i; + zoneid_t zid; + zone_entry_t *zent; - if (fetch_zents() != Z_OK) + if ((zid = getzoneidbyname(name)) == -1) return (NULL); - for (i = 0; i < nzents; i++) { - if (strcmp(str, zents[i].zname) == 0) - return (&zents[i]); + if ((zent = malloc(sizeof (zone_entry_t))) == NULL) + return (NULL); + + if (lookup_zone_info(name, zid, zent) != Z_OK) { + free(zent); + return (NULL); } - return (NULL); + return (zent); } /* @@ -1012,8 +1025,12 @@ validate_zonepath(char *path, int cmd_num) (void) printf(gettext("WARNING: %s is on a temporary " "file system.\n"), rpath); } - if (crosscheck_zonepaths(rpath) != Z_OK) - return (Z_ERR); + if (cmd_num != CMD_BOOT && cmd_num != CMD_REBOOT && + cmd_num != CMD_READY) { + /* we checked when we installed, no need to check each boot */ + if (crosscheck_zonepaths(rpath) != Z_OK) + return (Z_ERR); + } /* * Try to collect and report as many minor errors as possible * before returning, so the user can learn everything that needs @@ -1200,6 +1217,7 @@ static int ready_func(int argc, char *argv[]) { zone_cmd_arg_t zarg; + boolean_t debug = B_FALSE; int arg; if (zonecfg_in_alt_root()) { @@ -1208,11 +1226,14 @@ ready_func(int argc, char *argv[]) } optind = 0; - if ((arg = getopt(argc, argv, "?")) != EOF) { + if ((arg = getopt(argc, argv, "?X")) != EOF) { switch (arg) { case '?': sub_usage(SHELP_READY, CMD_READY); return (optopt == '?' ? Z_OK : Z_USAGE); + case 'X': + debug = B_TRUE; + break; default: sub_usage(SHELP_READY, CMD_READY); return (Z_USAGE); @@ -1229,6 +1250,7 @@ ready_func(int argc, char *argv[]) return (Z_ERR); zarg.cmd = Z_READY; + zarg.debug = debug; if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { zerror(gettext("call to %s failed"), "zoneadmd"); return (Z_ERR); @@ -1241,6 +1263,7 @@ boot_func(int argc, char *argv[]) { zone_cmd_arg_t zarg; boolean_t force = B_FALSE; + boolean_t debug = B_FALSE; int arg; if (zonecfg_in_alt_root()) { @@ -1267,7 +1290,7 @@ boot_func(int argc, char *argv[]) * zoneadm -z myzone boot -- -s -v -m verbose. */ optind = 0; - while ((arg = getopt(argc, argv, "?fs")) != EOF) { + while ((arg = getopt(argc, argv, "?fsX")) != EOF) { switch (arg) { case '?': sub_usage(SHELP_BOOT, CMD_BOOT); @@ -1279,6 +1302,9 @@ boot_func(int argc, char *argv[]) case 'f': force = B_TRUE; break; + case 'X': + debug = B_TRUE; + break; default: sub_usage(SHELP_BOOT, CMD_BOOT); return (Z_USAGE); @@ -1304,6 +1330,7 @@ boot_func(int argc, char *argv[]) if (verify_details(CMD_BOOT, argv) != Z_OK) return (Z_ERR); zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT; + zarg.debug = debug; if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { zerror(gettext("call to %s failed"), "zoneadmd"); return (Z_ERR); @@ -1819,6 +1846,7 @@ static int halt_func(int argc, char *argv[]) { zone_cmd_arg_t zarg; + boolean_t debug = B_FALSE; int arg; if (zonecfg_in_alt_root()) { @@ -1827,11 +1855,14 @@ halt_func(int argc, char *argv[]) } optind = 0; - if ((arg = getopt(argc, argv, "?")) != EOF) { + if ((arg = getopt(argc, argv, "?X")) != EOF) { switch (arg) { case '?': sub_usage(SHELP_HALT, CMD_HALT); return (optopt == '?' ? Z_OK : Z_USAGE); + case 'X': + debug = B_TRUE; + break; default: sub_usage(SHELP_HALT, CMD_HALT); return (Z_USAGE); @@ -1857,6 +1888,7 @@ halt_func(int argc, char *argv[]) return (Z_ERR); zarg.cmd = Z_HALT; + zarg.debug = debug; return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) == 0) ? Z_OK : Z_ERR); } @@ -1934,6 +1966,7 @@ static int reboot_func(int argc, char *argv[]) { zone_cmd_arg_t zarg; + boolean_t debug = B_FALSE; int arg; if (zonecfg_in_alt_root()) { @@ -1942,11 +1975,14 @@ reboot_func(int argc, char *argv[]) } optind = 0; - if ((arg = getopt(argc, argv, "?")) != EOF) { + if ((arg = getopt(argc, argv, "?X")) != EOF) { switch (arg) { case '?': sub_usage(SHELP_REBOOT, CMD_REBOOT); return (optopt == '?' ? Z_OK : Z_USAGE); + case 'X': + debug = B_TRUE; + break; default: sub_usage(SHELP_REBOOT, CMD_REBOOT); return (Z_USAGE); @@ -1981,6 +2017,7 @@ reboot_func(int argc, char *argv[]) return (Z_ERR); zarg.cmd = Z_REBOOT; + zarg.debug = debug; return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) == 0) ? Z_OK : Z_ERR); } @@ -2208,6 +2245,10 @@ verify_fs_special(struct zone_fstab *fstab) if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0) return (verify_fs_zfs(fstab)); + if (strcmp(fstab->zone_fs_type, MNTTYPE_HYPRLOFS) == 0 && + strcmp(fstab->zone_fs_special, "swap") == 0) + return (Z_OK); + if (stat64(fstab->zone_fs_special, &st) != 0) { (void) fprintf(stderr, gettext("could not verify fs " "%s: could not access %s: %s\n"), fstab->zone_fs_dir, @@ -2611,7 +2652,6 @@ verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[]) dladm_handle_t dh; dladm_status_t status; datalink_id_t linkid; - char errmsg[DLADM_STRSIZE]; in_alt_root = zonecfg_in_alt_root(); if (in_alt_root) @@ -2694,11 +2734,6 @@ verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[]) dladm_close(dh); } if (status != DLADM_STATUS_OK) { - (void) fprintf(stderr, - gettext("WARNING: skipping network " - "interface '%s': %s\n"), - nwiftab.zone_nwif_physical, - dladm_status2str(status, errmsg)); break; } dl_owner_zid = ALL_ZONES; @@ -2782,6 +2817,61 @@ no_net: return (return_code); } +/* + * Called when readying or booting a zone. We double check that the zone's + * debug ID is set and is unique. This covers the case of pre-existing zones + * with no ID. Also, its possible that a zone was migrated to this host + * and as a result it has a duplicate ID. In this case we preserve the ID + * of the first zone we match on in the index file (since it was there before + * the current zone) and we assign a new unique ID to the current zone. + * Return true if we assigned a new ID, indicating that the zone configuration + * needs to be saved. + */ +static boolean_t +verify_fix_did(zone_dochandle_t handle) +{ + zoneid_t mydid; + zone_entry_t zent; + FILE *cookie; + char *name; + boolean_t fix = B_FALSE; + + mydid = zonecfg_get_did(handle); + if (mydid == -1) { + zonecfg_set_did(handle); + return (B_TRUE); + } + + /* Get the full list of zones from the configuration. */ + cookie = setzoneent(); + while ((name = getzoneent(cookie)) != NULL) { + if (strcmp(target_zone, name) == 0) { + free(name); + break; /* Once we find our entry, stop. */ + } + + if (strcmp(name, "global") == 0 || + lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) { + free(name); + continue; + } + + free(name); + if (zent.zdid == mydid) { + fix = B_TRUE; + break; + } + } + endzoneent(cookie); + + if (fix) { + zonecfg_set_did(handle); + return (B_TRUE); + } + + return (B_FALSE); +} + static int verify_details(int cmd_num, char *argv[]) { @@ -2841,6 +2931,18 @@ verify_details(int cmd_num, char *argv[]) if (verify_handle(cmd_num, handle, argv) != Z_OK) return_code = Z_ERR; + if (cmd_num == CMD_READY || cmd_num == CMD_BOOT) { + int vcommit = 0, obscommit = 0; + + vcommit = verify_fix_did(handle); + obscommit = zonecfg_fix_obsolete(handle); + + if (vcommit || obscommit) + if (zonecfg_save(handle) != Z_OK) + (void) fprintf(stderr, gettext("Could not save " + "updated configuration.\n")); + } + zonecfg_fini_handle(handle); if (return_code == Z_ERR) (void) fprintf(stderr, @@ -2926,6 +3028,7 @@ install_func(int argc, char *argv[]) int status; boolean_t do_postinstall = B_FALSE; boolean_t brand_help = B_FALSE; + boolean_t do_dataset = B_TRUE; char opts[128]; if (target_zone == NULL) { @@ -3001,6 +3104,12 @@ install_func(int argc, char *argv[]) } /* Ignore unknown options - may be brand specific. */ break; + case 'x': + if (strcmp(optarg, "nodataset") == 0) { + do_dataset = B_FALSE; + continue; /* internal arg, don't pass thru */ + } + break; default: /* Ignore unknown options - may be brand specific. */ break; @@ -3053,7 +3162,8 @@ install_func(int argc, char *argv[]) goto done; } - create_zfs_zonepath(zonepath); + if (do_dataset) + create_zfs_zonepath(zonepath); } status = do_subproc(cmdbuf); @@ -3863,10 +3973,10 @@ cleanup_zonepath(char *zonepath, boolean_t all) * exist if the zone was force-attached after a * migration. */ - char *std_entries[] = {"dev", "lu", "root", - "SUNWattached.xml", NULL}; - /* (MAXPATHLEN * 3) is for the 3 std_entries dirs */ - char cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64]; + char *std_entries[] = {"dev", "lastexited", "logs", "lu", + "root", "SUNWattached.xml", NULL}; + /* (MAXPATHLEN * 5) is for the 5 std_entries dirs */ + char cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 5) + 64]; /* * We shouldn't need these checks but lets be paranoid since we @@ -5016,6 +5126,7 @@ uninstall_func(int argc, char *argv[]) if (zonecfg_ping_zoneadmd(target_zone) == Z_OK) { zone_cmd_arg_t zarg; zarg.cmd = Z_NOTE_UNINSTALLING; + zarg.debug = B_FALSE; /* we don't care too much if this fails, just plow on */ (void) zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE); @@ -5131,6 +5242,7 @@ mount_func(int argc, char *argv[]) return (Z_ERR); zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT; + zarg.debug = B_FALSE; zarg.bootbuf[0] = '\0'; if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { zerror(gettext("call to %s failed"), "zoneadmd"); @@ -5152,6 +5264,7 @@ unmount_func(int argc, char *argv[]) return (Z_ERR); zarg.cmd = Z_UNMOUNT; + zarg.debug = B_FALSE; if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { zerror(gettext("call to %s failed"), "zoneadmd"); return (Z_ERR); @@ -5373,7 +5486,7 @@ apply_func(int argc, char *argv[]) priv_set_t *privset; zoneid_t zoneid; zone_dochandle_t handle; - struct zone_mcaptab mcap; + uint64_t mcap; char pool_err[128]; zoneid = getzoneid(); @@ -5464,19 +5577,12 @@ apply_func(int argc, char *argv[]) } /* - * If a memory cap is configured, set the cap in the kernel using - * zone_setattr() and make sure the rcapd SMF service is enabled. + * If a memory cap is configured, make sure the rcapd SMF service is + * enabled. */ - if (zonecfg_getmcapent(handle, &mcap) == Z_OK) { - uint64_t num; + if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &mcap) == Z_OK) { char smf_err[128]; - num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10); - if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) { - zerror(gettext("could not set zone memory cap")); - res = Z_ERR; - } - if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) { zerror(gettext("enabling system/rcap service failed: " "%s"), smf_err); diff --git a/usr/src/cmd/zoneadm/zones.xml b/usr/src/cmd/zoneadm/zones.xml index 9c8e305f89..1b6f8cd49b 100644 --- a/usr/src/cmd/zoneadm/zones.xml +++ b/usr/src/cmd/zoneadm/zones.xml @@ -54,11 +54,19 @@ <service_fmri value='svc:/milestone/multi-user-server' /> </dependency> + <dependency + name='metadata' + type='service' + grouping='require_all' + restart_on='none'> + <service_fmri value='svc:/system/smartdc/metadata' /> + </dependency> + <exec_method type='method' name='start' exec='/lib/svc/method/svc-zones %m' - timeout_seconds='60'> + timeout_seconds='0'> </exec_method> <!-- diff --git a/usr/src/cmd/zoneadmd/Makefile b/usr/src/cmd/zoneadmd/Makefile index 8324f7fefa..e81e4631aa 100644 --- a/usr/src/cmd/zoneadmd/Makefile +++ b/usr/src/cmd/zoneadmd/Makefile @@ -18,57 +18,54 @@ # # CDDL HEADER END - -# - # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2014 Nexenta Systems, Inc. All rights reserved. +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # PROG= zoneadmd include ../Makefile.cmd +include ../Makefile.ctf -ROOTCMDDIR= $(ROOTLIB)/zones - -OBJS= zoneadmd.o zcons.o vplat.o -SRCS = $(OBJS:.o=.c) -POFILE=zoneadmd_all.po -POFILES= $(OBJS:%.o=%.po) +$(64ONLY)SUBDIRS= $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-switch -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized +all := TARGET = all +install := TARGET = install +clean := TARGET = clean +clobber := TARGET = clobber +lint := TARGET = lint -LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \ - -lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm -ltsnet -ltsol \ - -linetutil -lscf XGETFLAGS += -a -x zoneadmd.xcl +ROOTUSRLIBZONES = $(ROOT)/usr/lib/zones + .KEEP_STATE: .PARALLEL: -all: $(PROG) +all: $(SUBDIRS) $(PROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) -install: all $(ROOTCMD) - -$(POFILE): $(POFILES) - $(RM) $@ - $(CAT) $(POFILES) > $@ +install: $(SUBDIRS) + -$(RM) $(ROOTUSRLIBZONES)/$(PROG) + -$(LN) $(ISAEXEC) $(ROOTUSRLIBZONES)/$(PROG) -clean: - $(RM) $(OBJS) +$(POFILE): -lint: lint_SRCS +clean clobebr lint: $(SUBDIRS) check: - $(CSTYLE) -p -P $(SRCS:%=%) + $(CSTYLE) -p -P *.c + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: include ../Makefile.targ diff --git a/usr/src/cmd/zoneadmd/Makefile.com b/usr/src/cmd/zoneadmd/Makefile.com new file mode 100644 index 0000000000..c8becc3e8c --- /dev/null +++ b/usr/src/cmd/zoneadmd/Makefile.com @@ -0,0 +1,70 @@ +# +# 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) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2014, Joyent, Inc. All rights reserved. +# + +PROG= zoneadmd + +include ../../Makefile.cmd +include ../../Makefile.ctf + +ROOTCMDDIR= $(ROOTLIB)/zones + +OBJS= zoneadmd.o zcons.o zfd.o vplat.o mcap.o + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \ + -lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm -ltsnet -ltsol \ + -linetutil -lproc -lscf + +.KEEP_STATE: + +%.o: ../%.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + +ROOTUSRLIBZONES = $(ROOT)/usr/lib/zones +ROOTUSRLIBZONES32 = $(ROOTUSRLIBZONES)/$(MACH32) +ROOTUSRLIBZONES64 = $(ROOTUSRLIBZONES)/$(MACH64) +ROOTUSRLIBZONESPROG32 = $(ROOTUSRLIBZONES32)/$(PROG) +ROOTUSRLIBZONESPROG64 = $(ROOTUSRLIBZONES64)/$(PROG) +$(ROOTUSRLIBZONES32)/%: $(ROOTUSRLIBZONES32) % + $(INS.file) +$(ROOTUSRLIBZONES64)/%: $(ROOTUSRLIBZONES64) % + $(INS.file) +$(ROOTUSRLIBZONES32): + $(INS.dir) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +clean: + $(RM) $(OBJS) + +lint: + $(LINT.c) ../*.c $(LDLIBS) + +include ../../Makefile.targ diff --git a/usr/src/cmd/ssh/libopenbsd-compat/sparc/Makefile b/usr/src/cmd/zoneadmd/amd64/Makefile index fde6250470..75ac51db32 100644 --- a/usr/src/cmd/ssh/libopenbsd-compat/sparc/Makefile +++ b/usr/src/cmd/zoneadmd/amd64/Makefile @@ -19,12 +19,13 @@ # # CDDL HEADER END # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # +.KEEP_STATE: + include ../Makefile.com +include ../../Makefile.cmd.64 -install: all +install: all $(ROOTUSRLIBZONES64) $(ROOTUSRLIBZONESPROG64) diff --git a/usr/src/cmd/ssh/libssh/i386/Makefile b/usr/src/cmd/zoneadmd/i386/Makefile index fde6250470..a8764e0638 100644 --- a/usr/src/cmd/ssh/libssh/i386/Makefile +++ b/usr/src/cmd/zoneadmd/i386/Makefile @@ -19,12 +19,12 @@ # # CDDL HEADER END # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # +.KEEP_STATE: + include ../Makefile.com -install: all +install: all $(ROOTUSRLIBZONES32) $(ROOTUSRLIBZONESPROG32) diff --git a/usr/src/cmd/zoneadmd/mcap.c b/usr/src/cmd/zoneadmd/mcap.c new file mode 100644 index 0000000000..16cd2dd07a --- /dev/null +++ b/usr/src/cmd/zoneadmd/mcap.c @@ -0,0 +1,1182 @@ +/* + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2014, Joyent, Inc. All rights reserved. + */ + +/* + * This file implements the code which runs a thread inside zoneadmd to cap + * the associated zone's physical memory. A thread to do this is started + * when the zone boots and is halted when the zone shuts down. + * + * Because of the way that the VM system is currently implemented, there is no + * way to go from the bottom up (page to process to zone). Thus, there is no + * obvious way to hook an rctl into the kernel's paging code to enforce a hard + * memory cap. Instead, we implement a soft physical memory cap which looks + * at the zone's overall rss and once it is over the cap, works from the top + * down (zone to process to page), looking at zone processes, to determine + * what to try to pageout to get the zone under its memory cap. + * + * The code uses the fast, cheap, but potentially very inaccurate sum of the + * rss values from psinfo_t to first approximate the zone's rss and will + * fallback to the vm_getusage syscall to determine the zone's rss if needed. + * It then checks the rss against the zone's zone.max-physical-memory rctl. + * Once the zone goes over its cap, then this thread will work through the + * zone's /proc process list, Pgrab-bing each process and stepping through the + * address space segments attempting to use pr_memcntl(...MS_INVALCURPROC...) + * to pageout pages, until the zone is again under its cap. + * + * Although zone memory capping is implemented as a soft cap by this user-level + * thread, the interfaces around memory caps that are exposed to the user are + * the standard ones; an rctl and kstats. This thread uses the rctl value + * to obtain the cap and works with the zone kernel code to update the kstats. + * If the implementation ever moves into the kernel, these exposed interfaces + * do not need to change. + * + * The thread adaptively sleeps, periodically checking the state of the + * zone. As the zone's rss gets closer to the cap, the thread will wake up + * more often to check the zone's status. Once the zone is over the cap, + * the thread will work to pageout until the zone is under the cap, as shown + * by updated vm_usage data. + * + * NOTE: The pagedata page maps (at least on x86) are not useful. Those flags + * are set by hrm_setbits() and on x86 that code path is only executed by + * segvn_pagelock -> hat_setstat -> hrm_setbits + * segvn_softunlock -^ + * On SPARC there is an additional code path which may make this data + * useful (sfmmu_ttesync), but since it is not generic, we ignore the page + * maps. If we ever fix this issue, then we could generalize this mcap code to + * do more with the data on active pages. + * + * For debugging, touch the file {zonepath}/mcap_debug.log. This will + * cause the thread to start logging its actions into that file (it may take + * a minute or two if the thread is currently sleeping). Removing that + * file will cause logging to stop. + */ + +#include <sys/mman.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <libproc.h> +#include <limits.h> +#include <procfs.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <time.h> +#include <unistd.h> +#include <sys/priocntl.h> +#include <dirent.h> +#include <zone.h> +#include <libzonecfg.h> +#include <thread.h> +#include <values.h> +#include <sys/vm_usage.h> +#include <sys/resource.h> +#include <sys/debug.h> +#include <synch.h> +#include <wait.h> +#include <libcontract.h> +#include <libcontract_priv.h> +#include <sys/contract/process.h> +#include "zoneadmd.h" + + /* round up to next y = 2^n */ +#define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) + +#define CAP_REFRESH ((uint64_t)300 * NANOSEC) /* every 5 minutes */ + +/* + * zonecfg attribute tunables for memory capping. + * phys-mcap-cmd + * type: string + * specifies a command that can be run when over the cap + * phys-mcap-no-vmusage + * type: boolean + * true disables vm_getusage and just uses zone's proc. rss sum + * phys-mcap-no-pageout + * type: boolean + * true disables pageout when over + * phys-mcap-no-pf-throttle + * type: boolean + * true disables page fault throttling when over + */ +#define TUNE_CMD "phys-mcap-cmd" +#define TUNE_NVMU "phys-mcap-no-vmusage" +#define TUNE_NPAGE "phys-mcap-no-pageout" +#define TUNE_NPFTHROT "phys-mcap-no-pf-throttle" + +/* + * These are only used in get_mem_info but global. We always need scale_rss and + * prev_fast_rss to be persistent but we also have the other two global so we + * can easily see these with mdb. + */ +uint64_t scale_rss = 0; +uint64_t prev_fast_rss = 0; +uint64_t fast_rss = 0; +uint64_t accurate_rss = 0; + +static char zoneproc[MAXPATHLEN]; +static char debug_log[MAXPATHLEN]; +static zoneid_t zid; +static mutex_t shutdown_mx; +static cond_t shutdown_cv; +static int shutting_down = 0; +static thread_t mcap_tid; +static FILE *debug_log_fp = NULL; +static uint64_t zone_rss_cap; /* RSS cap(KB) */ +static char over_cmd[2 * BUFSIZ]; /* same size as zone_attr_value */ +static boolean_t skip_vmusage = B_FALSE; +static boolean_t skip_pageout = B_FALSE; +static boolean_t skip_pf_throttle = B_FALSE; + +static zlog_t *logp; + +static int64_t check_suspend(); +static void get_mcap_tunables(); + +/* + * Structure to hold current state about a process address space that we're + * working on. + */ +typedef struct { + int pr_curr; /* the # of the mapping we're working on */ + int pr_nmap; /* number of mappings in address space */ + prmap_t *pr_mapp; /* process's map array */ +} proc_map_t; + +typedef struct zsd_vmusage64 { + id_t vmu_zoneid; + uint_t vmu_type; + id_t vmu_id; + /* + * An amd64 kernel will align the following uint64_t members, but a + * 32bit i386 process will not without help. + */ + int vmu_align_next_members_on_8_bytes; + uint64_t vmu_rss_all; + uint64_t vmu_rss_private; + uint64_t vmu_rss_shared; + uint64_t vmu_swap_all; + uint64_t vmu_swap_private; + uint64_t vmu_swap_shared; +} zsd_vmusage64_t; + +/* + * Output a debug log message. + */ +/*PRINTFLIKE1*/ +static void +debug(char *fmt, ...) +{ + va_list ap; + + if (debug_log_fp == NULL) + return; + + va_start(ap, fmt); + (void) vfprintf(debug_log_fp, fmt, ap); + va_end(ap); + (void) fflush(debug_log_fp); +} + +/* + * Like sleep(3C) but can be interupted by cond_signal which is posted when + * we're shutting down the mcap thread. + */ +static void +sleep_shutdown(int secs) +{ + timestruc_t to; + + to.tv_sec = secs; + to.tv_nsec = 0; + + (void) mutex_lock(&shutdown_mx); + if (!shutting_down) + (void) cond_reltimedwait(&shutdown_cv, &shutdown_mx, &to); + (void) mutex_unlock(&shutdown_mx); +} + +static boolean_t +proc_issystem(pid_t pid) +{ + char pc_clname[PC_CLNMSZ]; + + if (priocntl(P_PID, pid, PC_GETXPARMS, NULL, PC_KY_CLNAME, pc_clname, + PC_KY_NULL) != -1) + return (strcmp(pc_clname, "SYS") == 0); + + return (B_TRUE); +} + +/* + * Fork a child that enters the zone and runs the "phys-mcap-cmd" command. + */ +static void +run_over_cmd() +{ + int ctfd; + int err; + pid_t childpid; + siginfo_t info; + ctid_t ct; + + /* + * Before we enter the zone, we need to create a new process contract + * for the child, as required by zone_enter(). + */ + if ((ctfd = open64("/system/contract/process/template", O_RDWR)) == -1) + return; + if (ct_tmpl_set_critical(ctfd, 0) != 0 || + ct_tmpl_set_informative(ctfd, 0) != 0 || + ct_pr_tmpl_set_fatal(ctfd, CT_PR_EV_HWERR) != 0 || + ct_pr_tmpl_set_param(ctfd, CT_PR_PGRPONLY) != 0 || + ct_tmpl_activate(ctfd) != 0) { + (void) close(ctfd); + return; + } + + childpid = fork(); + switch (childpid) { + case -1: + (void) ct_tmpl_clear(ctfd); + (void) close(ctfd); + break; + case 0: /* Child */ + (void) ct_tmpl_clear(ctfd); + (void) close(ctfd); + if (zone_enter(zid) == -1) + _exit(errno); + err = system(over_cmd); + _exit(err); + break; + default: /* Parent */ + if (contract_latest(&ct) == -1) + ct = -1; + (void) ct_tmpl_clear(ctfd); + (void) close(ctfd); + err = waitid(P_PID, childpid, &info, WEXITED); + (void) contract_abandon_id(ct); + if (err == -1 || info.si_status != 0) + debug("over_cmd failed"); + break; + } +} + +/* + * Get the next mapping. + */ +static prmap_t * +nextmapping(proc_map_t *pmp) +{ + if (pmp->pr_mapp == NULL || pmp->pr_curr >= pmp->pr_nmap) + return (NULL); + + return (&pmp->pr_mapp[pmp->pr_curr++]); +} + +/* + * Initialize the proc_map_t to access the first mapping of an address space. + */ +static prmap_t * +init_map(proc_map_t *pmp, pid_t pid) +{ + int fd; + int res; + struct stat st; + char pathbuf[MAXPATHLEN]; + + bzero(pmp, sizeof (proc_map_t)); + pmp->pr_nmap = -1; + + (void) snprintf(pathbuf, sizeof (pathbuf), "%s/%d/map", zoneproc, pid); + if ((fd = open(pathbuf, O_RDONLY, 0)) < 0) + return (NULL); + +redo: + errno = 0; + if (fstat(fd, &st) != 0) + goto done; + + if ((pmp->pr_mapp = malloc(st.st_size)) == NULL) { + debug("cannot malloc() %ld bytes for xmap", st.st_size); + goto done; + } + (void) bzero(pmp->pr_mapp, st.st_size); + + errno = 0; + if ((res = pread(fd, pmp->pr_mapp, st.st_size, 0)) != st.st_size) { + free(pmp->pr_mapp); + pmp->pr_mapp = NULL; + if (res > 0 || errno == E2BIG) { + goto redo; + } else { + debug("pid %ld cannot read xmap\n", pid); + goto done; + } + } + + pmp->pr_nmap = st.st_size / sizeof (prmap_t); + +done: + (void) close(fd); + return (nextmapping(pmp)); +} + +/* + * Attempt to invalidate the entire mapping from within the given process's + * address space. May return nonzero with errno as: + * ESRCH - process not found + * ENOMEM - segment not found + * EINVAL - mapping exceeds a single segment + */ +static int +pageout_mapping(pid_t pid, prmap_t *pmp) +{ + int res; + + if (pmp->pr_mflags & MA_ISM || pmp->pr_mflags & MA_SHM) + return (0); + + errno = 0; + res = syscall(SYS_rusagesys, _RUSAGESYS_INVALMAP, pid, pmp->pr_vaddr, + pmp->pr_size); + + return (res); +} + +/* + * Work through a process paging out mappings until the whole address space was + * examined or the excess is < 0. Return our estimate of the updated excess. + */ +static int64_t +pageout_process(pid_t pid, int64_t excess) +{ + int psfd; + prmap_t *pmap; + proc_map_t cur; + int res; + int64_t sum_d_rss, d_rss; + int64_t old_rss; + int map_cnt; + psinfo_t psinfo; + char pathbuf[MAXPATHLEN]; + + (void) snprintf(pathbuf, sizeof (pathbuf), "%s/%d/psinfo", zoneproc, + pid); + if ((psfd = open(pathbuf, O_RDONLY, 0000)) < 0) + return (excess); + + cur.pr_mapp = NULL; + + if (pread(psfd, &psinfo, sizeof (psinfo), 0) != sizeof (psinfo)) + goto done; + + old_rss = (int64_t)psinfo.pr_rssize; + map_cnt = 0; + + /* If unscannable, skip it. */ + if (psinfo.pr_nlwp == 0 || proc_issystem(pid)) { + debug("pid %ld: system process, skipping %s\n", + pid, psinfo.pr_psargs); + goto done; + } + + /* If tiny RSS (16KB), skip it. */ + if (old_rss <= 16) { + debug("pid %ld: skipping, RSS %lldKB %s\n", + pid, old_rss, psinfo.pr_psargs); + goto done; + } + + /* Get segment residency information. */ + pmap = init_map(&cur, pid); + + /* Skip process if it has no mappings. */ + if (pmap == NULL) { + debug("pid %ld: map unreadable; ignoring\n", pid); + goto done; + } + + debug("pid %ld: nmap %d sz %dKB rss %lldKB %s\n", + pid, cur.pr_nmap, psinfo.pr_size, old_rss, psinfo.pr_psargs); + + /* + * Within the process's address space, attempt to page out mappings. + */ + sum_d_rss = 0; + while (excess > 0 && pmap != NULL && !shutting_down) { + /* invalidate the entire mapping */ + if ((res = pageout_mapping(pid, pmap)) < 0) + debug("pid %ld: mapping 0x%p %ldkb unpageable (%d)\n", + pid, pmap->pr_vaddr, pmap->pr_size / 1024, errno); + + map_cnt++; + + /* + * Re-check the process rss and get the delta. + */ + if (pread(psfd, &psinfo, sizeof (psinfo), 0) + != sizeof (psinfo)) { + excess -= old_rss; + goto done; + } + + d_rss = (int64_t)psinfo.pr_rssize - old_rss; + old_rss = (int64_t)psinfo.pr_rssize; + sum_d_rss += d_rss; + + /* + * d_rss hopefully should be negative (or 0 if nothing + * invalidated) but can be positive if more got paged in. + */ + excess += d_rss; + + if (excess <= 0) { + debug("pid %ld: (part.) nmap %d delta_rss %lldKB " + "excess %lldKB\n", pid, map_cnt, + (unsigned long long)sum_d_rss, (long long)excess); + map_cnt = 0; + + /* + * If we're actually under, this will suspend checking + * in the middle of this process's address space. + */ + excess = check_suspend(); + if (shutting_down) + goto done; + + /* + * since we might have suspended, re-read process's rss + */ + if (pread(psfd, &psinfo, sizeof (psinfo), 0) + != sizeof (psinfo)) { + excess -= old_rss; + goto done; + } + + old_rss = (int64_t)psinfo.pr_rssize; + + debug("pid %ld: resume pageout; excess %lld\n", pid, + (long long)excess); + sum_d_rss = 0; + } + + pmap = nextmapping(&cur); + } + + debug("pid %ld: nmap %d delta_rss %lldKB excess %lldKB\n", + pid, map_cnt, (unsigned long long)sum_d_rss, (long long)excess); + +done: + if (cur.pr_mapp != NULL) + free(cur.pr_mapp); + + (void) close(psfd); + + if (shutting_down) + return (0); + + return (excess); +} + +/* + * Get the zone's RSS data. + */ +static uint64_t +get_mem_info() +{ + uint64_t n = 1; + zsd_vmusage64_t buf; + uint64_t tmp_rss; + DIR *pdir = NULL; + struct dirent *dent; + + /* + * Start by doing the fast, cheap RSS calculation using the rss value + * in psinfo_t. Because that's per-process, it can lead to double + * counting some memory and overestimating how much is being used, but + * as long as that's not over the cap, then we don't need do the + * expensive calculation. + * + * If we have to do the expensive calculation, we remember the scaling + * factor so that we can try to use that on subsequent iterations for + * the fast rss. + */ + if (shutting_down) + return (0); + + if ((pdir = opendir(zoneproc)) == NULL) + return (0); + + accurate_rss = 0; + fast_rss = 0; + while (!shutting_down && (dent = readdir(pdir)) != NULL) { + pid_t pid; + int psfd; + int64_t rss; + char pathbuf[MAXPATHLEN]; + psinfo_t psinfo; + + if (strcmp(".", dent->d_name) == 0 || + strcmp("..", dent->d_name) == 0) + continue; + + pid = atoi(dent->d_name); + if (pid == 0 || pid == 1) + continue; + + (void) snprintf(pathbuf, sizeof (pathbuf), "%s/%d/psinfo", + zoneproc, pid); + + rss = 0; + if ((psfd = open(pathbuf, O_RDONLY, 0000)) != -1) { + if (pread(psfd, &psinfo, sizeof (psinfo), 0) == + sizeof (psinfo)) + rss = (int64_t)psinfo.pr_rssize; + + (void) close(psfd); + } + + fast_rss += rss; + } + + (void) closedir(pdir); + + if (shutting_down) + return (0); + + debug("fast rss: %lluKB, scale: %llu, prev: %lluKB\n", fast_rss, + scale_rss, prev_fast_rss); + + /* see if we can get by with a scaled fast rss */ + tmp_rss = fast_rss; + if (scale_rss > 1 && prev_fast_rss > 0) { + /* + * Only scale the fast value if it hasn't ballooned too much + * to trust. + */ + if (fast_rss / prev_fast_rss < 2) { + fast_rss /= scale_rss; + debug("scaled fast rss: %lluKB\n", fast_rss); + } + } + + if (fast_rss <= zone_rss_cap || skip_vmusage) { + uint64_t zone_rss_bytes; + + zone_rss_bytes = fast_rss * 1024; + /* Use the zone's approx. RSS in the kernel */ + (void) zone_setattr(zid, ZONE_ATTR_RSS, &zone_rss_bytes, 0); + return (fast_rss); + } + + buf.vmu_id = zid; + + /* get accurate usage (cached data may be up to 5 seconds old) */ + if (syscall(SYS_rusagesys, _RUSAGESYS_GETVMUSAGE, VMUSAGE_A_ZONE, 5, + (uintptr_t)&buf, (uintptr_t)&n) != 0) { + debug("vmusage failed\n"); + (void) sleep_shutdown(1); + return (0); + } + + if (n > 1) { + /* This should never happen */ + debug("vmusage returned more than one result\n"); + (void) sleep_shutdown(1); + return (0); + } + + if (buf.vmu_id != zid) { + /* This should never happen */ + debug("vmusage returned the incorrect zone\n"); + (void) sleep_shutdown(1); + return (0); + } + + accurate_rss = buf.vmu_rss_all / 1024; + + /* calculate scaling factor to use for fast_rss from now on */ + if (accurate_rss > 0) { + scale_rss = fast_rss / accurate_rss; + debug("new scaling factor: %llu\n", scale_rss); + /* remember the fast rss when we had to get the accurate rss */ + prev_fast_rss = tmp_rss; + } + + debug("accurate rss: %lluKB, scale: %llu, prev: %lluKB\n", accurate_rss, + scale_rss, prev_fast_rss); + return (accurate_rss); +} + +/* + * Needed to read the zones physical-memory-cap rctl. + */ +static struct ps_prochandle * +grab_zone_proc() +{ + DIR *dirp; + struct dirent *dentp; + struct ps_prochandle *ph = NULL; + int tmp; + + if ((dirp = opendir(zoneproc)) == NULL) + return (NULL); + + while (!shutting_down && (dentp = readdir(dirp))) { + int pid; + + if (strcmp(".", dentp->d_name) == 0 || + strcmp("..", dentp->d_name) == 0) + continue; + + pid = atoi(dentp->d_name); + /* attempt to grab process */ + if ((ph = Pgrab(pid, 0, &tmp)) != NULL) { + if (Psetflags(ph, PR_RLC) == 0) { + if (Pcreate_agent(ph) == 0) { + (void) closedir(dirp); + return (ph); + } + } + Prelease(ph, 0); + } + } + + (void) closedir(dirp); + return (NULL); +} + +static uint64_t +get_zone_cap() +{ + rctlblk_t *rblk; + uint64_t mcap; + struct ps_prochandle *ph; + + if ((rblk = (rctlblk_t *)malloc(rctlblk_size())) == NULL) + return (UINT64_MAX); + + if ((ph = grab_zone_proc()) == NULL) { + free(rblk); + return (UINT64_MAX); + } + + if (pr_getrctl(ph, "zone.max-physical-memory", NULL, rblk, + RCTL_FIRST)) { + Pdestroy_agent(ph); + Prelease(ph, 0); + free(rblk); + return (UINT64_MAX); + } + + Pdestroy_agent(ph); + Prelease(ph, 0); + + mcap = rctlblk_get_value(rblk); + free(rblk); + return (mcap); +} + +/* + * check_suspend is invoked at the beginning of every pass through the process + * list or after we've paged out enough so that we think the excess is under + * the cap. The purpose is to periodically check the zone's rss and return + * the excess when the zone is over the cap. The rest of the time this + * function will sleep, periodically waking up to check the current rss. + * + * Depending on the percentage of penetration of the zone's rss into the + * cap we sleep for longer or shorter amounts. This reduces the impact of this + * work on the system, which is important considering that each zone will be + * monitoring its rss. + */ +static int64_t +check_suspend() +{ + static hrtime_t last_cap_read = 0; + static uint64_t addon; + static uint64_t lo_thresh; /* Thresholds for how long to sleep */ + static uint64_t hi_thresh; /* when under the cap (80% & 90%). */ + static uint64_t prev_zone_rss = 0; + static uint32_t pfdelay = 0; /* usec page fault delay when over */ + + /* Wait a second to give the async pageout a chance to catch up. */ + (void) sleep_shutdown(1); + + while (!shutting_down) { + int64_t new_excess; + int sleep_time; + hrtime_t now; + struct stat st; + uint64_t zone_rss; /* total RSS(KB) */ + + /* + * Check if the debug log files exists and enable or disable + * debug. + */ + if (debug_log_fp == NULL) { + if (stat(debug_log, &st) == 0) + debug_log_fp = fopen(debug_log, "w"); + } else { + if (stat(debug_log, &st) == -1) { + (void) fclose(debug_log_fp); + debug_log_fp = NULL; + } + } + + /* + * If the CAP_REFRESH interval has passed, re-get the current + * cap in case it has been dynamically updated. + */ + now = gethrtime(); + if (now - last_cap_read > CAP_REFRESH) { + uint64_t mcap; + + last_cap_read = now; + + mcap = get_zone_cap(); + if (mcap != 0 && mcap != UINT64_MAX) + zone_rss_cap = ROUNDUP(mcap, 1024) / 1024; + else + zone_rss_cap = UINT64_MAX; + + lo_thresh = (uint64_t)(zone_rss_cap * .8); + hi_thresh = (uint64_t)(zone_rss_cap * .9); + addon = (uint64_t)(zone_rss_cap * 0.05); + + /* + * We allow the memory cap tunables to be changed on + * the fly. + */ + get_mcap_tunables(); + + debug("%s: %s\n", TUNE_CMD, over_cmd); + debug("%s: %d\n", TUNE_NVMU, skip_vmusage); + debug("%s: %d\n", TUNE_NPAGE, skip_pageout); + debug("%s: %d\n", TUNE_NPFTHROT, skip_pf_throttle); + debug("current cap %lluKB lo %lluKB hi %lluKB\n", + zone_rss_cap, lo_thresh, hi_thresh); + } + + /* No cap, nothing to do. */ + if (zone_rss_cap == 0 || zone_rss_cap == UINT64_MAX) { + debug("no cap, sleep 120 seconds\n"); + (void) sleep_shutdown(120); + continue; + } + + zone_rss = get_mem_info(); + + /* calculate excess */ + new_excess = zone_rss - zone_rss_cap; + + debug("rss %lluKB, cap %lluKB, excess %lldKB\n", + zone_rss, zone_rss_cap, new_excess); + + /* + * If necessary, updates stats. + */ + + /* + * If it looks like we did some paging out since last over the + * cap then update the kstat so we can approximate how much was + * paged out. + */ + if (prev_zone_rss > zone_rss_cap && zone_rss < prev_zone_rss) { + uint64_t diff; + + /* assume diff is num bytes we paged out */ + diff = (prev_zone_rss - zone_rss) * 1024; + + (void) zone_setattr(zid, ZONE_ATTR_PMCAP_PAGEOUT, + &diff, 0); + } + prev_zone_rss = zone_rss; + + if (new_excess > 0) { + uint64_t n = 1; + + /* Increment "nover" kstat. */ + (void) zone_setattr(zid, ZONE_ATTR_PMCAP_NOVER, &n, 0); + + if (!skip_pf_throttle) { + /* + * Tell the kernel to start throttling page + * faults by some number of usecs to help us + * catch up. If we are persistently over the + * cap the delay ramps up to a max of 2000usecs. + * Note that for delays less than 1 tick + * (i.e. all of these) we busy-wait in as_fault. + * delay faults/sec + * 125 8000 + * 250 4000 + * 500 2000 + * 1000 1000 + * 2000 500 + */ + if (pfdelay == 0) + pfdelay = 125; + else if (pfdelay < 2000) + pfdelay *= 2; + + (void) zone_setattr(zid, ZONE_ATTR_PG_FLT_DELAY, + &pfdelay, 0); + } + + /* + * Once we go over the cap, then we want to + * page out a little extra instead of stopping + * right at the cap. To do this we add 5% to + * the excess so that pageout_proces will work + * a little longer before stopping. + */ + return ((int64_t)(new_excess + addon)); + } + + /* + * At this point we are under the cap. + * + * Tell the kernel to stop throttling page faults. + * + * Scale the amount of time we sleep before rechecking the + * zone's memory usage. Also, scale the accpetable age of + * cached results from vm_getusage. We do this based on the + * penetration into the capped limit. + */ + if (pfdelay > 0) { + pfdelay = 0; + (void) zone_setattr(zid, ZONE_ATTR_PG_FLT_DELAY, + &pfdelay, 0); + } + + if (zone_rss <= lo_thresh) { + sleep_time = 120; + } else if (zone_rss <= hi_thresh) { + sleep_time = 60; + } else { + sleep_time = 30; + } + + debug("sleep %d seconds\n", sleep_time); + (void) sleep_shutdown(sleep_time); + } + + /* Shutting down, tell the kernel so it doesn't throttle */ + if (pfdelay > 0) { + pfdelay = 0; + (void) zone_setattr(zid, ZONE_ATTR_PG_FLT_DELAY, &pfdelay, 0); + } + + return (0); +} + +static void +get_mcap_tunables() +{ + zone_dochandle_t handle; + struct zone_attrtab attr; + + over_cmd[0] = '\0'; + if ((handle = zonecfg_init_handle()) == NULL) + return; + + if (zonecfg_get_handle(zone_name, handle) != Z_OK) + goto done; + + /* Reset to defaults in case rebooting and settings have changed */ + over_cmd[0] = '\0'; + skip_vmusage = B_FALSE; + skip_pageout = B_FALSE; + skip_pf_throttle = B_FALSE; + + if (zonecfg_setattrent(handle) != Z_OK) + goto done; + while (zonecfg_getattrent(handle, &attr) == Z_OK) { + if (strcmp(TUNE_CMD, attr.zone_attr_name) == 0) { + (void) strlcpy(over_cmd, attr.zone_attr_value, + sizeof (over_cmd)); + } else if (strcmp(TUNE_NVMU, attr.zone_attr_name) == 0) { + if (strcmp("true", attr.zone_attr_value) == 0) + skip_vmusage = B_TRUE; + } else if (strcmp(TUNE_NPAGE, attr.zone_attr_name) == 0) { + if (strcmp("true", attr.zone_attr_value) == 0) + skip_pageout = B_TRUE; + } else if (strcmp(TUNE_NPFTHROT, attr.zone_attr_name) == 0) { + if (strcmp("true", attr.zone_attr_value) == 0) + skip_pf_throttle = B_TRUE; + } + } + (void) zonecfg_endattrent(handle); + +done: + zonecfg_fini_handle(handle); +} + +/* ARGSUSED */ +static int +chk_proc_fs(void *data, const char *spec, const char *dir, + const char *fstype, const char *opt) +{ + if (fstype != NULL && strcmp(fstype, "proc") == 0) + *((boolean_t *)data) = B_TRUE; + + return (0); +} + +static boolean_t +has_proc() +{ + brand_handle_t bh; + boolean_t fnd = B_FALSE; + + if ((bh = brand_open(brand_name)) != NULL) { + (void) brand_platform_iter_mounts(bh, chk_proc_fs, &fnd); + } + + brand_close(bh); + return (fnd); +} + +/* + * We run this loop for brands with no /proc to simply update the RSS, using + * the cheap GZ /proc data, every 5 minutes. + */ +static void +no_procfs() +{ + DIR *pdir = NULL; + struct dirent *dent; + uint64_t zone_rss_bytes; + + (void) sleep_shutdown(30); + while (!shutting_down) { + /* + * Just do the fast, cheap RSS calculation using the rss value + * in psinfo_t. Because that's per-process, it can lead to + * double counting some memory and overestimating how much is + * being used. Since there is no /proc in the zone, we use the + * GZ /proc and check for the correct zone. + */ + if ((pdir = opendir("/proc")) == NULL) + return; + + fast_rss = 0; + while (!shutting_down && (dent = readdir(pdir)) != NULL) { + pid_t pid; + int psfd; + int64_t rss; + char pathbuf[MAXPATHLEN]; + psinfo_t psinfo; + + if (strcmp(".", dent->d_name) == 0 || + strcmp("..", dent->d_name) == 0) + continue; + + pid = atoi(dent->d_name); + if (pid == 0 || pid == 1) + continue; + + (void) snprintf(pathbuf, sizeof (pathbuf), + "/proc/%d/psinfo", pid); + + rss = 0; + if ((psfd = open(pathbuf, O_RDONLY, 0000)) != -1) { + if (pread(psfd, &psinfo, sizeof (psinfo), 0) == + sizeof (psinfo)) { + if (psinfo.pr_zoneid == zid) + rss = (int64_t)psinfo.pr_rssize; + } + + (void) close(psfd); + } + + fast_rss += rss; + } + + (void) closedir(pdir); + + if (shutting_down) + return; + + zone_rss_bytes = fast_rss * 1024; + /* Use the zone's approx. RSS in the kernel */ + (void) zone_setattr(zid, ZONE_ATTR_RSS, &zone_rss_bytes, 0); + + (void) sleep_shutdown(300); + } +} + +/* + * Thread that checks zone's memory usage and when over the cap, goes through + * the zone's process list trying to pageout processes to get under the cap. + */ +static void +mcap_zone() +{ + DIR *pdir = NULL; + int64_t excess; + + debug("thread startup\n"); + + get_mcap_tunables(); + + /* + * If the zone has no /proc filesystem, we can't use the fast algorithm + * to check RSS or pageout any processes. All we can do is periodically + * update it's RSS kstat using the expensive sycall. + */ + if (!has_proc()) { + no_procfs(); + debug("thread shutdown\n"); + return; + } + + /* + * When first starting it is likely lots of other zones are starting + * too because the system is booting. Since we just started the zone + * we're not worried about being over the cap right away, so we let + * things settle a bit and tolerate some older data here to minimize + * the load on the system. + */ + (void) sleep_shutdown(15); /* wait 15 secs. so the zone can get going */ + + /* Wait until zone's /proc is mounted */ + while (!shutting_down) { + struct stat st; + + if (stat(zoneproc, &st) == 0 && + strcmp(st.st_fstype, "proc") == 0) + break; + sleep_shutdown(5); + } + + /* Open zone's /proc and walk entries. */ + while (!shutting_down) { + if ((pdir = opendir(zoneproc)) != NULL) + break; + sleep_shutdown(5); + } + + while (!shutting_down) { + struct dirent *dirent; + + /* Wait until we've gone over the cap. */ + excess = check_suspend(); + + debug("starting to scan, excess %lldk\n", (long long)excess); + + if (over_cmd[0] != '\0') { + uint64_t zone_rss; /* total RSS(KB) */ + + debug("run phys_mcap_cmd: %s\n", over_cmd); + run_over_cmd(); + + zone_rss = get_mem_info(); + excess = zone_rss - zone_rss_cap; + debug("rss %lluKB, cap %lluKB, excess %lldKB\n", + zone_rss, zone_rss_cap, excess); + if (excess <= 0) + continue; + } + + while (!shutting_down && (dirent = readdir(pdir)) != NULL) { + pid_t pid; + + if (strcmp(".", dirent->d_name) == 0 || + strcmp("..", dirent->d_name) == 0) + continue; + + pid = atoi(dirent->d_name); + if (pid == 0 || pid == 1) + continue; + + if (skip_pageout) + (void) sleep_shutdown(2); + else + excess = pageout_process(pid, excess); + + if (excess <= 0) { + debug("apparently under; excess %lld\n", + (long long)excess); + /* Double check the current excess */ + excess = check_suspend(); + } + } + + debug("process pass done; excess %lld\n", (long long)excess); + rewinddir(pdir); + + if (skip_pageout) + (void) sleep_shutdown(120); + } + + if (pdir != NULL) + (void) closedir(pdir); + debug("thread shutdown\n"); +} + +void +create_mcap_thread(zlog_t *zlogp, zoneid_t id) +{ + int res; + + shutting_down = 0; + zid = id; + logp = zlogp; + + /* all but the lx brand currently use /proc */ + if (strcmp(brand_name, "lx") == 0) { + (void) snprintf(zoneproc, sizeof (zoneproc), + "%s/root/native/proc", zonepath); + } else { + (void) snprintf(zoneproc, sizeof (zoneproc), "%s/root/proc", + zonepath); + } + + (void) snprintf(debug_log, sizeof (debug_log), "%s/mcap_debug.log", + zonepath); + + res = thr_create(NULL, NULL, (void *(*)(void *))mcap_zone, NULL, NULL, + &mcap_tid); + if (res != 0) { + zerror(zlogp, B_FALSE, "error %d creating memory cap thread", + res); + mcap_tid = 0; + } +} + +void +destroy_mcap_thread() +{ + if (mcap_tid != 0) { + shutting_down = 1; + (void) cond_signal(&shutdown_cv); + (void) thr_join(mcap_tid, NULL, NULL); + mcap_tid = 0; + } +} diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c index b9954b81b3..7b36c6de5b 100644 --- a/usr/src/cmd/zoneadmd/vplat.c +++ b/usr/src/cmd/zoneadmd/vplat.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent Inc. All rights reserved. + * Copyright 2015, Joyent Inc. All rights reserved. */ /* @@ -137,6 +137,9 @@ #define ALT_MOUNT(mount_cmd) ((mount_cmd) != Z_MNT_BOOT) +/* Number of times to retry unmounting if it fails */ +#define UMOUNT_RETRIES 30 + /* a reasonable estimate for the number of lwps per process */ #define LWPS_PER_PROCESS 10 @@ -160,11 +163,25 @@ static priv_set_t *zprivs = NULL; static const char *DFLT_FS_ALLOWED = "hsfs,smbfs,nfs,nfs3,nfs4,nfsdyn"; +typedef struct zone_proj_rctl_map { + char *zpr_zone_rctl; + char *zpr_project_rctl; +} zone_proj_rctl_map_t; + +static zone_proj_rctl_map_t zone_proj_rctl_map[] = { + {"zone.max-msg-ids", "project.max-msg-ids"}, + {"zone.max-sem-ids", "project.max-sem-ids"}, + {"zone.max-shm-ids", "project.max-shm-ids"}, + {"zone.max-shm-memory", "project.max-shm-memory"}, + {NULL, NULL} +}; + /* from libsocket, not in any header file */ extern int getnetmaskbyaddr(struct in_addr, struct in_addr *); /* from zoneadmd */ extern char query_hook[]; +extern char post_statechg_hook[]; /* * For each "net" resource configured in zonecfg, we track a zone_addr_list_t @@ -201,7 +218,7 @@ autofs_cleanup(zoneid_t zoneid) /* * Ask autofs to unmount all trigger nodes in the given zone. */ - return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid)); + return (_autofssys(AUTOFS_UNMOUNTALL, (void *)((uintptr_t)zoneid))); } static void @@ -592,6 +609,24 @@ root_to_lu(zlog_t *zlogp, char *zroot, size_t zrootlen, boolean_t isresolved) } /* + * Perform brand-specific cleanup if we are unable to unmount a FS. + */ +static void +brand_umount_cleanup(zlog_t *zlogp, char *path) +{ + char cmdbuf[2 * MAXPATHLEN]; + + if (post_statechg_hook[0] == '\0') + return; + + if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook, + ZONE_STATE_DOWN, Z_UNMOUNT, path) > sizeof (cmdbuf)) + return; + + (void) do_subproc(zlogp, cmdbuf, NULL, B_FALSE); +} + +/* * The general strategy for unmounting filesystems is as follows: * * - Remote filesystems may be dead, and attempting to contact them as @@ -624,6 +659,7 @@ static int unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd) { int error = 0; + int fail = 0; FILE *mnttab; struct mnttab *mnts; uint_t nmnt; @@ -711,18 +747,39 @@ unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd) if (umount2(path, MS_FORCE) == 0) { unmounted = B_TRUE; stuck = B_FALSE; + fail = 0; } else { /* - * The first failure indicates a - * mount we won't be able to get - * rid of automatically, so we - * bail. + * We may hit a failure here if there + * is an app in the GZ with an open + * pipe into the zone (commonly into + * the zone's /var/run). This type + * of app will notice the closed + * connection and cleanup, but it may + * take a while and we have no easy + * way to notice that. To deal with + * this case, we will wait and retry + * a few times before we give up. */ - error++; - zerror(zlogp, B_FALSE, - "unable to unmount '%s'", path); - free_mnttable(mnts, nmnt); - goto out; + fail++; + if (fail < (UMOUNT_RETRIES - 1)) { + zerror(zlogp, B_FALSE, + "unable to unmount '%s', " + "retrying in 2 seconds", + path); + (void) sleep(2); + } else if (fail > UMOUNT_RETRIES) { + error++; + zerror(zlogp, B_FALSE, + "unmount of '%s' failed", + path); + free_mnttable(mnts, nmnt); + goto out; + } else { + /* Try the hook 2 times */ + brand_umount_cleanup(zlogp, + path); + } } } /* @@ -1060,23 +1117,10 @@ mount_one_dev_symlink_cb(void *arg, const char *source, const char *target) int vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep) { - zone_dochandle_t handle; - - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - if (zonecfg_get_iptype(handle, iptypep) != Z_OK) { + if (zonecfg_get_iptype(snap_hndl, iptypep) != Z_OK) { zerror(zlogp, B_FALSE, "invalid ip-type configuration"); - zonecfg_fini_handle(handle); return (-1); } - zonecfg_fini_handle(handle); return (0); } @@ -1089,14 +1133,13 @@ static int mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) { char brand[MAXNAMELEN]; - zone_dochandle_t handle = NULL; brand_handle_t bh = NULL; struct zone_devtab ztab; di_prof_t prof = NULL; int err; int retval = -1; zone_iptype_t iptype; - const char *curr_iptype; + const char *curr_iptype = NULL; if (di_prof_init(devpath, &prof)) { zerror(zlogp, B_TRUE, "failed to initialize profile"); @@ -1131,6 +1174,8 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) curr_iptype = "exclusive"; break; } + if (curr_iptype == NULL) + abort(); if (brand_platform_iter_devices(bh, zone_name, mount_one_dev_device_cb, prof, curr_iptype) != 0) { @@ -1145,28 +1190,19 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) } /* Add user-specified devices and directories */ - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_FALSE, "can't initialize zone handle"); - goto cleanup; - } - if (err = zonecfg_get_handle(zone_name, handle)) { - zerror(zlogp, B_FALSE, "can't get handle for zone " - "%s: %s", zone_name, zonecfg_strerror(err)); - goto cleanup; - } - if (err = zonecfg_setdevent(handle)) { + if ((err = zonecfg_setdevent(snap_hndl)) != 0) { zerror(zlogp, B_FALSE, "%s: %s", zone_name, zonecfg_strerror(err)); goto cleanup; } - while (zonecfg_getdevent(handle, &ztab) == Z_OK) { + while (zonecfg_getdevent(snap_hndl, &ztab) == Z_OK) { if (di_prof_add_dev(prof, ztab.zone_dev_match)) { zerror(zlogp, B_TRUE, "failed to add " "user-specified device"); goto cleanup; } } - (void) zonecfg_enddevent(handle); + (void) zonecfg_enddevent(snap_hndl); /* Send profile to kernel */ if (di_prof_commit(prof)) { @@ -1179,8 +1215,6 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) cleanup: if (bh != NULL) brand_close(bh); - if (handle != NULL) - zonecfg_fini_handle(handle); if (prof) di_prof_fini(prof); return (retval); @@ -1670,12 +1704,10 @@ static int mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) { char rootpath[MAXPATHLEN]; - char zonepath[MAXPATHLEN]; char brand[MAXNAMELEN]; char luroot[MAXPATHLEN]; int i, num_fs = 0; struct zone_fstab *fs_ptr = NULL; - zone_dochandle_t handle = NULL; zone_state_t zstate; brand_handle_t bh; plat_gmount_cb_data_t cb; @@ -1689,22 +1721,12 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) goto bad; } - if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) { - zerror(zlogp, B_TRUE, "unable to determine zone path"); - goto bad; - } - if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) { zerror(zlogp, B_TRUE, "unable to determine zone root"); goto bad; } - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - goto bad; - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK || - zonecfg_setfsent(handle) != Z_OK) { + if (zonecfg_setfsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "invalid configuration"); goto bad; } @@ -1722,7 +1744,6 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) /* Get a handle to the brand info for this zone */ if ((bh = brand_open(brand)) == NULL) { zerror(zlogp, B_FALSE, "unable to determine zone brand"); - zonecfg_fini_handle(handle); return (-1); } @@ -1733,11 +1754,10 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) cb.pgcd_zlogp = zlogp; cb.pgcd_fs_tab = &fs_ptr; cb.pgcd_num_fs = &num_fs; - if (brand_platform_iter_gmounts(bh, zonepath, + if (brand_platform_iter_gmounts(bh, zone_name, zonepath, plat_gmount_cb, &cb) != 0) { zerror(zlogp, B_FALSE, "unable to mount filesystems"); brand_close(bh); - zonecfg_fini_handle(handle); return (-1); } brand_close(bh); @@ -1748,13 +1768,10 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) * higher level directories (e.g., /usr) get mounted before * any beneath them (e.g., /usr/local). */ - if (mount_filesystems_fsent(handle, zlogp, &fs_ptr, &num_fs, + if (mount_filesystems_fsent(snap_hndl, zlogp, &fs_ptr, &num_fs, mount_cmd) != 0) goto bad; - zonecfg_fini_handle(handle); - handle = NULL; - /* * Normally when we mount a zone all the zone filesystems * get mounted relative to rootpath, which is usually @@ -1833,8 +1850,6 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) return (0); bad: - if (handle != NULL) - zonecfg_fini_handle(handle); free_fs_data(fs_ptr, num_fs); return (-1); } @@ -2190,13 +2205,7 @@ configure_one_interface(zlog_t *zlogp, zoneid_t zone_id, if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) { /* * Here, we know that the interface can't be brought up. - * A similar warning message was already printed out to - * the console by zoneadm(1M) so instead we log the - * message to syslog and continue. */ - zerror(&logsys, B_TRUE, "WARNING: skipping network interface " - "'%s' which may not be present/plumbed in the " - "global zone.", lifr.lifr_name); (void) close(s); return (Z_OK); } @@ -2409,7 +2418,6 @@ bad: static int configure_shared_network_interfaces(zlog_t *zlogp) { - zone_dochandle_t handle; struct zone_nwiftab nwiftab, loopback_iftab; zoneid_t zoneid; @@ -2418,29 +2426,19 @@ configure_shared_network_interfaces(zlog_t *zlogp) return (-1); } - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - if (zonecfg_setnwifent(handle) == Z_OK) { + if (zonecfg_setnwifent(snap_hndl) == Z_OK) { for (;;) { - if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK) + if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK) break; + nwifent_free_attrs(&nwiftab); if (configure_one_interface(zlogp, zoneid, &nwiftab) != Z_OK) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); return (-1); } } - (void) zonecfg_endnwifent(handle); + (void) zonecfg_endnwifent(snap_hndl); } - zonecfg_fini_handle(handle); if (is_system_labeled()) { /* * Labeled zones share the loopback interface @@ -2894,7 +2892,6 @@ free_ip_interface(zone_addr_list_t *zalist) static int configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) { - zone_dochandle_t handle; struct zone_nwiftab nwiftab; char rootpath[MAXPATHLEN]; char path[MAXPATHLEN]; @@ -2903,30 +2900,18 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) boolean_t added = B_FALSE; zone_addr_list_t *zalist = NULL, *new; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - - if (zonecfg_setnwifent(handle) != Z_OK) { - zonecfg_fini_handle(handle); + if (zonecfg_setnwifent(snap_hndl) != Z_OK) return (0); - } for (;;) { - if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK) + if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK) break; + nwifent_free_attrs(&nwiftab); if (prof == NULL) { if (zone_get_devroot(zone_name, rootpath, sizeof (rootpath)) != Z_OK) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); zerror(zlogp, B_TRUE, "unable to determine dev root"); return (-1); @@ -2934,8 +2919,7 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) (void) snprintf(path, sizeof (path), "%s%s", rootpath, "/dev"); if (di_prof_init(path, &prof) != 0) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); zerror(zlogp, B_TRUE, "failed to initialize profile"); return (-1); @@ -2959,17 +2943,17 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) nwiftab.zone_nwif_physical) == 0) { added = B_TRUE; } else { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); - zerror(zlogp, B_TRUE, "failed to add network device"); - return (-1); + /* + * Failed to add network device, but the brand hook + * might be doing this for us, so keep silent. + */ + continue; } /* set up the new IP interface, and add them all later */ new = malloc(sizeof (*new)); if (new == NULL) { zerror(zlogp, B_TRUE, "no memory for %s", nwiftab.zone_nwif_physical); - zonecfg_fini_handle(handle); free_ip_interface(zalist); } bzero(new, sizeof (*new)); @@ -2979,16 +2963,14 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) } if (zalist != NULL) { if ((errno = add_net(zlogp, zoneid, zalist)) != 0) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); zerror(zlogp, B_TRUE, "failed to add address"); free_ip_interface(zalist); return (-1); } free_ip_interface(zalist); } - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); if (prof != NULL && added) { if (di_prof_commit(prof) != 0) { @@ -3124,48 +3106,23 @@ remove_datalink_protect(zlog_t *zlogp, zoneid_t zoneid) /* datalink does not belong to the GZ */ continue; } - if (dlstatus != DLADM_STATUS_OK) { + if (dlstatus != DLADM_STATUS_OK) zerror(zlogp, B_FALSE, + "clear 'protection' link property: %s", dladm_status2str(dlstatus, dlerr)); - free(dllinks); - return (-1); - } + dlstatus = dladm_set_linkprop(dld_handle, *dllink, "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE); - if (dlstatus != DLADM_STATUS_OK) { + if (dlstatus != DLADM_STATUS_OK) zerror(zlogp, B_FALSE, + "clear 'allowed-ips' link property: %s", dladm_status2str(dlstatus, dlerr)); - free(dllinks); - return (-1); - } } free(dllinks); return (0); } static int -unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) -{ - int dlnum = 0; - - /* - * The kernel shutdown callback for the dls module should have removed - * all datalinks from this zone. If any remain, then there's a - * problem. - */ - if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) { - zerror(zlogp, B_TRUE, "unable to list network interfaces"); - return (-1); - } - if (dlnum != 0) { - zerror(zlogp, B_FALSE, - "datalinks remain in zone after shutdown"); - return (-1); - } - return (0); -} - -static int tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid, const struct sockaddr_storage *local, const struct sockaddr_storage *remote) { @@ -3247,26 +3204,14 @@ static int get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd) { int error = -1; - zone_dochandle_t handle; char *privname = NULL; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - if (ALT_MOUNT(mount_cmd)) { zone_iptype_t iptype; - const char *curr_iptype; + const char *curr_iptype = NULL; - if (zonecfg_get_iptype(handle, &iptype) != Z_OK) { + if (zonecfg_get_iptype(snap_hndl, &iptype) != Z_OK) { zerror(zlogp, B_TRUE, "unable to determine ip-type"); - zonecfg_fini_handle(handle); return (-1); } @@ -3279,17 +3224,15 @@ get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd) break; } - if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) { - zonecfg_fini_handle(handle); + if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) return (0); - } + zerror(zlogp, B_FALSE, "failed to determine the zone's default privilege set"); - zonecfg_fini_handle(handle); return (-1); } - switch (zonecfg_get_privset(handle, privs, &privname)) { + switch (zonecfg_get_privset(snap_hndl, privs, &privname)) { case Z_OK: error = 0; break; @@ -3312,10 +3255,22 @@ get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd) } free(privname); - zonecfg_fini_handle(handle); return (error); } +static char * +zone_proj_rctl(const char *name) +{ + int i; + + for (i = 0; zone_proj_rctl_map[i].zpr_zone_rctl != NULL; i++) { + if (strcmp(name, zone_proj_rctl_map[i].zpr_zone_rctl) == 0) { + return (zone_proj_rctl_map[i].zpr_project_rctl); + } + } + return (NULL); +} + static int get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) { @@ -3325,7 +3280,6 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) nvlist_t **nvlv = NULL; int rctlcount = 0; int error = -1; - zone_dochandle_t handle; struct zone_rctltab rctltab; rctlblk_t *rctlblk = NULL; uint64_t maxlwps; @@ -3334,16 +3288,6 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) *bufp = NULL; *bufsizep = 0; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - rctltab.zone_rctl_valptr = NULL; if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { zerror(zlogp, B_TRUE, "%s failed", "nvlist_alloc"); @@ -3356,18 +3300,18 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) * max-processes property. If only the max-processes property is set, * we add a max-lwps property with a limit derived from max-processes. */ - if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPROCS, &maxprocs) + if (zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXPROCS, &maxprocs) == Z_OK && - zonecfg_get_aliased_rctl(handle, ALIAS_MAXLWPS, &maxlwps) + zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXLWPS, &maxlwps) == Z_NO_ENTRY) { - if (zonecfg_set_aliased_rctl(handle, ALIAS_MAXLWPS, + if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXLWPS, maxprocs * LWPS_PER_PROCESS) != Z_OK) { zerror(zlogp, B_FALSE, "unable to set max-lwps alias"); goto out; } } - if (zonecfg_setrctlent(handle) != Z_OK) { + if (zonecfg_setrctlent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent"); goto out; } @@ -3376,10 +3320,11 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) zerror(zlogp, B_TRUE, "memory allocation failed"); goto out; } - while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { + while (zonecfg_getrctlent(snap_hndl, &rctltab) == Z_OK) { struct zone_rctlvaltab *rctlval; uint_t i, count; const char *name = rctltab.zone_rctl_name; + char *proj_nm; /* zoneadm should have already warned about unknown rctls. */ if (!zonecfg_is_rctl(name)) { @@ -3446,6 +3391,26 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) } zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); rctltab.zone_rctl_valptr = NULL; + + /* + * With no action on our part we will start zsched with the + * project rctl values for our (zoneadmd) current project. For + * brands running a variant of Illumos, that's not a problem + * since they will setup their own projects, but for a + * non-native brand like lx, where there are no projects, we + * want to start things up with the same project rctls as the + * corresponding zone rctls, since nothing within the zone will + * ever change the project rctls. + */ + if ((proj_nm = zone_proj_rctl(name)) != NULL) { + if (nvlist_add_nvlist_array(nvl, proj_nm, nvlv, count) + != 0) { + zerror(zlogp, B_FALSE, + "nvlist_add_nvlist_arrays failed"); + goto out; + } + } + if (nvlist_add_nvlist_array(nvl, (char *)name, nvlv, count) != 0) { zerror(zlogp, B_FALSE, "%s failed", @@ -3458,7 +3423,7 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) nvlv = NULL; rctlcount++; } - (void) zonecfg_endrctlent(handle); + (void) zonecfg_endrctlent(snap_hndl); if (rctlcount == 0) { error = 0; @@ -3483,8 +3448,6 @@ out: nvlist_free(nvl); if (nvlv != NULL) free(nvlv); - if (handle != NULL) - zonecfg_fini_handle(handle); return (error); } @@ -3500,7 +3463,7 @@ get_implicit_datasets(zlog_t *zlogp, char **retstr) > sizeof (cmdbuf)) return (-1); - if (do_subproc(zlogp, cmdbuf, retstr) != 0) + if (do_subproc(zlogp, cmdbuf, retstr, B_FALSE) != 0) return (-1); return (0); @@ -3509,7 +3472,6 @@ get_implicit_datasets(zlog_t *zlogp, char **retstr) static int get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) { - zone_dochandle_t handle; struct zone_dstab dstab; size_t total, offset, len; int error = -1; @@ -3520,30 +3482,20 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) *bufp = NULL; *bufsizep = 0; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - if (get_implicit_datasets(zlogp, &implicit_datasets) != 0) { zerror(zlogp, B_FALSE, "getting implicit datasets failed"); goto out; } - if (zonecfg_setdsent(handle) != Z_OK) { + if (zonecfg_setdsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent"); goto out; } total = 0; - while (zonecfg_getdsent(handle, &dstab) == Z_OK) + while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) total += strlen(dstab.zone_dataset_name) + 1; - (void) zonecfg_enddsent(handle); + (void) zonecfg_enddsent(snap_hndl); if (implicit_datasets != NULL) implicit_len = strlen(implicit_datasets); @@ -3560,12 +3512,12 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) goto out; } - if (zonecfg_setdsent(handle) != Z_OK) { + if (zonecfg_setdsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent"); goto out; } offset = 0; - while (zonecfg_getdsent(handle, &dstab) == Z_OK) { + while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) { len = strlen(dstab.zone_dataset_name); (void) strlcpy(str + offset, dstab.zone_dataset_name, total - offset); @@ -3573,7 +3525,7 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) if (offset < total - 1) str[offset++] = ','; } - (void) zonecfg_enddsent(handle); + (void) zonecfg_enddsent(snap_hndl); if (implicit_len > 0) (void) strlcpy(str + offset, implicit_datasets, total - offset); @@ -3585,8 +3537,6 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) out: if (error != 0 && str != NULL) free(str); - if (handle != NULL) - zonecfg_fini_handle(handle); if (implicit_datasets != NULL) free(implicit_datasets); @@ -3596,40 +3546,26 @@ out: static int validate_datasets(zlog_t *zlogp) { - zone_dochandle_t handle; struct zone_dstab dstab; zfs_handle_t *zhp; libzfs_handle_t *hdl; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (-1); - } - if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { + if (zonecfg_setdsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (-1); - } - - if (zonecfg_setdsent(handle) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); return (-1); } if ((hdl = libzfs_init()) == NULL) { zerror(zlogp, B_FALSE, "opening ZFS library"); - zonecfg_fini_handle(handle); return (-1); } - while (zonecfg_getdsent(handle, &dstab) == Z_OK) { + while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) { if ((zhp = zfs_open(hdl, dstab.zone_dataset_name, ZFS_TYPE_FILESYSTEM)) == NULL) { zerror(zlogp, B_FALSE, "cannot open ZFS dataset '%s'", dstab.zone_dataset_name); - zonecfg_fini_handle(handle); libzfs_fini(hdl); return (-1); } @@ -3644,7 +3580,6 @@ validate_datasets(zlog_t *zlogp) zerror(zlogp, B_FALSE, "cannot set 'zoned' " "property for ZFS dataset '%s'\n", dstab.zone_dataset_name); - zonecfg_fini_handle(handle); zfs_close(zhp); libzfs_fini(hdl); return (-1); @@ -3652,9 +3587,8 @@ validate_datasets(zlog_t *zlogp) zfs_close(zhp); } - (void) zonecfg_enddsent(handle); + (void) zonecfg_enddsent(snap_hndl); - zonecfg_fini_handle(handle); libzfs_fini(hdl); return (0); @@ -3708,17 +3642,11 @@ validate_rootds_label(zlog_t *zlogp, char *rootpath, m_label_t *zone_sl) zfs_handle_t *zhp; libzfs_handle_t *hdl; m_label_t ds_sl; - char zonepath[MAXPATHLEN]; char ds_hexsl[MAXNAMELEN]; if (!is_system_labeled()) return (0); - if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) { - zerror(zlogp, B_TRUE, "unable to determine zone path"); - return (-1); - } - if (!is_zonepath_zfs(zonepath)) return (0); @@ -4388,62 +4316,25 @@ duplicate_reachable_path(zlog_t *zlogp, const char *rootpath) } /* - * Set memory cap and pool info for the zone's resource management - * configuration. + * Set pool info for the zone's resource management configuration. */ static int setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) { int res; uint64_t tmp; - struct zone_mcaptab mcap; char sched[MAXNAMELEN]; - zone_dochandle_t handle = NULL; char pool_err[128]; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (Z_BAD_HANDLE); - } - - if ((res = zonecfg_get_snapshot_handle(zone_name, handle)) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - zonecfg_fini_handle(handle); - return (res); - } - - /* - * If a memory cap is configured, set the cap in the kernel using - * zone_setattr() and make sure the rcapd SMF service is enabled. - */ - if (zonecfg_getmcapent(handle, &mcap) == Z_OK) { - uint64_t num; - char smf_err[128]; - - num = (uint64_t)strtoull(mcap.zone_physmem_cap, NULL, 10); - if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) { - zerror(zlogp, B_TRUE, "could not set zone memory cap"); - zonecfg_fini_handle(handle); - return (Z_INVAL); - } - - if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) { - zerror(zlogp, B_FALSE, "enabling system/rcap service " - "failed: %s", smf_err); - zonecfg_fini_handle(handle); - return (Z_INVAL); - } - } - /* Get the scheduling class set in the zone configuration. */ - if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK && + if (zonecfg_get_sched_class(snap_hndl, sched, sizeof (sched)) == Z_OK && strlen(sched) > 0) { if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, sched, strlen(sched)) == -1) zerror(zlogp, B_TRUE, "WARNING: unable to set the " "default scheduling class"); - } else if (zonecfg_get_aliased_rctl(handle, ALIAS_SHARES, &tmp) + } else if (zonecfg_get_aliased_rctl(snap_hndl, ALIAS_SHARES, &tmp) == Z_OK) { /* * If the zone has the zone.cpu-shares rctl set then we want to @@ -4454,7 +4345,7 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) */ char class_name[PC_CLNMSZ]; - if (zonecfg_get_dflt_sched_class(handle, class_name, + if (zonecfg_get_dflt_sched_class(snap_hndl, class_name, sizeof (class_name)) != Z_OK) { zerror(zlogp, B_FALSE, "WARNING: unable to determine " "the zone's scheduling class"); @@ -4487,7 +4378,7 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) * right thing in all cases (reuse or create) based on the current * zonecfg. */ - if ((res = zonecfg_bind_tmp_pool(handle, zoneid, pool_err, + if ((res = zonecfg_bind_tmp_pool(snap_hndl, zoneid, pool_err, sizeof (pool_err))) != Z_OK) { if (res == Z_POOL || res == Z_POOL_CREATE || res == Z_POOL_BIND) zerror(zlogp, B_FALSE, "%s: %s\ndedicated-cpu setting " @@ -4496,14 +4387,13 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) else zerror(zlogp, B_FALSE, "could not bind zone to " "temporary pool: %s", zonecfg_strerror(res)); - zonecfg_fini_handle(handle); return (Z_POOL_BIND); } /* * Check if we need to warn about poold not being enabled. */ - if (zonecfg_warn_poold(handle)) { + if (zonecfg_warn_poold(snap_hndl)) { zerror(zlogp, B_FALSE, "WARNING: A range of dedicated-cpus has " "been specified\nbut the dynamic pool service is not " "enabled.\nThe system will not dynamically adjust the\n" @@ -4513,7 +4403,7 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) } /* The following is a warning, not an error. */ - if ((res = zonecfg_bind_pool(handle, zoneid, pool_err, + if ((res = zonecfg_bind_pool(snap_hndl, zoneid, pool_err, sizeof (pool_err))) != Z_OK) { if (res == Z_POOL_BIND) zerror(zlogp, B_FALSE, "WARNING: unable to bind to " @@ -4527,10 +4417,9 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) } /* Update saved pool name in case it has changed */ - (void) zonecfg_get_poolname(handle, zone_name, pool_name, + (void) zonecfg_get_poolname(snap_hndl, zone_name, pool_name, sizeof (pool_name)); - zonecfg_fini_handle(handle); return (Z_OK); } @@ -4631,33 +4520,28 @@ setup_zone_fs_allowed(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid) } static int -setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid) +setup_zone_attrs(zlog_t *zlogp, zoneid_t zoneid) { - zone_dochandle_t handle; int res = Z_OK; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, "getting zone configuration handle"); - return (Z_BAD_HANDLE); - } - if ((res = zonecfg_get_snapshot_handle(zone_namep, handle)) != Z_OK) { - zerror(zlogp, B_FALSE, "invalid configuration"); - goto out; - } - - if ((res = setup_zone_hostid(handle, zlogp, zoneid)) != Z_OK) + if ((res = setup_zone_hostid(snap_hndl, zlogp, zoneid)) != Z_OK) goto out; - if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK) + if ((res = setup_zone_fs_allowed(snap_hndl, zlogp, zoneid)) != Z_OK) goto out; out: - zonecfg_fini_handle(handle); return (res); } +/* + * The zone_did is a persistent debug ID. Each zone should have a unique ID + * in the kernel. This is used for things like DTrace which want to monitor + * zones across reboots. They can't use the zoneid since that changes on + * each boot. + */ zoneid_t -vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) +vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zone_did) { zoneid_t rval = -1; priv_set_t *privs; @@ -4673,7 +4557,7 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) tsol_zcent_t *zcent = NULL; int match = 0; int doi = 0; - int flags; + int flags = -1; zone_iptype_t iptype; if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) { @@ -4695,6 +4579,8 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) flags = ZCF_NET_EXCL; break; } + if (flags == -1) + abort(); if ((privs = priv_allocset()) == NULL) { zerror(zlogp, B_TRUE, "%s failed", "priv_allocset"); @@ -4798,7 +4684,7 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) xerr = 0; if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf, rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel, - flags)) == -1) { + flags, zone_did)) == -1) { if (xerr == ZE_AREMOUNTS) { if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) { zerror(zlogp, B_FALSE, @@ -4844,7 +4730,7 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) struct brand_attr attr; char modname[MAXPATHLEN]; - if (setup_zone_attrs(zlogp, zone_name, zoneid) != Z_OK) + if (setup_zone_attrs(zlogp, zoneid) != Z_OK) goto error; if ((bh = brand_open(brand_name)) == NULL) { @@ -4902,6 +4788,8 @@ error: } if (rctlbuf != NULL) free(rctlbuf); + if (zfsbuf != NULL) + free(zfsbuf); priv_freeset(privs); if (fp != NULL) zonecfg_close_scratch(fp); @@ -4990,7 +4878,7 @@ write_index_file(zoneid_t zoneid) int vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid) { - char zonepath[MAXPATHLEN]; + char zpath[MAXPATHLEN]; if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) { lofs_discard_mnttab(); @@ -5001,15 +4889,11 @@ vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid) * Before we try to mount filesystems we need to create the * attribute backing store for /dev */ - if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) { - lofs_discard_mnttab(); - return (-1); - } - resolve_lofs(zlogp, zonepath, sizeof (zonepath)); + (void) strlcpy(zpath, zonepath, sizeof (zpath)); + resolve_lofs(zlogp, zpath, sizeof (zpath)); /* Make /dev directory owned by root, grouped sys */ - if (make_one_dir(zlogp, zonepath, "/dev", DEFAULT_DIR_MODE, - 0, 3) != 0) { + if (make_one_dir(zlogp, zpath, "/dev", DEFAULT_DIR_MODE, 0, 3) != 0) { lofs_discard_mnttab(); return (-1); } @@ -5044,6 +4928,8 @@ vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid) return (-1); } break; + default: + abort(); } } @@ -5119,13 +5005,13 @@ unmounted: } int -vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) +vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, + boolean_t debug) { char *kzone; zoneid_t zoneid; int res; char pool_err[128]; - char zpath[MAXPATHLEN]; char cmdbuf[MAXPATHLEN]; brand_handle_t bh = NULL; dladm_status_t status; @@ -5158,16 +5044,12 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) goto error; } - if (remove_datalink_pool(zlogp, zoneid) != 0) { + if (remove_datalink_pool(zlogp, zoneid) != 0) zerror(zlogp, B_FALSE, "unable clear datalink pool property"); - goto error; - } - if (remove_datalink_protect(zlogp, zoneid) != 0) { + if (remove_datalink_protect(zlogp, zoneid) != 0) zerror(zlogp, B_FALSE, "unable clear datalink protect property"); - goto error; - } /* * The datalinks assigned to the zone will be removed from the NGZ as @@ -5181,12 +5063,6 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) goto error; } - /* Get the zonepath of this zone */ - if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) { - zerror(zlogp, B_FALSE, "unable to determine zone path"); - goto error; - } - /* Get a handle to the brand info for this zone */ if ((bh = brand_open(brand_name)) == NULL) { zerror(zlogp, B_FALSE, "unable to determine zone brand"); @@ -5197,7 +5073,7 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) * brand a chance to cleanup any custom configuration. */ (void) strcpy(cmdbuf, EXEC_PREFIX); - if (brand_get_halt(bh, zone_name, zpath, cmdbuf + EXEC_LEN, + if (brand_get_halt(bh, zone_name, zonepath, cmdbuf + EXEC_LEN, sizeof (cmdbuf) - EXEC_LEN) < 0) { brand_close(bh); zerror(zlogp, B_FALSE, "unable to determine branded zone's " @@ -5207,7 +5083,7 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) brand_close(bh); if ((strlen(cmdbuf) > EXEC_LEN) && - (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) { + (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) { zerror(zlogp, B_FALSE, "%s failed", cmdbuf); goto error; } @@ -5239,12 +5115,6 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) } break; case ZS_EXCLUSIVE: - if (unconfigure_exclusive_network_interfaces(zlogp, - zoneid) != 0) { - zerror(zlogp, B_FALSE, "unable to unconfigure " - "network interfaces in zone"); - goto error; - } status = dladm_zone_halt(dld_handle, zoneid); if (status != DLADM_STATUS_OK) { zerror(zlogp, B_FALSE, "unable to notify " @@ -5281,14 +5151,9 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) if (rebooting) { struct zone_psettab pset_tab; - zone_dochandle_t handle; - if ((handle = zonecfg_init_handle()) != NULL && - zonecfg_get_handle(zone_name, handle) == Z_OK && - zonecfg_lookup_pset(handle, &pset_tab) == Z_OK) + if (zonecfg_lookup_pset(snap_hndl, &pset_tab) == Z_OK) destroy_tmp_pool = B_FALSE; - - zonecfg_fini_handle(handle); } if (destroy_tmp_pool) { diff --git a/usr/src/cmd/zoneadmd/zcons.c b/usr/src/cmd/zoneadmd/zcons.c index 1466217587..30e4a35a35 100644 --- a/usr/src/cmd/zoneadmd/zcons.c +++ b/usr/src/cmd/zoneadmd/zcons.c @@ -22,7 +22,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2012 Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ @@ -118,9 +118,10 @@ #define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock" +#define ZCONS_RETRY 10 + static int serverfd = -1; /* console server unix domain socket fd */ char boot_args[BOOTARGS_MAX]; -char bad_boot_arg[BOOTARGS_MAX]; /* * The eventstream is a simple one-directional flow of messages from the @@ -130,7 +131,10 @@ char bad_boot_arg[BOOTARGS_MAX]; */ static int eventstream[2]; - +/* flag used to cope with race creating master zcons devlink */ +static boolean_t master_zcons_failed = B_FALSE; +/* flag to track if we've seen a state change when there is no master zcons */ +static boolean_t state_changed = B_FALSE; int eventstream_init() @@ -322,7 +326,7 @@ destroy_console_devs(zlog_t *zlogp) * interfaces to instantiate a new zone console node. We do a lot of * sanity checking, and are careful to reuse a console if one exists. * - * Once the device is in the device tree, we kick devfsadm via di_init_devs() + * Once the device is in the device tree, we kick devfsadm via di_devlink_init() * to ensure that the appropriate symlinks (to the master and slave console * devices) are placed in /dev in the global zone. */ @@ -408,43 +412,63 @@ devlinks: * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl, * which will cause the master to retain a reference to the slave. * This prevents ttymon from blowing through the slave's STREAMS anchor. + * + * In very rare cases the open returns ENOENT if devfs doesn't have + * everything setup yet due to heavy zone startup load. Wait for + * 1 sec. and retry a few times. Even if we can't setup the zone's + * console, we still go ahead and boot the zone. */ (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME); - if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) { + for (i = 0; i < ZCONS_RETRY; i++) { + masterfd = open(conspath, O_RDWR | O_NOCTTY); + if (masterfd >= 0 || errno != ENOENT) + break; + (void) sleep(1); + } + if (masterfd == -1) { zerror(zlogp, B_TRUE, "ERROR: could not open master side of " "zone console for %s to acquire slave handle", zone_name); - goto error; + master_zcons_failed = B_TRUE; } + (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", zone_name, ZCONS_SLAVE_NAME); - if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) == -1) { + for (i = 0; i < ZCONS_RETRY; i++) { + slavefd = open(conspath, O_RDWR | O_NOCTTY); + if (slavefd >= 0 || errno != ENOENT) + break; + (void) sleep(1); + } + if (slavefd == -1) zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone" " console for %s to acquire slave handle", zone_name); - (void) close(masterfd); - goto error; - } + /* * This ioctl can occasionally return ENXIO if devfs doesn't have * everything plumbed up yet due to heavy zone startup load. Wait for * 1 sec. and retry a few times before we fail to boot the zone. */ - for (i = 0; i < 5; i++) { - if (ioctl(masterfd, ZC_HOLDSLAVE, (caddr_t)(intptr_t)slavefd) - == 0) { - rv = 0; - break; - } else if (errno != ENXIO) { - break; + if (masterfd != -1 && slavefd != -1) { + for (i = 0; i < ZCONS_RETRY; i++) { + if (ioctl(masterfd, ZC_HOLDSLAVE, + (caddr_t)(intptr_t)slavefd) == 0) { + rv = 0; + break; + } else if (errno != ENXIO) { + break; + } + (void) sleep(1); } - (void) sleep(1); + if (rv != 0) + zerror(zlogp, B_TRUE, "ERROR: error while acquiring " + "slave handle of zone console for %s", zone_name); } - if (rv != 0) - zerror(zlogp, B_TRUE, "ERROR: error while acquiring slave " - "handle of zone console for %s", zone_name); - (void) close(slavefd); - (void) close(masterfd); + if (slavefd != -1) + (void) close(slavefd); + if (masterfd != -1) + (void) close(masterfd); error: if (ddef_hdl) @@ -517,6 +541,7 @@ get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len, size_t buflen = sizeof (buf); char c = '\0'; int i = 0, r; + ucred_t *cred = NULL; /* "eat up the ident string" case, for simplicity */ if (pid == NULL) { @@ -550,18 +575,22 @@ get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len, break; } + if (getpeerucred(clifd, &cred) == 0) { + *pid = ucred_getpid((const ucred_t *)cred); + ucred_free(cred); + } else { + return (-1); + } + /* * Parse buffer for message of the form: - * IDENT <pid> <locale> <disconnect flag> + * IDENT <locale> <disconnect flag> */ bufp = buf; if (strncmp(bufp, "IDENT ", 6) != 0) return (-1); bufp += 6; errno = 0; - *pid = strtoll(bufp, &bufp, 10); - if (errno != 0) - return (-1); while (*bufp != '\0' && isspace(*bufp)) bufp++; @@ -667,14 +696,6 @@ event_message(int clifd, char *clilocale, zone_evt_t evt, int dflag) else str = "NOTICE: Zone boot failed"; break; - case Z_EVT_ZONE_BADARGS: - /*LINTED*/ - (void) snprintf(lmsg, sizeof (lmsg), - localize_msg(clilocale, - "WARNING: Ignoring invalid boot arguments: %s"), - bad_boot_arg); - lstr = lmsg; - break; default: return; } @@ -878,7 +899,6 @@ init_console(zlog_t *zlogp) if (init_console_dev(zlogp) == -1) { zerror(zlogp, B_FALSE, "console setup: device initialization failed"); - return (-1); } if ((serverfd = init_console_sock(zlogp)) == -1) { @@ -890,6 +910,17 @@ init_console(zlog_t *zlogp) } /* + * Maintain a simple flag that tracks if we have seen at least one state + * change. This is currently only used to handle the special case where we are + * running without a console device, which is what normally drives shutdown. + */ +void +zcons_statechanged() +{ + state_changed = B_TRUE; +} + +/* * serve_console() is the master loop for driving console I/O. It is also the * routine which is ultimately responsible for "pulling the plug" on zoneadmd * when it realizes that the daemon should shut down. @@ -907,6 +938,7 @@ serve_console(zlog_t *zlogp) int masterfd; zone_state_t zstate; char conspath[MAXPATHLEN]; + static boolean_t cons_warned = B_FALSE; (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME); @@ -914,6 +946,46 @@ serve_console(zlog_t *zlogp) for (;;) { masterfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY); if (masterfd == -1) { + if (master_zcons_failed) { + /* + * If we don't have a console and the zone is + * not shutting down, there may have been a + * race/failure with devfs while creating the + * console. In this case we want to leave the + * zone up, even without a console, so + * periodically recheck. + */ + int i; + + /* + * In the normal flow of this loop, we use + * do_console_io to give things a chance to get + * going first. However, in this case we can't + * use that, so we have to wait for at least + * one state change before checking the state. + */ + for (i = 0; i < 60; i++) { + if (state_changed) + break; + (void) sleep(1); + } + + if (i < 60 && zone_get_state(zone_name, + &zstate) == Z_OK && + (zstate == ZONE_STATE_READY || + zstate == ZONE_STATE_RUNNING)) { + if (!cons_warned) { + zerror(zlogp, B_FALSE, + "WARNING: missing zone " + "console for %s", + zone_name); + cons_warned = B_TRUE; + } + (void) sleep(ZCONS_RETRY); + continue; + } + } + zerror(zlogp, B_TRUE, "failed to open console master"); (void) mutex_lock(&lock); goto death; diff --git a/usr/src/cmd/zoneadmd/zfd.c b/usr/src/cmd/zoneadmd/zfd.c new file mode 100644 index 0000000000..662d3fbccd --- /dev/null +++ b/usr/src/cmd/zoneadmd/zfd.c @@ -0,0 +1,1361 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright 2015 Joyent, Inc. All rights reserved. + */ + +/* + * Zone file descriptor support is used as a mechanism for a process inside the + * zone to either log messages to the GZ zoneadmd or as a way to interact + * directly with the process (via zlogin -I). The zfd thread is modeled on + * the zcons thread so see the comment header in zcons.c for a general overview. + * Unlike with zcons, which has a single endpoint within the zone and a single + * endpoint used by zoneadmd, we setup multiple endpoints within the zone. + * + * The mode, which is controlled by the zone attribute "zlog-mode" is somewhat + * of a misnomer since its purpose has evolved. The attribute currently + * can have four values, with misleading names due to backward compatability, + * but which are used to control how many zfd devices are created inside the + * zone, and to control if the output on the device(s) is logged in the GZ. + * See the comment in uts/common/io/zfd.c for more details. + * + * Internally the zfd_mode_t struct holds the number of stdio devs (1 or 3) and + * the number of additional devs corresponding to the zone attr value. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/termios.h> +#include <sys/zfd.h> +#include <sys/mkdev.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <stropts.h> +#include <thread.h> +#include <ucred.h> +#include <unistd.h> +#include <zone.h> +#include <signal.h> +#include <wchar.h> + +#include <libdevinfo.h> +#include <libdevice.h> +#include <libzonecfg.h> + +#include <syslog.h> +#include <sys/modctl.h> + +#include "zoneadmd.h" + +static zlog_t *zlogp; +static int shutting_down = 0; +static thread_t logger_tid; +static int logfd = -1; + +/* + * The eventstream is a simple one-directional flow of messages implemented + * with a pipe. It is used to wake up the poller when it needs to shutdown. + */ +static int eventstream[2] = {-1, -1}; + +#define LOGNAME "stdio.log" +#define ZLOG_MODE "zlog-mode" +#define ZFDNEX_DEVTREEPATH "/pseudo/zfdnex@2" +#define ZFDNEX_FILEPATH "/devices/pseudo/zfdnex@2" +#define SERVER_SOCKPATH ZONES_TMPDIR "/%s.server_%s" +#define ZTTY_RETRY 5 + +typedef struct zfd_mode { + uint_t zmode_n_stddevs; + uint_t zmode_n_addl_devs; +} zfd_mode_t; +static zfd_mode_t mode; + +/* + * count_zfd_devs() and its helper count_cb() do a walk of the subtree of the + * device tree where zfd nodes are represented. The goal is to count zfd + * instances already setup for a zone with the given name. + * + * Note: this algorithm is a linear search of nodes in the zfdnex subtree + * of the device tree, and could be a scalability problem, but I don't see + * how to avoid it. + */ + +/* + * cb_data is shared by count_cb and destroy_cb for simplicity. + */ +struct cb_data { + zlog_t *zlogp; + int found; + int killed; +}; + +static int +count_cb(di_node_t node, void *arg) +{ + struct cb_data *cb = (struct cb_data *)arg; + char *prop_data; + + if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname", + &prop_data) != -1) { + assert(prop_data != NULL); + if (strcmp(prop_data, zone_name) == 0) { + cb->found++; + return (DI_WALK_CONTINUE); + } + } + return (DI_WALK_CONTINUE); +} + +static int +count_zfd_devs(zlog_t *zlogp) +{ + di_node_t root; + struct cb_data cb; + + bzero(&cb, sizeof (cb)); + cb.zlogp = zlogp; + + if ((root = di_init(ZFDNEX_DEVTREEPATH, DINFOCPYALL)) == DI_NODE_NIL) { + zerror(zlogp, B_TRUE, "di_init failed"); + return (-1); + } + + (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, count_cb); + di_fini(root); + return (cb.found); +} + +/* + * destroy_zfd_devs() and its helper destroy_cb() tears down any zfd instances + * associated with this zone. If things went very wrong, we might have an + * incorrect number of instances hanging around. This routine hunts down and + * tries to remove all of them. Of course, if the fd is open, the instance will + * not detach, which is a potential issue. + */ +static int +destroy_cb(di_node_t node, void *arg) +{ + struct cb_data *cb = (struct cb_data *)arg; + char *prop_data; + char *tmp; + char devpath[MAXPATHLEN]; + devctl_hdl_t hdl; + + if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname", + &prop_data) == -1) + return (DI_WALK_CONTINUE); + + assert(prop_data != NULL); + if (strcmp(prop_data, zone_name) != 0) { + /* this is a zfd for a different zone */ + return (DI_WALK_CONTINUE); + } + + cb->found++; + tmp = di_devfs_path(node); + (void) snprintf(devpath, sizeof (devpath), "/devices/%s", tmp); + di_devfs_path_free(tmp); + + if ((hdl = devctl_device_acquire(devpath, 0)) == NULL) { + zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, " + "but it could not be controlled.", devpath); + return (DI_WALK_CONTINUE); + } + if (devctl_device_remove(hdl) == 0) { + cb->killed++; + } else { + zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, " + "but it could not be removed.", devpath); + } + devctl_release(hdl); + return (DI_WALK_CONTINUE); +} + +static int +destroy_zfd_devs(zlog_t *zlogp) +{ + di_node_t root; + struct cb_data cb; + + bzero(&cb, sizeof (cb)); + cb.zlogp = zlogp; + + if ((root = di_init(ZFDNEX_DEVTREEPATH, DINFOCPYALL)) == DI_NODE_NIL) { + zerror(zlogp, B_TRUE, "di_init failed"); + return (-1); + } + + (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb); + + di_fini(root); + return (0); +} + +static void +make_tty(zlog_t *zlogp, int id) +{ + int i; + int fd = -1; + char stdpath[MAXPATHLEN]; + + /* + * Open the master side of the dev and issue the ZFD_MAKETTY ioctl, + * which will cause the the various tty-related streams modules to be + * pushed when the slave opens the device. + * + * In very rare cases the open returns ENOENT if devfs doesn't have + * everything setup yet due to heavy zone startup load. Wait for + * 1 sec. and retry a few times. Even if we can't setup tty mode + * we still move on. + */ + (void) snprintf(stdpath, sizeof (stdpath), "/dev/zfd/%s/master/%d", + zone_name, id); + + for (i = 0; !shutting_down && i < ZTTY_RETRY; i++) { + fd = open(stdpath, O_RDWR | O_NOCTTY); + if (fd >= 0 || errno != ENOENT) + break; + (void) sleep(1); + } + if (fd == -1) { + zerror(zlogp, B_TRUE, "ERROR: could not open zfd %d for " + "zone %s to set tty mode", id, zone_name); + } else { + /* + * This ioctl can occasionally return ENXIO if devfs doesn't + * have everything plumbed up yet due to heavy zone startup + * load. Wait for 1 sec. and retry a few times before we give + * up. + */ + for (i = 0; !shutting_down && i < ZTTY_RETRY; i++) { + if (ioctl(fd, ZFD_MAKETTY) == 0) { + break; + } else if (errno != ENXIO) { + break; + } + (void) sleep(1); + } + } + + if (fd != -1) + (void) close(fd); +} + +/* + * init_zfd_devs() drives the device-tree configuration of the zone fd devices. + * The general strategy is to use the libdevice (devctl) interfaces to + * instantiate the correct number of new zone fd nodes. We do a lot of sanity + * checking, and are careful to reuse a dev if one exists. + * + * Once the devices are in the device tree, we kick devfsadm via + * di_devlink_init() to ensure that the appropriate symlinks (to the master and + * slave fd devices) are placed in /dev in the global zone. + */ +static int +init_zfd_dev(zlog_t *zlogp, devctl_hdl_t bus_hdl, int id) +{ + int rv = -1; + devctl_ddef_t ddef_hdl = NULL; + devctl_hdl_t dev_hdl = NULL; + + if ((ddef_hdl = devctl_ddef_alloc("zfd", 0)) == NULL) { + zerror(zlogp, B_TRUE, "failed to allocate ddef handle"); + goto error; + } + + /* + * Set four properties on this node; the name of the zone, the dev name + * seen inside the zone, a flag which lets pseudo know that it is OK to + * automatically allocate an instance # for this device, and the last + * one tells the device framework not to auto-detach this node - we + * need the node to still be there when we ask devfsadmd to make links, + * and when we need to open it. + */ + if (devctl_ddef_string(ddef_hdl, "zfd_zname", zone_name) == -1) { + zerror(zlogp, B_TRUE, "failed to create zfd_zname property"); + goto error; + } + if (devctl_ddef_int(ddef_hdl, "zfd_id", id) == -1) { + zerror(zlogp, B_TRUE, "failed to create zfd_id property"); + goto error; + } + if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) { + zerror(zlogp, B_TRUE, "failed to create auto-assign-instance " + "property"); + goto error; + } + if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) { + zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach " + "property"); + goto error; + } + if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) { + zerror(zlogp, B_TRUE, "failed to create zfd node"); + goto error; + } + rv = 0; + +error: + if (ddef_hdl) + devctl_ddef_free(ddef_hdl); + if (dev_hdl) + devctl_release(dev_hdl); + return (rv); +} + +static int +init_zfd_devs(zlog_t *zlogp, zfd_mode_t *mode) +{ + devctl_hdl_t bus_hdl = NULL; + di_devlink_handle_t dl = NULL; + int rv = -1; + int ndevs; + uint_t tot_devs; + int i; + + tot_devs = mode->zmode_n_stddevs + mode->zmode_n_addl_devs; + + /* + * We have to re-setup zone fd devs if they already exist since we + * might be changing zlog modes. + */ + ndevs = count_zfd_devs(zlogp); + if (ndevs > 0 || ndevs == -1) { + if (destroy_zfd_devs(zlogp) == -1) + goto error; + } + + /* + * Time to make the devices. + */ + if ((bus_hdl = devctl_bus_acquire(ZFDNEX_FILEPATH, 0)) == NULL) { + zerror(zlogp, B_TRUE, "devctl_bus_acquire failed"); + goto error; + } + + for (i = 0; i < tot_devs; i++) { + if (init_zfd_dev(zlogp, bus_hdl, i) != 0) + goto error; + } + + if ((dl = di_devlink_init("zfd", DI_MAKE_LINK)) == NULL) { + zerror(zlogp, B_TRUE, "failed to create devlinks"); + goto error; + } + + (void) di_devlink_fini(&dl); + rv = 0; + + if (mode->zmode_n_stddevs == 1) { + /* We want the primary stream to look like a tty. */ + make_tty(zlogp, 0); + } + +error: + if (bus_hdl) + devctl_release(bus_hdl); + return (rv); +} + +static int +init_server_sock(zlog_t *zlogp, int *servfd, char *nm) +{ + int resfd = -1; + struct sockaddr_un servaddr; + + bzero(&servaddr, sizeof (servaddr)); + servaddr.sun_family = AF_UNIX; + (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path), + SERVER_SOCKPATH, zone_name, nm); + + if ((resfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + zerror(zlogp, B_TRUE, "server setup: could not create socket"); + goto err; + } + (void) unlink(servaddr.sun_path); + + if (bind(resfd, (struct sockaddr *)&servaddr, sizeof (servaddr)) + == -1) { + zerror(zlogp, B_TRUE, + "server setup: could not bind to socket"); + goto err; + } + + if (listen(resfd, 4) == -1) { + zerror(zlogp, B_TRUE, + "server setup: could not listen on socket"); + goto err; + } + + *servfd = resfd; + return (0); + +err: + (void) unlink(servaddr.sun_path); + if (resfd != -1) + (void) close(resfd); + return (-1); +} + +static void +destroy_server_sock(int servfd, char *nm) +{ + char path[MAXPATHLEN]; + + (void) snprintf(path, sizeof (path), SERVER_SOCKPATH, zone_name, nm); + (void) unlink(path); + (void) shutdown(servfd, SHUT_RDWR); + (void) close(servfd); +} + +/* + * Read the "ident" string from the client's descriptor; this routine also + * tolerates being called with pid=NULL, for times when you want to "eat" + * the ident string from a client without saving it. + */ +static int +get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len, + uint_t *flagsp) +{ + char buf[BUFSIZ], *bufp; + size_t buflen = sizeof (buf); + char c = '\0'; + int i = 0, r; + ucred_t *cred = NULL; + + /* "eat up the ident string" case, for simplicity */ + if (pid == NULL) { + assert(locale == NULL && locale_len == 0); + while (read(clifd, &c, 1) == 1) { + if (c == '\n') + return (0); + } + } + + bzero(buf, sizeof (buf)); + while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) { + buflen--; + if (c == '\n') + break; + + buf[i] = c; + i++; + } + if (r == -1) + return (-1); + + /* + * We've filled the buffer, but still haven't seen \n. Keep eating + * until we find it; we don't expect this to happen, but this is + * defensive. + */ + if (c != '\n') { + while ((r = read(clifd, &c, sizeof (c))) > 0) + if (c == '\n') + break; + } + + /* + * Parse buffer for message of the form: + * IDENT <locale> <flags> + */ + bufp = buf; + if (strncmp(bufp, "IDENT ", 6) != 0) + return (-1); + bufp += 6; + + if (getpeerucred(clifd, &cred) == 0) { + *pid = ucred_getpid((const ucred_t *)cred); + ucred_free(cred); + } else { + return (-1); + } + + while (*bufp != '\0' && isspace(*bufp)) + bufp++; + buflen = strlen(bufp) - 1; + bufp[buflen - 1] = '\0'; + (void) strlcpy(locale, bufp, locale_len); + + *flagsp = atoi(&bufp[buflen]); + + return (0); +} + +static int +accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len, + uint_t *flagsp) +{ + int connfd; + struct sockaddr_un cliaddr; + socklen_t clilen; + int flags; + + clilen = sizeof (cliaddr); + connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); + if (connfd == -1) + return (-1); + if (pid != NULL) { + if (get_client_ident(connfd, pid, locale, locale_len, flagsp) + == -1) { + (void) shutdown(connfd, SHUT_RDWR); + (void) close(connfd); + return (-1); + } + (void) write(connfd, "OK\n", 3); + } + + flags = fcntl(connfd, F_GETFL, 0); + if (flags != -1) + (void) fcntl(connfd, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC); + + return (connfd); +} + +static void +reject_client(int servfd, pid_t clientpid) +{ + int connfd; + struct sockaddr_un cliaddr; + socklen_t clilen; + char nak[MAXPATHLEN]; + + clilen = sizeof (cliaddr); + connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); + + /* + * After getting its ident string, tell client to get lost. + */ + if (get_client_ident(connfd, NULL, NULL, 0, NULL) == 0) { + (void) snprintf(nak, sizeof (nak), "%lu\n", + clientpid); + (void) write(connfd, nak, strlen(nak)); + } + (void) shutdown(connfd, SHUT_RDWR); + (void) close(connfd); +} + +static int +accept_socket(int servfd, pid_t verpid) +{ + int connfd; + struct sockaddr_un cliaddr; + socklen_t clilen = sizeof (cliaddr); + ucred_t *cred = NULL; + pid_t rpid = -1; + int flags; + + connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); + if (connfd == -1) + return (-1); + + /* Confirm connecting process is who we expect */ + if (getpeerucred(connfd, &cred) == 0) { + rpid = ucred_getpid((const ucred_t *)cred); + ucred_free(cred); + } + if (rpid == -1 || rpid != verpid) { + (void) shutdown(connfd, SHUT_RDWR); + (void) close(connfd); + return (-1); + } + + flags = fcntl(connfd, F_GETFL, 0); + if (flags != -1) + (void) fcntl(connfd, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC); + + return (connfd); +} + +static void +ctlcmd_process(int sockfd, int stdoutfd, unsigned int *flags) +{ + char buf[BUFSIZ]; + int i; + for (i = 0; i < BUFSIZ-1; i++) { + char c; + if (read(sockfd, &c, 1) != 1 || + c == '\n' || c == '\0') { + break; + } + buf[i] = c; + } + if (i == 0) { + goto fail; + } + buf[i+1] = '\0'; + + if (strncmp(buf, "TIOCSWINSZ ", 11) == 0) { + char *next = buf + 11; + struct winsize ws; + errno = 0; + ws.ws_row = strtol(next, &next, 10); + if (errno == EINVAL) { + goto fail; + } + ws.ws_col = strtol(next + 1, &next, 10); + if (errno == EINVAL) { + goto fail; + } + if (ioctl(stdoutfd, TIOCSWINSZ, &ws) == 0) { + (void) write(sockfd, "OK\n", 3); + return; + } + } + if (strncmp(buf, "SETFLAGS ", 9) == 0) { + char *next = buf + 9; + unsigned int result; + errno = 0; + result = strtoul(next, &next, 10); + if (errno == EINVAL) { + goto fail; + } + *flags = result; + (void) write(sockfd, "OK\n", 3); + return; + } +fail: + (void) write(sockfd, "FAIL\n", 5); +} + +/* + * Check to see if the client at the other end of the socket is still alive; we + * know it is not if it throws EPIPE at us when we try to write an otherwise + * harmless 0-length message to it. + */ +static int +test_client(int clifd) +{ + if ((write(clifd, "", 0) == -1) && errno == EPIPE) + return (-1); + return (0); +} + +/* + * Modify the input string with json escapes. Since the destination can thus + * be larger than the source, it may get truncated, although we do use a + * larger buffer. + */ +static void +escape_json(char *sbuf, int slen, char *dbuf, int dlen) +{ + int i; + mbstate_t mbr; + wchar_t c; + size_t sz; + + bzero(&mbr, sizeof (mbr)); + + sbuf[slen] = '\0'; + i = 0; + while (i < dlen && (sz = mbrtowc(&c, sbuf, MB_CUR_MAX, &mbr)) > 0) { + switch (c) { + case '\\': + dbuf[i++] = '\\'; + dbuf[i++] = '\\'; + break; + + case '"': + dbuf[i++] = '\\'; + dbuf[i++] = '"'; + break; + + case '\b': + dbuf[i++] = '\\'; + dbuf[i++] = 'b'; + break; + + case '\f': + dbuf[i++] = '\\'; + dbuf[i++] = 'f'; + break; + + case '\n': + dbuf[i++] = '\\'; + dbuf[i++] = 'n'; + break; + + case '\r': + dbuf[i++] = '\\'; + dbuf[i++] = 'r'; + break; + + case '\t': + dbuf[i++] = '\\'; + dbuf[i++] = 't'; + break; + + default: + if ((c >= 0x00 && c <= 0x1f) || + (c > 0x7f && c <= 0xffff)) { + + i += snprintf(&dbuf[i], (dlen - i), "\\u%04x", + (int)(0xffff & c)); + } else if (c >= 0x20 && c <= 0x7f) { + dbuf[i++] = 0xff & c; + } + + break; + } + sbuf += sz; + } + + if (i == dlen) + dbuf[--i] = '\0'; + else + dbuf[i] = '\0'; +} + +/* + * We output to the log file as json. + * ex. for string 'msg\n' on the zone's stdout: + * {"log":"msg\n","stream":"stdout","time":"2014-10-24T20:12:11.101973117Z"} + * + * We use ns in the last field of the timestamp for compatability. + */ +static void +wr_log_msg(char *buf, int len, int from) +{ + struct timeval tv; + int olen; + char ts[64]; + char nbuf[BUFSIZ * 2]; + char obuf[BUFSIZ * 2]; + + if (logfd == -1) + return; + + escape_json(buf, len, nbuf, sizeof (nbuf)); + + if (gettimeofday(&tv, NULL) != 0) + return; + (void) strftime(ts, sizeof (ts), "%FT%T", gmtime(&tv.tv_sec)); + + olen = snprintf(obuf, sizeof (obuf), + "{\"log\":\"%s\",\"stream\":\"%s\",\"time\":\"%s.%ldZ\"}\n", + nbuf, (from == 1) ? "stdout" : "stderr", ts, tv.tv_usec * 1000); + + (void) write(logfd, obuf, olen); +} + +/* + * We want to sleep for a little while but need to be responsive if the zone is + * halting. We poll/sleep on the event stream so we can notice if we're halting. + * Return true if halting, otherwise false. + */ +static boolean_t +halt_sleep(int slptime) +{ + struct pollfd evfd[1]; + + evfd[0].fd = eventstream[1]; + evfd[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; + + if (poll(evfd, 1, slptime) > 0) { + /* zone halting */ + return (B_TRUE); + } + return (B_FALSE); +} + +/* + * This routine drives the logging and interactive I/O loop. It polls for + * input from the zone side of the fd (output to stdout/stderr), and from the + * client (input to the zone's stdin). Additionally, it polls on the server + * fd, and disconnects any clients that might try to hook up with the zone + * while the fd's are in use. + * + * Data from the zone's stdout and stderr is formatted in json and written to + * the log file whether an interactive client is connected or not. + * + * When the client first calls us up, it is expected to send a line giving its + * "identity"; this consists of the string 'IDENT <pid> <locale>'. This is so + * that we can report that the fd's are busy, along with some diagnostics + * about who has them busy; the locale is ignore here but kept for compatability + * with the zlogin code when running on the zone's console. + * + * We need to handle the case where there is no server within the zone (or + * the server gets stuck) and data that we're writing to the zone server's + * stdin fills the pipe. Because of the way the zfd device works writes can + * flow into the stream and simply be dropped, if there is no server, or writes + * could return -1 with EAGAIN if the server is stuck. Since we ignore errors + * on the write to stdin, we won't get blocked in that case but we'd like to + * avoid dropping initial input if the server within the zone hasn't started + * yet. To handle this we wait to read initial input until we detect that there + * is a server inside the zone. We have to poll for this so that we can + * re-run the ioctl to notice when a server shows up. This poll/wait is handled + * by halt_sleep() so that we can be responsive if the zone wants to halt. + * We only do this check to avoid dropping initial input so it is possible for + * the server within the zone to go away later. At that point zfd will just + * drop any new input flowing into the stream. + */ +static void +do_zfd_io(int gzctlfd, int gzservfd, int gzerrfd, int stdinfd, int stdoutfd, + int stderrfd) +{ + struct pollfd pollfds[8]; + char ibuf[BUFSIZ + 1]; + int cc, ret; + int ctlfd = -1; + int clifd = -1; + int clierrfd = -1; + int pollerr = 0; + char clilocale[MAXPATHLEN]; + pid_t clipid = 0; + uint_t flags = 0; + boolean_t stdin_ready = B_FALSE; + int slptime = 250; /* initial poll sleep time in ms */ + + /* client control socket, watch for read events */ + pollfds[0].fd = ctlfd; + pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | + POLLPRI | POLLERR | POLLHUP | POLLNVAL; + + /* client socket, watch for read events */ + pollfds[1].fd = clifd; + pollfds[1].events = pollfds[0].events; + + /* stdout, watch for read events */ + pollfds[2].fd = stdoutfd; + pollfds[2].events = pollfds[0].events; + + /* stderr, watch for read events */ + pollfds[3].fd = stderrfd; + pollfds[3].events = pollfds[0].events; + + /* the server control socket; watch for new connections */ + pollfds[4].fd = gzctlfd; + pollfds[4].events = POLLIN | POLLRDNORM; + + /* the server stdin/out socket; watch for new connections */ + pollfds[5].fd = gzservfd; + pollfds[5].events = POLLIN | POLLRDNORM; + + /* the server stderr socket; watch for new connections */ + pollfds[6].fd = gzerrfd; + pollfds[6].events = POLLIN | POLLRDNORM; + + /* the eventstream; any input means the zone is halting */ + pollfds[7].fd = eventstream[1]; + pollfds[7].events = pollfds[0].events; + + while (!shutting_down) { + pollfds[0].revents = pollfds[1].revents = 0; + pollfds[2].revents = pollfds[3].revents = 0; + pollfds[4].revents = pollfds[5].revents = 0; + pollfds[6].revents = pollfds[7].revents = 0; + + ret = poll(pollfds, 8, -1); + if (ret == -1 && errno != EINTR) { + zerror(zlogp, B_TRUE, "poll failed"); + /* we are hosed, close connection */ + break; + } + + /* control events from client */ + if (pollfds[0].revents & + (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { + /* process control message */ + ctlcmd_process(ctlfd, stdoutfd, &flags); + } else if (pollfds[0].revents) { + /* bail if any error occurs */ + pollerr = pollfds[0].revents; + zerror(zlogp, B_FALSE, "closing connection " + "with control channel, pollerr %d\n", pollerr); + break; + } + + /* event from client side */ + if (pollfds[1].revents) { + if (stdin_ready) { + if (pollfds[1].revents & (POLLIN | + POLLRDNORM | POLLRDBAND | POLLPRI)) { + errno = 0; + cc = read(clifd, ibuf, BUFSIZ); + if (cc > 0) { + /* + * See comment for this + * function on what happens if + * there is no reader in the + * zone. EOF is handled below. + */ + (void) write(stdinfd, ibuf, cc); + } + } else if (pollfds[1].revents & (POLLERR | + POLLNVAL)) { + pollerr = pollfds[1].revents; + zerror(zlogp, B_FALSE, + "closing connection " + "with client, pollerr %d\n", + pollerr); + break; + } + + if (pollfds[1].revents & POLLHUP) { + if (flags & ZLOGIN_ZFD_EOF) { + /* + * Let the client know. We've + * already serviced any pending + * regular input. Let the + * stream clear since the EOF + * ioctl jumps to the head. + */ + (void) ioctl(stdinfd, I_FLUSH); + if (halt_sleep(250)) + break; + (void) ioctl(stdinfd, ZFD_EOF); + } + break; + } + } else { + if (ioctl(stdinfd, ZFD_HAS_SLAVE) == 0) { + stdin_ready = B_TRUE; + } else { + /* + * There is nothing in the zone to read + * our input. Presumably the user + * providing input expects something to + * show up, but that is no guarantee. + * Since we haven't serviced the pending + * input poll yet, we don't want to + * immediately loop around but we also + * need to be responsive if the zone is + * halting. + */ + if (halt_sleep(slptime)) + break; + + if (slptime < 5000) + slptime += 250; + } + } + } + + /* event from the zone's stdout */ + if (pollfds[2].revents) { + if (pollfds[2].revents & + (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { + errno = 0; + cc = read(stdoutfd, ibuf, BUFSIZ); + if (cc <= 0 && (errno != EINTR) && + (errno != EAGAIN)) + break; + if (cc > 0) { + wr_log_msg(ibuf, cc, 1); + + /* + * Lose output if no one is listening, + * otherwise pass it on. + */ + if (clifd != -1) + (void) write(clifd, ibuf, cc); + } + } else { + pollerr = pollfds[2].revents; + zerror(zlogp, B_FALSE, + "closing connection with stdout zfd, " + "pollerr %d\n", pollerr); + break; + } + } + + /* event from the zone's stderr */ + if (pollfds[3].revents) { + if (pollfds[3].revents & + (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { + errno = 0; + cc = read(stderrfd, ibuf, BUFSIZ); + if (cc <= 0 && (errno != EINTR) && + (errno != EAGAIN)) + break; + if (cc > 0) { + wr_log_msg(ibuf, cc, 2); + + /* + * Lose output if no one is listening, + * otherwise pass it on. + */ + if (clierrfd != -1) + (void) write(clierrfd, ibuf, + cc); + } + } else { + pollerr = pollfds[3].revents; + zerror(zlogp, B_FALSE, + "closing connection with stderr zfd, " + "pollerr %d\n", pollerr); + break; + } + } + + /* connect event from server control socket */ + if (pollfds[4].revents) { + if (ctlfd != -1) { + /* + * Test the client to see if it is really + * still alive. If it has died but we + * haven't yet detected that, we might + * deny a legitimate connect attempt. If it + * is dead, we break out; once we tear down + * the old connection, the new connection + * will happen. + */ + if (test_client(ctlfd) == -1) { + break; + } + /* we're already handling a client */ + reject_client(gzctlfd, clipid); + } else { + ctlfd = accept_client(gzctlfd, &clipid, + clilocale, sizeof (clilocale), &flags); + if (ctlfd != -1) { + pollfds[0].fd = ctlfd; + } else { + break; + } + } + } + + /* connect event from server stdin/out socket */ + if (pollfds[5].revents) { + if (ctlfd == -1) { + /* + * This shouldn't happen since the client is + * expected to connect on the control socket + * first. If we see this, tear everything down + * and start over. + */ + zerror(zlogp, B_FALSE, "GZ zfd stdin/stdout " + "connection attempt with no GZ control\n"); + break; + } + assert(clifd == -1); + if ((clifd = accept_socket(gzservfd, clipid)) != -1) { + /* No need to watch for other new connections */ + pollfds[5].fd = -1; + /* Client input is of interest, though */ + pollfds[1].fd = clifd; + } else { + break; + } + } + + /* connection event from server stderr socket */ + if (pollfds[6].revents) { + if (ctlfd == -1) { + /* + * Same conditions apply to stderr as stdin/out. + */ + zerror(zlogp, B_FALSE, "GZ zfd stderr " + "connection attempt with no GZ control\n"); + break; + } + assert(clierrfd == -1); + if ((clierrfd = accept_socket(gzerrfd, clipid)) != -1) { + /* No need to watch for other new connections */ + pollfds[6].fd = -1; + } else { + break; + } + } + + /* + * Watch for events on the eventstream. This is how we get + * notified of the zone halting, etc. It provides us a + * "wakeup" from poll when important things happen, which + * is good. + */ + if (pollfds[7].revents) { + break; + } + } + + if (clifd != -1) { + (void) shutdown(clifd, SHUT_RDWR); + (void) close(clifd); + } + + if (clierrfd != -1) { + (void) shutdown(clierrfd, SHUT_RDWR); + (void) close(clierrfd); + } +} + +static int +open_fd(zlog_t *zlogp, int id, int rw) +{ + int fd; + int flag = O_NONBLOCK | O_NOCTTY | O_CLOEXEC; + int retried = 0; + char stdpath[MAXPATHLEN]; + + (void) snprintf(stdpath, sizeof (stdpath), "/dev/zfd/%s/master/%d", + zone_name, id); + flag |= rw; + + while (!shutting_down) { + if ((fd = open(stdpath, flag)) != -1) { + /* + * Setting RPROTDIS on the stream means that the + * control portion of messages received (which we don't + * care about) will be discarded by the stream head. If + * we allowed such messages, we wouldn't be able to use + * read(2), as it fails (EBADMSG) when a message with a + * control element is received. + */ + if (ioctl(fd, I_SRDOPT, RNORM|RPROTDIS) == -1) { + zerror(zlogp, B_TRUE, + "failed to set options on zfd"); + return (-1); + } + return (fd); + } + + if (retried++ > 60) + break; + + (void) sleep(1); + } + + zerror(zlogp, B_TRUE, "failed to open zfd"); + return (-1); +} + +static void +open_logfile() +{ + char logpath[MAXPATHLEN]; + + logfd = -1; + + (void) snprintf(logpath, sizeof (logpath), "%s/logs", zonepath); + (void) mkdir(logpath, 0700); + + (void) snprintf(logpath, sizeof (logpath), "%s/logs/%s", zonepath, + LOGNAME); + + if ((logfd = open(logpath, O_WRONLY | O_APPEND | O_CREAT, 0600)) == -1) + zerror(zlogp, B_TRUE, "failed to open log file"); +} + +/* ARGSUSED */ +void +hup_handler(int i) +{ + if (logfd != -1) { + (void) close(logfd); + open_logfile(); + } +} + +/* + * Body of the worker thread to log the zfd's stdout and stderr to a log file + * and to perform interactive IO to the stdin, stdout and stderr zfd's. + * + * The stdin, stdout and stderr are from the perspective of the process inside + * the zone, so the zoneadmd view is opposite (i.e. we write to the stdin fd + * and read from the stdout/stderr fds). + */ +static void +srvr(void *modearg) +{ + zfd_mode_t *mode = (zfd_mode_t *)modearg; + int gzctlfd = -1; + int gzoutfd = -1; + int stdinfd = -1; + int stdoutfd = -1; + sigset_t blockset; + int gzerrfd = -1; + int stderrfd = -1; + + if (!shutting_down && mode->zmode_n_addl_devs == 0) + open_logfile(); + + /* + * This thread should receive SIGHUP so that it can close the log + * file, and reopen it, during log rotation. + */ + sigset(SIGHUP, hup_handler); + (void) sigfillset(&blockset); + (void) sigdelset(&blockset, SIGHUP); + (void) thr_sigsetmask(SIG_BLOCK, &blockset, NULL); + + if (!shutting_down) { + if (pipe(eventstream) != 0) { + zerror(zlogp, B_TRUE, "failed to open logger control " + "pipe"); + return; + } + } + + while (!shutting_down) { + if (init_server_sock(zlogp, &gzctlfd, "ctl") == -1) { + zerror(zlogp, B_FALSE, + "server setup: control socket init failed"); + goto death; + } + if (init_server_sock(zlogp, &gzoutfd, "out") == -1) { + zerror(zlogp, B_FALSE, + "server setup: stdout socket init failed"); + goto death; + } + if (init_server_sock(zlogp, &gzerrfd, "err") == -1) { + zerror(zlogp, B_FALSE, + "server setup: stderr socket init failed"); + goto death; + } + + if (mode->zmode_n_stddevs == 1) { + if ((stdinfd = open_fd(zlogp, 0, O_RDWR)) == -1) { + goto death; + } + stdoutfd = stdinfd; + } else { + if ((stdinfd = open_fd(zlogp, 0, O_WRONLY)) == -1 || + (stdoutfd = open_fd(zlogp, 1, O_RDONLY)) == -1 || + (stderrfd = open_fd(zlogp, 2, O_RDONLY)) == -1) { + goto death; + } + } + + do_zfd_io(gzctlfd, gzoutfd, gzerrfd, stdinfd, stdoutfd, + stderrfd); +death: + destroy_server_sock(gzctlfd, "ctl"); + destroy_server_sock(gzoutfd, "out"); + destroy_server_sock(gzerrfd, "err"); + (void) close(stdinfd); + if (mode->zmode_n_stddevs == 3) { + (void) close(stdoutfd); + (void) close(stderrfd); + } + } + + (void) close(eventstream[0]); + eventstream[0] = -1; + (void) close(eventstream[1]); + eventstream[1] = -1; + if (logfd != -1) + (void) close(logfd); +} + +/* + * The value strings we're matching on don't make a lot of sense for how + * this is used internally, but we're stuck with these values for legacy + * compatability. + */ +static void +get_mode(zfd_mode_t *mode) +{ + zone_dochandle_t handle; + struct zone_attrtab attr; + + bzero(mode, sizeof (zfd_mode_t)); + + if ((handle = zonecfg_init_handle()) == NULL) + return; + + if (zonecfg_get_handle(zone_name, handle) != Z_OK) + goto done; + + if (zonecfg_setattrent(handle) != Z_OK) + goto done; + while (zonecfg_getattrent(handle, &attr) == Z_OK) { + if (strcmp(ZLOG_MODE, attr.zone_attr_name) == 0) { + if (strncmp("log", attr.zone_attr_value, 3) == 0) { + mode->zmode_n_stddevs = 3; + mode->zmode_n_addl_devs = 0; + } else if (strncmp("nolog", + attr.zone_attr_value, 5) == 0) { + mode->zmode_n_stddevs = 3; + mode->zmode_n_addl_devs = 2; + } else if (strncmp("int", + attr.zone_attr_value, 3) == 0) { + mode->zmode_n_stddevs = 1; + mode->zmode_n_addl_devs = 0; + } else if (strncmp("nlint", + attr.zone_attr_value, 5) == 0) { + mode->zmode_n_stddevs = 1; + mode->zmode_n_addl_devs = 1; + } + break; + } + } + (void) zonecfg_endattrent(handle); + +done: + zonecfg_fini_handle(handle); +} + +void +create_log_thread(zlog_t *logp, zoneid_t id) +{ + int res; + + shutting_down = 0; + zlogp = logp; + + get_mode(&mode); + if (mode.zmode_n_stddevs == 0) + return; + + if (init_zfd_devs(zlogp, &mode) == -1) { + zerror(zlogp, B_FALSE, + "zfd setup: device initialization failed"); + return; + } + + res = thr_create(NULL, 0, (void * (*)(void *))srvr, (void *)&mode, 0, + &logger_tid); + if (res != 0) { + zerror(zlogp, B_FALSE, "error %d creating logger thread", res); + logger_tid = 0; + } +} + +void +destroy_log_thread() +{ + if (logger_tid != 0) { + int stop = 1; + + shutting_down = 1; + /* break out of poll to shutdown */ + if (eventstream[0] != -1) + (void) write(eventstream[0], &stop, sizeof (stop)); + (void) thr_join(logger_tid, NULL, NULL); + logger_tid = 0; + } + + (void) destroy_zfd_devs(zlogp); +} diff --git a/usr/src/cmd/zoneadmd/zoneadmd.c b/usr/src/cmd/zoneadmd/zoneadmd.c index cb81b77727..521393bd10 100644 --- a/usr/src/cmd/zoneadmd/zoneadmd.c +++ b/usr/src/cmd/zoneadmd/zoneadmd.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015, Joyent, Inc. All rights reserved. */ /* @@ -68,6 +69,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/sysmacros.h> +#include <sys/time.h> #include <bsm/adt.h> #include <bsm/adt_event.h> @@ -108,6 +110,8 @@ static char *progname; char *zone_name; /* zone which we are managing */ +zone_dochandle_t snap_hndl; /* handle for snapshot created when ready */ +char zonepath[MAXNAMELEN]; char pool_name[MAXNAMELEN]; char default_brand[MAXNAMELEN]; char brand_name[MAXNAMELEN]; @@ -116,10 +120,11 @@ boolean_t zone_iscluster; boolean_t zone_islabeled; boolean_t shutdown_in_progress; static zoneid_t zone_id; +static zoneid_t zone_did = 0; dladm_handle_t dld_handle = NULL; -static char pre_statechg_hook[2 * MAXPATHLEN]; -static char post_statechg_hook[2 * MAXPATHLEN]; +char pre_statechg_hook[2 * MAXPATHLEN]; +char post_statechg_hook[2 * MAXPATHLEN]; char query_hook[2 * MAXPATHLEN]; zlog_t logsys; @@ -141,6 +146,9 @@ boolean_t bringup_failure_recovery = B_FALSE; /* ignore certain failures */ #define DEFAULT_LOCALE "C" +#define RSRC_NET "net" +#define RSRC_DEV "device" + static const char * z_cmd_name(zone_cmd_t zcmd) { @@ -257,34 +265,31 @@ zerror(zlog_t *zlogp, boolean_t use_strerror, const char *fmt, ...) } /* - * Emit a warning for any boot arguments which are unrecognized. Since - * Solaris boot arguments are getopt(3c) compatible (see kernel(1m)), we + * Since Solaris boot arguments are getopt(3c) compatible (see kernel(1m)), we * put the arguments into an argv style array, use getopt to process them, - * and put the resultant argument string back into outargs. + * and put the resultant argument string back into outargs. Non-Solaris brands + * may support alternate forms of boot arguments so we must handle that as well. * * During the filtering, we pull out any arguments which are truly "boot" * arguments, leaving only those which are to be passed intact to the * progenitor process. The one we support at the moment is -i, which * indicates to the kernel which program should be launched as 'init'. * - * A return of Z_INVAL indicates specifically that the arguments are - * not valid; this is a non-fatal error. Except for Z_OK, all other return - * values are treated as fatal. + * Except for Z_OK, all other return values are treated as fatal. */ static int filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs, - char *init_file, char *badarg) + char *init_file) { int argc = 0, argc_save; int i; - int err; + int err = Z_OK; char *arg, *lasts, **argv = NULL, **argv_save; char zonecfg_args[BOOTARGS_MAX]; char scratchargs[BOOTARGS_MAX], *sargs; char c; bzero(outargs, BOOTARGS_MAX); - bzero(badarg, BOOTARGS_MAX); /* * If the user didn't specify transient boot arguments, check @@ -292,25 +297,10 @@ filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs, * and use them if applicable. */ if (inargs == NULL || inargs[0] == '\0') { - zone_dochandle_t handle; - if ((handle = zonecfg_init_handle()) == NULL) { - zerror(zlogp, B_TRUE, - "getting zone configuration handle"); - return (Z_BAD_HANDLE); - } - err = zonecfg_get_snapshot_handle(zone_name, handle); - if (err != Z_OK) { - zerror(zlogp, B_FALSE, - "invalid configuration snapshot"); - zonecfg_fini_handle(handle); - return (Z_BAD_HANDLE); - } - bzero(zonecfg_args, sizeof (zonecfg_args)); - (void) zonecfg_get_bootargs(handle, zonecfg_args, + (void) zonecfg_get_bootargs(snap_hndl, zonecfg_args, sizeof (zonecfg_args)); inargs = zonecfg_args; - zonecfg_fini_handle(handle); } if (strlen(inargs) >= BOOTARGS_MAX) { @@ -390,36 +380,29 @@ filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs, break; case '?': /* - * We warn about unknown arguments but pass them - * along anyway-- if someone wants to develop their - * own init replacement, they can pass it whatever - * args they want. + * If a brand has its own init, we need to pass along + * whatever the user provides. We use the entire + * unknown string here so that we correctly handle + * unknown long options (e.g. --debug). */ - err = Z_INVAL; (void) snprintf(outargs, BOOTARGS_MAX, - "%s -%c", outargs, optopt); - (void) snprintf(badarg, BOOTARGS_MAX, - "%s -%c", badarg, optopt); + "%s %s", outargs, argv[optind - 1]); break; } } /* - * For Solaris Zones we warn about and discard non-option arguments. - * Hence 'boot foo bar baz gub' --> 'boot'. However, to be similar - * to the kernel, we concat up all the other remaining boot args. - * and warn on them as a group. + * We need to pass along everything else since we don't know what + * the brand's init is expecting. For example, an argument list like: + * --confdir /foo --debug + * will cause the getopt parsing to stop at '/foo' but we need to pass + * that on, along with the '--debug'. This does mean that we require + * any of our known options (-ifms) to preceed the brand-specific ones. */ - if (optind < argc) { - err = Z_INVAL; - while (optind < argc) { - (void) snprintf(badarg, BOOTARGS_MAX, "%s%s%s", - badarg, strlen(badarg) > 0 ? " " : "", - argv[optind]); - optind++; - } - zerror(zlogp, B_FALSE, "WARNING: Unused or invalid boot " - "arguments `%s'.", badarg); + while (optind < argc) { + (void) snprintf(outargs, BOOTARGS_MAX, "%s %s", outargs, + argv[optind]); + optind++; } done: @@ -458,7 +441,7 @@ mkzonedir(zlog_t *zlogp) * Run the brand's pre-state change callback, if it exists. */ static int -brand_prestatechg(zlog_t *zlogp, int state, int cmd) +brand_prestatechg(zlog_t *zlogp, int state, int cmd, boolean_t debug) { char cmdbuf[2 * MAXPATHLEN]; const char *altroot; @@ -471,7 +454,7 @@ brand_prestatechg(zlog_t *zlogp, int state, int cmd) state, cmd, altroot) > sizeof (cmdbuf)) return (-1); - if (do_subproc(zlogp, cmdbuf, NULL) != 0) + if (do_subproc(zlogp, cmdbuf, NULL, debug) != 0) return (-1); return (0); @@ -481,7 +464,7 @@ brand_prestatechg(zlog_t *zlogp, int state, int cmd) * Run the brand's post-state change callback, if it exists. */ static int -brand_poststatechg(zlog_t *zlogp, int state, int cmd) +brand_poststatechg(zlog_t *zlogp, int state, int cmd, boolean_t debug) { char cmdbuf[2 * MAXPATHLEN]; const char *altroot; @@ -494,7 +477,7 @@ brand_poststatechg(zlog_t *zlogp, int state, int cmd) state, cmd, altroot) > sizeof (cmdbuf)) return (-1); - if (do_subproc(zlogp, cmdbuf, NULL) != 0) + if (do_subproc(zlogp, cmdbuf, NULL, debug) != 0) return (-1); return (0); @@ -533,35 +516,44 @@ notify_zonestatd(zoneid_t zoneid) * subcommand. */ static int -zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate) +zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate, boolean_t debug) { int err; + boolean_t snapped = B_FALSE; - if (brand_prestatechg(zlogp, zstate, Z_READY) != 0) - return (-1); - + if ((snap_hndl = zonecfg_init_handle()) == NULL) { + zerror(zlogp, B_TRUE, "getting zone configuration handle"); + goto bad; + } if ((err = zonecfg_create_snapshot(zone_name)) != Z_OK) { zerror(zlogp, B_FALSE, "unable to create snapshot: %s", zonecfg_strerror(err)); goto bad; } + snapped = B_TRUE; - if ((zone_id = vplat_create(zlogp, mount_cmd)) == -1) { - if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK) - zerror(zlogp, B_FALSE, "destroying snapshot: %s", - zonecfg_strerror(err)); + if (zonecfg_get_snapshot_handle(zone_name, snap_hndl) != Z_OK) { + zerror(zlogp, B_FALSE, "invalid configuration snapshot"); goto bad; } + + if (zone_did == 0) + zone_did = zone_get_did(zone_name); + + if (brand_prestatechg(zlogp, zstate, Z_READY, debug) != 0) + goto bad; + + if ((zone_id = vplat_create(zlogp, mount_cmd, zone_did)) == -1) + goto bad; + if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) { bringup_failure_recovery = B_TRUE; - (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE); - if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK) - zerror(zlogp, B_FALSE, "destroying snapshot: %s", - zonecfg_strerror(err)); + (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE, + debug); goto bad; } - if (brand_poststatechg(zlogp, zstate, Z_READY) != 0) + if (brand_poststatechg(zlogp, zstate, Z_READY, debug) != 0) goto bad; return (0); @@ -571,7 +563,13 @@ bad: * If something goes wrong, we up the zones's state to the target * state, READY, and then invoke the hook as if we're halting. */ - (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT); + (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT, debug); + if (snapped) + if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK) + zerror(zlogp, B_FALSE, "destroying snapshot: %s", + zonecfg_strerror(err)); + zonecfg_fini_handle(snap_hndl); + snap_hndl = NULL; return (-1); } @@ -623,15 +621,8 @@ mount_early_fs(void *data, const char *spec, const char *dir, /* determine the zone rootpath */ if (mount_cmd) { - char zonepath[MAXPATHLEN]; char luroot[MAXPATHLEN]; - if (zone_get_zonepath(zone_name, - zonepath, sizeof (zonepath)) != Z_OK) { - zerror(zlogp, B_FALSE, "unable to determine zone path"); - return (-1); - } - (void) snprintf(luroot, sizeof (luroot), "%s/lu", zonepath); resolve_lofs(zlogp, luroot, sizeof (luroot)); (void) strlcpy(rootpath, luroot, sizeof (rootpath)); @@ -686,6 +677,8 @@ mount_early_fs(void *data, const char *spec, const char *dir, char opt_buf[MAX_MNTOPT_STR]; int optlen = 0; int mflag = MS_DATA; + int i; + int ret; (void) ct_tmpl_clear(tmpl_fd); /* @@ -713,9 +706,26 @@ mount_early_fs(void *data, const char *spec, const char *dir, optlen = MAX_MNTOPT_STR; mflag = MS_OPTIONSTR; } - if (mount(spec, dir, mflag, fstype, NULL, 0, opt, optlen) != 0) - _exit(errno); - _exit(0); + + /* + * There is an obscure race condition which can cause mount + * to return EBUSY. This happens for example on the mount + * of the zone's /etc/svc/volatile file system if there is + * a GZ process running svcs -Z, which will touch the + * mountpoint, just as we're trying to do the mount. To cope + * with this, we retry up to 3 times to let this transient + * process get out of the way. + */ + for (i = 0; i < 3; i++) { + ret = 0; + if (mount(spec, dir, mflag, fstype, NULL, 0, opt, + optlen) != 0) + ret = errno; + if (ret != EBUSY) + break; + (void) sleep(1); + } + _exit(ret); } /* parent */ @@ -739,12 +749,150 @@ mount_early_fs(void *data, const char *spec, const char *dir, } /* + * env variable name format + * _ZONECFG_{resource name}_{identifying attr. name}_{property name} + * Any dashes (-) in the property names are replaced with underscore (_). + */ +static void +set_zonecfg_env(char *rsrc, char *attr, char *name, char *val) +{ + char *p; + char nm[MAXNAMELEN]; + + if (attr == NULL) + (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s", rsrc, + name); + else + (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s_%s", rsrc, + attr, name); + + p = nm; + while ((p = strchr(p, '-')) != NULL) + *p++ = '_'; + + (void) setenv(nm, val, 1); +} + +/* + * Export zonecfg network and device properties into environment for the boot + * and state change hooks. + * If debug is true, export the brand hook debug env. variable as well. + * + * We could export more of the config in the future, as necessary. + */ +static int +setup_subproc_env(boolean_t debug) +{ + int res; + struct zone_nwiftab ntab; + struct zone_devtab dtab; + struct zone_attrtab atab; + char net_resources[MAXNAMELEN * 2]; + char dev_resources[MAXNAMELEN * 2]; + + /* snap_hndl is null when called through the set_brand_env code path */ + if (snap_hndl == NULL) + return (Z_OK); + + net_resources[0] = '\0'; + if ((res = zonecfg_setnwifent(snap_hndl)) != Z_OK) + goto done; + + while (zonecfg_getnwifent(snap_hndl, &ntab) == Z_OK) { + struct zone_res_attrtab *rap; + char *phys; + + phys = ntab.zone_nwif_physical; + + (void) strlcat(net_resources, phys, sizeof (net_resources)); + (void) strlcat(net_resources, " ", sizeof (net_resources)); + + set_zonecfg_env(RSRC_NET, phys, "physical", phys); + + set_zonecfg_env(RSRC_NET, phys, "address", + ntab.zone_nwif_address); + set_zonecfg_env(RSRC_NET, phys, "allowed-address", + ntab.zone_nwif_allowed_address); + set_zonecfg_env(RSRC_NET, phys, "defrouter", + ntab.zone_nwif_defrouter); + set_zonecfg_env(RSRC_NET, phys, "global-nic", + ntab.zone_nwif_gnic); + set_zonecfg_env(RSRC_NET, phys, "mac-addr", ntab.zone_nwif_mac); + set_zonecfg_env(RSRC_NET, phys, "vlan-id", + ntab.zone_nwif_vlan_id); + + for (rap = ntab.zone_nwif_attrp; rap != NULL; + rap = rap->zone_res_attr_next) + set_zonecfg_env(RSRC_NET, phys, rap->zone_res_attr_name, + rap->zone_res_attr_value); + nwifent_free_attrs(&ntab); + } + + (void) setenv("_ZONECFG_net_resources", net_resources, 1); + + (void) zonecfg_endnwifent(snap_hndl); + + if ((res = zonecfg_setdevent(snap_hndl)) != Z_OK) + goto done; + + while (zonecfg_getdevent(snap_hndl, &dtab) == Z_OK) { + struct zone_res_attrtab *rap; + char *match; + + match = dtab.zone_dev_match; + + (void) strlcat(dev_resources, match, sizeof (dev_resources)); + (void) strlcat(dev_resources, " ", sizeof (dev_resources)); + + for (rap = dtab.zone_dev_attrp; rap != NULL; + rap = rap->zone_res_attr_next) + set_zonecfg_env(RSRC_DEV, match, + rap->zone_res_attr_name, rap->zone_res_attr_value); + } + + (void) zonecfg_enddevent(snap_hndl); + + if ((res = zonecfg_setattrent(snap_hndl)) != Z_OK) + goto done; + + while (zonecfg_getattrent(snap_hndl, &atab) == Z_OK) { + set_zonecfg_env("attr", NULL, atab.zone_attr_name, + atab.zone_attr_value); + } + + (void) zonecfg_endattrent(snap_hndl); + + if (debug) + (void) setenv("_ZONEADMD_brand_debug", "1", 1); + else + (void) setenv("_ZONEADMD_brand_debug", "", 1); + + res = Z_OK; + +done: + return (res); +} + +void +nwifent_free_attrs(struct zone_nwiftab *np) +{ + struct zone_res_attrtab *rap; + + for (rap = np->zone_nwif_attrp; rap != NULL; ) { + struct zone_res_attrtab *tp = rap; + + rap = rap->zone_res_attr_next; + free(tp); + } +} + +/* * If retstr is not NULL, the output of the subproc is returned in the str, * otherwise it is output using zerror(). Any memory allocated for retstr * should be freed by the caller. */ int -do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr) +do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr, boolean_t debug) { char buf[1024]; /* arbitrary large amount */ char *inbuf; @@ -763,6 +911,11 @@ do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr) inbuf = buf; } + if (setup_subproc_env(debug) != Z_OK) { + zerror(zlogp, B_FALSE, "failed to setup environment"); + return (-1); + } + file = popen(cmdbuf, "r"); if (file == NULL) { zerror(zlogp, B_TRUE, "could not launch: %s", cmdbuf); @@ -771,8 +924,13 @@ do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr) while (fgets(inbuf, 1024, file) != NULL) { if (retstr == NULL) { - if (zlogp != &logsys) + if (zlogp != &logsys) { + int last = strlen(inbuf) - 1; + + if (inbuf[last] == '\n') + inbuf[last] = '\0'; zerror(zlogp, B_FALSE, "%s", inbuf); + } } else { char *p; @@ -802,24 +960,66 @@ do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr) return (WEXITSTATUS(status)); } +/* + * Get the path for this zone's init(1M) (or equivalent) process. First look + * for a zone-specific init-name attr, then get it from the brand. + */ static int -zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate) +get_initname(brand_handle_t bh, char *initname, int len) +{ + struct zone_attrtab a; + + bzero(&a, sizeof (a)); + (void) strlcpy(a.zone_attr_name, "init-name", + sizeof (a.zone_attr_name)); + + if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK) { + (void) strlcpy(initname, a.zone_attr_value, len); + return (0); + } + + return (brand_get_initname(bh, initname, len)); +} + +/* + * Get the restart-init flag for this zone's init(1M) (or equivalent) process. + * First look for a zone-specific restart-init attr, then get it from the brand. + */ +static boolean_t +restartinit(brand_handle_t bh) +{ + struct zone_attrtab a; + + bzero(&a, sizeof (a)); + (void) strlcpy(a.zone_attr_name, "restart-init", + sizeof (a.zone_attr_name)); + + if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK) { + if (strcmp(a.zone_attr_value, "false") == 0) + return (B_FALSE); + return (B_TRUE); + } + + return (brand_restartinit(bh)); +} + +static int +zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate, boolean_t debug) { zoneid_t zoneid; struct stat st; - char zpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN]; + char rpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN]; char nbootargs[BOOTARGS_MAX]; char cmdbuf[MAXPATHLEN]; fs_callback_t cb; brand_handle_t bh; zone_iptype_t iptype; - boolean_t links_loaded = B_FALSE; dladm_status_t status; char errmsg[DLADM_STRSIZE]; int err; boolean_t restart_init; - if (brand_prestatechg(zlogp, zstate, Z_BOOT) != 0) + if (brand_prestatechg(zlogp, zstate, Z_BOOT, debug) != 0) return (-1); if ((zoneid = getzoneidbyname(zone_name)) == -1) { @@ -852,13 +1052,8 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate) /* * Get the brand's boot callback if it exists. */ - if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) { - zerror(zlogp, B_FALSE, "unable to determine zone path"); - brand_close(bh); - goto bad; - } (void) strcpy(cmdbuf, EXEC_PREFIX); - if (brand_get_boot(bh, zone_name, zpath, cmdbuf + EXEC_LEN, + if (brand_get_boot(bh, zone_name, zonepath, cmdbuf + EXEC_LEN, sizeof (cmdbuf) - EXEC_LEN) != 0) { zerror(zlogp, B_FALSE, "unable to determine branded zone's boot callback"); @@ -867,41 +1062,43 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate) } /* Get the path for this zone's init(1M) (or equivalent) process. */ - if (brand_get_initname(bh, init_file, MAXPATHLEN) != 0) { + if (get_initname(bh, init_file, MAXPATHLEN) != 0) { zerror(zlogp, B_FALSE, "unable to determine zone's init(1M) location"); brand_close(bh); goto bad; } - /* See if this zone's brand should restart init if it dies. */ - restart_init = brand_restartinit(bh); + /* See if we should restart init if it dies. */ + restart_init = restartinit(bh); brand_close(bh); - err = filter_bootargs(zlogp, bootargs, nbootargs, init_file, - bad_boot_arg); - if (err == Z_INVAL) - eventstream_write(Z_EVT_ZONE_BADARGS); - else if (err != Z_OK) + err = filter_bootargs(zlogp, bootargs, nbootargs, init_file); + if (err != Z_OK) goto bad; assert(init_file[0] != '\0'); - /* Try to anticipate possible problems: Make sure init is executable. */ - if (zone_get_rootpath(zone_name, zpath, sizeof (zpath)) != Z_OK) { + /* + * Try to anticipate possible problems: If possible, make sure init is + * executable. + */ + if (zone_get_rootpath(zone_name, rpath, sizeof (rpath)) != Z_OK) { zerror(zlogp, B_FALSE, "unable to determine zone root"); goto bad; } - (void) snprintf(initpath, sizeof (initpath), "%s%s", zpath, init_file); + (void) snprintf(initpath, sizeof (initpath), "%s%s", rpath, init_file); - if (stat(initpath, &st) == -1) { + if (lstat(initpath, &st) == -1) { zerror(zlogp, B_TRUE, "could not stat %s", initpath); goto bad; } - if ((st.st_mode & S_IXUSR) == 0) { + if ((st.st_mode & S_IFMT) == S_IFLNK) { + /* symlink, we'll have to wait and resolve when we boot */ + } else if ((st.st_mode & S_IXUSR) == 0) { zerror(zlogp, B_FALSE, "%s is not executable", initpath); goto bad; } @@ -919,7 +1116,6 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate) " %s", dladm_status2str(status, errmsg)); goto bad; } - links_loaded = B_TRUE; } /* @@ -928,7 +1124,7 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate) * is booted. */ if ((strlen(cmdbuf) > EXEC_LEN) && - (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) { + (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) { zerror(zlogp, B_FALSE, "%s failed", cmdbuf); goto bad; } @@ -960,9 +1156,15 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate) goto bad; } - if (brand_poststatechg(zlogp, zstate, Z_BOOT) != 0) + if (brand_poststatechg(zlogp, zstate, Z_BOOT, debug) != 0) goto bad; + /* Startup a thread to perform zfd logging/tty svc for the zone. */ + create_log_thread(zlogp, zone_id); + + /* Startup a thread to perform memory capping for the zone. */ + create_mcap_thread(zlogp, zone_id); + return (0); bad: @@ -970,32 +1172,42 @@ bad: * If something goes wrong, we up the zones's state to the target * state, RUNNING, and then invoke the hook as if we're halting. */ - (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT); - if (links_loaded) - (void) dladm_zone_halt(dld_handle, zoneid); + (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT, debug); + return (-1); } static int -zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate) +zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate, + boolean_t debug) { int err; - if (brand_prestatechg(zlogp, zstate, Z_HALT) != 0) + if (brand_prestatechg(zlogp, zstate, Z_HALT, debug) != 0) return (-1); - if (vplat_teardown(zlogp, unmount_cmd, rebooting) != 0) { + /* Shutting down, stop the memcap thread */ + destroy_mcap_thread(); + + if (vplat_teardown(zlogp, unmount_cmd, rebooting, debug) != 0) { if (!bringup_failure_recovery) zerror(zlogp, B_FALSE, "unable to destroy zone"); + destroy_log_thread(); return (-1); } + /* Shut down is done, stop the log thread */ + destroy_log_thread(); + + if (brand_poststatechg(zlogp, zstate, Z_HALT, debug) != 0) + return (-1); + if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK) zerror(zlogp, B_FALSE, "destroying snapshot: %s", zonecfg_strerror(err)); - if (brand_poststatechg(zlogp, zstate, Z_HALT) != 0) - return (-1); + zonecfg_fini_handle(snap_hndl); + snap_hndl = NULL; return (0); } @@ -1007,7 +1219,6 @@ zone_graceful_shutdown(zlog_t *zlogp) pid_t child; char cmdbuf[MAXPATHLEN]; brand_handle_t bh = NULL; - char zpath[MAXPATHLEN]; ctid_t ct; int tmpl_fd; int child_status; @@ -1028,18 +1239,12 @@ zone_graceful_shutdown(zlog_t *zlogp) return (-1); } - if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) { - zerror(zlogp, B_FALSE, "unable to determine zone path"); - brand_close(bh); - return (-1); - } - /* * If there is a brand 'shutdown' callback, execute it now to give the * brand a chance to cleanup any custom configuration. */ (void) strcpy(cmdbuf, EXEC_PREFIX); - if (brand_get_shutdown(bh, zone_name, zpath, cmdbuf + EXEC_LEN, + if (brand_get_shutdown(bh, zone_name, zonepath, cmdbuf + EXEC_LEN, sizeof (cmdbuf) - EXEC_LEN) != 0 || strlen(cmdbuf) <= EXEC_LEN) { (void) strcat(cmdbuf, SHUTDOWN_DEFAULT); } @@ -1177,6 +1382,36 @@ audit_put_record(zlog_t *zlogp, ucred_t *uc, int return_val, } /* + * Log the exit time and status of the zone's init process into + * {zonepath}/lastexited. If the zone shutdown normally, the exit status will + * be -1, otherwise it will be the exit status as described in wait.3c. + * If the zone is configured to restart init, then nothing will be logged if + * init exits unexpectedly (the kernel will never upcall in this case). + */ +static void +log_init_exit(int status) +{ + char p[MAXPATHLEN]; + char buf[128]; + struct timeval t; + int fd; + + if (snprintf(p, sizeof (p), "%s/lastexited", zonepath) > sizeof (p)) + return; + if (gettimeofday(&t, NULL) != 0) + return; + if (snprintf(buf, sizeof (buf), "%ld.%ld %d\n", t.tv_sec, t.tv_usec, + status) > sizeof (buf)) + return; + if ((fd = open(p, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) + return; + + (void) write(fd, buf, strlen(buf)); + + (void) close(fd); +} + +/* * The main routine for the door server that deals with zone state transitions. */ /* ARGSUSED */ @@ -1189,9 +1424,11 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, zone_state_t zstate; zone_cmd_t cmd; + boolean_t debug; + int init_status; zone_cmd_arg_t *zargp; - boolean_t kernelcall; + boolean_t kernelcall = B_TRUE; int rval = -1; uint64_t uniqid; @@ -1241,6 +1478,8 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, goto out; } cmd = zargp->cmd; + debug = zargp->debug; + init_status = zargp->status; if (door_ucred(&uc) != 0) { zerror(&logsys, B_TRUE, "door_ucred"); @@ -1347,23 +1586,25 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, case ZONE_STATE_INSTALLED: switch (cmd) { case Z_READY: - rval = zone_ready(zlogp, Z_MNT_BOOT, zstate); + rval = zone_ready(zlogp, Z_MNT_BOOT, zstate, debug); if (rval == 0) eventstream_write(Z_EVT_ZONE_READIED); + zcons_statechanged(); break; case Z_BOOT: case Z_FORCEBOOT: eventstream_write(Z_EVT_ZONE_BOOTING); - if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) - == 0) { + if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate, + debug)) == 0) { rval = zone_bootup(zlogp, zargp->bootbuf, - zstate); + zstate, debug); } audit_put_record(zlogp, uc, rval, "boot"); + zcons_statechanged(); if (rval != 0) { bringup_failure_recovery = B_TRUE; (void) zone_halt(zlogp, B_FALSE, B_FALSE, - zstate); + zstate, debug); eventstream_write(Z_EVT_ZONE_BOOTFAILED); } break; @@ -1415,7 +1656,7 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, rval = zone_ready(zlogp, strcmp(zargp->bootbuf, "-U") == 0 ? - Z_MNT_UPDATE : Z_MNT_SCRATCH, zstate); + Z_MNT_UPDATE : Z_MNT_SCRATCH, zstate, debug); if (rval != 0) break; @@ -1477,15 +1718,18 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, rval = 0; break; case Z_BOOT: + case Z_FORCEBOOT: (void) strlcpy(boot_args, zargp->bootbuf, sizeof (boot_args)); eventstream_write(Z_EVT_ZONE_BOOTING); - rval = zone_bootup(zlogp, zargp->bootbuf, zstate); + rval = zone_bootup(zlogp, zargp->bootbuf, zstate, + debug); audit_put_record(zlogp, uc, rval, "boot"); + zcons_statechanged(); if (rval != 0) { bringup_failure_recovery = B_TRUE; (void) zone_halt(zlogp, B_FALSE, B_TRUE, - zstate); + zstate, debug); eventstream_write(Z_EVT_ZONE_BOOTFAILED); } boot_args[0] = '\0'; @@ -1493,15 +1737,17 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, case Z_HALT: if (kernelcall) /* Invalid; can't happen */ abort(); - if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate)) - != 0) + if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate, + debug)) != 0) break; + zcons_statechanged(); eventstream_write(Z_EVT_ZONE_HALTED); break; case Z_SHUTDOWN: case Z_REBOOT: case Z_NOTE_UNINSTALLING: case Z_MOUNT: + case Z_FORCEMOUNT: case Z_UNMOUNT: if (kernelcall) /* Invalid; can't happen */ abort(); @@ -1518,7 +1764,7 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, case Z_UNMOUNT: if (kernelcall) /* Invalid; can't happen */ abort(); - rval = zone_halt(zlogp, B_TRUE, B_FALSE, zstate); + rval = zone_halt(zlogp, B_TRUE, B_FALSE, zstate, debug); if (rval == 0) { eventstream_write(Z_EVT_ZONE_HALTED); (void) sema_post(&scratch_sem); @@ -1540,15 +1786,18 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, case ZONE_STATE_DOWN: switch (cmd) { case Z_READY: - if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate)) - != 0) + if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate, + debug)) != 0) break; - if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) == 0) + zcons_statechanged(); + if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate, + debug)) == 0) eventstream_write(Z_EVT_ZONE_READIED); else eventstream_write(Z_EVT_ZONE_HALTED); break; case Z_BOOT: + case Z_FORCEBOOT: /* * We could have two clients racing to boot this * zone; the second client loses, but his request @@ -1559,32 +1808,40 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, rval = 0; break; case Z_HALT: - if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate)) - != 0) + if (kernelcall) { + log_init_exit(init_status); + } else { + log_init_exit(-1); + } + if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate, + debug)) != 0) break; eventstream_write(Z_EVT_ZONE_HALTED); + zcons_statechanged(); break; case Z_REBOOT: (void) strlcpy(boot_args, zargp->bootbuf, sizeof (boot_args)); eventstream_write(Z_EVT_ZONE_REBOOTING); - if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate)) - != 0) { + if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate, + debug)) != 0) { eventstream_write(Z_EVT_ZONE_BOOTFAILED); boot_args[0] = '\0'; break; } - if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) - != 0) { + zcons_statechanged(); + if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate, + debug)) != 0) { eventstream_write(Z_EVT_ZONE_BOOTFAILED); boot_args[0] = '\0'; break; } - rval = zone_bootup(zlogp, zargp->bootbuf, zstate); + rval = zone_bootup(zlogp, zargp->bootbuf, zstate, + debug); audit_put_record(zlogp, uc, rval, "reboot"); if (rval != 0) { (void) zone_halt(zlogp, B_FALSE, B_TRUE, - zstate); + zstate, debug); eventstream_write(Z_EVT_ZONE_BOOTFAILED); } boot_args[0] = '\0'; @@ -1596,6 +1853,7 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, break; case Z_NOTE_UNINSTALLING: case Z_MOUNT: + case Z_FORCEMOUNT: case Z_UNMOUNT: zerror(zlogp, B_FALSE, "%s operation is invalid " "for zones in state '%s'", z_cmd_name(cmd), @@ -1759,11 +2017,38 @@ top: * state. */ if (zstate > ZONE_STATE_INSTALLED) { + static zoneid_t zid; + zerror(zlogp, B_FALSE, "zone '%s': WARNING: zone is in state '%s', but " "zoneadmd does not appear to be available; " "restarted zoneadmd to recover.", zone_name, zone_state_str(zstate)); + + /* + * Startup a thread to perform the zfd logging/tty svc + * and a thread to perform memory capping for the + * zone. zlogp won't be valid for much longer so use + * logsys. + */ + if ((zid = getzoneidbyname(zone_name)) != -1) { + create_log_thread(&logsys, zid); + create_mcap_thread(&logsys, zid); + } + + /* recover the global configuration snapshot */ + if (snap_hndl == NULL) { + if ((snap_hndl = zonecfg_init_handle()) + == NULL || + zonecfg_create_snapshot(zone_name) + != Z_OK || + zonecfg_get_snapshot_handle(zone_name, + snap_hndl) != Z_OK) { + zerror(zlogp, B_FALSE, "recovering " + "zone configuration handle"); + goto out; + } + } } (void) fdetach(zone_door_path); @@ -1777,21 +2062,62 @@ out: } /* - * Setup the brand's pre and post state change callbacks, as well as the - * query callback, if any of these exist. + * Run the query hook with the 'env' parameter. It should return a + * string of tab-delimited key-value pairs, each of which should be set + * in the environment. + * + * Because the env_vars string values become part of the environment, the + * string is static and we don't free it. + * + * This function is always called before zoneadmd forks and makes itself + * exclusive, so it is possible there could more than one instance of zoneadmd + * running in parallel at this point. Thus, we have no zonecfg snapshot and + * shouldn't take one yet (i.e. snap_hndl is NULL). Thats ok, since we don't + * need any zonecfg info to query for a brand-specific env value. */ static int -brand_callback_init(brand_handle_t bh, char *zone_name) +set_brand_env(zlog_t *zlogp) { - char zpath[MAXPATHLEN]; + int ret = 0; + static char *env_vars = NULL; + char buf[2 * MAXPATHLEN]; - if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) + if (query_hook[0] == '\0' || env_vars != NULL) + return (0); + + if (snprintf(buf, sizeof (buf), "%s env", query_hook) > sizeof (buf)) + return (-1); + + if (do_subproc(zlogp, buf, &env_vars, B_FALSE) != 0) return (-1); + if (env_vars != NULL) { + char *sp; + + sp = strtok(env_vars, "\t"); + while (sp != NULL) { + if (putenv(sp) != 0) { + ret = -1; + break; + } + sp = strtok(NULL, "\t"); + } + } + + return (ret); +} + +/* + * Setup the brand's pre and post state change callbacks, as well as the + * query callback, if any of these exist. + */ +static int +brand_callback_init(brand_handle_t bh, char *zone_name) +{ (void) strlcpy(pre_statechg_hook, EXEC_PREFIX, sizeof (pre_statechg_hook)); - if (brand_get_prestatechange(bh, zone_name, zpath, + if (brand_get_prestatechange(bh, zone_name, zonepath, pre_statechg_hook + EXEC_LEN, sizeof (pre_statechg_hook) - EXEC_LEN) != 0) return (-1); @@ -1802,7 +2128,7 @@ brand_callback_init(brand_handle_t bh, char *zone_name) (void) strlcpy(post_statechg_hook, EXEC_PREFIX, sizeof (post_statechg_hook)); - if (brand_get_poststatechange(bh, zone_name, zpath, + if (brand_get_poststatechange(bh, zone_name, zonepath, post_statechg_hook + EXEC_LEN, sizeof (post_statechg_hook) - EXEC_LEN) != 0) return (-1); @@ -1813,7 +2139,7 @@ brand_callback_init(brand_handle_t bh, char *zone_name) (void) strlcpy(query_hook, EXEC_PREFIX, sizeof (query_hook)); - if (brand_get_query(bh, zone_name, zpath, query_hook + EXEC_LEN, + if (brand_get_query(bh, zone_name, zonepath, query_hook + EXEC_LEN, sizeof (query_hook) - EXEC_LEN) != 0) return (-1); @@ -1941,6 +2267,11 @@ main(int argc, char *argv[]) return (1); } + if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) { + zerror(zlogp, B_FALSE, "unable to determine zone path"); + return (-1); + } + if (zonecfg_default_brand(default_brand, sizeof (default_brand)) != Z_OK) { zerror(zlogp, B_FALSE, "unable to determine default brand"); @@ -2012,6 +2343,11 @@ main(int argc, char *argv[]) } priv_freeset(privset); + if (set_brand_env(zlogp) != 0) { + zerror(zlogp, B_FALSE, "Unable to setup brand's environment"); + return (1); + } + if (mkzonedir(zlogp) != 0) return (1); @@ -2052,6 +2388,13 @@ main(int argc, char *argv[]) (void) sigaddset(&block_cld, SIGCHLD); (void) sigprocmask(SIG_BLOCK, &block_cld, NULL); + /* + * The parent only needs stderr after the fork, so close other fd's + * that we inherited from zoneadm so that the parent doesn't have those + * open while waiting. The child will close the rest after the fork. + */ + closefrom(3); + if ((ctfd = init_template()) == -1) { zerror(zlogp, B_TRUE, "failed to create contract"); return (1); diff --git a/usr/src/cmd/zoneadmd/zoneadmd.h b/usr/src/cmd/zoneadmd/zoneadmd.h index d784a303b3..7e5dcea432 100644 --- a/usr/src/cmd/zoneadmd/zoneadmd.h +++ b/usr/src/cmd/zoneadmd/zoneadmd.h @@ -22,6 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2014, Joyent, Inc. All rights reserved. */ #ifndef _ZONEADMD_H @@ -90,17 +91,19 @@ extern mutex_t msglock; extern boolean_t in_death_throes; extern boolean_t bringup_failure_recovery; extern char *zone_name; +extern char zonepath[MAXNAMELEN]; +extern zone_dochandle_t snap_hndl; extern char pool_name[MAXNAMELEN]; extern char brand_name[MAXNAMELEN]; extern char default_brand[MAXNAMELEN]; extern char boot_args[BOOTARGS_MAX]; -extern char bad_boot_arg[BOOTARGS_MAX]; extern boolean_t zone_isnative; extern boolean_t zone_iscluster; extern dladm_handle_t dld_handle; extern void zerror(zlog_t *, boolean_t, const char *, ...); extern char *localize_msg(char *locale, const char *msg); +extern void nwifent_free_attrs(struct zone_nwiftab *); /* * Eventstream interfaces. @@ -112,8 +115,7 @@ typedef enum { Z_EVT_ZONE_HALTED, Z_EVT_ZONE_READIED, Z_EVT_ZONE_UNINSTALLING, - Z_EVT_ZONE_BOOTFAILED, - Z_EVT_ZONE_BADARGS + Z_EVT_ZONE_BOOTFAILED } zone_evt_t; extern int eventstream_init(); @@ -135,9 +137,9 @@ typedef enum { /* * Virtual platform interfaces. */ -extern zoneid_t vplat_create(zlog_t *, zone_mnt_t); +extern zoneid_t vplat_create(zlog_t *, zone_mnt_t, zoneid_t); extern int vplat_bringup(zlog_t *, zone_mnt_t, zoneid_t); -extern int vplat_teardown(zlog_t *, boolean_t, boolean_t); +extern int vplat_teardown(zlog_t *, boolean_t, boolean_t, boolean_t); extern int vplat_get_iptype(zlog_t *, zone_iptype_t *); /* @@ -154,6 +156,19 @@ extern void resolve_lofs(zlog_t *zlogp, char *path, size_t pathlen); */ extern int init_console(zlog_t *); extern void serve_console(zlog_t *); +extern void zcons_statechanged(); + +/* + * Memory capping thread creation. + */ +extern void create_mcap_thread(zlog_t *, zoneid_t); +extern void destroy_mcap_thread(); + +/* + * Zone FD log thread creation. + */ +extern void create_log_thread(zlog_t *, zoneid_t); +extern void destroy_log_thread(); /* * Contract handling. @@ -163,7 +178,7 @@ extern int init_template(void); /* * Routine to manage child processes. */ -extern int do_subproc(zlog_t *, char *, char **); +extern int do_subproc(zlog_t *, char *, char **, boolean_t); #ifdef __cplusplus } diff --git a/usr/src/cmd/zonecfg/Makefile b/usr/src/cmd/zonecfg/Makefile index ae8f5c11d1..94d725776b 100644 --- a/usr/src/cmd/zonecfg/Makefile +++ b/usr/src/cmd/zonecfg/Makefile @@ -27,6 +27,7 @@ PROG= zonecfg OBJS= zonecfg.o zonecfg_lex.o zonecfg_grammar.tab.o include ../Makefile.cmd +include ../Makefile.ctf # zonecfg has a name clash with main() and libl.so.1. However, zonecfg must # still export a number of "yy*" (libl) interfaces. Reduce all other symbols @@ -36,7 +37,7 @@ MAPOPTS = $(MAPFILES:%=-M%) LFLAGS = -t YFLAGS = -d -b zonecfg_grammar -LDLIBS += -lzonecfg -ll -lnsl -ltecla -lzfs -lbrand -ldladm -linetutil +LDLIBS += -lzonecfg -ll -lnsl -ltecla -lzfs -lbrand -ldladm -linetutil -luuid CPPFLAGS += -I. LDFLAGS += $(MAPOPTS) CLEANFILES += zonecfg_lex.c zonecfg_grammar.tab.c zonecfg_grammar.tab.h diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c index 3dbec383bf..235019ef46 100644 --- a/usr/src/cmd/zonecfg/zonecfg.c +++ b/usr/src/cmd/zonecfg/zonecfg.c @@ -23,6 +23,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright 2014 Gary Mills + * Copyright 2013, Joyent Inc. All rights reserved. */ /* @@ -79,6 +80,7 @@ #include <libinetutil.h> #include <pwd.h> #include <inet/ip.h> +#include <uuid/uuid.h> #include <libzonecfg.h> #include "zonecfg.h" @@ -126,7 +128,7 @@ extern int lex_lineno; #define SHELP_REMOVE "remove [-F] <resource-type> " \ "[ <property-name>=<property-value> ]*\n" \ "\t(global scope)\n" \ - "remove <property-name> <property-value>\n" \ + "remove [-F] <property-name> <property-value>\n" \ "\t(resource scope)" #define SHELP_REVERT "revert [-F]" #define SHELP_SELECT "select <resource-type> { <property-name>=" \ @@ -187,6 +189,8 @@ char *res_types[] = { "admin", "fs-allowed", ALIAS_MAXPROCS, + ALIAS_ZFSPRI, + "uuid", NULL }; @@ -234,6 +238,12 @@ char *prop_types[] = { "fs-allowed", ALIAS_MAXPROCS, "allowed-address", + ALIAS_ZFSPRI, + "mac-addr", + "vlan-id", + "global-nic", + "property", + "uuid", NULL }; @@ -299,6 +309,7 @@ static const char *clear_cmds[] = { "clear " ALIAS_MAXSEMIDS, "clear " ALIAS_SHARES, "clear " ALIAS_MAXPROCS, + "clear " ALIAS_ZFSPRI, NULL }; @@ -349,6 +360,8 @@ static const char *set_cmds[] = { "set hostid=", "set fs-allowed=", "set " ALIAS_MAXPROCS "=", + "set " ALIAS_ZFSPRI "=", + "set uuid=", NULL }; @@ -381,6 +394,7 @@ static const char *info_cmds[] = { "info admin", "info fs-allowed", "info max-processes", + "info uuid", NULL }; @@ -406,9 +420,20 @@ static const char *net_res_scope_cmds[] = { "exit", "help", "info", + "add property ", + "clear allowed-address", + "clear defrouter", + "clear global-nic", + "clear mac-addr", + "clear vlan-id", + "remove property ", "set address=", - "set physical=", + "set allowed-address=", "set defrouter=", + "set global-nic=", + "set mac-addr=", + "set physical=", + "set vlan-id=", NULL }; @@ -418,6 +443,7 @@ static const char *device_res_scope_cmds[] = { "exit", "help", "info", + "add property ", "set match=", NULL }; @@ -525,6 +551,7 @@ static zone_dochandle_t handle; /* used all over the place */ static char zone[ZONENAME_MAX]; static char revert_zone[ZONENAME_MAX]; +static char new_uuid[UUID_PRINTABLE_STRING_LENGTH]; /* global brand operations */ static brand_handle_t brand; @@ -579,7 +606,6 @@ static struct zone_rctltab old_rctltab, in_progress_rctltab; static struct zone_attrtab old_attrtab, in_progress_attrtab; static struct zone_dstab old_dstab, in_progress_dstab; static struct zone_psettab old_psettab, in_progress_psettab; -static struct zone_mcaptab old_mcaptab, in_progress_mcaptab; static struct zone_admintab old_admintab, in_progress_admintab; static GetLine *gl; /* The gl_get_line() resource object */ @@ -1078,11 +1104,20 @@ usage(boolean_t verbose, uint_t flags) (void) fprintf(fp, gettext("Valid commands:\n")); (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS), gettext("<IP-address>")); + (void) fprintf(fp, "\t%s %s (%s=<value>,%s=<value>)\n", + cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP), + pt_to_str(PT_NAME), pt_to_str(PT_VALUE)); (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS), gettext("<IP-address>")); (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), pt_to_str(PT_PHYSICAL), gettext("<interface>")); + (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), + pt_to_str(PT_MAC), gettext("<mac-address>")); + (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), + pt_to_str(PT_GNIC), gettext("<global zone NIC>")); + (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), + pt_to_str(PT_VLANID), gettext("<vlan ID>")); (void) fprintf(fp, gettext("See ifconfig(1M) for " "details of the <interface> string.\n")); (void) fprintf(fp, gettext("%s %s is valid " @@ -1090,10 +1125,12 @@ usage(boolean_t verbose, uint_t flags) "must not be set.\n"), cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS), pt_to_str(PT_IPTYPE), gettext("shared")); - (void) fprintf(fp, gettext("%s %s is valid " - "if the %s property is set to %s, otherwise it " - "must not be set.\n"), - cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS), + (void) fprintf(fp, gettext("%s (%s, %s, %s, %s) are " + "valid if the %s property is set to %s, otherwise " + "they must not be set.\n"), + cmd_to_str(CMD_SET), + pt_to_str(PT_ALLOWED_ADDRESS), pt_to_str(PT_MAC), + pt_to_str(PT_VLANID), pt_to_str(PT_GNIC), pt_to_str(PT_IPTYPE), gettext("exclusive")); (void) fprintf(fp, gettext("\t%s %s=%s\n%s %s " "is valid if the %s or %s property is set, " @@ -1109,6 +1146,9 @@ usage(boolean_t verbose, uint_t flags) "used to configure a device node.\n"), rt_to_str(resource_scope)); (void) fprintf(fp, gettext("Valid commands:\n")); + (void) fprintf(fp, "\t%s %s (%s=<value>,%s=<value>)\n", + cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP), + pt_to_str(PT_NAME), pt_to_str(PT_VALUE)); (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), pt_to_str(PT_MATCH), gettext("<device-path>")); break; @@ -1240,10 +1280,12 @@ usage(boolean_t verbose, uint_t flags) if (flags & HELP_USAGE) { (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"), execname, cmd_to_str(CMD_HELP)); - (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n", + (void) fprintf(fp, "\t%s {-z <zone>|-u <uuid>}\t\t\t(%s)\n", execname, gettext("interactive")); - (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname); - (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n", + (void) fprintf(fp, "\t%s {-z <zone>|-u <uuid>} <command>\n", + execname); + (void) fprintf(fp, + "\t%s {-z <zone>|-u <uuid>} -f <command-file>\n", execname); } if (flags & HELP_SUBCMDS) { @@ -1332,15 +1374,22 @@ usage(boolean_t verbose, uint_t flags) pt_to_str(PT_MAXSEMIDS)); (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), pt_to_str(PT_SHARES)); + (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), + pt_to_str(PT_UUID)); + (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), + pt_to_str(PT_ZFSPRI)); (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n", rt_to_str(RT_FS), pt_to_str(PT_DIR), pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW), pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS)); - (void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET), + (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s, %s, %s %s\n", + rt_to_str(RT_NET), pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS), - pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER)); - (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE), - pt_to_str(PT_MATCH)); + pt_to_str(PT_GNIC), pt_to_str(PT_MAC), + pt_to_str(PT_PHYSICAL), pt_to_str(PT_NPROP), + pt_to_str(PT_VLANID), pt_to_str(PT_DEFROUTER)); + (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_DEVICE), + pt_to_str(PT_MATCH), pt_to_str(PT_NPROP)); (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL), pt_to_str(PT_NAME), pt_to_str(PT_VALUE)); (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR), @@ -1395,6 +1444,9 @@ initialize(boolean_t handle_expected) if (zonecfg_check_handle(handle) != Z_OK) { if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) { got_handle = B_TRUE; + + (void) zonecfg_fix_obsolete(handle); + if (zonecfg_get_brand(handle, brandname, sizeof (brandname)) != Z_OK) { zerr("Zone %s is inconsistent: missing " @@ -1662,6 +1714,7 @@ create_func(cmd_t *cmd) boolean_t force = B_FALSE; boolean_t attach = B_FALSE; boolean_t arg_err = B_FALSE; + uuid_t uuid; assert(cmd != NULL); @@ -1669,7 +1722,7 @@ create_func(cmd_t *cmd) (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template)); optind = 0; - while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:")) + while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:X")) != EOF) { switch (arg) { case '?': @@ -1695,6 +1748,17 @@ create_func(cmd_t *cmd) (void) strlcpy(zone_template, optarg, sizeof (zone_template)); break; + case 'X': + (void) snprintf(zone_template, sizeof (zone_template), + "%s/%s.xml", ZONE_CONFIG_ROOT, zone); + err = zonecfg_get_xml_handle(zone_template, handle); + if (err != Z_OK) { + zone_perror(execname, err, B_TRUE); + exit(Z_ERR); + } + got_handle = B_TRUE; + need_to_commit = B_TRUE; + return; default: short_usage(CMD_CREATE); arg_err = B_TRUE; @@ -1751,6 +1815,10 @@ create_func(cmd_t *cmd) zonecfg_fini_handle(handle); handle = tmphandle; got_handle = B_TRUE; + + /* Allocate a new uuid for this new zone */ + uuid_generate(uuid); + uuid_unparse(uuid, new_uuid); } /* @@ -1797,8 +1865,8 @@ export_func(cmd_t *cmd) struct zone_rctltab rctltab; struct zone_dstab dstab; struct zone_psettab psettab; - struct zone_mcaptab mcaptab; struct zone_rctlvaltab *valptr; + struct zone_res_attrtab *rap; struct zone_admintab admintab; int err, arg; char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN]; @@ -1811,6 +1879,7 @@ export_func(cmd_t *cmd) FILE *of; boolean_t autoboot; zone_iptype_t iptype; + uuid_t uuid; boolean_t need_to_close = B_FALSE; boolean_t arg_err = B_FALSE; @@ -1921,6 +1990,14 @@ export_func(cmd_t *cmd) pt_to_str(PT_FS_ALLOWED), fsallowedp); } + if (zonecfg_get_uuid(zone, uuid) == Z_OK && !uuid_is_null(uuid)) { + char suuid[UUID_PRINTABLE_STRING_LENGTH]; + + uuid_unparse(uuid, suuid); + (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), + pt_to_str(PT_UUID), suuid); + } + if ((err = zonecfg_setfsent(handle)) != Z_OK) { zone_perror(zone, err, B_FALSE); goto done; @@ -1968,7 +2045,17 @@ export_func(cmd_t *cmd) export_prop(of, PT_ALLOWED_ADDRESS, nwiftab.zone_nwif_allowed_address); export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical); + export_prop(of, PT_MAC, nwiftab.zone_nwif_mac); + export_prop(of, PT_VLANID, nwiftab.zone_nwif_vlan_id); + export_prop(of, PT_GNIC, nwiftab.zone_nwif_gnic); export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter); + for (rap = nwiftab.zone_nwif_attrp; rap != NULL; + rap = rap->zone_res_attr_next) { + fprintf(of, "%s %s (%s=%s,%s=\"%s\")\n", + cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP), + pt_to_str(PT_NAME), rap->zone_res_attr_name, + pt_to_str(PT_VALUE), rap->zone_res_attr_value); + } (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); } (void) zonecfg_endnwifent(handle); @@ -1981,21 +2068,17 @@ export_func(cmd_t *cmd) (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), rt_to_str(RT_DEVICE)); export_prop(of, PT_MATCH, devtab.zone_dev_match); + for (rap = devtab.zone_dev_attrp; rap != NULL; + rap = rap->zone_res_attr_next) { + fprintf(of, "%s %s (%s=%s,%s=\"%s\")\n", + cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP), + pt_to_str(PT_NAME), rap->zone_res_attr_name, + pt_to_str(PT_VALUE), rap->zone_res_attr_value); + } (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); } (void) zonecfg_enddevent(handle); - if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) { - char buf[128]; - - (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), - rt_to_str(RT_MCAP)); - bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf)); - (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), - pt_to_str(PT_PHYSICAL), buf); - (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); - } - if ((err = zonecfg_setrctlent(handle)) != Z_OK) { zone_perror(zone, err, B_FALSE); goto done; @@ -2149,7 +2232,6 @@ add_resource(cmd_t *cmd) { int type; struct zone_psettab tmp_psettab; - struct zone_mcaptab tmp_mcaptab; uint64_t tmp; uint64_t tmp_mcap; char pool[MAXNAMELEN]; @@ -2241,9 +2323,10 @@ add_resource(cmd_t *cmd) * Make sure there isn't already a mem-cap entry or max-swap * or max-locked rctl. */ - if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK || - zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap) - == Z_OK || + if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, + &tmp_mcap) == Z_OK || + zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, + &tmp_mcap) == Z_OK || zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp_mcap) == Z_OK) { zerr(gettext("The %s resource or a related resource " @@ -2256,7 +2339,6 @@ add_resource(cmd_t *cmd) "to even the root user; " "this could render the system impossible\n" "to administer. Please use caution.")); - bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab)); return; case RT_ADMIN: bzero(&in_progress_admintab, sizeof (in_progress_admintab)); @@ -2359,6 +2441,68 @@ bad: zonecfg_free_rctl_value_list(rctlvaltab); } +/* + * Resource attribute ("property" resource embedded on net or dev resource) + */ +static void +do_res_attr(struct zone_res_attrtab **headp, complex_property_ptr_t cpp) +{ + complex_property_ptr_t cp; + struct zone_res_attrtab *np; + int err; + boolean_t seen_name = B_FALSE, seen_value = B_FALSE; + + if ((np = calloc(1, sizeof (struct zone_res_attrtab))) == NULL) { + zone_perror(zone, Z_NOMEM, B_TRUE); + exit(Z_ERR); + } + + for (cp = cpp; cp != NULL; cp = cp->cp_next) { + switch (cp->cp_type) { + case PT_NAME: + if (seen_name) { + zerr(gettext("%s already specified"), + pt_to_str(PT_NAME)); + goto bad; + } + (void) strlcpy(np->zone_res_attr_name, cp->cp_value, + sizeof (np->zone_res_attr_name)); + seen_name = B_TRUE; + break; + case PT_VALUE: + if (seen_value) { + zerr(gettext("%s already specified"), + pt_to_str(PT_VALUE)); + goto bad; + } + (void) strlcpy(np->zone_res_attr_value, cp->cp_value, + sizeof (np->zone_res_attr_value)); + seen_value = B_TRUE; + break; + default: + zone_perror(pt_to_str(PT_NPROP), Z_NO_PROPERTY_TYPE, + B_TRUE); + long_usage(CMD_ADD, B_TRUE); + usage(B_FALSE, HELP_PROPS); + zonecfg_free_res_attr_list(np); + return; + } + } + + if (!seen_name) + zerr(gettext("%s not specified"), pt_to_str(PT_NAME)); + if (!seen_value) + zerr(gettext("%s not specified"), pt_to_str(PT_VALUE)); + + err = zonecfg_add_res_attr(headp, np); + if (err != Z_OK) + zone_perror(pt_to_str(PT_NPROP), err, B_TRUE); + return; + +bad: + zonecfg_free_res_attr_list(np); +} + static void add_property(cmd_t *cmd) { @@ -2426,6 +2570,44 @@ add_property(cmd_t *cmd) } } return; + case RT_NET: + if (prop_type != PT_NPROP) { + zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, + B_TRUE); + long_usage(CMD_ADD, B_TRUE); + usage(B_FALSE, HELP_PROPS); + return; + } + pp = cmd->cmd_property_ptr[0]; + if (pp->pv_type != PROP_VAL_COMPLEX) { + zerr(gettext("A %s value was expected here."), + pvt_to_str(PROP_VAL_COMPLEX)); + saw_error = B_TRUE; + return; + } + + do_res_attr(&(in_progress_nwiftab.zone_nwif_attrp), + pp->pv_complex); + return; + case RT_DEVICE: + if (prop_type != PT_NPROP) { + zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, + B_TRUE); + long_usage(CMD_ADD, B_TRUE); + usage(B_FALSE, HELP_PROPS); + return; + } + pp = cmd->cmd_property_ptr[0]; + if (pp->pv_type != PROP_VAL_COMPLEX) { + zerr(gettext("A %s value was expected here."), + pvt_to_str(PROP_VAL_COMPLEX)); + saw_error = B_TRUE; + return; + } + + do_res_attr(&(in_progress_devtab.zone_dev_attrp), + pp->pv_complex); + return; case RT_RCTL: if (prop_type != PT_VALUE) { zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, @@ -2470,7 +2652,7 @@ static boolean_t gz_invalid_rt_property(int type) { return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH || - type == RT_AUTOBOOT || type == RT_LIMITPRIV || + type == RT_AUTOBOOT || type == RT_LIMITPRIV || type == RT_UUID || type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED || type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED)); } @@ -2479,7 +2661,7 @@ static boolean_t gz_invalid_property(int type) { return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH || - type == PT_AUTOBOOT || type == PT_LIMITPRIV || + type == PT_AUTOBOOT || type == PT_LIMITPRIV || type == PT_UUID || type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED || type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED)); } @@ -2530,8 +2712,9 @@ add_func(cmd_t *cmd) resource_scope = cmd->cmd_res_type; end_op = CMD_ADD; add_resource(cmd); - } else + } else { add_property(cmd); + } } /* @@ -2696,6 +2879,32 @@ fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only) return (zonecfg_lookup_filesystem(handle, fstab)); } +/* + * Turn an addr that looks like f:2:0:44:5:6C into 0f:02:00:44:05:6c + * We're expecting a dst of at least MAXMACADDRLEN size here. + */ +static void +normalize_mac_addr(char *dst, const char *src, int len) +{ + char *p, *e, *sep = ""; + long n; + char buf[MAXMACADDRLEN], tmp[4]; + + *dst = '\0'; + (void) strlcpy(buf, src, sizeof (buf)); + p = strtok(buf, ":"); + while (p != NULL) { + n = strtol(p, &e, 16); + if (*e != NULL || n > 0xff) + return; + (void) snprintf(tmp, sizeof (tmp), "%s%02x", sep, n); + (void) strlcat(dst, tmp, len); + + sep = ":"; + p = strtok(NULL, ":"); + } +} + static int fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab, boolean_t fill_in_only) @@ -2729,6 +2938,21 @@ fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab, pp->pv_simple, sizeof (nwiftab->zone_nwif_physical)); break; + case PT_MAC: + normalize_mac_addr(nwiftab->zone_nwif_mac, + pp->pv_simple, + sizeof (nwiftab->zone_nwif_mac)); + break; + case PT_VLANID: + (void) strlcpy(nwiftab->zone_nwif_vlan_id, + pp->pv_simple, + sizeof (nwiftab->zone_nwif_vlan_id)); + break; + case PT_GNIC: + (void) strlcpy(nwiftab->zone_nwif_gnic, + pp->pv_simple, + sizeof (nwiftab->zone_nwif_gnic)); + break; case PT_DEFROUTER: (void) strlcpy(nwiftab->zone_nwif_defrouter, pp->pv_simple, @@ -2979,6 +3203,8 @@ prompt_remove_resource(cmd_t *cmd, char *rsrc) num = zonecfg_num_resources(handle, rsrc); if (num == 0) { + if (force) + return (B_TRUE); z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY, B_TRUE); return (B_FALSE); @@ -3007,7 +3233,7 @@ prompt_remove_resource(cmd_t *cmd, char *rsrc) } static void -remove_fs(cmd_t *cmd) +remove_fs(cmd_t *cmd, boolean_t force) { int err; @@ -3016,13 +3242,16 @@ remove_fs(cmd_t *cmd) struct zone_fstab fstab; if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); return; } - if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); - else + if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); + } else { need_to_commit = B_TRUE; + } zonecfg_free_fs_option_list(fstab.zone_fs_options); return; } @@ -3041,7 +3270,7 @@ remove_fs(cmd_t *cmd) } static void -remove_net(cmd_t *cmd) +remove_net(cmd_t *cmd, boolean_t force) { int err; @@ -3050,13 +3279,18 @@ remove_net(cmd_t *cmd) struct zone_nwiftab nwiftab; if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, + B_TRUE); return; } - if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE); - else + if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, + B_TRUE); + } else { need_to_commit = B_TRUE; + } return; } @@ -3074,7 +3308,7 @@ remove_net(cmd_t *cmd) } static void -remove_device(cmd_t *cmd) +remove_device(cmd_t *cmd, boolean_t force) { int err; @@ -3083,13 +3317,18 @@ remove_device(cmd_t *cmd) struct zone_devtab devtab; if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, + B_TRUE); return; } - if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE); - else + if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, + B_TRUE); + } else { need_to_commit = B_TRUE; + } return; } @@ -3107,7 +3346,7 @@ remove_device(cmd_t *cmd) } static void -remove_attr(cmd_t *cmd) +remove_attr(cmd_t *cmd, boolean_t force) { int err; @@ -3116,13 +3355,18 @@ remove_attr(cmd_t *cmd) struct zone_attrtab attrtab; if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, + B_TRUE); return; } - if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE); - else + if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, + B_TRUE); + } else { need_to_commit = B_TRUE; + } return; } @@ -3140,7 +3384,7 @@ remove_attr(cmd_t *cmd) } static void -remove_dataset(cmd_t *cmd) +remove_dataset(cmd_t *cmd, boolean_t force) { int err; @@ -3149,13 +3393,18 @@ remove_dataset(cmd_t *cmd) struct zone_dstab dstab; if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, + B_TRUE); return; } - if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE); - else + if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, + B_TRUE); + } else { need_to_commit = B_TRUE; + } return; } @@ -3173,7 +3422,7 @@ remove_dataset(cmd_t *cmd) } static void -remove_rctl(cmd_t *cmd) +remove_rctl(cmd_t *cmd, boolean_t force) { int err; @@ -3182,13 +3431,18 @@ remove_rctl(cmd_t *cmd) struct zone_rctltab rctltab; if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, + B_TRUE); return; } - if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE); - else + if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, + B_TRUE); + } else { need_to_commit = B_TRUE; + } zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); return; } @@ -3207,72 +3461,90 @@ remove_rctl(cmd_t *cmd) } static void -remove_pset() +remove_pset(boolean_t force) { int err; struct zone_psettab psettab; if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE); return; } - if ((err = zonecfg_delete_pset(handle)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE); - else + if ((err = zonecfg_delete_pset(handle)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE); + } else { need_to_commit = B_TRUE; + } } static void -remove_pcap() +remove_pcap(boolean_t force) { int err; uint64_t tmp; if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) { - zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP), - zonecfg_strerror(Z_NO_RESOURCE_TYPE)); - saw_error = B_TRUE; + if (!force) { + zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), + rt_to_str(RT_PCAP), + zonecfg_strerror(Z_NO_RESOURCE_TYPE)); + saw_error = B_TRUE; + } return; } - if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE); - else + if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE); + } else { need_to_commit = B_TRUE; + } } static void -remove_mcap() +remove_mcap(boolean_t force) { int err, res1, res2, res3; uint64_t tmp; - struct zone_mcaptab mcaptab; boolean_t revert = B_FALSE; - res1 = zonecfg_lookup_mcap(handle, &mcaptab); + res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &tmp); res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp); res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp); /* if none of these exist, there is no resource to remove */ if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) { - zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP), - zonecfg_strerror(Z_NO_RESOURCE_TYPE)); - saw_error = B_TRUE; + if (!force) { + zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), + rt_to_str(RT_MCAP), + zonecfg_strerror(Z_NO_RESOURCE_TYPE)); + saw_error = B_TRUE; + } return; } if (res1 == Z_OK) { - if ((err = zonecfg_delete_mcap(handle)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE); - revert = B_TRUE; + if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXPHYSMEM)) + != Z_OK) { + if (!force) { + z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, + B_TRUE); + revert = B_TRUE; + } } else { need_to_commit = B_TRUE; } } + if (res2 == Z_OK) { if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE); - revert = B_TRUE; + if (!force) { + z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, + B_TRUE); + revert = B_TRUE; + } } else { need_to_commit = B_TRUE; } @@ -3280,8 +3552,11 @@ remove_mcap() if (res3 == Z_OK) { if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE); - revert = B_TRUE; + if (!force) { + z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, + B_TRUE); + revert = B_TRUE; + } } else { need_to_commit = B_TRUE; } @@ -3292,7 +3567,7 @@ remove_mcap() } static void -remove_admin(cmd_t *cmd) +remove_admin(cmd_t *cmd, boolean_t force) { int err; @@ -3301,34 +3576,33 @@ remove_admin(cmd_t *cmd) struct zone_admintab admintab; if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) { - z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, - err, B_TRUE); + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err, + B_TRUE); return; } if ((err = zonecfg_delete_admin(handle, &admintab, - zone)) - != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, - err, B_TRUE); - else + zone)) != Z_OK) { + if (!force) + z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err, + B_TRUE); + } else { need_to_commit = B_TRUE; + } return; - } else { - /* - * unqualified admin removal. - * remove all admins but prompt if more - * than one. - */ - if (!prompt_remove_resource(cmd, "admin")) - return; - - if ((err = zonecfg_delete_admins(handle, zone)) - != Z_OK) - z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, - err, B_TRUE); - else - need_to_commit = B_TRUE; } + + /* + * unqualified admin removal. + * remove all admins but prompt if more than one. + */ + if (!prompt_remove_resource(cmd, "admin")) + return; + + if ((err = zonecfg_delete_admins(handle, zone)) != Z_OK) + z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err, B_TRUE); + else + need_to_commit = B_TRUE; } static void @@ -3337,6 +3611,7 @@ remove_resource(cmd_t *cmd) int type; int arg; boolean_t arg_err = B_FALSE; + boolean_t force = B_FALSE; if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { long_usage(CMD_REMOVE, B_TRUE); @@ -3351,6 +3626,7 @@ remove_resource(cmd_t *cmd) arg_err = B_TRUE; break; case 'F': + force = B_TRUE; break; default: short_usage(CMD_REMOVE); @@ -3366,34 +3642,34 @@ remove_resource(cmd_t *cmd) switch (type) { case RT_FS: - remove_fs(cmd); + remove_fs(cmd, force); return; case RT_NET: - remove_net(cmd); + remove_net(cmd, force); return; case RT_DEVICE: - remove_device(cmd); + remove_device(cmd, force); return; case RT_RCTL: - remove_rctl(cmd); + remove_rctl(cmd, force); return; case RT_ATTR: - remove_attr(cmd); + remove_attr(cmd, force); return; case RT_DATASET: - remove_dataset(cmd); + remove_dataset(cmd, force); return; case RT_DCPU: - remove_pset(); + remove_pset(force); return; case RT_PCAP: - remove_pcap(); + remove_pcap(force); return; case RT_MCAP: - remove_mcap(); + remove_mcap(force); return; case RT_ADMIN: - remove_admin(cmd); + remove_admin(cmd, force); return; default: zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE); @@ -3410,7 +3686,27 @@ remove_property(cmd_t *cmd) int err, res_type, prop_type; property_value_ptr_t pp; struct zone_rctlvaltab *rctlvaltab; + struct zone_res_attrtab *np; complex_property_ptr_t cx; + int arg; + boolean_t force = B_FALSE; + boolean_t arg_err = B_FALSE; + + optind = 0; + while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) { + switch (arg) { + case 'F': + force = B_TRUE; + break; + default: + arg_err = B_TRUE; + break; + } + } + if (arg_err) { + saw_error = B_TRUE; + return; + } res_type = resource_scope; prop_type = cmd->cmd_prop_name[0]; @@ -3452,7 +3748,7 @@ remove_property(cmd_t *cmd) prop_id = pp->pv_simple; err = zonecfg_remove_fs_option(&in_progress_fstab, prop_id); - if (err != Z_OK) + if (err != Z_OK && !force) zone_perror(pt_to_str(prop_type), err, B_TRUE); } else { list_property_ptr_t list; @@ -3464,12 +3760,62 @@ remove_property(cmd_t *cmd) break; err = zonecfg_remove_fs_option( &in_progress_fstab, prop_id); - if (err != Z_OK) + if (err != Z_OK && !force) zone_perror(pt_to_str(prop_type), err, B_TRUE); } } return; + case RT_NET: /* FALLTHRU */ + case RT_DEVICE: + if (prop_type != PT_NPROP) { + zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, + B_TRUE); + long_usage(CMD_REMOVE, B_TRUE); + usage(B_FALSE, HELP_PROPS); + return; + } + pp = cmd->cmd_property_ptr[0]; + if (pp->pv_type != PROP_VAL_COMPLEX) { + zerr(gettext("A %s value was expected here."), + pvt_to_str(PROP_VAL_COMPLEX)); + saw_error = B_TRUE; + return; + } + + np = alloca(sizeof (struct zone_res_attrtab)); + for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) { + switch (cx->cp_type) { + case PT_NAME: + (void) strlcpy(np->zone_res_attr_name, + cx->cp_value, + sizeof (np->zone_res_attr_name)); + break; + case PT_VALUE: + (void) strlcpy(np->zone_res_attr_value, + cx->cp_value, + sizeof (np->zone_res_attr_value)); + break; + default: + zone_perror(pt_to_str(prop_type), + Z_NO_PROPERTY_TYPE, B_TRUE); + long_usage(CMD_REMOVE, B_TRUE); + usage(B_FALSE, HELP_PROPS); + return; + } + } + np->zone_res_attr_next = NULL; + + if (res_type == RT_NET) { + err = zonecfg_remove_res_attr( + &(in_progress_nwiftab.zone_nwif_attrp), np); + } else { /* RT_DEVICE */ + err = zonecfg_remove_res_attr( + &(in_progress_devtab.zone_dev_attrp), np); + } + if (err != Z_OK && !force) + zone_perror(pt_to_str(prop_type), err, B_TRUE); + return; case RT_RCTL: if (prop_type != PT_VALUE) { zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, @@ -3518,22 +3864,10 @@ remove_property(cmd_t *cmd) rctlvaltab->zone_rctlval_next = NULL; err = zonecfg_remove_rctl_value(&in_progress_rctltab, rctlvaltab); - if (err != Z_OK) + if (err != Z_OK && !force) zone_perror(pt_to_str(prop_type), err, B_TRUE); zonecfg_free_rctl_value_list(rctlvaltab); return; - case RT_NET: - if (prop_type != PT_DEFROUTER) { - zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, - B_TRUE); - long_usage(CMD_REMOVE, B_TRUE); - usage(B_FALSE, HELP_PROPS); - return; - } else { - bzero(&in_progress_nwiftab.zone_nwif_defrouter, - sizeof (in_progress_nwiftab.zone_nwif_defrouter)); - return; - } default: zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE); long_usage(CMD_REMOVE, B_TRUE); @@ -3596,8 +3930,7 @@ clear_property(cmd_t *cmd) case RT_MCAP: switch (prop_type) { case PT_PHYSICAL: - in_progress_mcaptab.zone_physmem_cap[0] = '\0'; - need_to_commit = B_TRUE; + remove_aliased_rctl(PT_PHYSICAL, ALIAS_MAXPHYSMEM); return; case PT_SWAP: remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP); @@ -3607,6 +3940,30 @@ clear_property(cmd_t *cmd) return; } break; + case RT_NET: + switch (prop_type) { + case PT_ALLOWED_ADDRESS: + in_progress_nwiftab.zone_nwif_allowed_address[0] = '\0'; + need_to_commit = B_TRUE; + return; + case PT_DEFROUTER: + in_progress_nwiftab.zone_nwif_defrouter[0] = '\0'; + need_to_commit = B_TRUE; + return; + case PT_GNIC: + in_progress_nwiftab.zone_nwif_gnic[0] = '\0'; + need_to_commit = B_TRUE; + return; + case PT_MAC: + in_progress_nwiftab.zone_nwif_mac[0] = '\0'; + need_to_commit = B_TRUE; + return; + case PT_VLANID: + in_progress_nwiftab.zone_nwif_vlan_id[0] = '\0'; + need_to_commit = B_TRUE; + return; + } + break; default: break; } @@ -3632,6 +3989,8 @@ clear_global(cmd_t *cmd) /* FALLTHRU */ case PT_ZONEPATH: /* FALLTHRU */ + case PT_UUID: + /* FALLTHRU */ case PT_BRAND: zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE); return; @@ -3694,6 +4053,9 @@ clear_global(cmd_t *cmd) case PT_SHARES: remove_aliased_rctl(PT_SHARES, ALIAS_SHARES); return; + case PT_ZFSPRI: + remove_aliased_rctl(PT_ZFSPRI, ALIAS_ZFSPRI); + return; case PT_HOSTID: if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK) z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE); @@ -3739,7 +4101,7 @@ clear_func(cmd_t *cmd) void select_func(cmd_t *cmd) { - int type, err, res; + int type, err; uint64_t limit; uint64_t tmp; @@ -3834,7 +4196,8 @@ select_func(cmd_t *cmd) return; case RT_MCAP: /* if none of these exist, there is no resource to select */ - if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK && + if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &limit) + != Z_OK && zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit) != Z_OK && zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit) @@ -3843,12 +4206,6 @@ select_func(cmd_t *cmd) B_TRUE); global_scope = B_TRUE; } - if (res == Z_OK) - bcopy(&old_mcaptab, &in_progress_mcaptab, - sizeof (struct zone_mcaptab)); - else - bzero(&in_progress_mcaptab, - sizeof (in_progress_mcaptab)); return; case RT_ADMIN: if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE)) @@ -4115,7 +4472,6 @@ set_func(cmd_t *cmd) boolean_t autoboot; zone_iptype_t iptype; boolean_t force_set = B_FALSE; - size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap); uint64_t mem_cap, mem_limit; float cap; char *unitp; @@ -4190,6 +4546,10 @@ set_func(cmd_t *cmd) res_type = RT_HOSTID; } else if (prop_type == PT_FS_ALLOWED) { res_type = RT_FS_ALLOWED; + } else if (prop_type == PT_ZFSPRI) { + res_type = RT_ZFSPRI; + } else if (prop_type == PT_UUID) { + res_type = RT_UUID; } else { zerr(gettext("Cannot set a resource-specific property " "from the global scope.")); @@ -4219,10 +4579,12 @@ set_func(cmd_t *cmd) * A nasty expression but not that complicated: * 1. fs options are simple or list (tested below) * 2. rctl value's are complex or list (tested below) + * 3. net attr's are complex (tested below) * Anything else should be simple. */ if (!(res_type == RT_FS && prop_type == PT_OPTIONS) && !(res_type == RT_RCTL && prop_type == PT_VALUE) && + !(res_type == RT_NET && prop_type == PT_NPROP) && (pp->pv_type != PROP_VAL_SIMPLE || (prop_id = pp->pv_simple) == NULL)) { zerr(gettext("A %s value was expected here."), @@ -4395,6 +4757,9 @@ set_func(cmd_t *cmd) case RT_SHARES: set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id); return; + case RT_ZFSPRI: + set_aliased_rctl(ALIAS_ZFSPRI, prop_type, prop_id); + return; case RT_HOSTID: if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) { if (err == Z_TOO_BIG) { @@ -4408,6 +4773,15 @@ set_func(cmd_t *cmd) } need_to_commit = B_TRUE; return; + case RT_UUID: + /* + * We can't set here. We have to wait until commit since the + * uuid will be updating the index file and we may not have + * created the zone yet. + */ + (void) strlcpy(new_uuid, prop_id, sizeof (new_uuid)); + need_to_commit = B_TRUE; + return; case RT_FS_ALLOWED: if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK) zone_perror(zone, err, B_TRUE); @@ -4482,6 +4856,21 @@ set_func(cmd_t *cmd) prop_id, sizeof (in_progress_nwiftab.zone_nwif_physical)); break; + case PT_MAC: + normalize_mac_addr(in_progress_nwiftab.zone_nwif_mac, + prop_id, + sizeof (in_progress_nwiftab.zone_nwif_mac)); + break; + case PT_VLANID: + (void) strlcpy(in_progress_nwiftab.zone_nwif_vlan_id, + prop_id, + sizeof (in_progress_nwiftab.zone_nwif_vlan_id)); + break; + case PT_GNIC: + (void) strlcpy(in_progress_nwiftab.zone_nwif_gnic, + prop_id, + sizeof (in_progress_nwiftab.zone_nwif_gnic)); + break; case PT_DEFROUTER: if (validate_net_address_syntax(prop_id, B_TRUE) != Z_OK) { @@ -4492,6 +4881,20 @@ set_func(cmd_t *cmd) prop_id, sizeof (in_progress_nwiftab.zone_nwif_defrouter)); break; + case PT_NPROP: + if (pp->pv_type != PROP_VAL_COMPLEX) { + zerr(gettext("A %s value was expected here."), + pvt_to_str(PROP_VAL_COMPLEX)); + saw_error = B_TRUE; + return; + } + zonecfg_free_res_attr_list( + in_progress_nwiftab.zone_nwif_attrp); + in_progress_nwiftab.zone_nwif_attrp = NULL; + if (!(pp->pv_type == PROP_VAL_LIST && + pp->pv_list == NULL)) + add_property(cmd); + break; default: zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE); @@ -4507,6 +4910,20 @@ set_func(cmd_t *cmd) prop_id, sizeof (in_progress_devtab.zone_dev_match)); break; + case PT_NPROP: + if (pp->pv_type != PROP_VAL_COMPLEX) { + zerr(gettext("A %s value was expected here."), + pvt_to_str(PROP_VAL_COMPLEX)); + saw_error = B_TRUE; + return; + } + zonecfg_free_res_attr_list( + in_progress_devtab.zone_dev_attrp); + in_progress_devtab.zone_dev_attrp = NULL; + if (!(pp->pv_type == PROP_VAL_LIST && + pp->pv_list == NULL)) + add_property(cmd); + break; default: zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE); @@ -4667,18 +5084,30 @@ set_func(cmd_t *cmd) case RT_MCAP: switch (prop_type) { case PT_PHYSICAL: + /* + * We have to check if an rctl is allowed here since + * there might already be a rctl defined that blocks + * the alias. + */ + if (!zonecfg_aliased_rctl_ok(handle, + ALIAS_MAXPHYSMEM)) { + zone_perror(pt_to_str(PT_LOCKED), + Z_ALIAS_DISALLOW, B_FALSE); + saw_error = B_TRUE; + return; + } + if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) { - zerr(gettext("A positive number with a " + zerr(gettext("A non-negative number with a " "required scale suffix (K, M, G or T) was " - "expected here.")); - saw_error = B_TRUE; - } else if (mem_cap < ONE_MB) { - zerr(gettext("%s value is too small. It must " - "be at least 1M."), pt_to_str(PT_PHYSICAL)); + "expected\nhere.")); saw_error = B_TRUE; } else { - snprintf(in_progress_mcaptab.zone_physmem_cap, - physmem_size, "%llu", mem_cap); + if ((err = zonecfg_set_aliased_rctl(handle, + ALIAS_MAXPHYSMEM, mem_cap)) != Z_OK) + zone_perror(zone, err, B_TRUE); + else + need_to_commit = B_TRUE; } break; case PT_SWAP: @@ -4950,6 +5379,23 @@ info_hostid(zone_dochandle_t handle, FILE *fp) } static void +info_uuid(FILE *fp) +{ + uuid_t uuid; + char suuid[UUID_PRINTABLE_STRING_LENGTH]; + + if (new_uuid[0] != '\0') { + (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_UUID), new_uuid); + } else if (zonecfg_get_uuid(zone, uuid) == Z_OK && + !uuid_is_null(uuid)) { + uuid_unparse(uuid, suuid); + (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_UUID), suuid); + } else { + (void) fprintf(fp, "%s:\n", pt_to_str(PT_UUID)); + } +} + +static void info_fs_allowed(zone_dochandle_t handle, FILE *fp) { char fsallowedp[ZONE_FS_ALLOWED_MAX]; @@ -5031,12 +5477,25 @@ loopend: static void output_net(FILE *fp, struct zone_nwiftab *nwiftab) { + struct zone_res_attrtab *np; + (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET)); output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE); output_prop(fp, PT_ALLOWED_ADDRESS, nwiftab->zone_nwif_allowed_address, B_TRUE); - output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE); output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE); + output_prop(fp, PT_GNIC, nwiftab->zone_nwif_gnic, B_TRUE); + output_prop(fp, PT_MAC, nwiftab->zone_nwif_mac, B_TRUE); + output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE); + output_prop(fp, PT_VLANID, nwiftab->zone_nwif_vlan_id, B_TRUE); + + for (np = nwiftab->zone_nwif_attrp; np != NULL; + np = np->zone_res_attr_next) { + fprintf(fp, "\t%s: (%s=%s,%s=\"%s\")\n", + pt_to_str(PT_NPROP), + pt_to_str(PT_NAME), np->zone_res_attr_name, + pt_to_str(PT_VALUE), np->zone_res_attr_value); + } } static void @@ -5079,8 +5538,18 @@ info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) static void output_dev(FILE *fp, struct zone_devtab *devtab) { + struct zone_res_attrtab *np; + (void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE)); output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE); + + for (np = devtab->zone_dev_attrp; np != NULL; + np = np->zone_res_attr_next) { + fprintf(fp, "\t%s: (%s=%s,%s=\"%s\")\n", + pt_to_str(PT_NPROP), + pt_to_str(PT_NAME), np->zone_res_attr_name, + pt_to_str(PT_VALUE), np->zone_res_attr_value); + } } static void @@ -5339,15 +5808,18 @@ bytes_to_units(char *str, char *buf, int bufsize) } static void -output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap, +output_mcap(FILE *fp, int showphys, uint64_t maxphys, int showswap, uint64_t maxswap, int showlocked, uint64_t maxlocked) { char buf[128]; (void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP)); - if (mcaptab->zone_physmem_cap[0] != '\0') { - bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf)); - output_prop(fp, PT_PHYSICAL, buf, B_TRUE); + + if (showphys == Z_OK) { + (void) snprintf(buf, sizeof (buf), "%llu", maxphys); + bytes_to_units(buf, buf, sizeof (buf)); + /* Print directly since "physical" also is a net property. */ + (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(PT_PHYSICAL), buf); } if (showswap == Z_OK) { @@ -5369,16 +5841,16 @@ info_mcap(zone_dochandle_t handle, FILE *fp) int res1, res2, res3; uint64_t swap_limit; uint64_t locked_limit; - struct zone_mcaptab lookup; + uint64_t phys_limit; - bzero(&lookup, sizeof (lookup)); - res1 = zonecfg_getmcapent(handle, &lookup); + res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &phys_limit); res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit); res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &locked_limit); if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK) - output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit); + output_mcap(fp, res1, phys_limit, res2, swap_limit, + res3, locked_limit); } static void @@ -5429,9 +5901,11 @@ info_func(cmd_t *cmd) FILE *fp = stdout; boolean_t need_to_close = B_FALSE; int type; - int res1, res2; + int res1, res2, res3; uint64_t swap_limit; uint64_t locked_limit; + uint64_t phys_limit; + struct stat statbuf; assert(cmd != NULL); @@ -5479,7 +5953,9 @@ info_func(cmd_t *cmd) &swap_limit); res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &locked_limit); - output_mcap(fp, &in_progress_mcaptab, res1, swap_limit, + res3 = zonecfg_get_aliased_rctl(handle, + ALIAS_MAXPHYSMEM, &phys_limit); + output_mcap(fp, res3, phys_limit, res1, swap_limit, res2, locked_limit); break; case RT_ADMIN: @@ -5519,6 +5995,7 @@ info_func(cmd_t *cmd) info_iptype(handle, fp); info_hostid(handle, fp); info_fs_allowed(handle, fp); + info_uuid(fp); } info_aliased_rctl(handle, fp, ALIAS_MAXLWPS); info_aliased_rctl(handle, fp, ALIAS_MAXPROCS); @@ -5527,6 +6004,7 @@ info_func(cmd_t *cmd) info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS); info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS); info_aliased_rctl(handle, fp, ALIAS_SHARES); + info_aliased_rctl(handle, fp, ALIAS_ZFSPRI); if (!global_zone) { info_fs(handle, fp, cmd); info_net(handle, fp, cmd); @@ -5590,6 +6068,9 @@ info_func(cmd_t *cmd) case RT_SHARES: info_aliased_rctl(handle, fp, ALIAS_SHARES); break; + case RT_ZFSPRI: + info_aliased_rctl(handle, fp, ALIAS_ZFSPRI); + break; case RT_FS: info_fs(handle, fp, cmd); break; @@ -5620,6 +6101,9 @@ info_func(cmd_t *cmd) case RT_HOSTID: info_hostid(handle, fp); break; + case RT_UUID: + info_uuid(fp); + break; case RT_ADMIN: info_auth(handle, fp, cmd); break; @@ -6101,11 +6585,29 @@ verify_func(cmd_t *cmd) if (save) { if (ret_val == Z_OK) { + /* + * If the zone doesn't yet have a debug ID, set one now. + */ + if (zonecfg_get_did(handle) == -1) + zonecfg_set_did(handle); + if ((ret_val = zonecfg_save(handle)) == Z_OK) { need_to_commit = B_FALSE; (void) strlcpy(revert_zone, zone, sizeof (revert_zone)); } + + /* + * Commit a new uuid at this point since we now know the + * zone index entry will exist. + */ + if (new_uuid[0] != '\0') { + if ((err = zonecfg_set_uuid(zone, zonepath, + new_uuid)) != Z_OK) + zone_perror(zone, err, B_FALSE); + else + new_uuid[0] = '\0'; + } } else { zerr(gettext("Zone %s failed to verify"), zone); } @@ -6275,6 +6777,7 @@ end_func(cmd_t *cmd) int err, arg, res1, res2, res3; uint64_t swap_limit; uint64_t locked_limit; + uint64_t phys_limit; uint64_t proc_cap; assert(cmd != NULL); @@ -6578,8 +7081,8 @@ end_func(cmd_t *cmd) break; case RT_MCAP: /* Make sure everything was filled in. */ - res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ? - Z_ERR : Z_OK; + res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, + &phys_limit); res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit); res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, @@ -6595,11 +7098,6 @@ end_func(cmd_t *cmd) /* if phys & locked are both set, verify locked <= phys */ if (res1 == Z_OK && res3 == Z_OK) { - uint64_t phys_limit; - char *endp; - - phys_limit = strtoull( - in_progress_mcaptab.zone_physmem_cap, &endp, 10); if (phys_limit < locked_limit) { zerr(gettext("The %s cap must be less than or " "equal to the %s cap."), @@ -6611,23 +7109,6 @@ end_func(cmd_t *cmd) } err = Z_OK; - if (res1 == Z_OK) { - /* - * We could be ending from either an add operation - * or a select operation. Since all of the properties - * within this resource are optional, we always use - * modify on the mcap entry. zonecfg_modify_mcap() - * will handle both adding and modifying a memory cap. - */ - err = zonecfg_modify_mcap(handle, &in_progress_mcaptab); - } else if (end_op == CMD_SELECT) { - /* - * If we're ending from a select and the physical - * memory cap is empty then the user could have cleared - * the physical cap value, so try to delete the entry. - */ - (void) zonecfg_delete_mcap(handle); - } break; case RT_ADMIN: /* First make sure everything was filled in. */ @@ -7176,8 +7657,10 @@ get_execbasename(char *execfullname) int main(int argc, char *argv[]) { - int err, arg; + int err, arg, uflag = 0, zflag = 0; struct stat st; + uuid_t uuidin; + char zonename[ZONENAME_MAX + 1]; /* This must be before anything goes to stdout. */ setbuf(stdout, NULL); @@ -7204,7 +7687,7 @@ main(int argc, char *argv[]) exit(Z_OK); } - while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) { + while ((arg = getopt(argc, argv, "?f:R:z:u:")) != EOF) { switch (arg) { case '?': if (optopt == '?') @@ -7231,6 +7714,21 @@ main(int argc, char *argv[]) } zonecfg_set_root(optarg); break; + case 'u': + if (uuid_parse((char *)optarg, uuidin) == -1) + return (Z_INVALID_PROPERTY); + + if (zonecfg_get_name_by_uuid(uuidin, zonename, + ZONENAME_MAX) != Z_OK) { + zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE); + usage(B_FALSE, HELP_SYNTAX); + exit(Z_USAGE); + } + + (void) strlcpy(zone, zonename, sizeof (zone)); + (void) strlcpy(revert_zone, zonename, sizeof (zone)); + uflag = 1; + break; case 'z': if (strcmp(optarg, GLOBAL_ZONENAME) == 0) { global_zone = B_TRUE; @@ -7241,6 +7739,7 @@ main(int argc, char *argv[]) } (void) strlcpy(zone, optarg, sizeof (zone)); (void) strlcpy(revert_zone, optarg, sizeof (zone)); + zflag = 1; break; default: usage(B_FALSE, HELP_USAGE); @@ -7248,7 +7747,7 @@ main(int argc, char *argv[]) } } - if (optind > argc || strcmp(zone, "") == 0) { + if (optind > argc || strcmp(zone, "") == 0 || (uflag && zflag)) { usage(B_FALSE, HELP_USAGE); exit(Z_USAGE); } diff --git a/usr/src/cmd/zonecfg/zonecfg.h b/usr/src/cmd/zonecfg/zonecfg.h index d8f8b14ce8..f8c78437ad 100644 --- a/usr/src/cmd/zonecfg/zonecfg.h +++ b/usr/src/cmd/zonecfg/zonecfg.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #ifndef _ZONECFG_H @@ -90,9 +91,11 @@ extern "C" { #define RT_ADMIN 26 #define RT_FS_ALLOWED 27 #define RT_MAXPROCS 28 /* really a rctl alias property, but for info */ +#define RT_ZFSPRI 29 /* really a rctl alias property, but for info */ +#define RT_UUID 30 /* really a property, but for info */ #define RT_MIN RT_UNKNOWN -#define RT_MAX RT_MAXPROCS +#define RT_MAX RT_UUID /* property types: increment PT_MAX when expanding this list */ #define PT_UNKNOWN 0 @@ -137,9 +140,15 @@ extern "C" { #define PT_FS_ALLOWED 39 #define PT_MAXPROCS 40 #define PT_ALLOWED_ADDRESS 41 +#define PT_ZFSPRI 42 +#define PT_MAC 43 +#define PT_VLANID 44 +#define PT_GNIC 45 +#define PT_NPROP 46 +#define PT_UUID 47 #define PT_MIN PT_UNKNOWN -#define PT_MAX PT_ALLOWED_ADDRESS +#define PT_MAX PT_UUID #define MAX_EQ_PROP_PAIRS 3 diff --git a/usr/src/cmd/zonecfg/zonecfg_grammar.y b/usr/src/cmd/zonecfg/zonecfg_grammar.y index d7f11b6a46..13a17876b7 100644 --- a/usr/src/cmd/zonecfg/zonecfg_grammar.y +++ b/usr/src/cmd/zonecfg/zonecfg_grammar.y @@ -22,6 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013, Joyent Inc. All rights reserved. */ /* @@ -136,6 +137,7 @@ complex_piece_func(int cp_type, const char *str, complex_property_ptr_t cp_next) %token OPEN_PAREN CLOSE_PAREN COMMA DATASET LIMITPRIV BOOTARGS BRAND PSET PCAP %token MCAP NCPUS IMPORTANCE SHARES MAXLWPS MAXSHMMEM MAXSHMIDS MAXMSGIDS %token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER ADMIN USER AUTHS MAXPROCS +%token ZFSPRI MAC VLANID GNIC NPROP UUID %type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET property_value OPEN_PAREN CLOSE_PAREN COMMA simple_prop_val @@ -145,7 +147,7 @@ complex_piece_func(int cp_type, const char *str, complex_property_ptr_t cp_next) %type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME MATCH ZONENAME ZONEPATH AUTOBOOT POOL LIMITPRIV BOOTARGS VALUE PRIV LIMIT ACTION BRAND SCHED IPTYPE DEFROUTER HOSTID USER AUTHS FS_ALLOWED - ALLOWED_ADDRESS + ALLOWED_ADDRESS MAC VLANID GNIC NPROP UUID %type <cmd> command %type <cmd> add_command ADD %type <cmd> cancel_command CANCEL @@ -650,6 +652,24 @@ info_command: INFO $$->cmd_res_type = RT_FS_ALLOWED; $$->cmd_prop_nv_pairs = 0; } + | INFO UUID + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd_handler = &info_func; + $$->cmd_res_type = RT_UUID; + $$->cmd_prop_nv_pairs = 0; + } + | INFO ZFSPRI + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd_handler = &info_func; + $$->cmd_res_type = RT_ZFSPRI; + $$->cmd_prop_nv_pairs = 0; + } | INFO resource_type property_name EQUAL property_value { if (($$ = alloc_cmd()) == NULL) @@ -734,6 +754,19 @@ remove_command: REMOVE $$->cmd_prop_name[0] = $2; $$->cmd_property_ptr[0] = &property[0]; } + | REMOVE TOKEN property_name property_value + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd_handler = &remove_func; + $$->cmd_argc = 1; + $$->cmd_argv[0] = claim_token($2); + $$->cmd_argv[1] = NULL; + $$->cmd_prop_nv_pairs = 1; + $$->cmd_prop_name[0] = $3; + $$->cmd_property_ptr[0] = &property[0]; + } | REMOVE resource_type property_name EQUAL property_value { if (($$ = alloc_cmd()) == NULL) @@ -745,6 +778,20 @@ remove_command: REMOVE $$->cmd_prop_name[0] = $3; $$->cmd_property_ptr[0] = &property[0]; } + | REMOVE TOKEN resource_type property_name EQUAL property_value + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd_handler = &remove_func; + $$->cmd_res_type = $3; + $$->cmd_argc = 1; + $$->cmd_argv[0] = claim_token($2); + $$->cmd_argv[1] = NULL; + $$->cmd_prop_nv_pairs = 1; + $$->cmd_prop_name[0] = $4; + $$->cmd_property_ptr[0] = &property[0]; + } | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value { if (($$ = alloc_cmd()) == NULL) @@ -758,6 +805,22 @@ remove_command: REMOVE $$->cmd_prop_name[1] = $6; $$->cmd_property_ptr[1] = &property[1]; } + | REMOVE TOKEN resource_type property_name EQUAL property_value property_name EQUAL property_value + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd_handler = &remove_func; + $$->cmd_res_type = $3; + $$->cmd_argc = 1; + $$->cmd_argv[0] = claim_token($2); + $$->cmd_argv[1] = NULL; + $$->cmd_prop_nv_pairs = 2; + $$->cmd_prop_name[0] = $4; + $$->cmd_property_ptr[0] = &property[0]; + $$->cmd_prop_name[1] = $7; + $$->cmd_property_ptr[1] = &property[1]; + } | REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value { if (($$ = alloc_cmd()) == NULL) @@ -773,6 +836,24 @@ remove_command: REMOVE $$->cmd_prop_name[2] = $9; $$->cmd_property_ptr[2] = &property[2]; } + | REMOVE TOKEN resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd_handler = &remove_func; + $$->cmd_res_type = $3; + $$->cmd_argc = 1; + $$->cmd_argv[0] = claim_token($2); + $$->cmd_argv[1] = NULL; + $$->cmd_prop_nv_pairs = 3; + $$->cmd_prop_name[0] = $4; + $$->cmd_property_ptr[0] = &property[0]; + $$->cmd_prop_name[1] = $7; + $$->cmd_property_ptr[1] = &property[1]; + $$->cmd_prop_name[2] = $10; + $$->cmd_property_ptr[2] = &property[2]; + } revert_command: REVERT { @@ -976,6 +1057,10 @@ property_name: SPECIAL { $$ = PT_SPECIAL; } | ALLOWED_ADDRESS { $$ = PT_ALLOWED_ADDRESS; } | PHYSICAL { $$ = PT_PHYSICAL; } | DEFROUTER { $$ = PT_DEFROUTER; } + | MAC { $$ = PT_MAC; } + | VLANID { $$ = PT_VLANID; } + | GNIC { $$ = PT_GNIC; } + | NPROP { $$ = PT_NPROP; } | NAME { $$ = PT_NAME; } | VALUE { $$ = PT_VALUE; } | MATCH { $$ = PT_MATCH; } @@ -999,6 +1084,8 @@ property_name: SPECIAL { $$ = PT_SPECIAL; } | USER { $$ = PT_USER; } | AUTHS { $$ = PT_AUTHS; } | FS_ALLOWED { $$ = PT_FS_ALLOWED; } + | UUID { $$ = PT_UUID; } + | ZFSPRI { $$ = PT_ZFSPRI; } /* * The grammar builds data structures from the bottom up. Thus various diff --git a/usr/src/cmd/zonecfg/zonecfg_lex.l b/usr/src/cmd/zonecfg/zonecfg_lex.l index 6a0b577b75..328a75c922 100644 --- a/usr/src/cmd/zonecfg/zonecfg_lex.l +++ b/usr/src/cmd/zonecfg/zonecfg_lex.l @@ -22,6 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <assert.h> @@ -57,10 +58,11 @@ extern void yyerror(char *s); static char *create_token(char *s); %} -%a 7000 +%a 8000 %p 5000 %e 2000 %n 1000 +%o 13000 %{ /* @@ -236,6 +238,18 @@ static char *create_token(char *s); <TSTATE>defrouter { return DEFROUTER; } <CSTATE>defrouter { return DEFROUTER; } +<TSTATE>mac-addr { return MAC; } +<CSTATE>mac-addr { return MAC; } + +<TSTATE>vlan-id { return VLANID; } +<CSTATE>vlan-id { return VLANID; } + +<TSTATE>global-nic { return GNIC; } +<CSTATE>global-nic { return GNIC; } + +<TSTATE>property { return NPROP; } +<CSTATE>property { return NPROP; } + <TSTATE>dir { return DIR; } <CSTATE>dir { return DIR; } @@ -308,6 +322,12 @@ static char *create_token(char *s); <TSTATE>fs-allowed { return FS_ALLOWED; } <CSTATE>fs-allowed { return FS_ALLOWED; } +<TSTATE>uuid { return UUID; } +<CSTATE>uuid { return UUID; } + +<TSTATE>zfs-io-priority { return ZFSPRI; } +<CSTATE>zfs-io-priority { return ZFSPRI; } + <TSTATE>= { return EQUAL; } <LSTATE>= { return EQUAL; } <CSTATE>= { return EQUAL; } @@ -357,6 +377,13 @@ static char *create_token(char *s); return TOKEN; } +<CSTATE>\"[^\"\n]*[\"\n] { + yylval.strval = create_token(yytext + 1); + if (yylval.strval[yyleng - 2] == '"') + yylval.strval[yyleng - 2] = 0; + return TOKEN; + } + <TSTATE>\"[^\"\n]*[\"\n] { yylval.strval = create_token(yytext + 1); if (yylval.strval[yyleng - 2] == '"') diff --git a/usr/src/cmd/zonename/Makefile b/usr/src/cmd/zonename/Makefile index 566e893a67..3a51952455 100644 --- a/usr/src/cmd/zonename/Makefile +++ b/usr/src/cmd/zonename/Makefile @@ -28,8 +28,10 @@ # PROG= zonename +OBJS= zonename.o include ../Makefile.cmd +include ../Makefile.ctf LDLIBS += -lzonecfg @@ -37,6 +39,10 @@ LDLIBS += -lzonecfg all: $(PROG) +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + install: all $(ROOTSBINPROG) $(RM) $(ROOTPROG) $(SYMLINK) ../../sbin/$(PROG) $(ROOTPROG) @@ -44,6 +50,10 @@ install: all $(ROOTSBINPROG) check: $(PROG).c $(CSTYLE) -pP $(PROG).c +%.o: %.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + clean: lint: lint_PROG diff --git a/usr/src/cmd/zonestat/zonestatd/zonestatd.c b/usr/src/cmd/zonestat/zonestatd/zonestatd.c index b764551131..6c293bcc0e 100644 --- a/usr/src/cmd/zonestat/zonestatd/zonestatd.c +++ b/usr/src/cmd/zonestat/zonestatd/zonestatd.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #include <alloca.h> #include <assert.h> @@ -2190,7 +2191,7 @@ zsd_get_zone_rctl_usage(char *name) return (rctlblk_get_value(rblk)); } -#define ZSD_NUM_RCTL_VALS 19 +#define ZSD_NUM_RCTL_VALS 20 /* * Fetch the limit information for a zone. This uses zone_enter() as the @@ -2237,12 +2238,6 @@ zsd_get_zone_caps(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t *cpu_shares, *msgids = 0; *lofi = 0; - /* Get the ram cap first since it is a zone attr */ - ret = zone_getattr(zone->zsz_id, ZONE_ATTR_PHYS_MCAP, - ram_cap, sizeof (*ram_cap)); - if (ret < 0 || *ram_cap == 0) - *ram_cap = ZS_LIMIT_NONE; - /* Get the zone's default scheduling class */ ret = zone_getattr(zone->zsz_id, ZONE_ATTR_SCHED_CLASS, class, sizeof (class)); @@ -2298,6 +2293,7 @@ zsd_get_zone_caps(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t *cpu_shares, vals[i++] = zsd_get_zone_rctl_usage("zone.max-msg-ids"); vals[i++] = zsd_get_zone_rctl_limit("zone.max-lofi"); vals[i++] = zsd_get_zone_rctl_usage("zone.max-lofi"); + vals[i++] = zsd_get_zone_rctl_usage("zone.max-physical-memory"); if (write(p[1], vals, ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) != ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) { @@ -2342,6 +2338,7 @@ zsd_get_zone_caps(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t *cpu_shares, *msgids = vals[i++]; *lofi_cap = vals[i++]; *lofi = vals[i++]; + *ram_cap = vals[i++]; /* Interpret maximum values as no cap */ if (*cpu_cap == UINT32_MAX || *cpu_cap == 0) diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c index 982057d1b5..521cf5ec15 100644 --- a/usr/src/cmd/zpool/zpool_main.c +++ b/usr/src/cmd/zpool/zpool_main.c @@ -25,6 +25,7 @@ * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2012 by Frederik Wessels. All rights reserved. * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved. + * Copyright (c) 2013 Joyent, Inc. All rights reserved. */ #include <assert.h> |