[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