[108350] trunk/dports/net/openssh/files/apple-keychain.patch

cal at macports.org cal at macports.org
Sat Jul 20 09:53:43 PDT 2013


Revision: 108350
          https://trac.macports.org/changeset/108350
Author:   cal at macports.org
Date:     2013-07-20 09:53:43 -0700 (Sat, 20 Jul 2013)
Log Message:
-----------
openssh: delete unreferenced patchfile

Removed Paths:
-------------
    trunk/dports/net/openssh/files/apple-keychain.patch

Deleted: trunk/dports/net/openssh/files/apple-keychain.patch
===================================================================
--- trunk/dports/net/openssh/files/apple-keychain.patch	2013-07-20 16:53:18 UTC (rev 108349)
+++ trunk/dports/net/openssh/files/apple-keychain.patch	2013-07-20 16:53:43 UTC (rev 108350)
@@ -1,2220 +0,0 @@
-From 94e42cad73ce6c03abb842a905824586313eabc6 Mon Sep 17 00:00:00 2001
-From: Lassi Tuura <lat at cern.ch>
-Date: Wed, 21 Sep 2011 19:35:54 +0200
-Subject: [PATCH 2/2] Apple keychain integration + other changes.
-
----
- Makefile.in   |   18 +-
- audit-bsm.c   |    7 +-
- auth-pam.c    |    5 +-
- auth.c        |    2 +-
- authfd.c      |   23 ++
- authfd.h      |    3 +
- config.h.in   |   12 +
- configure.ac  |   30 +++
- groupaccess.c |   59 +++++-
- groupaccess.h |    2 +-
- keychain.c    |  694 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- keychain.h    |   45 ++++
- readconf.c    |   20 ++-
- readconf.h    |    4 +
- scp.1         |    4 +-
- scp.c         |  148 ++++++++++++
- servconf.c    |    6 +-
- session.c     |    4 +
- ssh-add.0     |   11 +-
- ssh-add.1     |    8 +-
- ssh-add.c     |   61 ++++-
- ssh-agent.c   |  140 ++++++++++++
- ssh-keysign.8 |    3 +
- sshconnect1.c |    5 +
- sshconnect2.c |    5 +
- sshd.0        |    4 +-
- sshd.8        |    3 -
- sshd.c        |   12 +-
- sshd_config   |   12 +-
- sshd_config.0 |    4 +-
- sshd_config.5 |    4 +-
- 31 files changed, 1301 insertions(+), 57 deletions(-)
- create mode 100644 keychain.c
- create mode 100644 keychain.h
-
-diff --git Makefile.in Makefile.in
-index e479a44..65538db 100644
---- Makefile.in
-+++ Makefile.in
-@@ -56,6 +56,7 @@ SED=@SED@
- ENT=@ENT@
- XAUTH_PATH=@XAUTH_PATH@
- LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
-+KEYCHAIN_LDFLAGS=@KEYCHAIN_LDFLAGS@
- EXEEXT=@EXEEXT@
- MANFMT=@MANFMT@
- 
-@@ -93,6 +94,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
- 	roaming_common.o roaming_serv.o \
- 	sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
- 
-+KEYCHAINOBJS=keychain.o
-+
- MANPAGES	= moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
- MANPAGES_IN	= moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
- MANTYPE		= @MANTYPE@
-@@ -125,6 +128,7 @@ all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
- $(LIBSSH_OBJS): Makefile.in config.h
- $(SSHOBJS): Makefile.in config.h
- $(SSHDOBJS): Makefile.in config.h
-+$(KEYCHAINOBJS): Makefile.in config.h
- 
- .c.o:
- 	$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
-@@ -138,8 +142,8 @@ libssh.a: $(LIBSSH_OBJS)
- 	$(AR) rv $@ $(LIBSSH_OBJS)
- 	$(RANLIB) $@
- 
--ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
--	$(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
-+ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(KEYCHAINOBJS)
-+	$(LD) -o $@ $(SSHOBJS) $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
- 
- sshd$(EXEEXT): libssh.a	$(LIBCOMPAT) $(SSHDOBJS)
- 	$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
-@@ -147,11 +151,11 @@ sshd$(EXEEXT): libssh.a	$(LIBCOMPAT) $(SSHDOBJS)
- scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
- 	$(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
- 
--ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
--	$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-+ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(KEYCHAINOBJS)
-+	$(LD) -o $@ ssh-add.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
- 
--ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
--	$(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-+ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o $(KEYCHAINOBJS)
-+	$(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
- 
- ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
- 	$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-@@ -255,7 +259,7 @@ install-files:
- 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
- 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
- 	$(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
--	$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
-+	$(INSTALL) -m 0711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
- 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
- 	$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
- 	$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
-diff --git audit-bsm.c audit-bsm.c
-index f196d4f..2899ef5 100644
---- audit-bsm.c
-+++ audit-bsm.c
-@@ -194,7 +194,12 @@ bsm_audit_record(int typ, char *string, au_event_t event_no)
- 	pid_t		pid = getpid();
- 	AuditInfoTermID	tid = ssh_bsm_tid;
- 
--	if (the_authctxt != NULL && the_authctxt->valid) {
-+	if (the_authctxt == NULL) {
-+		error("BSM audit: audit record internal error (NULL ctxt)");
-+		abort();
-+	}
-+	
-+	if (the_authctxt->valid) {
- 		uid = the_authctxt->pw->pw_uid;
- 		gid = the_authctxt->pw->pw_gid;
- 	}
-diff --git auth-pam.c auth-pam.c
-index 675006e..a195899 100644
---- auth-pam.c
-+++ auth-pam.c
-@@ -793,10 +793,11 @@ sshpam_query(void *ctx, char **name, char **info,
- 				xfree(msg);
- 				return (0);
- 			}
--			error("PAM: %s for %s%.100s from %.100s", msg,
-+			error("PAM: %s for %s%.100s from %.100s via %s", msg,
- 			    sshpam_authctxt->valid ? "" : "illegal user ",
- 			    sshpam_authctxt->user,
--			    get_remote_name_or_ip(utmp_len, options.use_dns));
-+			    get_remote_name_or_ip(utmp_len, options.use_dns),
-+			    get_local_ipaddr(packet_get_connection_in()));
- 			/* FALLTHROUGH */
- 		default:
- 			*num = 0;
-diff --git auth.c auth.c
-index cd95da9..94fa21f 100644
---- auth.c
-+++ auth.c
-@@ -209,7 +209,7 @@ allowed_user(struct passwd * pw)
- 	}
- 	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) {
-+		if (ga_init(pw) == 0) {
- 			logit("User %.100s from %.100s not allowed because "
- 			    "not in any group", pw->pw_name, hostname);
- 			return 0;
-diff --git authfd.c authfd.c
-index f037e83..c25b157 100644
---- authfd.c
-+++ authfd.c
-@@ -689,6 +689,29 @@ ssh_remove_all_identities(AuthenticationConnection *auth, int version)
- 	return decode_reply(type);
- }
- 
-+/*
-+ * Adds identities using passphrases stored in the keychain.  This call is not
-+ * meant to be used by normal applications.
-+ */
-+
-+int
-+ssh_add_from_keychain(AuthenticationConnection *auth)
-+{
-+	Buffer msg;
-+	int type;
-+
-+	buffer_init(&msg);
-+	buffer_put_char(&msg, SSH_AGENTC_ADD_FROM_KEYCHAIN);
-+
-+	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)
- {
-diff --git authfd.h authfd.h
-index 2582a27..7b786fe 100644
---- authfd.h
-+++ authfd.h
-@@ -49,6 +49,9 @@
- #define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
- #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
- 
-+/* keychain */
-+#define SSH_AGENTC_ADD_FROM_KEYCHAIN		27
-+
- #define	SSH_AGENT_CONSTRAIN_LIFETIME		1
- #define	SSH_AGENT_CONSTRAIN_CONFIRM		2
- 
-diff --git config.h.in config.h.in
-index baf0011..431720a 100644
---- config.h.in
-+++ config.h.in
-@@ -71,6 +71,18 @@
- /* Define if your snprintf is busted */
- #undef BROKEN_SNPRINTF
- 
-+/* platform uses an in-memory credentials cache */
-+#undef USE_CCAPI
-+
-+/* platform has a Security Authorization Session API */
-+#undef USE_SECURITY_SESSION_API
-+
-+/* Define to 1 if you have the `copyfile' function. */
-+#undef HAVE_COPYFILE
-+
-+/* Define to 1 if you have the <copyfile.h> header file. */
-+#undef HAVE_COPYFILE_H
-+
- /* tcgetattr with ICANON may hang */
- #undef BROKEN_TCGETATTR_ICANON
- 
-diff --git configure.ac configure.ac
-index 8cc7ce9..bd8fdaa 100644
---- configure.ac
-+++ configure.ac
-@@ -4197,10 +4197,40 @@ if test ! -z "$blibpath" ; then
- 	AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile])
- fi
- 
-+dnl Keychain support
-+AC_ARG_WITH(keychain,
-+	[  --with-keychain=apple   Use Mac OS X Keychain],
-+	[
-+		case "$withval" in
-+		apple|no)
-+			KEYCHAIN=$withval
-+			;;
-+		*)
-+			AC_MSG_ERROR(invalid keychain type: $withval)
-+			;;
-+		esac
-+	]
-+)
-+if test ! -z "$KEYCHAIN" -a "$KEYCHAIN" != "no"; then
-+	case "$KEYCHAIN" in
-+	apple)
-+		AC_CHECK_HEADERS(Security/Security.h, [
-+				CPPFLAGS="$CPPFLAGS -D__APPLE_KEYCHAIN__"
-+				KEYCHAIN_LDFLAGS="-framework Security -framework CoreFoundation"
-+				AC_SUBST(KEYCHAIN_LDFLAGS)
-+				],
-+				AC_MSG_WARN([Security framework not found. Disabling Mac OS X Keychain support.]))
-+		;;
-+	esac
-+fi
-+
- dnl Adding -Werror to CFLAGS early prevents configure tests from running.
- dnl Add now.
- CFLAGS="$CFLAGS $werror_flags"
- 
-+AC_CHECK_FUNCS(copyfile)
-+AC_CHECK_HEADERS(copyfile.h)
-+
- if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
- 	TEST_SSH_IPV6=no
- else
-diff --git groupaccess.c groupaccess.c
-index 2381aeb..2b5c600 100644
---- groupaccess.c
-+++ groupaccess.c
-@@ -33,38 +33,67 @@
- #include <stdarg.h>
- #include <string.h>
- 
-+#ifdef __APPLE_MEMBERSHIP__
-+#include <membership.h>
-+#endif
-+
- #include "xmalloc.h"
- #include "groupaccess.h"
- #include "match.h"
- #include "log.h"
- 
-+#ifdef __APPLE_MEMBERSHIP__
-+// SPI for 5235093
-+int32_t getgrouplist_2(const char *, gid_t, gid_t **);
-+int32_t getgroupcount(const char *, gid_t);
-+#endif
-+
- static int ngroups;
- static char **groups_byname;
-+#ifdef __APPLE_MEMBERSHIP__
-+uuid_t u_uuid;
-+#endif
- 
- /*
-  * 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)
-+ga_init(struct passwd *pw)
- {
--	gid_t *groups_bygid;
-+	gid_t *groups_bygid = NULL;
- 	int i, j;
- 	struct group *gr;
- 
-+#ifdef __APPLE_MEMBERSHIP__
-+	if (0 != mbr_uid_to_uuid(pw->pw_uid, u_uuid))
-+		return 0;
-+#endif
-+
- 	if (ngroups > 0)
- 		ga_free();
- 
-+#ifndef __APPLE_MEMBERSHIP__
- 	ngroups = NGROUPS_MAX;
- #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
- 	ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX));
--#endif
--
-+#endif	
- 	groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid));
-+#else
-+	if (-1 == (ngroups = getgrouplist_2(pw->pw_name, pw->pw_gid,
-+	    &groups_bygid))) {
-+		logit("getgrouplist_2 failed");
-+		return 0;
-+	}
-+#endif
- 	groups_byname = xcalloc(ngroups, sizeof(*groups_byname));
--
--	if (getgrouplist(user, base, groups_bygid, &ngroups) == -1)
--		logit("getgrouplist: groups list too small");
-+#ifndef __APPLE_MEMBERSHIP__
-+	if (getgrouplist(pw->pw_name, pw->pw_gid, groups_bygid, &ngroups) == -1) {
-+	    logit("getgrouplist: groups list too small");
-+		xfree(groups_bygid);
-+		return 0;
-+	}
-+#endif
- 	for (i = 0, j = 0; i < ngroups; i++)
- 		if ((gr = getgrgid(groups_bygid[i])) != NULL)
- 			groups_byname[j++] = xstrdup(gr->gr_name);
-@@ -75,16 +104,32 @@ ga_init(const char *user, gid_t base)
- /*
-  * Return 1 if one of user's groups is contained in groups.
-  * Return 0 otherwise.  Use match_pattern() for string comparison.
-+ * Use mbr_check_membership() for membership checking on Mac OS X.
-  */
- int
- ga_match(char * const *groups, int n)
- {
-+#ifdef __APPLE_MEMBERSHIP__
-+	int i, ismember = 0;
-+	uuid_t g_uuid;
-+	struct group *grp;
-+
-+	for (i = 0; i < n; i++) {
-+		if ((grp = getgrnam(groups[i])) == NULL ||
-+		   (mbr_gid_to_uuid(grp->gr_gid, g_uuid) != 0) ||
-+		   (mbr_check_membership(u_uuid, g_uuid, &ismember) != 0))
-+			return 0;
-+		if (ismember)
-+			return 1;
-+	}
-+#else
- 	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;
-+#endif
- 	return 0;
- }
- 
-diff --git groupaccess.h groupaccess.h
-index 000578e..ddea117 100644
---- groupaccess.h
-+++ groupaccess.h
-@@ -27,7 +27,7 @@
- #ifndef GROUPACCESS_H
- #define GROUPACCESS_H
- 
--int	 ga_init(const char *, gid_t);
-+int	 ga_init(struct passwd *);
- int	 ga_match(char * const *, int);
- int	 ga_match_pattern_list(const char *);
- void	 ga_free(void);
-diff --git keychain.c keychain.c
-new file mode 100644
-index 0000000..a6d5855
---- /dev/null
-+++ keychain.c
-@@ -0,0 +1,694 @@
-+/*
-+ * Copyright (c) 2007 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_BSD_LICENSE_HEADER_START@
-+ * 
-+ * 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.  Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
-+ * 
-+ * @APPLE_BSD_LICENSE_HEADER_END@
-+ */
-+
-+#include "includes.h"
-+
-+#include <stdio.h>
-+#include <string.h>
-+
-+#include "xmalloc.h"
-+#include "key.h"
-+#include "authfd.h"
-+#include "authfile.h"
-+
-+#if defined(__APPLE_KEYCHAIN__)
-+
-+#include <CoreFoundation/CoreFoundation.h>
-+#include <Security/Security.h>
-+
-+/* Our Security/SecPassword.h is not yet API, so I will define the constants that I am using here. */
-+int kSecPasswordGet     = 1<<0;  // Get password from keychain or user
-+int kSecPasswordSet     = 1<<1;  // Set password (passed in if kSecPasswordGet not set, otherwise from user)
-+int kSecPasswordFail    = 1<<2;  // Wrong password (ignore item in keychain and flag error)
-+OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef);
-+OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data);
-+OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef);
-+
-+#endif
-+
-+/*
-+ * Platform-specific helper functions.
-+ */
-+
-+#if defined(__APPLE_KEYCHAIN__)
-+
-+static int get_boolean_preference(const char *key, int default_value,
-+    int foreground)
-+{
-+	int value = default_value;
-+	CFStringRef keyRef = NULL;
-+	CFPropertyListRef valueRef = NULL;
-+
-+	keyRef = CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
-+	if (keyRef != NULL)
-+		valueRef = CFPreferencesCopyAppValue(keyRef,
-+		    CFSTR("org.openbsd.openssh"));
-+	if (valueRef != NULL)
-+		if (CFGetTypeID(valueRef) == CFBooleanGetTypeID())
-+			value = CFBooleanGetValue(valueRef);
-+		else if (foreground)
-+			fprintf(stderr, "Ignoring nonboolean %s preference.\n", key);
-+
-+	if (keyRef)
-+		CFRelease(keyRef);
-+	if (valueRef)
-+		CFRelease(valueRef);
-+
-+	return value;
-+}
-+
-+#endif
-+
-+/*
-+ * Store the passphrase for a given identity in the keychain.
-+ */
-+void
-+store_in_keychain(const char *filename, const char *passphrase)
-+{
-+
-+#if defined(__APPLE_KEYCHAIN__)
-+
-+	/*
-+	 * store_in_keychain
-+	 * Mac OS X implementation
-+	 */
-+
-+	CFStringRef cfstr_relative_filename = NULL;
-+	CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
-+	CFStringRef cfstr_filename = NULL;
-+	CFDataRef cfdata_filename = NULL;
-+	CFIndex filename_len;
-+	UInt8 *label = NULL;
-+	UInt8 *utf8_filename;
-+	OSStatus rv;
-+	SecKeychainItemRef itemRef = NULL;
-+	SecTrustedApplicationRef apps[] = {NULL, NULL, NULL};
-+	CFArrayRef trustedlist = NULL;
-+	SecAccessRef initialAccess = NULL;
-+
-+	/* Bail out if KeychainIntegration preference is -bool NO */
-+	if (get_boolean_preference("KeychainIntegration", 1, 1) == 0) {
-+		fprintf(stderr, "Keychain integration is disabled.\n");
-+		goto err;
-+	}
-+
-+	/* Interpret filename with the correct encoding. */
-+	if ((cfstr_relative_filename =
-+	    CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
-+	    {
-+		fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
-+		goto err;
-+	}
-+	if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
-+	    cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
-+		fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
-+		goto err;
-+	}
-+	if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
-+	    NULL) {
-+		fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
-+		goto err;
-+	}
-+	if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
-+	    kCFURLPOSIXPathStyle)) == NULL) {
-+		fprintf(stderr, "CFURLCopyFileSystemPath failed\n");
-+		goto err;
-+	}
-+	if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
-+	    cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
-+		fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
-+		goto err;
-+	}
-+	filename_len = CFDataGetLength(cfdata_filename);
-+	if ((label = xmalloc(filename_len + 5)) == NULL) {
-+		fprintf(stderr, "xmalloc failed\n");
-+		goto err;
-+	}
-+	memcpy(label, "SSH: ", 5);
-+	utf8_filename = label + 5;
-+	CFDataGetBytes(cfdata_filename, CFRangeMake(0, filename_len),
-+	    utf8_filename);
-+
-+	/* Check if we already have this passphrase. */
-+	rv = SecKeychainFindGenericPassword(NULL, 3, "SSH", filename_len,
-+	    (char *)utf8_filename, NULL, NULL, &itemRef);
-+	if (rv == errSecItemNotFound) {
-+		/* Add a new keychain item. */
-+		SecKeychainAttribute attrs[] = {
-+			{kSecLabelItemAttr, filename_len + 5, label},
-+			{kSecServiceItemAttr, 3, "SSH"},
-+			{kSecAccountItemAttr, filename_len, utf8_filename}
-+		};
-+		SecKeychainAttributeList attrList =
-+		    {sizeof(attrs) / sizeof(attrs[0]), attrs};
-+		if (SecTrustedApplicationCreateFromPath("/usr/bin/ssh-agent",
-+		    &apps[0]) != noErr ||
-+		    SecTrustedApplicationCreateFromPath("/usr/bin/ssh-add",
-+		    &apps[1]) != noErr ||
-+		    SecTrustedApplicationCreateFromPath("/usr/bin/ssh",
-+		    &apps[2]) != noErr) {
-+			fprintf(stderr, "SecTrustedApplicationCreateFromPath failed\n");
-+			goto err;
-+		}
-+		if ((trustedlist = CFArrayCreate(NULL, (const void **)apps,
-+		    sizeof(apps) / sizeof(apps[0]), &kCFTypeArrayCallBacks)) ==
-+		    NULL) {
-+			fprintf(stderr, "CFArrayCreate failed\n");
-+			goto err;
-+		}
-+		if (SecAccessCreate(cfstr_filename, trustedlist,
-+		    &initialAccess) != noErr) {
-+			fprintf(stderr, "SecAccessCreate failed\n");
-+			goto err;
-+		}
-+		if (SecKeychainItemCreateFromContent(
-+		    kSecGenericPasswordItemClass, &attrList, strlen(passphrase),
-+		    passphrase, NULL, initialAccess, NULL) == noErr)
-+			fprintf(stderr, "Passphrase stored in keychain: %s\n", filename);
-+		else
-+			fprintf(stderr, "Could not create keychain item\n");
-+	} else if (rv == noErr) {
-+		/* Update an existing keychain item. */
-+		if (SecKeychainItemModifyAttributesAndData(itemRef, NULL,
-+		    strlen(passphrase), passphrase) == noErr)
-+			fprintf(stderr, "Passphrase updated in keychain: %s\n", filename);
-+		else
-+			fprintf(stderr, "Could not modify keychain item\n");
-+	} else
-+		fprintf(stderr, "Could not access keychain\n");
-+
-+err:	/* Clean up. */
-+	if (cfstr_relative_filename)
-+		CFRelease(cfstr_relative_filename);
-+	if (cfurl_relative_filename)
-+		CFRelease(cfurl_relative_filename);
-+	if (cfurl_filename)
-+		CFRelease(cfurl_filename);
-+	if (cfstr_filename)
-+		CFRelease(cfstr_filename);
-+	if (cfdata_filename)
-+		CFRelease(cfdata_filename);
-+	if (label)
-+		xfree(label);
-+	if (itemRef)
-+		CFRelease(itemRef);
-+	if (apps[0])
-+		CFRelease(apps[0]);
-+	if (apps[1])
-+		CFRelease(apps[1]);
-+	if (apps[2])
-+		CFRelease(apps[2]);
-+	if (trustedlist)
-+		CFRelease(trustedlist);
-+	if (initialAccess)
-+		CFRelease(initialAccess);
-+
-+#else
-+
-+	/*
-+	 * store_in_keychain
-+	 * no keychain implementation
-+	 */
-+
-+	fprintf(stderr, "Keychain is not available on this system\n");
-+
-+#endif
-+
-+}
-+
-+/*
-+ * Remove the passphrase for a given identity from the keychain.
-+ */
-+void
-+remove_from_keychain(const char *filename)
-+{
-+
-+#if defined(__APPLE_KEYCHAIN__)
-+
-+	/*
-+	 * remove_from_keychain
-+	 * Mac OS X implementation
-+	 */
-+
-+	CFStringRef cfstr_relative_filename = NULL;
-+	CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
-+	CFStringRef cfstr_filename = NULL;
-+	CFDataRef cfdata_filename = NULL;
-+	CFIndex filename_len;
-+	const UInt8 *utf8_filename;
-+	OSStatus rv;
-+	SecKeychainItemRef itemRef = NULL;
-+
-+	/* Bail out if KeychainIntegration preference is -bool NO */
-+	if (get_boolean_preference("KeychainIntegration", 1, 1) == 0) {
-+		fprintf(stderr, "Keychain integration is disabled.\n");
-+		goto err;
-+	}
-+
-+	/* Interpret filename with the correct encoding. */
-+	if ((cfstr_relative_filename =
-+	    CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
-+	    {
-+		fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
-+		goto err;
-+	}
-+	if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
-+	    cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
-+		fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
-+		goto err;
-+	}
-+	if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
-+	    NULL) {
-+		fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
-+		goto err;
-+	}
-+	if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
-+	    kCFURLPOSIXPathStyle)) == NULL) {
-+		fprintf(stderr, "CFURLCopyFileSystemPath failed\n");
-+		goto err;
-+	}
-+	if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
-+	    cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
-+		fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
-+		goto err;
-+	}
-+	filename_len = CFDataGetLength(cfdata_filename);
-+	utf8_filename = CFDataGetBytePtr(cfdata_filename);
-+
-+	/* Check if we already have this passphrase. */
-+	rv = SecKeychainFindGenericPassword(NULL, 3, "SSH", filename_len,
-+	    (const char *)utf8_filename, NULL, NULL, &itemRef);
-+	if (rv == noErr) {
-+		/* Remove the passphrase from the keychain. */
-+		if (SecKeychainItemDelete(itemRef) == noErr)
-+			fprintf(stderr, "Passphrase removed from keychain: %s\n", filename);
-+		else
-+			fprintf(stderr, "Could not remove keychain item\n");
-+	} else if (rv != errSecItemNotFound)
-+		fprintf(stderr, "Could not access keychain\n");
-+
-+err:	/* Clean up. */
-+	if (cfstr_relative_filename)
-+		CFRelease(cfstr_relative_filename);
-+	if (cfurl_relative_filename)
-+		CFRelease(cfurl_relative_filename);
-+	if (cfurl_filename)
-+		CFRelease(cfurl_filename);
-+	if (cfstr_filename)
-+		CFRelease(cfstr_filename);
-+	if (cfdata_filename)
-+		CFRelease(cfdata_filename);
-+	if (itemRef)
-+		CFRelease(itemRef);
-+
-+#else
-+
-+	/*
-+	 * remove_from_keychain
-+	 * no keychain implementation
-+	 */
-+
-+	fprintf(stderr, "Keychain is not available on this system\n");
-+
-+#endif
-+
-+}
-+
-+/*
-+ * Add identities to ssh-agent using passphrases stored in the keychain.
-+ * Returns zero on success and nonzero on failure.
-+ * add_identity is a callback into ssh-agent.  It takes a filename and a
-+ * passphrase, and attempts to add the identity to the agent.  It returns
-+ * zero on success and nonzero on failure.
-+ */
-+int
-+add_identities_using_keychain(int (*add_identity)(const char *, const char *))
-+{
-+
-+#if defined(__APPLE_KEYCHAIN__)
-+
-+	/*
-+	 * add_identities_using_keychain
-+	 * Mac OS X implementation
-+	 */
-+
-+	OSStatus rv;
-+	SecKeychainSearchRef searchRef;
-+	SecKeychainItemRef itemRef;
-+	UInt32 length;
-+	void *data;
-+	CFIndex maxsize;
-+
-+	/* Bail out if KeychainIntegration preference is -bool NO */
-+	if (get_boolean_preference("KeychainIntegration", 1, 0) == 0)
-+		return 0;
-+
-+	/* Search for SSH passphrases in the keychain */
-+	SecKeychainAttribute attrs[] = {
-+		{kSecServiceItemAttr, 3, "SSH"}
-+	};
-+	SecKeychainAttributeList attrList =
-+	    {sizeof(attrs) / sizeof(attrs[0]), attrs};
-+	if ((rv = SecKeychainSearchCreateFromAttributes(NULL,
-+	    kSecGenericPasswordItemClass, &attrList, &searchRef)) != noErr)
-+		return 0;
-+
-+	/* Iterate through the search results. */
-+	while ((rv = SecKeychainSearchCopyNext(searchRef, &itemRef)) == noErr) {
-+		UInt32 tag = kSecAccountItemAttr;
-+		UInt32 format = kSecFormatUnknown;
-+		SecKeychainAttributeInfo info = {1, &tag, &format};
-+		SecKeychainAttributeList *itemAttrList = NULL;
-+		CFStringRef cfstr_filename = NULL;
-+		char *filename = NULL;
-+		char *passphrase = NULL;
-+
-+		/* Retrieve filename and passphrase. */
-+		if ((rv = SecKeychainItemCopyAttributesAndData(itemRef, &info,
-+		    NULL, &itemAttrList, &length, &data)) != noErr)
-+			goto err;
-+		if (itemAttrList->count != 1)
-+			goto err;
-+		cfstr_filename = CFStringCreateWithBytes(NULL,
-+		    itemAttrList->attr->data, itemAttrList->attr->length,
-+		    kCFStringEncodingUTF8, true);
-+		maxsize = CFStringGetMaximumSizeOfFileSystemRepresentation(
-+		    cfstr_filename);
-+		if ((filename = xmalloc(maxsize)) == NULL)
-+			goto err;
-+		if (CFStringGetFileSystemRepresentation(cfstr_filename,
-+		    filename, maxsize) == false)
-+			goto err;
-+		if ((passphrase = xmalloc(length + 1)) == NULL)
-+			goto err;
-+		memcpy(passphrase, data, length);
-+		passphrase[length] = '\0';
-+
-+		/* Add the identity. */
-+		add_identity(filename, passphrase);
-+
-+err:		/* Clean up. */
-+		if (itemRef)
-+			CFRelease(itemRef);
-+		if (cfstr_filename)
-+			CFRelease(cfstr_filename);
-+		if (filename)
-+			xfree(filename);
-+		if (passphrase)
-+			xfree(passphrase);
-+		if (itemAttrList)
-+			SecKeychainItemFreeAttributesAndData(itemAttrList,
-+			    data);
-+	}
-+
-+	CFRelease(searchRef);
-+
-+	return 0;
-+
-+#else
-+
-+	/*
-+	 * add_identities_using_keychain
-+	 * no implementation
-+	 */
-+
-+	return 1;
-+
-+#endif
-+
-+}
-+
-+/*
-+ * Prompt the user for a key's passphrase.  The user will be offered the option
-+ * of storing the passphrase in their keychain.  Returns the passphrase
-+ * (which the caller is responsible for xfreeing), or NULL if this function
-+ * fails or is not implemented.  If this function is not implemented, ssh will
-+ * fall back on the standard read_passphrase function, and the user will need
-+ * to use ssh-add -K to add their keys to the keychain.
-+ */
-+char *
-+keychain_read_passphrase(const char *filename, int oAskPassGUI)
-+{
-+
-+#if defined(__APPLE_KEYCHAIN__)
-+
-+	/*
-+	 * keychain_read_passphrase
-+	 * Mac OS X implementation
-+	 */
-+
-+	CFStringRef cfstr_relative_filename = NULL;
-+	CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
-+	CFStringRef cfstr_filename = NULL;
-+	CFDataRef cfdata_filename = NULL;
-+	CFIndex filename_len;
-+	UInt8 *label = NULL;
-+	UInt8 *utf8_filename;
-+	SecPasswordRef passRef = NULL;
-+	SecTrustedApplicationRef apps[] = {NULL, NULL, NULL};
-+	CFArrayRef trustedlist = NULL;
-+	SecAccessRef initialAccess = NULL;
-+	CFURLRef path = NULL;
-+	CFStringRef pathFinal = NULL;
-+	CFURLRef bundle_url = NULL;
-+	CFBundleRef bundle = NULL;
-+	CFStringRef promptTemplate = NULL, prompt = NULL;
-+	UInt32 length;
-+	const void *data;
-+	AuthenticationConnection *ac = NULL;
-+	char *result = NULL;
-+
-+	/* Bail out if KeychainIntegration preference is -bool NO */
-+	if (get_boolean_preference("KeychainIntegration", 1, 1) == 0)
-+		goto err;
-+
-+	/* Bail out if the user set AskPassGUI preference to -bool NO */
-+	if (get_boolean_preference("AskPassGUI", 1, 1) == 0 || oAskPassGUI == 0)
-+		goto err;
-+
-+	/* Bail out if we can't communicate with ssh-agent */
-+	if ((ac = ssh_get_authentication_connection()) == NULL)
-+		goto err;
-+
-+	/* Interpret filename with the correct encoding. */
-+	if ((cfstr_relative_filename =
-+	    CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
-+	    {
-+		fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
-+		goto err;
-+	}
-+	if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
-+	    cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
-+		fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
-+		goto err;
-+	}
-+	if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
-+	    NULL) {
-+		fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
-+		goto err;
-+	}
-+	if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
-+	    kCFURLPOSIXPathStyle)) == NULL) {
-+		fprintf(stderr, "CFURLCopyFileSystemPath failed\n");
-+		goto err;
-+	}
-+	if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
-+	    cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
-+		fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
-+		goto err;
-+	}
-+	filename_len = CFDataGetLength(cfdata_filename);
-+	if ((label = xmalloc(filename_len + 5)) == NULL) {
-+		fprintf(stderr, "xmalloc failed\n");
-+		goto err;
-+	}
-+	memcpy(label, "SSH: ", 5);
-+	utf8_filename = label + 5;
-+	CFDataGetBytes(cfdata_filename, CFRangeMake(0, filename_len),
-+	    utf8_filename);
-+
-+	/* Build a SecPasswordRef. */
-+	SecKeychainAttribute searchAttrs[] = {
-+		{kSecServiceItemAttr, 3, "SSH"},
-+		{kSecAccountItemAttr, filename_len, utf8_filename}
-+	};
-+	SecKeychainAttributeList searchAttrList =
-+	    {sizeof(searchAttrs) / sizeof(searchAttrs[0]), searchAttrs};
-+	SecKeychainAttribute attrs[] = {
-+		{kSecLabelItemAttr, filename_len + 5, label},
-+		{kSecServiceItemAttr, 3, "SSH"},
-+		{kSecAccountItemAttr, filename_len, utf8_filename}
-+	};
-+	SecKeychainAttributeList attrList =
-+	    {sizeof(attrs) / sizeof(attrs[0]), attrs};
-+	if (SecGenericPasswordCreate(&searchAttrList, &attrList, &passRef) !=
-+	    noErr) {
-+		fprintf(stderr, "SecGenericPasswordCreate failed\n");
-+		goto err;
-+	}
-+	if (SecTrustedApplicationCreateFromPath("/usr/bin/ssh-agent", &apps[0])
-+	    != noErr ||
-+	    SecTrustedApplicationCreateFromPath("/usr/bin/ssh-add", &apps[1])
-+	    != noErr ||
-+	    SecTrustedApplicationCreateFromPath("/usr/bin/ssh", &apps[2])
-+	    != noErr) {
-+		fprintf(stderr, "SecTrustedApplicationCreateFromPath failed\n");
-+		goto err;
-+	}
-+	if ((trustedlist = CFArrayCreate(NULL, (const void **)apps,
-+	    sizeof(apps) / sizeof(apps[0]), &kCFTypeArrayCallBacks)) == NULL) {
-+		fprintf(stderr, "CFArrayCreate failed\n");
-+		goto err;
-+	}
-+	if (SecAccessCreate(cfstr_filename, trustedlist, &initialAccess)
-+	    != noErr) {
-+		fprintf(stderr, "SecAccessCreate failed\n");
-+		goto err;
-+	}
-+	if (SecPasswordSetInitialAccess(passRef, initialAccess) != noErr) {
-+		fprintf(stderr, "SecPasswordSetInitialAccess failed\n");
-+		goto err;
-+	}
-+
-+	/* Request the passphrase from the user. */
-+	if ((path = CFURLCreateFromFileSystemRepresentation(NULL,
-+	    (UInt8 *)filename, strlen(filename), false)) == NULL) {
-+		fprintf(stderr, "CFURLCreateFromFileSystemRepresentation failed\n");
-+		goto err;
-+	}
-+	if ((pathFinal = CFURLCopyLastPathComponent(path)) == NULL) {
-+		fprintf(stderr, "CFURLCopyLastPathComponent failed\n");
-+		goto err;
-+	}
-+	if (!((bundle_url = CFURLCreateWithFileSystemPath(NULL,
-+	    CFSTR("/System/Library/CoreServices/"), kCFURLPOSIXPathStyle, true))
-+	    != NULL && (bundle = CFBundleCreate(NULL, bundle_url)) != NULL &&
-+	    (promptTemplate = CFCopyLocalizedStringFromTableInBundle(
-+	    CFSTR("Enter your password for the SSH key \"%@\"."),
-+	    CFSTR("OpenSSH"), bundle, "Text of the dialog asking the user for"
-+	    "their passphrase.  The %@ will be replaced with the filename of a"
-+	    "specific key.")) != NULL) &&
-+	    (promptTemplate = CFStringCreateCopy(NULL,
-+	    CFSTR("Enter your password for the SSH key \"%@\"."))) == NULL) {
-+		fprintf(stderr, "CFStringCreateCopy failed\n");
-+		goto err;
-+	}
-+	if ((prompt = CFStringCreateWithFormat(NULL, NULL, promptTemplate,
-+	    pathFinal)) == NULL) {
-+		fprintf(stderr, "CFStringCreateWithFormat failed\n");
-+		goto err;
-+	}
-+	switch (SecPasswordAction(passRef, prompt,
-+	    kSecPasswordGet|kSecPasswordFail, &length, &data)) {
-+	case noErr:
-+		result = xmalloc(length + 1);
-+		memcpy(result, data, length);
-+		result[length] = '\0';
-+
-+		/* Save password in keychain if requested. */
-+		if (noErr != SecPasswordAction(passRef, CFSTR(""), kSecPasswordSet, &length, &data))
-+			fprintf(stderr, "Saving password to keychain failed\n");
-+
-+		/* Add password to agent. */
-+		char *comment = NULL;
-+		Key *private = key_load_private(filename, result, &comment);
-+		if (NULL == private)
-+			break;
-+		if (ssh_add_identity_constrained(ac, private, comment, 0, 0))
-+			fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
-+		else
-+			fprintf(stderr, "Could not add identity: %s\n", filename);
-+		xfree(comment);
-+		key_free(private);
-+		break;
-+	case errAuthorizationCanceled:
-+		result = xmalloc(1);
-+		*result = '\0';
-+		break;
-+	default:
-+		goto err;
-+	}
-+
-+err:	/* Clean up. */
-+	if (cfstr_relative_filename)
-+		CFRelease(cfstr_relative_filename);
-+	if (cfurl_relative_filename)
-+		CFRelease(cfurl_relative_filename);
-+	if (cfurl_filename)
-+		CFRelease(cfurl_filename);
-+	if (cfstr_filename)
-+		CFRelease(cfstr_filename);
-+	if (cfdata_filename)
-+		CFRelease(cfdata_filename);
-+	if (label)
-+		xfree(label);
-+	if (passRef)
-+		CFRelease(passRef);
-+	if (apps[0])
-+		CFRelease(apps[0]);
-+	if (apps[1])
-+		CFRelease(apps[1]);
-+	if (apps[2])
-+		CFRelease(apps[2]);
-+	if (trustedlist)
-+		CFRelease(trustedlist);
-+	if (initialAccess)
-+		CFRelease(initialAccess);
-+	if (path)
-+		CFRelease(path);
-+	if (pathFinal)
-+		CFRelease(pathFinal);
-+	if (bundle_url)
-+		CFRelease(bundle_url);
-+	if (bundle)
-+		CFRelease(bundle);
-+	if (promptTemplate)
-+		CFRelease(promptTemplate);
-+	if (prompt)
-+		CFRelease(prompt);
-+	if (ac)
-+		ssh_close_authentication_connection(ac);
-+
-+	return result;
-+
-+#else
-+
-+	/*
-+	 * keychain_read_passphrase
-+	 * no implementation
-+	 */
-+
-+	return NULL;
-+
-+#endif
-+
-+}
-diff --git keychain.h keychain.h
-new file mode 100644
-index 0000000..3ab1a6b
---- /dev/null
-+++ keychain.h
-@@ -0,0 +1,45 @@
-+/*
-+ * Copyright (c) 2007 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_BSD_LICENSE_HEADER_START@
-+ * 
-+ * 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.  Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
-+ * 
-+ * @APPLE_BSD_LICENSE_HEADER_END@
-+ */
-+
-+/*
-+ * KEYCHAIN indicates that keychain functionality is present.
-+ * KEYCHAIN_* indicates the implementation to use, and implies KEYCHAIN.
-+ */
-+#if defined(__APPLE_KEYCHAIN__)
-+#define KEYCHAIN
-+#endif
-+
-+void	 store_in_keychain(const char *filename, const char *passphrase);
-+void	 remove_from_keychain(const char *filename);
-+int	 add_identities_using_keychain(
-+	     int (*add_identity)(const char *, const char *));
-+char	*keychain_read_passphrase(const char *filename, int oAskPassGUI);
-diff --git readconf.c readconf.c
-index 60befde..0fe8fb1 100644
---- readconf.c
-+++ readconf.c
-@@ -137,6 +137,9 @@ typedef enum {
- 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
- 	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
- 	oKexAlgorithms, oIPQoS, oRequestTTY,
-+#ifdef __APPLE_KEYCHAIN__
-+	oAskPassGUI,
-+#endif
- 	oDeprecated, oUnsupported
- } OpCodes;
- 
-@@ -257,7 +260,9 @@ static struct {
- 	{ "kexalgorithms", oKexAlgorithms },
- 	{ "ipqos", oIPQoS },
- 	{ "requesttty", oRequestTTY },
--
-+#ifdef __APPLE_KEYCHAIN__
-+	{ "askpassgui", oAskPassGUI },
-+#endif
- 	{ NULL, oBadOption }
- };
- 
-@@ -1074,6 +1079,12 @@ parse_int:
- 			*intptr = value;
- 		break;
- 
-+#ifdef __APPLE_KEYCHAIN__
-+	case oAskPassGUI:
-+		intptr = &options->ask_pass_gui;
-+		goto parse_flag;
-+#endif
-+
- 	case oDeprecated:
- 		debug("%s line %d: Deprecated option \"%s\"",
- 		    filename, linenum, keyword);
-@@ -1238,6 +1249,9 @@ initialize_options(Options * options)
- 	options->ip_qos_interactive = -1;
- 	options->ip_qos_bulk = -1;
- 	options->request_tty = -1;
-+#ifdef __APPLE_KEYCHAIN__
-+	options->ask_pass_gui = -1;
-+#endif
- }
- 
- /*
-@@ -1408,6 +1422,10 @@ fill_default_options(Options * options)
- 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
- 	if (options->request_tty == -1)
- 		options->request_tty = REQUEST_TTY_AUTO;
-+#ifdef __APPLE_KEYCHAIN__
-+	if (options->ask_pass_gui == -1)
-+		options->ask_pass_gui = 1;
-+#endif
- 	/* options->local_command should not be set by default */
- 	/* options->proxy_command should not be set by default */
- 	/* options->user will be set in the main program if appropriate */
-diff --git readconf.h readconf.h
-index 617686f..150e95b 100644
---- readconf.h
-+++ readconf.h
-@@ -139,6 +139,10 @@ typedef struct {
- 	int	use_roaming;
- 
- 	int	request_tty;
-+
-+#ifdef __APPLE_KEYCHAIN__
-+	int ask_pass_gui;
-+#endif
- }       Options;
- 
- #define SSHCTL_MASTER_NO	0
-diff --git scp.1 scp.1
-index 577dd52..c93fb0e 100644
---- scp.1
-+++ scp.1
-@@ -19,7 +19,7 @@
- .Sh SYNOPSIS
- .Nm scp
- .Bk -words
--.Op Fl 12346BCpqrv
-+.Op Fl 12346BCEpqrv
- .Op Fl c Ar cipher
- .Op Fl F Ar ssh_config
- .Op Fl i Ar identity_file
-@@ -97,6 +97,8 @@ Passes the
- flag to
- .Xr ssh 1
- to enable compression.
-+.It Fl E
-+Preserves extended attributes, resource forks, and ACLs.  Requires both ends to be running Mac OS X 10.4 or later.
- .It Fl c Ar cipher
- Selects the cipher to use for encrypting the data transfer.
- This option is directly passed to
-diff --git scp.c scp.c
-index 18b2597..439530d 100644
---- scp.c
-+++ scp.c
-@@ -78,6 +78,9 @@
- #ifdef HAVE_SYS_STAT_H
- # include <sys/stat.h>
- #endif
-+#ifdef __APPLE_XSAN__
-+#include <sys/mount.h>
-+#endif
- #ifdef HAVE_POLL_H
- #include <poll.h>
- #else
-@@ -114,6 +117,11 @@
- #include "misc.h"
- #include "progressmeter.h"
- 
-+#ifdef HAVE_COPYFILE_H
-+#include <libgen.h>
-+#include <copyfile.h>
-+#endif
-+
- extern char *__progname;
- 
- #define COPY_BUFLEN	16384
-@@ -150,6 +158,12 @@ char *ssh_program = _PATH_SSH_PROGRAM;
- /* This is used to store the pid of ssh_program */
- pid_t do_cmd_pid = -1;
- 
-+#ifdef HAVE_COPYFILE
-+int copy_xattr = 0;
-+int md_flag = 0;
-+#endif
-+
-+
- static void
- killchild(int signo)
- {
-@@ -395,7 +409,11 @@ main(int argc, char **argv)
- 	addargs(&args, "-oClearAllForwardings=yes");
- 
- 	fflag = tflag = 0;
-+#if HAVE_COPYFILE
-+	while ((ch = getopt(argc, argv, "dfl:prtvBCEc:i:P:q12346S:o:F:")) != -1)
-+#else
- 	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
-+#endif
- 		switch (ch) {
- 		/* User-visible flags. */
- 		case '1':
-@@ -456,6 +474,11 @@ main(int argc, char **argv)
- 			showprogress = 0;
- 			break;
- 
-+#ifdef HAVE_COPYFILE
-+		case 'E':
-+			copy_xattr = 1;
-+			break;
-+#endif
- 		/* Server options. */
- 		case 'd':
- 			targetshouldbedirectory = 1;
-@@ -505,7 +528,12 @@ main(int argc, char **argv)
- 	remin = remout = -1;
- 	do_cmd_pid = -1;
- 	/* Command to be executed on remote system using "ssh". */
-+#if HAVE_COPYFILE
-+	(void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s%s",
-+	    copy_xattr ? " -E" : "",
-+#else
- 	(void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
-+#endif
- 	    verbose_mode ? " -v" : "",
- 	    iamrecursive ? " -r" : "", pflag ? " -p" : "",
- 	    targetshouldbedirectory ? " -d" : "");
-@@ -729,6 +757,10 @@ source(int argc, char **argv)
- 	int fd = -1, haderr, indx;
- 	char *last, *name, buf[2048], encname[MAXPATHLEN];
- 	int len;
-+#if HAVE_COPYFILE
-+	char md_name[MAXPATHLEN];
-+	char *md_tmp;
-+#endif
- 
- 	for (indx = 0; indx < argc; ++indx) {
- 		name = argv[indx];
-@@ -736,12 +768,26 @@ source(int argc, char **argv)
- 		len = strlen(name);
- 		while (len > 1 && name[len-1] == '/')
- 			name[--len] = '\0';
-+#if HAVE_COPYFILE
-+md_next:
-+		statbytes = 0;
-+		if (md_flag) {
-+		    fd = open(md_tmp, O_RDONLY, 0);
-+		    unlink(md_tmp);
-+		    free(md_tmp);
-+		    if (fd < 0)
-+			goto syserr;
-+		} else {
-+#endif
- 		if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
- 			goto syserr;
- 		if (strchr(name, '\n') != NULL) {
- 			strnvis(encname, name, sizeof(encname), VIS_NL);
- 			name = encname;
- 		}
-+#if HAVE_COPYFILE
-+		}
-+#endif
- 		if (fstat(fd, &stb) < 0) {
- syserr:			run_err("%s: %s", name, strerror(errno));
- 			goto next;
-@@ -838,6 +884,36 @@ next:			if (fd != -1) {
- 		else
- 			run_err("%s: %s", name, strerror(haderr));
- 		(void) response();
-+#ifdef HAVE_COPYFILE
-+		if (copy_xattr && md_flag == 0)
-+		{
-+		    if (!copyfile(name, NULL, 0,
-+			    COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_CHECK))
-+			continue;
-+
-+		    /*
-+		     * this file will hold the actual metadata
-+		     * to be transferred
-+		     */
-+		    md_tmp = strdup("/tmp/scp.md.XXXXXX");
-+		    md_tmp = mktemp(md_tmp);
-+
-+		    if(copyfile(name, md_tmp, 0,
-+				COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_PACK) == 0)
-+		    {
-+			/*
-+			 * this is the fake name to display
-+			 */
-+			snprintf(md_name, sizeof md_name, "%s/._%s", dirname(name), basename(name));
-+			name = md_name;
-+			md_flag = 1;
-+			if (verbose_mode)
-+			    fprintf(stderr, "copyfile(%s, %s, PACK)\n", name, md_tmp);
-+			goto md_next;
-+		    }
-+		} else
-+		    md_flag = 0;
-+#endif
- 	}
- }
- 
-@@ -932,6 +1008,10 @@ sink(int argc, char **argv)
- 	if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
- 		targisdir = 1;
- 	for (first = 1;; first = 0) {
-+#if HAVE_COPYFILE
-+		char md_src[MAXPATHLEN];
-+		char md_dst[MAXPATHLEN];
-+#endif
- 		cp = buf;
- 		if (atomicio(read, remin, cp, 1) != 1)
- 			return;
-@@ -1065,10 +1145,51 @@ sink(int argc, char **argv)
- 		}
- 		omode = mode;
- 		mode |= S_IWRITE;
-+
-+#if HAVE_COPYFILE
-+		if (copy_xattr && !strncmp(basename(curfile), "._", 2))
-+		{
-+			int mdfd;
-+			if (targisdir)
-+			{
-+			    snprintf(md_src, sizeof md_src, "%s.XXXXXX", np);
-+			    snprintf(md_dst, sizeof md_dst, "%s/%s",
-+				    dirname(np), basename(np) + 2);
-+			    if((mdfd = mkstemp(md_src)) < 0)
-+				continue;
-+			}
-+			else
-+			{
-+			    snprintf(md_src, sizeof md_src, "%s/._%s.XXXXXX",
-+				    dirname(np), basename(np));
-+			    snprintf(md_dst, sizeof md_dst, "%s", np);
-+			    if((mdfd = mkstemp(md_src)) < 0)
-+				continue;
-+			}
-+			if (mdfd >= 0)
-+				close(mdfd);
-+			np = md_src;
-+		}
-+#endif
- 		if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
- bad:			run_err("%s: %s", np, strerror(errno));
- 			continue;
- 		}
-+#ifdef __APPLE_XSAN__
-+		{
-+			/*
-+			 * Pre-allocate blocks for the destination file.
-+			 */
-+			fstore_t fst;
-+
-+			fst.fst_flags = 0;
-+			fst.fst_posmode = F_PEOFPOSMODE;
-+			fst.fst_offset = 0;
-+			fst.fst_length = size;
-+				
-+			(void) fcntl(ofd, F_PREALLOCATE, &fst);
-+		}
-+#endif /* __APPLE_XSAN__ */		
- 		(void) atomicio(vwrite, remout, "", 1);
- 		if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
- 			(void) close(ofd);
-@@ -1153,6 +1274,29 @@ bad:			run_err("%s: %s", np, strerror(errno));
- 			wrerrno = errno;
- 		}
- 		(void) response();
-+#ifdef HAVE_COPYFILE
-+		if (copy_xattr && strncmp(basename(np), "._", 2) == 0)
-+		{
-+			if (verbose_mode)
-+			    fprintf(stderr, "copyfile(%s, %s, UNPACK)\n", md_src, md_dst);
-+			if(!copyfile(md_src, md_dst, 0,
-+			    COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_UNPACK) < 0)
-+			{
-+			    snprintf(md_dst, sizeof md_dst, "%s/._%s",
-+				    dirname(md_dst), basename(md_dst));
-+			    rename(md_src, md_dst);
-+			} else
-+			    unlink(md_src);
-+			if (setimes && wrerr == NO) {
-+				setimes = 0;
-+				if (utimes(md_dst, tv) < 0) {
-+					run_err("%s: set times: %s",
-+					np, strerror(errno));
-+					wrerr = DISPLAYED;
-+				}
-+			}
-+		} else
-+#endif
- 		if (setimes && wrerr == NO) {
- 			setimes = 0;
- 			if (utimes(np, tv) < 0) {
-@@ -1214,7 +1358,11 @@ void
- usage(void)
- {
- 	(void) fprintf(stderr,
-+#if HAVE_COPYFILE
-+	    "usage: scp [-12346BCEpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
-+#else
- 	    "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
-+#endif
- 	    "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
- 	    "           [[user@]host1:]file1 ... [[user@]host2:]file2\n");
- 	exit(1);
-diff --git servconf.c servconf.c
-index 756a3a2..0e2678e 100644
---- servconf.c
-+++ servconf.c
-@@ -148,7 +148,7 @@ fill_default_server_options(ServerOptions *options)
- {
- 	/* Portable-specific options */
- 	if (options->use_pam == -1)
--		options->use_pam = 0;
-+		options->use_pam = 1;
- 
- 	/* Standard Options */
- 	if (options->protocol == SSH_PROTO_UNKNOWN)
-@@ -237,7 +237,7 @@ fill_default_server_options(ServerOptions *options)
- 	if (options->gss_store_rekey == -1)
- 		options->gss_store_rekey = 0;
- 	if (options->password_authentication == -1)
--		options->password_authentication = 1;
-+		options->password_authentication = 0;
- 	if (options->kbd_interactive_authentication == -1)
- 		options->kbd_interactive_authentication = 0;
- 	if (options->challenge_response_authentication == -1)
-@@ -602,7 +602,7 @@ match_cfg_line_group(const char *grps, int line, const char *user)
- 	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) {
-+	} else if (ga_init(pw) == 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) {
-diff --git session.c session.c
-index 6a70400..42e6fac 100644
---- session.c
-+++ session.c
-@@ -2063,8 +2063,10 @@ session_pty_req(Session *s)
- 		n_bytes = packet_remaining();
- 	tty_parse_modes(s->ttyfd, &n_bytes);
- 
-+#ifndef __APPLE_PRIVPTY__
- 	if (!use_privsep)
- 		pty_setowner(s->pw, s->tty);
-+#endif
- 
- 	/* Set window size from the packet. */
- 	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
-@@ -2304,9 +2306,11 @@ session_pty_cleanup2(Session *s)
- 	if (s->pid != 0)
- 		record_logout(s->pid, s->tty, s->pw->pw_name);
- 
-+#ifndef __APPLE_PRIVPTY__
- 	/* Release the pseudo-tty. */
- 	if (getuid() == 0)
- 		pty_release(s->tty);
-+#endif
- 
- 	/*
- 	 * Close the server side of the socket pairs.  We must do this after
-diff --git ssh-add.0 ssh-add.0
-index e1e2a64..74ee18a 100644
---- ssh-add.0
-+++ ssh-add.0
-@@ -1,10 +1,10 @@
- SSH-ADD(1)                 OpenBSD Reference Manual                 SSH-ADD(1)
- 
- NAME
--     ssh-add - adds private key identities to the authentication agent
-+     ssh-add -- adds private key identities to the authentication agent
- 
- SYNOPSIS
--     ssh-add [-cDdkLlXx] [-t life] [file ...]
-+     ssh-add [-cDdLlXxZz] [-t life] [file ...]
-      ssh-add -s pkcs11
-      ssh-add -e pkcs11
- 
-@@ -66,6 +66,13 @@
- 
-      -x      Lock the agent with a password.
- 
-+     -Z      When adding identities, each passphrase will also be stored in
-+             your keychain.  When removing identities with -d, each passphrase
-+             will be removed from your keychain.
-+
-+     -z      Add identities to the agent using any passphrases stored in your
-+             keychain.
-+
- ENVIRONMENT
-      DISPLAY and SSH_ASKPASS
-              If ssh-add needs a passphrase, it will read the passphrase from
-diff --git ssh-add.1 ssh-add.1
-index fd48ff9..0bd1114 100644
---- ssh-add.1
-+++ ssh-add.1
-@@ -43,7 +43,7 @@
- .Nd adds private key identities to the authentication agent
- .Sh SYNOPSIS
- .Nm ssh-add
--.Op Fl cDdkLlXx
-+.Op Fl cDdLlXxZz
- .Op Fl t Ar life
- .Op Ar
- .Nm ssh-add
-@@ -130,6 +130,12 @@
- Unlock the agent.
- .It Fl x
- Lock the agent with a password.
-+.It Fl Z
-+When adding identities, each passphrase will also be stored in your
-+keychain.  When removing identities with -d, each passphrase will be
-+removed from your keychain.
-+.It Fl z
-+Add identities to the agent using any passphrases stored in your keychain.
- .El
- .Sh ENVIRONMENT
- .Bl -tag -width Ds
-diff --git ssh-add.c ssh-add.c
-index 6d5e2a9..9621451 100644
---- ssh-add.c
-+++ ssh-add.c
-@@ -62,6 +62,7 @@
- #include "authfile.h"
- #include "pathnames.h"
- #include "misc.h"
-+#include "keychain.h"
- 
- /* argv0 */
- extern char *__progname;
-@@ -96,7 +97,17 @@
- }
- 
- static int
--delete_file(AuthenticationConnection *ac, const char *filename)
-+add_from_keychain(AuthenticationConnection *ac)
-+{
-+	if (ssh_add_from_keychain(ac) == 0)
-+		return -1;
-+
-+	fprintf(stderr, "Added keychain identities.\n");
-+	return 0;
-+}
-+
-+static int
-+delete_file(AuthenticationConnection *ac, int keychain, const char *filename)
- {
- 	Key *public;
- 	char *comment = NULL;
-@@ -139,7 +150,7 @@
- }
- 
- static int
--add_file(AuthenticationConnection *ac, const char *filename, int key_only)
-+add_file(AuthenticationConnection *ac, int keychain, const char *filename, int key_only)
- {
- 	Key *private, *cert;
- 	char *comment = NULL;
-@@ -176,11 +187,16 @@
- 
- 	/* At first, try empty passphrase */
- 	private = key_parse_private(&keyblob, filename, "", &comment);
-+	if (keychain && private != NULL)
-+		store_in_keychain(filename, "");
- 	if (comment == NULL)
- 		comment = xstrdup(filename);
- 	/* try last */
--	if (private == NULL && pass != NULL)
-+	if (private == NULL && pass != NULL) {
- 		private = key_parse_private(&keyblob, filename, pass, NULL);
-+		if (keychain && private != NULL)
-+			store_in_keychain(filename, pass);
-+	}
- 	if (private == NULL) {
- 		/* clear passphrase since it did not work */
- 		clear_pass();
-@@ -196,8 +212,11 @@
- 			}
- 			private = key_parse_private(&keyblob, filename, pass,
- 			    &comment);
--			if (private != NULL)
-+			if (private != NULL) {
-+				if (keychain)
-+					store_in_keychain(filename, pass);
- 				break;
-+			}
- 			clear_pass();
- 			snprintf(msg, sizeof msg,
- 			    "Bad passphrase, try again for %.200s: ", comment);
-@@ -351,13 +370,13 @@
- }
- 
- static int
--do_file(AuthenticationConnection *ac, int deleting, int key_only, char *file)
-+do_file(AuthenticationConnection *ac, int deleting, int keychain, int key_only, char *file)
- {
- 	if (deleting) {
--		if (delete_file(ac, file) == -1)
-+	  if (delete_file(ac, keychain, file) == -1)
- 			return -1;
- 	} else {
--		if (add_file(ac, file, key_only) == -1)
-+	  if (add_file(ac, keychain, file, key_only) == -1)
- 			return -1;
- 	}
- 	return 0;
-@@ -379,6 +398,11 @@
- 	fprintf(stderr, "  -X          Unlock agent.\n");
- 	fprintf(stderr, "  -s pkcs11   Add keys from PKCS#11 provider.\n");
- 	fprintf(stderr, "  -e pkcs11   Remove keys provided by PKCS#11 provider.\n");
-+#ifdef KEYCHAIN
-+	fprintf(stderr, "  -z          Add all identities stored in your keychain.\n");
-+	fprintf(stderr, "  -Z          Store passphrases in your keychain.\n");
-+	fprintf(stderr, "              With -d, remove passphrases from your keychain.\n");
-+#endif
- }
- 
- int
-@@ -389,6 +413,7 @@
- 	AuthenticationConnection *ac = NULL;
- 	char *pkcs11provider = NULL;
- 	int i, ch, deleting = 0, ret = 0, key_only = 0;
-+	int keychain = 0;
- 
- 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
- 	sanitise_stdfd();
-@@ -405,7 +430,7 @@
- 		    "Could not open a connection to your authentication agent.\n");
- 		exit(2);
- 	}
--	while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) {
-+	while ((ch = getopt(argc, argv, "klLcdDxXe:s:zZt:")) != -1) {
- 		switch (ch) {
- 		case 'k':
- 			key_only = 1;
-@@ -430,6 +455,13 @@
- 			if (delete_all(ac) == -1)
- 				ret = 1;
- 			goto done;
-+		case 'z':
-+			if (add_from_keychain(ac) == -1)
-+				ret = 1;
-+			goto done;
-+		case 'Z':
-+			keychain = 1;
-+			break;
- 		case 's':
- 			pkcs11provider = optarg;
- 			break;
-@@ -460,6 +492,7 @@
- 	if (argc == 0) {
- 		char buf[MAXPATHLEN];
- 		struct passwd *pw;
-+		char *pw_dir;
- 		struct stat st;
- 		int count = 0;
- 
-@@ -470,21 +503,25 @@
- 			goto done;
- 		}
- 
-+		pw_dir = xstrdup(pw->pw_dir);
-+
- 		for (i = 0; default_files[i]; i++) {
--			snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
-+			snprintf(buf, sizeof(buf), "%s/%s", pw_dir,
- 			    default_files[i]);
- 			if (stat(buf, &st) < 0)
- 				continue;
--			if (do_file(ac, deleting, key_only, buf) == -1)
-+			if (do_file(ac, deleting, keychain, key_only, buf) == -1)
- 				ret = 1;
- 			else
- 				count++;
- 		}
- 		if (count == 0)
- 			ret = 1;
-+
-+		xfree(pw_dir);
- 	} else {
- 		for (i = 0; i < argc; i++) {
--			if (do_file(ac, deleting, key_only, argv[i]) == -1)
-+		  if (do_file(ac, deleting, keychain, key_only, argv[i]) == -1)
- 				ret = 1;
- 		}
- 	}
-diff --git ssh-agent.c ssh-agent.c
-index b9498e6..a154096 100644
---- ssh-agent.c
-+++ ssh-agent.c
-@@ -65,6 +65,9 @@
- #include <time.h>
- #include <string.h>
- #include <unistd.h>
-+#ifdef __APPLE_LAUNCHD__
-+#include <launch.h>
-+#endif
- 
- #include "xmalloc.h"
- #include "ssh.h"
-@@ -72,9 +75,11 @@
- #include "buffer.h"
- #include "key.h"
- #include "authfd.h"
-+#include "authfile.h"
- #include "compat.h"
- #include "log.h"
- #include "misc.h"
-+#include "keychain.h"
- 
- #ifdef ENABLE_PKCS11
- #include "ssh-pkcs11.h"
-@@ -793,6 +798,61 @@ process_remove_smartcard_key(SocketEntry *e)
- }
- #endif /* ENABLE_PKCS11 */
- 
-+static int
-+add_identity_callback(const char *filename, const char *passphrase)
-+{
-+	Key *k;
-+	int version;
-+	Idtab *tab;
-+
-+	if ((k = key_load_private(filename, passphrase, NULL)) == NULL)
-+		return 1;
-+	switch (k->type) {
-+	case KEY_RSA:
-+	case KEY_RSA1:
-+		if (RSA_blinding_on(k->rsa, NULL) != 1) {
-+			key_free(k);
-+			return 1;
-+		}
-+		break;
-+	}
-+	version = k->type == KEY_RSA1 ? 1 : 2;
-+	tab = idtab_lookup(version);
-+	if (lookup_identity(k, version) == NULL) {
-+		Identity *id = xmalloc(sizeof(Identity));
-+		id->key = k;
-+		id->comment = xstrdup(filename);
-+		if (id->comment == NULL) {
-+			key_free(k);
-+			return 1;
-+		}
-+		id->death = 0;
-+		id->confirm = 0;
-+		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
-+		tab->nentries++;
-+	} else {
-+		key_free(k);
-+		return 1;
-+	}
-+
-+	return 0;
-+}
-+
-+static void
-+process_add_from_keychain(SocketEntry *e)
-+{
-+	int result;
-+
-+	result = add_identities_using_keychain(&add_identity_callback);
-+
-+	/* e will be NULL when ssh-agent adds keys on its own at startup */
-+	if (e) {
-+		buffer_put_int(&e->output, 1);
-+		buffer_put_char(&e->output,
-+		    result ? SSH_AGENT_FAILURE : SSH_AGENT_SUCCESS);
-+	}
-+}
-+
- /* dispatch incoming messages */
- 
- static void
-@@ -885,6 +945,9 @@ process_message(SocketEntry *e)
- 		process_remove_smartcard_key(e);
- 		break;
- #endif /* ENABLE_PKCS11 */
-+	case SSH_AGENTC_ADD_FROM_KEYCHAIN:
-+		process_add_from_keychain(e);
-+		break;
- 	default:
- 		/* Unknown message.  Respond with failure. */
- 		error("Unknown message %d", type);
-@@ -1126,7 +1189,11 @@ usage(void)
- int
- main(int ac, char **av)
- {
-+#ifdef __APPLE_LAUNCHD__
-+	int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, l_flag = 0;
-+#else
- 	int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
-+#endif
- 	int sock, fd, ch, result, saved_errno;
- 	u_int nalloc;
- 	char *shell, *format, *pidstr, *agentsocket = NULL;
-@@ -1160,7 +1227,11 @@ main(int ac, char **av)
- 	__progname = ssh_get_progname(av[0]);
- 	seed_rng();
- 
-+#ifdef __APPLE_LAUNCHD__
-+	while ((ch = getopt(ac, av, "cdklsa:t:")) != -1) {
-+#else
- 	while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
-+#endif
- 		switch (ch) {
- 		case 'c':
- 			if (s_flag)
-@@ -1170,6 +1241,11 @@ main(int ac, char **av)
- 		case 'k':
- 			k_flag++;
- 			break;
-+#ifdef __APPLE_LAUNCHD__
-+		case 'l':
-+			l_flag++;
-+			break;
-+#endif
- 		case 's':
- 			if (c_flag)
- 				usage();
-@@ -1196,7 +1272,11 @@ main(int ac, char **av)
- 	ac -= optind;
- 	av += optind;
- 
-+#ifdef __APPPLE_LAUNCHD__
-+	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || l_flag))
-+#else
- 	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
-+#endif
- 		usage();
- 
- 	if (ac == 0 && !c_flag && !s_flag) {
-@@ -1252,6 +1332,53 @@ main(int ac, char **av)
- 	 * Create socket early so it will exist before command gets run from
- 	 * the parent.
- 	 */
-+#ifdef __APPLE_LAUNCHD__
-+	if (l_flag) {
-+		launch_data_t resp, msg, tmp;
-+		size_t listeners_i;
-+
-+		msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
-+
-+		resp = launch_msg(msg);
-+
-+		if (NULL == resp) {
-+			perror("launch_msg");
-+			exit(1);
-+		}
-+		launch_data_free(msg);
-+		switch (launch_data_get_type(resp)) {
-+		case LAUNCH_DATA_ERRNO:
-+			errno = launch_data_get_errno(resp);
-+			perror("launch_msg response");
-+			exit(1);
-+		case LAUNCH_DATA_DICTIONARY:
-+			break;
-+		default:
-+			fprintf(stderr, "launch_msg unknown response");
-+			exit(1);
-+		}
-+		tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS);
-+
-+		if (NULL == tmp) {
-+			fprintf(stderr, "no sockets\n");
-+			exit(1);
-+		}
-+
-+		tmp = launch_data_dict_lookup(tmp, "Listeners");
-+
-+		if (NULL == tmp) {
-+			fprintf(stderr, "no known listeners\n");
-+			exit(1);
-+		}
-+
-+		for (listeners_i = 0; listeners_i < launch_data_array_get_count(tmp); listeners_i++) {
-+			launch_data_t obj_at_ind = launch_data_array_get_index(tmp, listeners_i);
-+			new_socket(AUTH_SOCKET, launch_data_get_fd(obj_at_ind));
-+		}
-+
-+		launch_data_free(resp);
-+	} else {
-+#endif
- 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
- 	if (sock < 0) {
- 		perror("socket");
-@@ -1273,6 +1400,14 @@ main(int ac, char **av)
- 		perror("listen");
- 		cleanup_exit(1);
- 	}
-+#ifdef __APPLE_LAUNCHD__
-+	}
-+#endif
-+
-+#ifdef __APPLE_LAUNCHD__
-+	if (l_flag)
-+		goto skip2;
-+#endif
- 
- 	/*
- 	 * Fork, and have the parent execute the command, if any, or present
-@@ -1345,6 +1480,7 @@ skip:
- 	pkcs11_init(0);
- #endif
- 	new_socket(AUTH_SOCKET, sock);
-+skip2:
- 	if (ac > 0)
- 		parent_alive_interval = 10;
- 	idtab_init();
-@@ -1355,6 +1491,10 @@ skip:
- 	signal(SIGTERM, cleanup_handler);
- 	nalloc = 0;
- 
-+#ifdef KEYCHAIN
-+	process_add_from_keychain(NULL);
-+#endif
-+
- 	while (1) {
- 		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
- 		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
-diff --git ssh-keysign.8 ssh-keysign.8
-index 5e09e02..612c8f8 100644
---- ssh-keysign.8
-+++ ssh-keysign.8
-@@ -71,6 +71,9 @@ accessible to others.
- Since they are readable only by root,
- .Nm
- must be set-uid root if host-based authentication is used.
-+Note that
-+.Nm
-+is not set-uid by default on Mac OS X.
- .Pp
- .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub
- .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub
-diff --git sshconnect1.c sshconnect1.c
-index fd07bbf..f9eaeba 100644
---- sshconnect1.c
-+++ sshconnect1.c
-@@ -47,6 +47,7 @@
- #include "canohost.h"
- #include "hostfile.h"
- #include "auth.h"
-+#include "keychain.h"
- 
- /* Session id for the current session. */
- u_char session_id[16];
-@@ -260,6 +261,10 @@ try_rsa_authentication(int idx)
- 		snprintf(buf, sizeof(buf),
- 		    "Enter passphrase for RSA key '%.100s': ", comment);
- 		for (i = 0; i < options.number_of_password_prompts; i++) {
-+#ifdef __APPLE_KEYCHAIN__
-+			passphrase = keychain_read_passphrase(comment, options.ask_pass_gui);
-+			if (passphrase == NULL)
-+#endif
- 			passphrase = read_passphrase(buf, 0);
- 			if (strcmp(passphrase, "") != 0) {
- 				private = key_load_private_type(KEY_RSA1,
-diff --git sshconnect2.c sshconnect2.c
-index 3ddef32..a8ed741 100644
---- sshconnect2.c
-+++ sshconnect2.c
-@@ -72,6 +72,7 @@
- #include "hostfile.h"
- #include "schnorr.h"
- #include "jpake.h"
-+#include "keychain.h"
- 
- #ifdef GSSAPI
- #include "ssh-gss.h"
-@@ -1447,6 +1448,10 @@ load_identity_file(char *filename)
- 		snprintf(prompt, sizeof prompt,
- 		    "Enter passphrase for key '%.100s': ", filename);
- 		for (i = 0; i < options.number_of_password_prompts; i++) {
-+#ifdef __APPLE_KEYCHAIN__
-+			passphrase = keychain_read_passphrase(filename, options.ask_pass_gui);
-+			if (passphrase == NULL)
-+#endif
- 			passphrase = read_passphrase(prompt, 0);
- 			if (strcmp(passphrase, "") != 0) {
- 				private = key_load_private_type(KEY_UNSPEC,
-diff --git sshd.0 sshd.0
-index e8b4983..471841c 100644
---- sshd.0
-+++ sshd.0
-@@ -617,8 +617,8 @@ FILES
- 
- SEE ALSO
-      scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1),
--     ssh-keyscan(1), chroot(2), hosts_access(5), login.conf(5), moduli(5),
--     sshd_config(5), inetd(8), sftp-server(8)
-+     ssh-keyscan(1), chroot(2), hosts_access(5), sshd_config(5)
-+     sftp-server(8)
- 
- AUTHORS
-      OpenSSH is a derivative of the original and free ssh 1.2.12 release by
-diff --git sshd.8 sshd.8
-index a91be0f..18941a6 100644
---- sshd.8
-+++ sshd.8
-@@ -950,10 +950,7 @@ The content of this file is not sensitive; it can be world-readable.
- .Xr ssh-keyscan 1 ,
- .Xr chroot 2 ,
- .Xr hosts_access 5 ,
--.Xr login.conf 5 ,
--.Xr moduli 5 ,
- .Xr sshd_config 5 ,
--.Xr inetd 8 ,
- .Xr sftp-server 8
- .Sh AUTHORS
- OpenSSH is a derivative of the original and free
-diff --git sshd.c sshd.c
-index 112a5f9..4773543 100644
---- sshd.c
-+++ sshd.c
-@@ -2076,6 +2076,12 @@ main(int ac, char **av)
- 	audit_event(SSH_AUTH_SUCCESS);
- #endif
- 
-+#ifdef USE_PAM
-+	if (options.use_pam) {
-+		do_pam_setcred(1);
-+		do_pam_session();
-+	}
-+#endif
- #ifdef GSSAPI
- 	if (options.gss_authentication) {
- 		temporarily_use_uid(authctxt->pw);
-@@ -2083,12 +2089,6 @@ main(int ac, char **av)
- 		restore_uid();
- 	}
- #endif
--#ifdef USE_PAM
--	if (options.use_pam) {
--		do_pam_setcred(1);
--		do_pam_session();
--	}
--#endif
- 
- 	/*
- 	 * In privilege separation, we fork another child and prepare
-diff --git sshd_config sshd_config
-index d02d7a7..53966ab 100644
---- sshd_config
-+++ sshd_config
-@@ -31,7 +31,7 @@
- 
- # Logging
- # obsoletes QuietMode and FascistLogging
--#SyslogFacility AUTH
-+SyslogFacility AUTHPRIV
- #LogLevel INFO
- 
- # Authentication:
-@@ -59,8 +59,9 @@ AuthorizedKeysFile	.ssh/authorized_keys
- # Don't read the user's ~/.rhosts and ~/.shosts files
- #IgnoreRhosts yes
- 
--# To disable tunneled clear text passwords, change to no here!
--#PasswordAuthentication yes
-+# To disable tunneled clear text passwords, change to no here! Also,
-+# remember to set the UsePAM setting to 'no'.
-+#PasswordAuthentication no
- #PermitEmptyPasswords no
- 
- # Change to no to disable s/key passwords
-@@ -87,7 +88,10 @@ AuthorizedKeysFile	.ssh/authorized_keys
- # If you just want the PAM account and session checks to run without
- # PAM authentication, then enable this but set PasswordAuthentication
- # and ChallengeResponseAuthentication to 'no'.
--#UsePAM no
-+# Also, PAM will deny null passwords by default.  If you need to allow
-+# null passwords, add the "	nullok" option to the end of the
-+# securityserver.so line in /etc/pam.d/sshd.
-+#UsePAM yes
- 
- #AllowAgentForwarding yes
- #AllowTcpForwarding yes
-diff --git sshd_config.0 sshd_config.0
-index e19ca87..5bee36a 100644
---- sshd_config.0
-+++ sshd_config.0
-@@ -436,7 +436,7 @@ DESCRIPTION
- 
-      PasswordAuthentication
-              Specifies whether password authentication is allowed.  The
--             default is ``yes''.
-+             default is ``no''.
- 
-      PermitEmptyPasswords
-              When password authentication is allowed, it specifies whether the
-@@ -619,7 +619,7 @@ DESCRIPTION
-              either PasswordAuthentication or ChallengeResponseAuthentication.
- 
-              If UsePAM is enabled, you will not be able to run sshd(8) as a
--             non-root user.  The default is ``no''.
-+             non-root user.  The default is ``yes''.
- 
-      UsePrivilegeSeparation
-              Specifies whether sshd(8) separates privileges by creating an
-diff --git sshd_config.5 sshd_config.5
-index 76c95aa..adebac6 100644
---- sshd_config.5
-+++ sshd_config.5
-@@ -794,7 +794,7 @@ are refused if the number of unauthenticated connections reaches
- .It Cm PasswordAuthentication
- Specifies whether password authentication is allowed.
- The default is
--.Dq yes .
-+.Dq no .
- .It Cm PermitEmptyPasswords
- When password authentication is allowed, it specifies whether the
- server allows login to accounts with empty password strings.
-@@ -1089,7 +1089,7 @@ is enabled, you will not be able to run
- .Xr sshd 8
- as a non-root user.
- The default is
--.Dq no .
-+.Dq yes .
- .It Cm UsePrivilegeSeparation
- Specifies whether
- .Xr sshd 8
--- 
-1.7.6.1
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20130720/2f80e6d5/attachment-0001.html>


More information about the macports-changes mailing list