Ticket #45323: 0003-Apple-keychain-integration-other-changes.patch

File 0003-Apple-keychain-integration-other-changes.patch, 65.6 KB (added by neverpanic (Clemens Lang), 10 years ago)

Keychain integration patch without the additional creation of .orig files

  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/Makefile.in openssh-6.7p1.patched/Makefile.in
    old new SED=@SED@ 
    5959ENT=@ENT@
    6060XAUTH_PATH=@XAUTH_PATH@
    6161LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
     62KEYCHAIN_LDFLAGS=@KEYCHAIN_LDFLAGS@
    6263EXEEXT=@EXEEXT@
    6364MANFMT=@MANFMT@
    6465
    SSHDOBJS=sshd.o auth-rhosts.o auth-passw 
    108109        sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
    109110        sandbox-seccomp-filter.o sandbox-capsicum.o
    110111
     112KEYCHAINOBJS=keychain.o
     113
    111114MANPAGES        = 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
    112115MANPAGES_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
    113116MANTYPE         = @MANTYPE@
    all: $(CONFIGFILES) $(MANPAGES) $(TARGET 
    143146$(LIBSSH_OBJS): Makefile.in config.h
    144147$(SSHOBJS): Makefile.in config.h
    145148$(SSHDOBJS): Makefile.in config.h
     149$(KEYCHAINOBJS): Makefile.in config.h
    146150
    147151.c.o:
    148152        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
    libssh.a: $(LIBSSH_OBJS) 
    156160        $(AR) rv $@ $(LIBSSH_OBJS)
    157161        $(RANLIB) $@
    158162
    159 ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
    160         $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS)
     163ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(KEYCHAINOBJS)
     164        $(LD) -o $@ $(SSHOBJS) $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS)
    161165
    162166sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
    163167        $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
    sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(S 
    165169scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
    166170        $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
    167171
    168 ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
    169         $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
     172ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(KEYCHAINOBJS)
     173        $(LD) -o $@ ssh-add.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
    170174
    171 ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
    172         $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
     175ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o $(KEYCHAINOBJS)
     176        $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
    173177
    174178ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
    175179        $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
    install-files: 
    293297        $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
    294298        $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
    295299        $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
    296         $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
     300        $(INSTALL) -m 0711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
    297301        $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
    298302        $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
    299303        $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/audit-bsm.c openssh-6.7p1.patched/audit-bsm.c
    old new bsm_audit_record(int typ, char *string,  
    263263        pid_t           pid = getpid();
    264264        AuditInfoTermID tid = ssh_bsm_tid;
    265265
    266         if (the_authctxt != NULL && the_authctxt->valid) {
     266        if (the_authctxt == NULL) {
     267                error("BSM audit: audit record internal error (NULL ctxt)");
     268                abort();
     269        }
     270       
     271        if (the_authctxt->valid) {
    267272                uid = the_authctxt->pw->pw_uid;
    268273                gid = the_authctxt->pw->pw_gid;
    269274        }
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/auth-pam.c openssh-6.7p1.patched/auth-pam.c
    old new sshpam_query(void *ctx, char **name, cha 
    793793                                free(msg);
    794794                                return (0);
    795795                        }
    796                         error("PAM: %s for %s%.100s from %.100s", msg,
     796                        error("PAM: %s for %s%.100s from %.100s via %s", msg,
    797797                            sshpam_authctxt->valid ? "" : "illegal user ",
    798798                            sshpam_authctxt->user,
    799                             get_remote_name_or_ip(utmp_len, options.use_dns));
     799                            get_remote_name_or_ip(utmp_len, options.use_dns),
     800                            get_local_ipaddr(packet_get_connection_in()));
    800801                        /* FALLTHROUGH */
    801802                default:
    802803                        *num = 0;
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/auth.c openssh-6.7p1.patched/auth.c
    old new allowed_user(struct passwd * pw) 
    211211        }
    212212        if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
    213213                /* Get the user's group access list (primary and supplementary) */
    214                 if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
     214                if (ga_init(pw) == 0) {
    215215                        logit("User %.100s from %.100s not allowed because "
    216216                            "not in any group", pw->pw_name, hostname);
    217217                        return 0;
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/authfd.c openssh-6.7p1.patched/authfd.c
    old new ssh_remove_all_identities(Authentication 
    650650        return decode_reply(type);
    651651}
    652652
     653/*
     654 * Adds identities using passphrases stored in the keychain.  This call is not
     655 * meant to be used by normal applications.
     656 */
     657
     658int
     659ssh_add_from_keychain(AuthenticationConnection *auth)
     660{
     661        Buffer msg;
     662        int type;
     663
     664        buffer_init(&msg);
     665        buffer_put_char(&msg, SSH_AGENTC_ADD_FROM_KEYCHAIN);
     666
     667        if (ssh_request_reply(auth, &msg, &msg) == 0) {
     668                buffer_free(&msg);
     669                return 0;
     670        }
     671        type = buffer_get_char(&msg);
     672        buffer_free(&msg);
     673        return decode_reply(type);
     674}
     675
    653676int
    654677decode_reply(int type)
    655678{
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/authfd.h openssh-6.7p1.patched/authfd.h
    old new  
    4949#define SSH2_AGENTC_ADD_ID_CONSTRAINED          25
    5050#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
    5151
     52/* keychain */
     53#define SSH_AGENTC_ADD_FROM_KEYCHAIN            27
     54
    5255#define SSH_AGENT_CONSTRAIN_LIFETIME            1
    5356#define SSH_AGENT_CONSTRAIN_CONFIRM             2
    5457
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/config.h.in openssh-6.7p1.patched/config.h.in
    old new  
    8181/* FreeBSD strnvis argument order is swapped compared to OpenBSD */
    8282#undef BROKEN_STRNVIS
    8383
     84/* platform uses an in-memory credentials cache */
     85#undef USE_CCAPI
     86
     87/* platform has a Security Authorization Session API */
     88#undef USE_SECURITY_SESSION_API
     89
     90/* Define to 1 if you have the `copyfile' function. */
     91#undef HAVE_COPYFILE
     92
     93/* Define to 1 if you have the <copyfile.h> header file. */
     94#undef HAVE_COPYFILE_H
     95
    8496/* tcgetattr with ICANON may hang */
    8597#undef BROKEN_TCGETATTR_ICANON
    8698
  • configure.ac

    diff -urp --new-file openssh-6.7p1/configure.ac openssh-6.7p1.patched/configure.ac
    old new AC_CHECK_MEMBER([struct utmp.ut_line], [ 
    47664766#endif
    47674767        ])
    47684768
     4769dnl Keychain support
     4770AC_ARG_WITH(keychain,
     4771        [  --with-keychain=apple   Use Mac OS X Keychain],
     4772        [
     4773                case "$withval" in
     4774                apple|no)
     4775                        KEYCHAIN=$withval
     4776                        ;;
     4777                *)
     4778                        AC_MSG_ERROR(invalid keychain type: $withval)
     4779                        ;;
     4780                esac
     4781        ]
     4782)
     4783if test ! -z "$KEYCHAIN" -a "$KEYCHAIN" != "no"; then
     4784        case "$KEYCHAIN" in
     4785        apple)
     4786                AC_CHECK_HEADERS(Security/Security.h, [
     4787                                CPPFLAGS="$CPPFLAGS -D__APPLE_KEYCHAIN__"
     4788                                KEYCHAIN_LDFLAGS="-framework Security -framework CoreFoundation"
     4789                                AC_SUBST(KEYCHAIN_LDFLAGS)
     4790                                ],
     4791                                AC_MSG_WARN([Security framework not found. Disabling Mac OS X Keychain support.]))
     4792                ;;
     4793        esac
     4794fi
     4795
    47694796dnl Adding -Werror to CFLAGS early prevents configure tests from running.
    47704797dnl Add now.
    47714798CFLAGS="$CFLAGS $werror_flags"
    47724799
     4800AC_CHECK_FUNCS(copyfile)
     4801AC_CHECK_HEADERS(copyfile.h)
     4802
    47734803if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
    47744804        TEST_SSH_IPV6=no
    47754805else
  • groupaccess.c

    diff -urp --new-file openssh-6.7p1/groupaccess.c openssh-6.7p1.patched/groupaccess.c
    old new  
    3434#include <stdlib.h>
    3535#include <string.h>
    3636
     37#ifdef __APPLE_MEMBERSHIP__
     38#include <membership.h>
     39#endif
     40
    3741#include "xmalloc.h"
    3842#include "groupaccess.h"
    3943#include "match.h"
    4044#include "log.h"
    4145
     46#ifdef __APPLE_MEMBERSHIP__
     47// SPI for 5235093
     48int32_t getgrouplist_2(const char *, gid_t, gid_t **);
     49int32_t getgroupcount(const char *, gid_t);
     50#endif
     51
    4252static int ngroups;
    4353static char **groups_byname;
     54#ifdef __APPLE_MEMBERSHIP__
     55uuid_t u_uuid;
     56#endif
    4457
    4558/*
    4659 * Initialize group access list for user with primary (base) and
    4760 * supplementary groups.  Return the number of groups in the list.
    4861 */
    4962int
    50 ga_init(const char *user, gid_t base)
     63ga_init(struct passwd *pw)
    5164{
    52         gid_t *groups_bygid;
     65        gid_t *groups_bygid = NULL;
    5366        int i, j;
    5467        struct group *gr;
    5568
     69#ifdef __APPLE_MEMBERSHIP__
     70        if (0 != mbr_uid_to_uuid(pw->pw_uid, u_uuid))
     71                return 0;
     72#endif
     73
    5674        if (ngroups > 0)
    5775                ga_free();
    5876
     77#ifndef __APPLE_MEMBERSHIP__
    5978        ngroups = NGROUPS_MAX;
    6079#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
    6180        ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX));
    62 #endif
    63 
     81#endif 
    6482        groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid));
     83#else
     84        if (-1 == (ngroups = getgrouplist_2(pw->pw_name, pw->pw_gid,
     85            &groups_bygid))) {
     86                logit("getgrouplist_2 failed");
     87                return 0;
     88        }
     89#endif
    6590        groups_byname = xcalloc(ngroups, sizeof(*groups_byname));
    66 
    67         if (getgrouplist(user, base, groups_bygid, &ngroups) == -1)
    68                 logit("getgrouplist: groups list too small");
     91#ifndef __APPLE_MEMBERSHIP__
     92        if (getgrouplist(pw->pw_name, pw->pw_gid, groups_bygid, &ngroups) == -1) {
     93            logit("getgrouplist: groups list too small");
     94                free(groups_bygid);
     95                return 0;
     96        }
     97#endif
    6998        for (i = 0, j = 0; i < ngroups; i++)
    7099                if ((gr = getgrgid(groups_bygid[i])) != NULL)
    71100                        groups_byname[j++] = xstrdup(gr->gr_name);
    ga_init(const char *user, gid_t base) 
    76105/*
    77106 * Return 1 if one of user's groups is contained in groups.
    78107 * Return 0 otherwise.  Use match_pattern() for string comparison.
     108 * Use mbr_check_membership() for membership checking on Mac OS X.
    79109 */
    80110int
    81111ga_match(char * const *groups, int n)
    82112{
     113#ifdef __APPLE_MEMBERSHIP__
     114        int i, ismember = 0;
     115        uuid_t g_uuid;
     116        struct group *grp;
     117
     118        for (i = 0; i < n; i++) {
     119                if ((grp = getgrnam(groups[i])) == NULL ||
     120                   (mbr_gid_to_uuid(grp->gr_gid, g_uuid) != 0) ||
     121                   (mbr_check_membership(u_uuid, g_uuid, &ismember) != 0))
     122                        return 0;
     123                if (ismember)
     124                        return 1;
     125        }
     126#else
    83127        int i, j;
    84128
    85129        for (i = 0; i < ngroups; i++)
    86130                for (j = 0; j < n; j++)
    87131                        if (match_pattern(groups_byname[i], groups[j]))
    88132                                return 1;
     133#endif
    89134        return 0;
    90135}
    91136
  • groupaccess.h

    diff -urp --new-file openssh-6.7p1/groupaccess.h openssh-6.7p1.patched/groupaccess.h
    old new  
    2727#ifndef GROUPACCESS_H
    2828#define GROUPACCESS_H
    2929
    30 int      ga_init(const char *, gid_t);
     30int      ga_init(struct passwd *);
    3131int      ga_match(char * const *, int);
    3232int      ga_match_pattern_list(const char *);
    3333void     ga_free(void);
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/keychain.c openssh-6.7p1.patched/keychain.c
    old new  
     1/*
     2 * Copyright (c) 2007 Apple Inc. All rights reserved.
     3 *
     4 * @APPLE_BSD_LICENSE_HEADER_START@
     5 *
     6 * Redistribution and use in source and binary forms, with or without
     7 * modification, are permitted provided that the following conditions
     8 * are met:
     9 *
     10 * 1.  Redistributions of source code must retain the above copyright
     11 *     notice, this list of conditions and the following disclaimer.
     12 * 2.  Redistributions in binary form must reproduce the above copyright
     13 *     notice, this list of conditions and the following disclaimer in the
     14 *     documentation and/or other materials provided with the distribution.
     15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
     16 *     contributors may be used to endorse or promote products derived from
     17 *     this software without specific prior written permission.
     18 *
     19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 *
     30 * @APPLE_BSD_LICENSE_HEADER_END@
     31 */
     32
     33#include "includes.h"
     34
     35#include <stdio.h>
     36#include <string.h>
     37
     38#include "xmalloc.h"
     39#include "key.h"
     40#include "authfd.h"
     41#include "authfile.h"
     42
     43#if defined(__APPLE_KEYCHAIN__)
     44
     45#include <CoreFoundation/CoreFoundation.h>
     46#include <Security/Security.h>
     47
     48/* Our Security/SecPassword.h is not yet API, so I will define the constants that I am using here. */
     49int kSecPasswordGet     = 1<<0;  // Get password from keychain or user
     50int kSecPasswordSet     = 1<<1;  // Set password (passed in if kSecPasswordGet not set, otherwise from user)
     51int kSecPasswordFail    = 1<<2;  // Wrong password (ignore item in keychain and flag error)
     52OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef);
     53OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data);
     54OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef);
     55
     56#endif
     57
     58/*
     59 * Platform-specific helper functions.
     60 */
     61
     62#if defined(__APPLE_KEYCHAIN__)
     63
     64static int get_boolean_preference(const char *key, int default_value,
     65    int foreground)
     66{
     67        int value = default_value;
     68        CFStringRef keyRef = NULL;
     69        CFPropertyListRef valueRef = NULL;
     70
     71        keyRef = CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
     72        if (keyRef != NULL)
     73                valueRef = CFPreferencesCopyAppValue(keyRef,
     74                    CFSTR("org.openbsd.openssh"));
     75        if (valueRef != NULL)
     76                if (CFGetTypeID(valueRef) == CFBooleanGetTypeID())
     77                        value = CFBooleanGetValue(valueRef);
     78                else if (foreground)
     79                        fprintf(stderr, "Ignoring nonboolean %s preference.\n", key);
     80
     81        if (keyRef)
     82                CFRelease(keyRef);
     83        if (valueRef)
     84                CFRelease(valueRef);
     85
     86        return value;
     87}
     88
     89#endif
     90
     91/*
     92 * Store the passphrase for a given identity in the keychain.
     93 */
     94void
     95store_in_keychain(const char *filename, const char *passphrase)
     96{
     97
     98#if defined(__APPLE_KEYCHAIN__)
     99
     100        /*
     101         * store_in_keychain
     102         * Mac OS X implementation
     103         */
     104
     105        CFStringRef cfstr_relative_filename = NULL;
     106        CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
     107        CFStringRef cfstr_filename = NULL;
     108        CFDataRef cfdata_filename = NULL;
     109        CFIndex filename_len;
     110        UInt8 *label = NULL;
     111        UInt8 *utf8_filename;
     112        OSStatus rv;
     113        SecKeychainItemRef itemRef = NULL;
     114        SecTrustedApplicationRef apps[] = {NULL, NULL, NULL};
     115        CFArrayRef trustedlist = NULL;
     116        SecAccessRef initialAccess = NULL;
     117
     118        /* Bail out if KeychainIntegration preference is -bool NO */
     119        if (get_boolean_preference("KeychainIntegration", 1, 1) == 0) {
     120                fprintf(stderr, "Keychain integration is disabled.\n");
     121                goto err;
     122        }
     123
     124        /* Interpret filename with the correct encoding. */
     125        if ((cfstr_relative_filename =
     126            CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
     127            {
     128                fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
     129                goto err;
     130        }
     131        if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
     132            cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
     133                fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
     134                goto err;
     135        }
     136        if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
     137            NULL) {
     138                fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
     139                goto err;
     140        }
     141        if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
     142            kCFURLPOSIXPathStyle)) == NULL) {
     143                fprintf(stderr, "CFURLCopyFileSystemPath failed\n");
     144                goto err;
     145        }
     146        if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
     147            cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
     148                fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
     149                goto err;
     150        }
     151        filename_len = CFDataGetLength(cfdata_filename);
     152        if ((label = xmalloc(filename_len + 5)) == NULL) {
     153                fprintf(stderr, "xmalloc failed\n");
     154                goto err;
     155        }
     156        memcpy(label, "SSH: ", 5);
     157        utf8_filename = label + 5;
     158        CFDataGetBytes(cfdata_filename, CFRangeMake(0, filename_len),
     159            utf8_filename);
     160
     161        /* Check if we already have this passphrase. */
     162        rv = SecKeychainFindGenericPassword(NULL, 3, "SSH", filename_len,
     163            (char *)utf8_filename, NULL, NULL, &itemRef);
     164        if (rv == errSecItemNotFound) {
     165                /* Add a new keychain item. */
     166                SecKeychainAttribute attrs[] = {
     167                        {kSecLabelItemAttr, filename_len + 5, label},
     168                        {kSecServiceItemAttr, 3, "SSH"},
     169                        {kSecAccountItemAttr, filename_len, utf8_filename}
     170                };
     171                SecKeychainAttributeList attrList =
     172                    {sizeof(attrs) / sizeof(attrs[0]), attrs};
     173                if (SecTrustedApplicationCreateFromPath("/usr/bin/ssh-agent",
     174                    &apps[0]) != noErr ||
     175                    SecTrustedApplicationCreateFromPath("/usr/bin/ssh-add",
     176                    &apps[1]) != noErr ||
     177                    SecTrustedApplicationCreateFromPath("/usr/bin/ssh",
     178                    &apps[2]) != noErr) {
     179                        fprintf(stderr, "SecTrustedApplicationCreateFromPath failed\n");
     180                        goto err;
     181                }
     182                if ((trustedlist = CFArrayCreate(NULL, (const void **)apps,
     183                    sizeof(apps) / sizeof(apps[0]), &kCFTypeArrayCallBacks)) ==
     184                    NULL) {
     185                        fprintf(stderr, "CFArrayCreate failed\n");
     186                        goto err;
     187                }
     188                if (SecAccessCreate(cfstr_filename, trustedlist,
     189                    &initialAccess) != noErr) {
     190                        fprintf(stderr, "SecAccessCreate failed\n");
     191                        goto err;
     192                }
     193                if (SecKeychainItemCreateFromContent(
     194                    kSecGenericPasswordItemClass, &attrList, strlen(passphrase),
     195                    passphrase, NULL, initialAccess, NULL) == noErr)
     196                        fprintf(stderr, "Passphrase stored in keychain: %s\n", filename);
     197                else
     198                        fprintf(stderr, "Could not create keychain item\n");
     199        } else if (rv == noErr) {
     200                /* Update an existing keychain item. */
     201                if (SecKeychainItemModifyAttributesAndData(itemRef, NULL,
     202                    strlen(passphrase), passphrase) == noErr)
     203                        fprintf(stderr, "Passphrase updated in keychain: %s\n", filename);
     204                else
     205                        fprintf(stderr, "Could not modify keychain item\n");
     206        } else
     207                fprintf(stderr, "Could not access keychain\n");
     208
     209err:    /* Clean up. */
     210        if (cfstr_relative_filename)
     211                CFRelease(cfstr_relative_filename);
     212        if (cfurl_relative_filename)
     213                CFRelease(cfurl_relative_filename);
     214        if (cfurl_filename)
     215                CFRelease(cfurl_filename);
     216        if (cfstr_filename)
     217                CFRelease(cfstr_filename);
     218        if (cfdata_filename)
     219                CFRelease(cfdata_filename);
     220        if (label)
     221                free(label);
     222        if (itemRef)
     223                CFRelease(itemRef);
     224        if (apps[0])
     225                CFRelease(apps[0]);
     226        if (apps[1])
     227                CFRelease(apps[1]);
     228        if (apps[2])
     229                CFRelease(apps[2]);
     230        if (trustedlist)
     231                CFRelease(trustedlist);
     232        if (initialAccess)
     233                CFRelease(initialAccess);
     234
     235#else
     236
     237        /*
     238         * store_in_keychain
     239         * no keychain implementation
     240         */
     241
     242        fprintf(stderr, "Keychain is not available on this system\n");
     243
     244#endif
     245
     246}
     247
     248/*
     249 * Remove the passphrase for a given identity from the keychain.
     250 */
     251void
     252remove_from_keychain(const char *filename)
     253{
     254
     255#if defined(__APPLE_KEYCHAIN__)
     256
     257        /*
     258         * remove_from_keychain
     259         * Mac OS X implementation
     260         */
     261
     262        CFStringRef cfstr_relative_filename = NULL;
     263        CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
     264        CFStringRef cfstr_filename = NULL;
     265        CFDataRef cfdata_filename = NULL;
     266        CFIndex filename_len;
     267        const UInt8 *utf8_filename;
     268        OSStatus rv;
     269        SecKeychainItemRef itemRef = NULL;
     270
     271        /* Bail out if KeychainIntegration preference is -bool NO */
     272        if (get_boolean_preference("KeychainIntegration", 1, 1) == 0) {
     273                fprintf(stderr, "Keychain integration is disabled.\n");
     274                goto err;
     275        }
     276
     277        /* Interpret filename with the correct encoding. */
     278        if ((cfstr_relative_filename =
     279            CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
     280            {
     281                fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
     282                goto err;
     283        }
     284        if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
     285            cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
     286                fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
     287                goto err;
     288        }
     289        if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
     290            NULL) {
     291                fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
     292                goto err;
     293        }
     294        if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
     295            kCFURLPOSIXPathStyle)) == NULL) {
     296                fprintf(stderr, "CFURLCopyFileSystemPath failed\n");
     297                goto err;
     298        }
     299        if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
     300            cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
     301                fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
     302                goto err;
     303        }
     304        filename_len = CFDataGetLength(cfdata_filename);
     305        utf8_filename = CFDataGetBytePtr(cfdata_filename);
     306
     307        /* Check if we already have this passphrase. */
     308        rv = SecKeychainFindGenericPassword(NULL, 3, "SSH", filename_len,
     309            (const char *)utf8_filename, NULL, NULL, &itemRef);
     310        if (rv == noErr) {
     311                /* Remove the passphrase from the keychain. */
     312                if (SecKeychainItemDelete(itemRef) == noErr)
     313                        fprintf(stderr, "Passphrase removed from keychain: %s\n", filename);
     314                else
     315                        fprintf(stderr, "Could not remove keychain item\n");
     316        } else if (rv != errSecItemNotFound)
     317                fprintf(stderr, "Could not access keychain\n");
     318
     319err:    /* Clean up. */
     320        if (cfstr_relative_filename)
     321                CFRelease(cfstr_relative_filename);
     322        if (cfurl_relative_filename)
     323                CFRelease(cfurl_relative_filename);
     324        if (cfurl_filename)
     325                CFRelease(cfurl_filename);
     326        if (cfstr_filename)
     327                CFRelease(cfstr_filename);
     328        if (cfdata_filename)
     329                CFRelease(cfdata_filename);
     330        if (itemRef)
     331                CFRelease(itemRef);
     332
     333#else
     334
     335        /*
     336         * remove_from_keychain
     337         * no keychain implementation
     338         */
     339
     340        fprintf(stderr, "Keychain is not available on this system\n");
     341
     342#endif
     343
     344}
     345
     346/*
     347 * Add identities to ssh-agent using passphrases stored in the keychain.
     348 * Returns zero on success and nonzero on failure.
     349 * add_identity is a callback into ssh-agent.  It takes a filename and a
     350 * passphrase, and attempts to add the identity to the agent.  It returns
     351 * zero on success and nonzero on failure.
     352 */
     353int
     354add_identities_using_keychain(int (*add_identity)(const char *, const char *))
     355{
     356
     357#if defined(__APPLE_KEYCHAIN__)
     358
     359        /*
     360         * add_identities_using_keychain
     361         * Mac OS X implementation
     362         */
     363
     364        OSStatus rv;
     365        SecKeychainSearchRef searchRef;
     366        SecKeychainItemRef itemRef;
     367        UInt32 length;
     368        void *data;
     369        CFIndex maxsize;
     370
     371        /* Bail out if KeychainIntegration preference is -bool NO */
     372        if (get_boolean_preference("KeychainIntegration", 1, 0) == 0)
     373                return 0;
     374
     375        /* Search for SSH passphrases in the keychain */
     376        SecKeychainAttribute attrs[] = {
     377                {kSecServiceItemAttr, 3, "SSH"}
     378        };
     379        SecKeychainAttributeList attrList =
     380            {sizeof(attrs) / sizeof(attrs[0]), attrs};
     381        if ((rv = SecKeychainSearchCreateFromAttributes(NULL,
     382            kSecGenericPasswordItemClass, &attrList, &searchRef)) != noErr)
     383                return 0;
     384
     385        /* Iterate through the search results. */
     386        while ((rv = SecKeychainSearchCopyNext(searchRef, &itemRef)) == noErr) {
     387                UInt32 tag = kSecAccountItemAttr;
     388                UInt32 format = kSecFormatUnknown;
     389                SecKeychainAttributeInfo info = {1, &tag, &format};
     390                SecKeychainAttributeList *itemAttrList = NULL;
     391                CFStringRef cfstr_filename = NULL;
     392                char *filename = NULL;
     393                char *passphrase = NULL;
     394
     395                /* Retrieve filename and passphrase. */
     396                if ((rv = SecKeychainItemCopyAttributesAndData(itemRef, &info,
     397                    NULL, &itemAttrList, &length, &data)) != noErr)
     398                        goto err;
     399                if (itemAttrList->count != 1)
     400                        goto err;
     401                cfstr_filename = CFStringCreateWithBytes(NULL,
     402                    itemAttrList->attr->data, itemAttrList->attr->length,
     403                    kCFStringEncodingUTF8, true);
     404                maxsize = CFStringGetMaximumSizeOfFileSystemRepresentation(
     405                    cfstr_filename);
     406                if ((filename = xmalloc(maxsize)) == NULL)
     407                        goto err;
     408                if (CFStringGetFileSystemRepresentation(cfstr_filename,
     409                    filename, maxsize) == false)
     410                        goto err;
     411                if ((passphrase = xmalloc(length + 1)) == NULL)
     412                        goto err;
     413                memcpy(passphrase, data, length);
     414                passphrase[length] = '\0';
     415
     416                /* Add the identity. */
     417                add_identity(filename, passphrase);
     418
     419err:            /* Clean up. */
     420                if (itemRef)
     421                        CFRelease(itemRef);
     422                if (cfstr_filename)
     423                        CFRelease(cfstr_filename);
     424                if (filename)
     425                        free(filename);
     426                if (passphrase)
     427                        free(passphrase);
     428                if (itemAttrList)
     429                        SecKeychainItemFreeAttributesAndData(itemAttrList,
     430                            data);
     431        }
     432
     433        CFRelease(searchRef);
     434
     435        return 0;
     436
     437#else
     438
     439        /*
     440         * add_identities_using_keychain
     441         * no implementation
     442         */
     443
     444        return 1;
     445
     446#endif
     447
     448}
     449
     450/*
     451 * Prompt the user for a key's passphrase.  The user will be offered the option
     452 * of storing the passphrase in their keychain.  Returns the passphrase
     453 * (which the caller is responsible for freeing), or NULL if this function
     454 * fails or is not implemented.  If this function is not implemented, ssh will
     455 * fall back on the standard read_passphrase function, and the user will need
     456 * to use ssh-add -K to add their keys to the keychain.
     457 */
     458char *
     459keychain_read_passphrase(const char *filename, int oAskPassGUI)
     460{
     461
     462#if defined(__APPLE_KEYCHAIN__)
     463
     464        /*
     465         * keychain_read_passphrase
     466         * Mac OS X implementation
     467         */
     468
     469        CFStringRef cfstr_relative_filename = NULL;
     470        CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
     471        CFStringRef cfstr_filename = NULL;
     472        CFDataRef cfdata_filename = NULL;
     473        CFIndex filename_len;
     474        UInt8 *label = NULL;
     475        UInt8 *utf8_filename;
     476        SecPasswordRef passRef = NULL;
     477        SecTrustedApplicationRef apps[] = {NULL, NULL, NULL};
     478        CFArrayRef trustedlist = NULL;
     479        SecAccessRef initialAccess = NULL;
     480        CFURLRef path = NULL;
     481        CFStringRef pathFinal = NULL;
     482        CFURLRef bundle_url = NULL;
     483        CFBundleRef bundle = NULL;
     484        CFStringRef promptTemplate = NULL, prompt = NULL;
     485        UInt32 length;
     486        const void *data;
     487        AuthenticationConnection *ac = NULL;
     488        char *result = NULL;
     489
     490        /* Bail out if KeychainIntegration preference is -bool NO */
     491        if (get_boolean_preference("KeychainIntegration", 1, 1) == 0)
     492                goto err;
     493
     494        /* Bail out if the user set AskPassGUI preference to -bool NO */
     495        if (get_boolean_preference("AskPassGUI", 1, 1) == 0 || oAskPassGUI == 0)
     496                goto err;
     497
     498        /* Bail out if we can't communicate with ssh-agent */
     499        if ((ac = ssh_get_authentication_connection()) == NULL)
     500                goto err;
     501
     502        /* Interpret filename with the correct encoding. */
     503        if ((cfstr_relative_filename =
     504            CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
     505            {
     506                fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
     507                goto err;
     508        }
     509        if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
     510            cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
     511                fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
     512                goto err;
     513        }
     514        if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
     515            NULL) {
     516                fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
     517                goto err;
     518        }
     519        if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
     520            kCFURLPOSIXPathStyle)) == NULL) {
     521                fprintf(stderr, "CFURLCopyFileSystemPath failed\n");
     522                goto err;
     523        }
     524        if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
     525            cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
     526                fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
     527                goto err;
     528        }
     529        filename_len = CFDataGetLength(cfdata_filename);
     530        if ((label = xmalloc(filename_len + 5)) == NULL) {
     531                fprintf(stderr, "xmalloc failed\n");
     532                goto err;
     533        }
     534        memcpy(label, "SSH: ", 5);
     535        utf8_filename = label + 5;
     536        CFDataGetBytes(cfdata_filename, CFRangeMake(0, filename_len),
     537            utf8_filename);
     538
     539        /* Build a SecPasswordRef. */
     540        SecKeychainAttribute searchAttrs[] = {
     541                {kSecServiceItemAttr, 3, "SSH"},
     542                {kSecAccountItemAttr, filename_len, utf8_filename}
     543        };
     544        SecKeychainAttributeList searchAttrList =
     545            {sizeof(searchAttrs) / sizeof(searchAttrs[0]), searchAttrs};
     546        SecKeychainAttribute attrs[] = {
     547                {kSecLabelItemAttr, filename_len + 5, label},
     548                {kSecServiceItemAttr, 3, "SSH"},
     549                {kSecAccountItemAttr, filename_len, utf8_filename}
     550        };
     551        SecKeychainAttributeList attrList =
     552            {sizeof(attrs) / sizeof(attrs[0]), attrs};
     553        if (SecGenericPasswordCreate(&searchAttrList, &attrList, &passRef) !=
     554            noErr) {
     555                fprintf(stderr, "SecGenericPasswordCreate failed\n");
     556                goto err;
     557        }
     558        if (SecTrustedApplicationCreateFromPath("/usr/bin/ssh-agent", &apps[0])
     559            != noErr ||
     560            SecTrustedApplicationCreateFromPath("/usr/bin/ssh-add", &apps[1])
     561            != noErr ||
     562            SecTrustedApplicationCreateFromPath("/usr/bin/ssh", &apps[2])
     563            != noErr) {
     564                fprintf(stderr, "SecTrustedApplicationCreateFromPath failed\n");
     565                goto err;
     566        }
     567        if ((trustedlist = CFArrayCreate(NULL, (const void **)apps,
     568            sizeof(apps) / sizeof(apps[0]), &kCFTypeArrayCallBacks)) == NULL) {
     569                fprintf(stderr, "CFArrayCreate failed\n");
     570                goto err;
     571        }
     572        if (SecAccessCreate(cfstr_filename, trustedlist, &initialAccess)
     573            != noErr) {
     574                fprintf(stderr, "SecAccessCreate failed\n");
     575                goto err;
     576        }
     577        if (SecPasswordSetInitialAccess(passRef, initialAccess) != noErr) {
     578                fprintf(stderr, "SecPasswordSetInitialAccess failed\n");
     579                goto err;
     580        }
     581
     582        /* Request the passphrase from the user. */
     583        if ((path = CFURLCreateFromFileSystemRepresentation(NULL,
     584            (UInt8 *)filename, strlen(filename), false)) == NULL) {
     585                fprintf(stderr, "CFURLCreateFromFileSystemRepresentation failed\n");
     586                goto err;
     587        }
     588        if ((pathFinal = CFURLCopyLastPathComponent(path)) == NULL) {
     589                fprintf(stderr, "CFURLCopyLastPathComponent failed\n");
     590                goto err;
     591        }
     592        if (!((bundle_url = CFURLCreateWithFileSystemPath(NULL,
     593            CFSTR("/System/Library/CoreServices/"), kCFURLPOSIXPathStyle, true))
     594            != NULL && (bundle = CFBundleCreate(NULL, bundle_url)) != NULL &&
     595            (promptTemplate = CFCopyLocalizedStringFromTableInBundle(
     596            CFSTR("Enter your password for the SSH key \"%@\"."),
     597            CFSTR("OpenSSH"), bundle, "Text of the dialog asking the user for"
     598            "their passphrase.  The %@ will be replaced with the filename of a"
     599            "specific key.")) != NULL) &&
     600            (promptTemplate = CFStringCreateCopy(NULL,
     601            CFSTR("Enter your password for the SSH key \"%@\"."))) == NULL) {
     602                fprintf(stderr, "CFStringCreateCopy failed\n");
     603                goto err;
     604        }
     605        if ((prompt = CFStringCreateWithFormat(NULL, NULL, promptTemplate,
     606            pathFinal)) == NULL) {
     607                fprintf(stderr, "CFStringCreateWithFormat failed\n");
     608                goto err;
     609        }
     610        switch (SecPasswordAction(passRef, prompt,
     611            kSecPasswordGet|kSecPasswordFail, &length, &data)) {
     612        case noErr:
     613                result = xmalloc(length + 1);
     614                memcpy(result, data, length);
     615                result[length] = '\0';
     616
     617                /* Save password in keychain if requested. */
     618                if (noErr != SecPasswordAction(passRef, CFSTR(""), kSecPasswordSet, &length, &data))
     619                        fprintf(stderr, "Saving password to keychain failed\n");
     620
     621                /* Add password to agent. */
     622                char *comment = NULL;
     623                Key *private = key_load_private(filename, result, &comment);
     624                if (NULL == private)
     625                        break;
     626                if (ssh_add_identity_constrained(ac, private, comment, 0, 0))
     627                        fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
     628                else
     629                        fprintf(stderr, "Could not add identity: %s\n", filename);
     630                free(comment);
     631                key_free(private);
     632                break;
     633        case errAuthorizationCanceled:
     634                result = xmalloc(1);
     635                *result = '\0';
     636                break;
     637        default:
     638                goto err;
     639        }
     640
     641err:    /* Clean up. */
     642        if (cfstr_relative_filename)
     643                CFRelease(cfstr_relative_filename);
     644        if (cfurl_relative_filename)
     645                CFRelease(cfurl_relative_filename);
     646        if (cfurl_filename)
     647                CFRelease(cfurl_filename);
     648        if (cfstr_filename)
     649                CFRelease(cfstr_filename);
     650        if (cfdata_filename)
     651                CFRelease(cfdata_filename);
     652        if (label)
     653                free(label);
     654        if (passRef)
     655                CFRelease(passRef);
     656        if (apps[0])
     657                CFRelease(apps[0]);
     658        if (apps[1])
     659                CFRelease(apps[1]);
     660        if (apps[2])
     661                CFRelease(apps[2]);
     662        if (trustedlist)
     663                CFRelease(trustedlist);
     664        if (initialAccess)
     665                CFRelease(initialAccess);
     666        if (path)
     667                CFRelease(path);
     668        if (pathFinal)
     669                CFRelease(pathFinal);
     670        if (bundle_url)
     671                CFRelease(bundle_url);
     672        if (bundle)
     673                CFRelease(bundle);
     674        if (promptTemplate)
     675                CFRelease(promptTemplate);
     676        if (prompt)
     677                CFRelease(prompt);
     678        if (ac)
     679                ssh_close_authentication_connection(ac);
     680
     681        return result;
     682
     683#else
     684
     685        /*
     686         * keychain_read_passphrase
     687         * no implementation
     688         */
     689
     690        return NULL;
     691
     692#endif
     693
     694}
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/keychain.h openssh-6.7p1.patched/keychain.h
    old new  
     1/*
     2 * Copyright (c) 2007 Apple Inc. All rights reserved.
     3 *
     4 * @APPLE_BSD_LICENSE_HEADER_START@
     5 *
     6 * Redistribution and use in source and binary forms, with or without
     7 * modification, are permitted provided that the following conditions
     8 * are met:
     9 *
     10 * 1.  Redistributions of source code must retain the above copyright
     11 *     notice, this list of conditions and the following disclaimer.
     12 * 2.  Redistributions in binary form must reproduce the above copyright
     13 *     notice, this list of conditions and the following disclaimer in the
     14 *     documentation and/or other materials provided with the distribution.
     15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
     16 *     contributors may be used to endorse or promote products derived from
     17 *     this software without specific prior written permission.
     18 *
     19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 *
     30 * @APPLE_BSD_LICENSE_HEADER_END@
     31 */
     32
     33/*
     34 * KEYCHAIN indicates that keychain functionality is present.
     35 * KEYCHAIN_* indicates the implementation to use, and implies KEYCHAIN.
     36 */
     37#if defined(__APPLE_KEYCHAIN__)
     38#define KEYCHAIN
     39#endif
     40
     41void     store_in_keychain(const char *filename, const char *passphrase);
     42void     remove_from_keychain(const char *filename);
     43int      add_identities_using_keychain(
     44             int (*add_identity)(const char *, const char *));
     45char    *keychain_read_passphrase(const char *filename, int oAskPassGUI);
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/readconf.c openssh-6.7p1.patched/readconf.c
    old new typedef enum { 
    149149        oVisualHostKey, oUseRoaming,
    150150        oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
    151151        oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
     152#ifdef __APPLE_KEYCHAIN__
     153        oAskPassGUI,
     154#endif
    152155        oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
    153156        oStreamLocalBindMask, oStreamLocalBindUnlink,
    154157        oIgnoredUnknownOption, oDeprecated, oUnsupported
    static struct { 
    266269        { "streamlocalbindmask", oStreamLocalBindMask },
    267270        { "streamlocalbindunlink", oStreamLocalBindUnlink },
    268271        { "ignoreunknown", oIgnoreUnknown },
     272#ifdef __APPLE_KEYCHAIN__
     273        { "askpassgui", oAskPassGUI },
     274#endif
    269275
    270276        { NULL, oBadOption }
    271277};
    parse_int: 
    13581364                charptr = &options->ignored_unknown;
    13591365                goto parse_string;
    13601366
     1367#ifdef __APPLE_KEYCHAIN__
     1368        case oAskPassGUI:
     1369                intptr = &options->ask_pass_gui;
     1370                goto parse_flag;
     1371#endif
     1372
    13611373        case oProxyUseFdpass:
    13621374                intptr = &options->proxy_use_fdpass;
    13631375                goto parse_flag;
    initialize_options(Options * options) 
    16041616        options->request_tty = -1;
    16051617        options->proxy_use_fdpass = -1;
    16061618        options->ignored_unknown = NULL;
     1619#ifdef __APPLE_KEYCHAIN__
     1620        options->ask_pass_gui = -1;
     1621#endif
    16071622        options->num_canonical_domains = 0;
    16081623        options->num_permitted_cnames = 0;
    16091624        options->canonicalize_max_dots = -1;
    fill_default_options(Options * options) 
    17781793                options->ip_qos_bulk = IPTOS_THROUGHPUT;
    17791794        if (options->request_tty == -1)
    17801795                options->request_tty = REQUEST_TTY_AUTO;
     1796#ifdef __APPLE_KEYCHAIN__
     1797        if (options->ask_pass_gui == -1)
     1798                options->ask_pass_gui = 1;
     1799#endif
    17811800        if (options->proxy_use_fdpass == -1)
    17821801                options->proxy_use_fdpass = 0;
    17831802        if (options->canonicalize_max_dots == -1)
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/readconf.h openssh-6.7p1.patched/readconf.h
    old new typedef struct { 
    145145        struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
    146146
    147147        char    *ignored_unknown; /* Pattern list of unknown tokens to ignore */
     148
     149#ifdef __APPLE_KEYCHAIN__
     150        int ask_pass_gui;
     151#endif
    148152}       Options;
    149153
    150154#define SSH_CANONICALISE_NO     0
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/scp.1 openssh-6.7p1.patched/scp.1
    old new  
    1919.Sh SYNOPSIS
    2020.Nm scp
    2121.Bk -words
    22 .Op Fl 12346BCpqrv
     22.Op Fl 12346BCEpqrv
    2323.Op Fl c Ar cipher
    2424.Op Fl F Ar ssh_config
    2525.Op Fl i Ar identity_file
    Passes the 
    9595flag to
    9696.Xr ssh 1
    9797to enable compression.
     98.It Fl E
     99Preserves extended attributes, resource forks, and ACLs.  Requires both ends to be running Mac OS X 10.4 or later.
    98100.It Fl c Ar cipher
    99101Selects the cipher to use for encrypting the data transfer.
    100102This option is directly passed to
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/scp.c openssh-6.7p1.patched/scp.c
    old new  
    7878#ifdef HAVE_SYS_STAT_H
    7979# include <sys/stat.h>
    8080#endif
     81#ifdef __APPLE_XSAN__
     82#include <sys/mount.h>
     83#endif
    8184#ifdef HAVE_POLL_H
    8285#include <poll.h>
    8386#else
     
    114117#include "misc.h"
    115118#include "progressmeter.h"
    116119
     120#ifdef HAVE_COPYFILE_H
     121#include <libgen.h>
     122#include <copyfile.h>
     123#endif
     124
    117125extern char *__progname;
    118126
    119127#define COPY_BUFLEN     16384
    char *ssh_program = _PATH_SSH_PROGRAM; 
    150158/* This is used to store the pid of ssh_program */
    151159pid_t do_cmd_pid = -1;
    152160
     161#ifdef HAVE_COPYFILE
     162int copy_xattr = 0;
     163int md_flag = 0;
     164#endif
     165
     166
    153167static void
    154168killchild(int signo)
    155169{
    main(int argc, char **argv) 
    395409        addargs(&args, "-oClearAllForwardings=yes");
    396410
    397411        fflag = tflag = 0;
     412#if HAVE_COPYFILE
     413        while ((ch = getopt(argc, argv, "dfl:prtvBCEc:i:P:q12346S:o:F:")) != -1)
     414#else
    398415        while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
     416#endif
    399417                switch (ch) {
    400418                /* User-visible flags. */
    401419                case '1':
    main(int argc, char **argv) 
    456474                        showprogress = 0;
    457475                        break;
    458476
     477#ifdef HAVE_COPYFILE
     478                case 'E':
     479                        copy_xattr = 1;
     480                        break;
     481#endif
    459482                /* Server options. */
    460483                case 'd':
    461484                        targetshouldbedirectory = 1;
    main(int argc, char **argv) 
    505528        remin = remout = -1;
    506529        do_cmd_pid = -1;
    507530        /* Command to be executed on remote system using "ssh". */
     531#if HAVE_COPYFILE
     532        (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s%s",
     533            copy_xattr ? " -E" : "",
     534#else
    508535        (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
     536#endif
    509537            verbose_mode ? " -v" : "",
    510538            iamrecursive ? " -r" : "", pflag ? " -p" : "",
    511539            targetshouldbedirectory ? " -d" : "");
    source(int argc, char **argv) 
    751779        int fd = -1, haderr, indx;
    752780        char *last, *name, buf[2048], encname[MAXPATHLEN];
    753781        int len;
     782#if HAVE_COPYFILE
     783        char md_name[MAXPATHLEN];
     784        char *md_tmp;
     785#endif
    754786
    755787        for (indx = 0; indx < argc; ++indx) {
    756788                name = argv[indx];
    source(int argc, char **argv) 
    758790                len = strlen(name);
    759791                while (len > 1 && name[len-1] == '/')
    760792                        name[--len] = '\0';
     793#if HAVE_COPYFILE
     794md_next:
     795                statbytes = 0;
     796                if (md_flag) {
     797                    fd = open(md_tmp, O_RDONLY, 0);
     798                    unlink(md_tmp);
     799                    free(md_tmp);
     800                    if (fd < 0)
     801                        goto syserr;
     802                } else {
     803#endif
    761804                if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
    762805                        goto syserr;
    763806                if (strchr(name, '\n') != NULL) {
    764807                        strnvis(encname, name, sizeof(encname), VIS_NL);
    765808                        name = encname;
    766809                }
     810#if HAVE_COPYFILE
     811                }
     812#endif
    767813                if (fstat(fd, &stb) < 0) {
    768814syserr:                 run_err("%s: %s", name, strerror(errno));
    769815                        goto next;
    next: if (fd != -1) { 
    850896                else
    851897                        run_err("%s: %s", name, strerror(haderr));
    852898                (void) response();
     899#ifdef HAVE_COPYFILE
     900                if (copy_xattr && md_flag == 0)
     901                {
     902                    if (!copyfile(name, NULL, 0,
     903                            COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_CHECK))
     904                        continue;
     905
     906                    /*
     907                     * this file will hold the actual metadata
     908                     * to be transferred
     909                     */
     910                    md_tmp = strdup("/tmp/scp.md.XXXXXX");
     911                    md_tmp = mktemp(md_tmp);
     912
     913                    if(copyfile(name, md_tmp, 0,
     914                                COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_PACK) == 0)
     915                    {
     916                        /*
     917                         * this is the fake name to display
     918                         */
     919                        snprintf(md_name, sizeof md_name, "%s/._%s", dirname(name), basename(name));
     920                        name = md_name;
     921                        md_flag = 1;
     922                        if (verbose_mode)
     923                            fprintf(stderr, "copyfile(%s, %s, PACK)\n", name, md_tmp);
     924                        goto md_next;
     925                    }
     926                } else
     927                    md_flag = 0;
     928#endif
    853929        }
    854930}
    855931
    sink(int argc, char **argv) 
    9411017        if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
    9421018                targisdir = 1;
    9431019        for (first = 1;; first = 0) {
     1020#if HAVE_COPYFILE
     1021                char md_src[MAXPATHLEN];
     1022                char md_dst[MAXPATHLEN];
     1023#endif
    9441024                cp = buf;
    9451025                if (atomicio(read, remin, cp, 1) != 1)
    9461026                        return;
    sink(int argc, char **argv) 
    10861166                }
    10871167                omode = mode;
    10881168                mode |= S_IWUSR;
     1169
     1170#if HAVE_COPYFILE
     1171                if (copy_xattr && !strncmp(basename(curfile), "._", 2))
     1172                {
     1173                        int mdfd;
     1174                        if (targisdir)
     1175                        {
     1176                            snprintf(md_src, sizeof md_src, "%s.XXXXXX", np);
     1177                            snprintf(md_dst, sizeof md_dst, "%s/%s",
     1178                                    dirname(np), basename(np) + 2);
     1179                            if((mdfd = mkstemp(md_src)) < 0)
     1180                                continue;
     1181                        }
     1182                        else
     1183                        {
     1184                            snprintf(md_src, sizeof md_src, "%s/._%s.XXXXXX",
     1185                                    dirname(np), basename(np));
     1186                            snprintf(md_dst, sizeof md_dst, "%s", np);
     1187                            if((mdfd = mkstemp(md_src)) < 0)
     1188                                continue;
     1189                        }
     1190                        if (mdfd >= 0)
     1191                                close(mdfd);
     1192                        np = md_src;
     1193                }
     1194#endif
    10891195                if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
    10901196bad:                    run_err("%s: %s", np, strerror(errno));
    10911197                        continue;
    10921198                }
     1199#ifdef __APPLE_XSAN__
     1200                {
     1201                        /*
     1202                         * Pre-allocate blocks for the destination file.
     1203                         */
     1204                        fstore_t fst;
     1205
     1206                        fst.fst_flags = 0;
     1207                        fst.fst_posmode = F_PEOFPOSMODE;
     1208                        fst.fst_offset = 0;
     1209                        fst.fst_length = size;
     1210                               
     1211                        (void) fcntl(ofd, F_PREALLOCATE, &fst);
     1212                }
     1213#endif /* __APPLE_XSAN__ */             
    10931214                (void) atomicio(vwrite, remout, "", 1);
    10941215                if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
    10951216                        (void) close(ofd);
    bad: run_err("%s: %s", np, strerror(er 
    11741295                        wrerrno = errno;
    11751296                }
    11761297                (void) response();
     1298#ifdef HAVE_COPYFILE
     1299                if (copy_xattr && strncmp(basename(np), "._", 2) == 0)
     1300                {
     1301                        if (verbose_mode)
     1302                            fprintf(stderr, "copyfile(%s, %s, UNPACK)\n", md_src, md_dst);
     1303                        if(!copyfile(md_src, md_dst, 0,
     1304                            COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_UNPACK) < 0)
     1305                        {
     1306                            snprintf(md_dst, sizeof md_dst, "%s/._%s",
     1307                                    dirname(md_dst), basename(md_dst));
     1308                            rename(md_src, md_dst);
     1309                        } else
     1310                            unlink(md_src);
     1311                        if (setimes && wrerr == NO) {
     1312                                setimes = 0;
     1313                                if (utimes(md_dst, tv) < 0) {
     1314                                        run_err("%s: set times: %s",
     1315                                        np, strerror(errno));
     1316                                        wrerr = DISPLAYED;
     1317                                }
     1318                        }
     1319                } else
     1320#endif
    11771321                if (setimes && wrerr == NO) {
    11781322                        setimes = 0;
    11791323                        if (utimes(np, tv) < 0) {
    void 
    12351379usage(void)
    12361380{
    12371381        (void) fprintf(stderr,
     1382#if HAVE_COPYFILE
     1383            "usage: scp [-12346BCEpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
     1384#else
    12381385            "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
     1386#endif
    12391387            "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
    12401388            "           [[user@]host1:]file1 ... [[user@]host2:]file2\n");
    12411389        exit(1);
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/servconf.c openssh-6.7p1.patched/servconf.c
    old new fill_default_server_options(ServerOption 
    253253        if (options->gss_cleanup_creds == -1)
    254254                options->gss_cleanup_creds = 1;
    255255        if (options->password_authentication == -1)
    256                 options->password_authentication = 1;
     256                options->password_authentication = 0;
    257257        if (options->kbd_interactive_authentication == -1)
    258258                options->kbd_interactive_authentication = 0;
    259259        if (options->challenge_response_authentication == -1)
    match_cfg_line_group(const char *grps, i 
    639639        if ((pw = getpwnam(user)) == NULL) {
    640640                debug("Can't match group at line %d because user %.100s does "
    641641                    "not exist", line, user);
    642         } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
     642        } else if (ga_init(pw) == 0) {
    643643                debug("Can't Match group because user %.100s not in any group "
    644644                    "at line %d", user, line);
    645645        } else if (ga_match_pattern_list(grps) != 1) {
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/session.c openssh-6.7p1.patched/session.c
    old new session_pty_req(Session *s) 
    21132113                n_bytes = packet_remaining();
    21142114        tty_parse_modes(s->ttyfd, &n_bytes);
    21152115
     2116#ifndef __APPLE_PRIVPTY__
    21162117        if (!use_privsep)
    21172118                pty_setowner(s->pw, s->tty);
     2119#endif
    21182120
    21192121        /* Set window size from the packet. */
    21202122        pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
    session_pty_cleanup2(Session *s) 
    23542356        if (s->pid != 0)
    23552357                record_logout(s->pid, s->tty, s->pw->pw_name);
    23562358
     2359#ifndef __APPLE_PRIVPTY__
    23572360        /* Release the pseudo-tty. */
    23582361        if (getuid() == 0)
    23592362                pty_release(s->tty);
     2363#endif
    23602364
    23612365        /*
    23622366         * Close the server side of the socket pairs.  We must do this after
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/ssh-add.0 openssh-6.7p1.patched/ssh-add.0
    old new NAME 
    44     ssh-add - adds private key identities to the authentication agent
    55
    66SYNOPSIS
    7      ssh-add [-cDdkLlXx] [-t life] [file ...]
     7     ssh-add [-cDdkKLlXx] [-t life] [file ...]
    88     ssh-add -s pkcs11
    99     ssh-add -e pkcs11
    1010
    DESCRIPTION 
    5555     -l      Lists fingerprints of all identities currently represented by the
    5656             agent.
    5757
     58     -m      Add identities to the agent using any passphrases stored in your
     59             Mac OS X keychain.
     60
     61         -M      When adding identities, each passphrase will also be stored in
     62                         your Mac OS X keychain.  When removing identities with -d, each
     63                         passphrase will be removed from your Mac OS X keychain.
     64
    5865     -s pkcs11
    5966             Add keys provided by the PKCS#11 shared library pkcs11.
    6067
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/ssh-add.1 openssh-6.7p1.patched/ssh-add.1
    old new  
    4343.Nd adds private key identities to the authentication agent
    4444.Sh SYNOPSIS
    4545.Nm ssh-add
    46 .Op Fl cDdkLlXx
     46.Op Fl cDdkLlMmXx
    4747.Op Fl t Ar life
    4848.Op Ar
    4949.Nm ssh-add
    Lists public key parameters of all ident 
    119119by the agent.
    120120.It Fl l
    121121Lists fingerprints of all identities currently represented by the agent.
     122.It Fl m
     123Add identities to the agent using any passphrases stored in your Mac OS
     124X keychain.
     125.It Fl M
     126When adding identities, each passphrase will also be stored in your Mac OS
     127Xkeychain.  When removing identities with -d, each passphrase will be removed
     128from your Mac OS X keychain.
    122129.It Fl s Ar pkcs11
    123130Add keys provided by the PKCS#11 shared library
    124131.Ar pkcs11 .
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/ssh-add.c openssh-6.7p1.patched/ssh-add.c
    old new  
    6262#include "authfile.h"
    6363#include "pathnames.h"
    6464#include "misc.h"
     65#include "keychain.h"
    6566#include "ssherr.h"
    6667
    6768/* argv0 */
    clear_pass(void) 
    9899}
    99100
    100101static int
    101 delete_file(AuthenticationConnection *ac, const char *filename, int key_only)
     102add_from_keychain(AuthenticationConnection *ac)
     103{
     104        if (ssh_add_from_keychain(ac) == 0)
     105                return -1;
     106
     107        fprintf(stderr, "Added keychain identities.\n");
     108        return 0;
     109}
     110
     111static int
     112delete_file(AuthenticationConnection *ac, int keychain, const char *filename, int key_only)
    102113{
    103114        Key *public = NULL, *cert = NULL;
    104115        char *certpath = NULL, *comment = NULL;
    105116        int ret = -1;
    106117
     118        if (keychain)
     119                remove_from_keychain(filename);
    107120        public = key_load_public(filename, &comment);
    108121        if (public == NULL) {
    109122                printf("Bad key file %s\n", filename);
    delete_all(AuthenticationConnection *ac) 
    166179}
    167180
    168181static int
    169 add_file(AuthenticationConnection *ac, const char *filename, int key_only)
     182add_file(AuthenticationConnection *ac, int keychain, const char *filename, int key_only)
    170183{
    171184        Key *private, *cert;
    172185        char *comment = NULL;
    add_file(AuthenticationConnection *ac, c 
    205218        if ((r = sshkey_parse_private_fileblob(&keyblob, "", filename,
    206219            &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE)
    207220                fatal("Cannot parse %s: %s", filename, ssh_err(r));
     221        if (keychain && private != NULL)
     222                store_in_keychain(filename, "");
    208223        /* try last */
    209224        if (private == NULL && pass != NULL) {
    210225                if ((r = sshkey_parse_private_fileblob(&keyblob, pass, filename,
    211226                    &private, &comment)) != 0 &&
    212227                    r != SSH_ERR_KEY_WRONG_PASSPHRASE)
    213228                        fatal("Cannot parse %s: %s", filename, ssh_err(r));
     229                if (keychain && private != NULL)
     230                        store_in_keychain(filename, pass);
    214231        }
    215232        if (comment == NULL)
    216233                comment = xstrdup(filename);
    add_file(AuthenticationConnection *ac, c 
    232249                            r != SSH_ERR_KEY_WRONG_PASSPHRASE)
    233250                                fatal("Cannot parse %s: %s",
    234251                                            filename, ssh_err(r));
    235                         if (private != NULL)
     252                        if (private != NULL) {
     253                                if (keychain)
     254                                        store_in_keychain(filename, pass);
    236255                                break;
     256                        }
    237257                        clear_pass();
    238258                        snprintf(msg, sizeof msg,
    239259                            "Bad passphrase, try again for %.200s: ", comment);
    lock_agent(AuthenticationConnection *ac, 
    390410}
    391411
    392412static int
    393 do_file(AuthenticationConnection *ac, int deleting, int key_only, char *file)
     413do_file(AuthenticationConnection *ac, int deleting, int keychain, int key_only, char *file)
    394414{
    395415        if (deleting) {
    396                 if (delete_file(ac, file, key_only) == -1)
     416                if (delete_file(ac, keychain, file, key_only) == -1)
    397417                        return -1;
    398418        } else {
    399                 if (add_file(ac, file, key_only) == -1)
     419                if (add_file(ac, keychain, file, key_only) == -1)
    400420                        return -1;
    401421        }
    402422        return 0;
    usage(void) 
    418438        fprintf(stderr, "  -X          Unlock agent.\n");
    419439        fprintf(stderr, "  -s pkcs11   Add keys from PKCS#11 provider.\n");
    420440        fprintf(stderr, "  -e pkcs11   Remove keys provided by PKCS#11 provider.\n");
     441#ifdef KEYCHAIN
     442        fprintf(stderr, "  -m          Add all identities stored in your Mac OS X keychain.\n");
     443        fprintf(stderr, "  -M          Store passphrases in your Mac OS X keychain.\n");
     444        fprintf(stderr, "              With -d, remove passphrases from your Mac OS X keychain.\n");
     445#endif
    421446}
    422447
    423448int
    main(int argc, char **argv) 
    428453        AuthenticationConnection *ac = NULL;
    429454        char *pkcs11provider = NULL;
    430455        int i, ch, deleting = 0, ret = 0, key_only = 0;
     456        int keychain = 0;
    431457
    432458        /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
    433459        sanitise_stdfd();
    main(int argc, char **argv) 
    446472                    "Could not open a connection to your authentication agent.\n");
    447473                exit(2);
    448474        }
    449         while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) {
     475        while ((ch = getopt(argc, argv, "kKlLcdDxXmMe:s:t:")) != -1) {
    450476                switch (ch) {
    451477                case 'k':
    452478                        key_only = 1;
    main(int argc, char **argv) 
    485511                                goto done;
    486512                        }
    487513                        break;
     514                case 'm':
     515                        if (add_from_keychain(ac) == -1)
     516                                ret = 1;
     517                        goto done;
     518                case 'M':
     519                        keychain = 1;
     520                        break;
    488521                default:
    489522                        usage();
    490523                        ret = 1;
    main(int argc, char **argv) 
    516549                            default_files[i]);
    517550                        if (stat(buf, &st) < 0)
    518551                                continue;
    519                         if (do_file(ac, deleting, key_only, buf) == -1)
     552                        if (do_file(ac, deleting, keychain, key_only, buf) == -1)
    520553                                ret = 1;
    521554                        else
    522555                                count++;
    main(int argc, char **argv) 
    525558                        ret = 1;
    526559        } else {
    527560                for (i = 0; i < argc; i++) {
    528                         if (do_file(ac, deleting, key_only, argv[i]) == -1)
     561                        if (do_file(ac, deleting, keychain, key_only, argv[i]) == -1)
    529562                                ret = 1;
    530563                }
    531564        }
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/ssh-agent.c openssh-6.7p1.patched/ssh-agent.c
    old new  
    6666#include <time.h>
    6767#include <string.h>
    6868#include <unistd.h>
     69#ifdef __APPLE_LAUNCHD__
     70#include <launch.h>
     71#endif
    6972
    7073#include "xmalloc.h"
    7174#include "ssh.h"
     
    7376#include "buffer.h"
    7477#include "key.h"
    7578#include "authfd.h"
     79#include "authfile.h"
    7680#include "compat.h"
    7781#include "log.h"
    7882#include "misc.h"
    7983#include "digest.h"
     84#include "keychain.h"
    8085
    8186#ifdef ENABLE_PKCS11
    8287#include "ssh-pkcs11.h"
    process_remove_smartcard_key(SocketEntry 
    701706}
    702707#endif /* ENABLE_PKCS11 */
    703708
     709static int
     710add_identity_callback(const char *filename, const char *passphrase)
     711{
     712        Key *k;
     713        int version;
     714        Idtab *tab;
     715
     716        if ((k = key_load_private(filename, passphrase, NULL)) == NULL)
     717                return 1;
     718        switch (k->type) {
     719        case KEY_RSA:
     720        case KEY_RSA1:
     721                if (RSA_blinding_on(k->rsa, NULL) != 1) {
     722                        key_free(k);
     723                        return 1;
     724                }
     725                break;
     726        }
     727        version = k->type == KEY_RSA1 ? 1 : 2;
     728        tab = idtab_lookup(version);
     729        if (lookup_identity(k, version) == NULL) {
     730                Identity *id = xmalloc(sizeof(Identity));
     731                id->key = k;
     732                id->comment = xstrdup(filename);
     733                if (id->comment == NULL) {
     734                        key_free(k);
     735                        return 1;
     736                }
     737                id->death = 0;
     738                id->confirm = 0;
     739                TAILQ_INSERT_TAIL(&tab->idlist, id, next);
     740                tab->nentries++;
     741        } else {
     742                key_free(k);
     743                return 1;
     744        }
     745
     746        return 0;
     747}
     748
     749static void
     750process_add_from_keychain(SocketEntry *e)
     751{
     752        int result;
     753
     754        result = add_identities_using_keychain(&add_identity_callback);
     755
     756        /* e will be NULL when ssh-agent adds keys on its own at startup */
     757        if (e) {
     758                buffer_put_int(&e->output, 1);
     759                buffer_put_char(&e->output,
     760                    result ? SSH_AGENT_FAILURE : SSH_AGENT_SUCCESS);
     761        }
     762}
     763
    704764/* dispatch incoming messages */
    705765
    706766static void
    process_message(SocketEntry *e) 
    795855                process_remove_smartcard_key(e);
    796856                break;
    797857#endif /* ENABLE_PKCS11 */
     858        case SSH_AGENTC_ADD_FROM_KEYCHAIN:
     859                process_add_from_keychain(e);
     860                break;
    798861        default:
    799862                /* Unknown message.  Respond with failure. */
    800863                error("Unknown message %d", type);
    usage(void) 
    10341097int
    10351098main(int ac, char **av)
    10361099{
     1100#ifdef __APPLE_LAUNCHD__
     1101        int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, l_flag = 0;
     1102#else
    10371103        int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
     1104#endif
    10381105        int sock, fd, ch, result, saved_errno;
    10391106        u_int nalloc;
    10401107        char *shell, *format, *pidstr, *agentsocket = NULL;
    main(int ac, char **av) 
    10691136        __progname = ssh_get_progname(av[0]);
    10701137        seed_rng();
    10711138
     1139#ifdef __APPLE_LAUNCHD__
     1140        while ((ch = getopt(ac, av, "cdklsa:t:")) != -1) {
     1141#else
    10721142        while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
     1143#endif
    10731144                switch (ch) {
    10741145                case 'c':
    10751146                        if (s_flag)
    main(int ac, char **av) 
    10791150                case 'k':
    10801151                        k_flag++;
    10811152                        break;
     1153#ifdef __APPLE_LAUNCHD__
     1154                case 'l':
     1155                        l_flag++;
     1156                        break;
     1157#endif
    10821158                case 's':
    10831159                        if (c_flag)
    10841160                                usage();
    main(int ac, char **av) 
    11051181        ac -= optind;
    11061182        av += optind;
    11071183
     1184#ifdef __APPPLE_LAUNCHD__
     1185        if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || l_flag))
     1186#else
    11081187        if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
     1188#endif
    11091189                usage();
    11101190
    11111191        if (ac == 0 && !c_flag && !s_flag) {
    main(int ac, char **av) 
    11611241         * Create socket early so it will exist before command gets run from
    11621242         * the parent.
    11631243         */
     1244#ifdef __APPLE_LAUNCHD__
     1245        if (l_flag) {
     1246                launch_data_t resp, msg, tmp;
     1247                size_t listeners_i;
     1248
     1249                msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
     1250
     1251                resp = launch_msg(msg);
     1252
     1253                if (NULL == resp) {
     1254                        perror("launch_msg");
     1255                        exit(1);
     1256                }
     1257                launch_data_free(msg);
     1258                switch (launch_data_get_type(resp)) {
     1259                case LAUNCH_DATA_ERRNO:
     1260                        errno = launch_data_get_errno(resp);
     1261                        perror("launch_msg response");
     1262                        exit(1);
     1263                case LAUNCH_DATA_DICTIONARY:
     1264                        break;
     1265                default:
     1266                        fprintf(stderr, "launch_msg unknown response");
     1267                        exit(1);
     1268                }
     1269                tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS);
     1270
     1271                if (NULL == tmp) {
     1272                        fprintf(stderr, "no sockets\n");
     1273                        exit(1);
     1274                }
     1275
     1276                tmp = launch_data_dict_lookup(tmp, "Listeners");
     1277
     1278                if (NULL == tmp) {
     1279                        fprintf(stderr, "no known listeners\n");
     1280                        exit(1);
     1281                }
     1282
     1283                for (listeners_i = 0; listeners_i < launch_data_array_get_count(tmp); listeners_i++) {
     1284                        launch_data_t obj_at_ind = launch_data_array_get_index(tmp, listeners_i);
     1285                        new_socket(AUTH_SOCKET, launch_data_get_fd(obj_at_ind));
     1286                }
     1287
     1288                launch_data_free(resp);
     1289        } else {
     1290#endif
    11641291        prev_mask = umask(0177);
    11651292        sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
    11661293        if (sock < 0) {
    main(int ac, char **av) 
    12151342                error("setsid: %s", strerror(errno));
    12161343                cleanup_exit(1);
    12171344        }
     1345#ifdef __APPLE_LAUNCHD__
     1346        }
     1347#endif
     1348
     1349#ifdef __APPLE_LAUNCHD__
     1350        if (l_flag)
     1351                goto skip2;
     1352#endif
    12181353
    12191354        (void)chdir("/");
    12201355        if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
    skip: 
    12431378        pkcs11_init(0);
    12441379#endif
    12451380        new_socket(AUTH_SOCKET, sock);
     1381skip2:
    12461382        if (ac > 0)
    12471383                parent_alive_interval = 10;
    12481384        idtab_init();
    skip: 
    12521388        signal(SIGTERM, cleanup_handler);
    12531389        nalloc = 0;
    12541390
     1391#ifdef KEYCHAIN
     1392        process_add_from_keychain(NULL);
     1393#endif
     1394
    12551395        while (1) {
    12561396                prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
    12571397                result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
  • ssh-keysign.8

    diff -urp --new-file openssh-6.7p1/ssh-keysign.8 openssh-6.7p1.patched/ssh-keysign.8
    old new accessible to others. 
    7272Since they are readable only by root,
    7373.Nm
    7474must be set-uid root if host-based authentication is used.
     75Note that
     76.Nm
     77is not set-uid by default on Mac OS X.
    7578.Pp
    7679.It Pa /etc/ssh/ssh_host_dsa_key-cert.pub
    7780.It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub
  • sshconnect1.c

    diff -urp --new-file openssh-6.7p1/sshconnect1.c openssh-6.7p1.patched/sshconnect1.c
    old new  
    4747#include "hostfile.h"
    4848#include "auth.h"
    4949#include "digest.h"
     50#include "keychain.h"
    5051
    5152/* Session id for the current session. */
    5253u_char session_id[16];
    try_rsa_authentication(int idx) 
    262263                snprintf(buf, sizeof(buf),
    263264                    "Enter passphrase for RSA key '%.100s': ", comment);
    264265                for (i = 0; i < options.number_of_password_prompts; i++) {
     266#ifdef __APPLE_KEYCHAIN__
     267                        passphrase = keychain_read_passphrase(comment, options.ask_pass_gui);
     268                        if (passphrase == NULL)
     269#endif
    265270                        passphrase = read_passphrase(buf, 0);
    266271                        if (strcmp(passphrase, "") != 0) {
    267272                                private = key_load_private_type(KEY_RSA1,
  • sshconnect2.c

    diff -urp --new-file openssh-6.7p1/sshconnect2.c openssh-6.7p1.patched/sshconnect2.c
    old new  
    7070#include "pathnames.h"
    7171#include "uidswap.h"
    7272#include "hostfile.h"
     73#include "keychain.h"
    7374
    7475#ifdef GSSAPI
    7576#include "ssh-gss.h"
    load_identity_file(char *filename, int u 
    11221123                snprintf(prompt, sizeof prompt,
    11231124                    "Enter passphrase for key '%.100s': ", filename);
    11241125                for (i = 0; i < options.number_of_password_prompts; i++) {
     1126#ifdef __APPLE_KEYCHAIN__
     1127                        passphrase = keychain_read_passphrase(filename, options.ask_pass_gui);
     1128                        if (passphrase == NULL)
     1129#endif
    11251130                        passphrase = read_passphrase(prompt, 0);
    11261131                        if (strcmp(passphrase, "") != 0) {
    11271132                                private = key_load_private_type(KEY_UNSPEC,
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/sshd.8 openssh-6.7p1.patched/sshd.8
    old new The content of this file is not sensitiv 
    954954.Xr ssh-keygen 1 ,
    955955.Xr ssh-keyscan 1 ,
    956956.Xr chroot 2 ,
    957 .Xr login.conf 5 ,
    958 .Xr moduli 5 ,
    959957.Xr sshd_config 5 ,
    960 .Xr inetd 8 ,
    961958.Xr sftp-server 8
    962959.Sh AUTHORS
    963960OpenSSH is a derivative of the original and free
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/sshd.c openssh-6.7p1.patched/sshd.c
    old new main(int ac, char **av) 
    21372137        audit_event(SSH_AUTH_SUCCESS);
    21382138#endif
    21392139
     2140#ifdef USE_PAM
     2141        if (options.use_pam) {
     2142                do_pam_setcred(1);
     2143                do_pam_session();
     2144        }
     2145#endif
    21402146#ifdef GSSAPI
    21412147        if (options.gss_authentication) {
    21422148                temporarily_use_uid(authctxt->pw);
    main(int ac, char **av) 
    21442150                restore_uid();
    21452151        }
    21462152#endif
    2147 #ifdef USE_PAM
    2148         if (options.use_pam) {
    2149                 do_pam_setcred(1);
    2150                 do_pam_session();
    2151         }
    2152 #endif
    21532153
    21542154        /*
    21552155         * In privilege separation, we fork another child and prepare
  • openssh-6.7p1

    diff -urp --new-file openssh-6.7p1/sshd_config openssh-6.7p1.patched/sshd_config
    old new  
    3535
    3636# Logging
    3737# obsoletes QuietMode and FascistLogging
    38 #SyslogFacility AUTH
     38SyslogFacility AUTHPRIV
    3939#LogLevel INFO
    4040
    4141# Authentication:
    AuthorizedKeysFile .ssh/authorized_keys 
    6868# Don't read the user's ~/.rhosts and ~/.shosts files
    6969#IgnoreRhosts yes
    7070
    71 # To disable tunneled clear text passwords, change to no here!
    72 #PasswordAuthentication yes
     71# To disable tunneled clear text passwords, change to no here! Also,
     72# remember to set the UsePAM setting to 'no'.
     73#PasswordAuthentication no
    7374#PermitEmptyPasswords no
    7475
    7576# Change to no to disable s/key passwords
    AuthorizedKeysFile .ssh/authorized_keys 
    9495# If you just want the PAM account and session checks to run without
    9596# PAM authentication, then enable this but set PasswordAuthentication
    9697# and ChallengeResponseAuthentication to 'no'.
    97 #UsePAM no
     98# Also, PAM will deny null passwords by default.  If you need to allow
     99# null passwords, add the "     nullok" option to the end of the
     100# securityserver.so line in /etc/pam.d/sshd.
     101#UsePAM yes
    98102
    99103#AllowAgentForwarding yes
    100104#AllowTcpForwarding yes
  • sshd_config.0

    diff -urp --new-file openssh-6.7p1/sshd_config.0 openssh-6.7p1.patched/sshd_config.0
    old new DESCRIPTION 
    571571
    572572     PasswordAuthentication
    573573             Specifies whether password authentication is allowed.  The
    574              default is ``yes''.
     574             default is ``no''.
    575575
    576576     PermitEmptyPasswords
    577577             When password authentication is allowed, it specifies whether the
    DESCRIPTION 
    802802             either PasswordAuthentication or ChallengeResponseAuthentication.
    803803
    804804             If UsePAM is enabled, you will not be able to run sshd(8) as a
    805              non-root user.  The default is ``no''.
     805             non-root user.  The default is ``yes''.
    806806
    807807     UsePrivilegeSeparation
    808808             Specifies whether sshd(8) separates privileges by creating an
  • sshd_config.5

    diff -urp --new-file openssh-6.7p1/sshd_config.5 openssh-6.7p1.patched/sshd_config.5
    old new are refused if the number of unauthentic 
    977977.It Cm PasswordAuthentication
    978978Specifies whether password authentication is allowed.
    979979The default is
    980 .Dq yes .
     980.Dq no .
    981981.It Cm PermitEmptyPasswords
    982982When password authentication is allowed, it specifies whether the
    983983server allows login to accounts with empty password strings.
    is enabled, you will not be able to run 
    13431343.Xr sshd 8
    13441344as a non-root user.
    13451345The default is
    1346 .Dq no .
     1346.Dq yes .
    13471347.It Cm UsePrivilegeSeparation
    13481348Specifies whether
    13491349.Xr sshd 8